Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

hwgenrefactor #120

Open
wants to merge 19 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
lib/velosihwgen: getting back support for the registers
Signed-off-by: Reto Achermann <[email protected]>
  • Loading branch information
achreto committed Nov 29, 2024
commit c08aac914c088dd74318993a5fb2054bda8de579
12 changes: 6 additions & 6 deletions lib/velosihwgen/src/fastmodels/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,10 +170,7 @@ impl VelosiHwGenBackend for ArmFastModelsModule {

let top_file = unit_header_file(top_files[0]); // e.g. X86_MMU_unit.hpp
let top_class = unit_class_name(top_files[0]); // e.g. X86_MMU
let unit_files: Vec<String> = dag
.iter()
.map(|n| unit_impl_file(n))
.collect();
let unit_files: Vec<String> = dag.iter().map(|n| unit_impl_file(n)).collect();

fill_template(
self.support_dir.join("TranslationUnit.lisa.template"),
Expand All @@ -200,7 +197,10 @@ impl VelosiHwGenBackend for ArmFastModelsModule {
self.support_dir.join("Makefile.template"),
self.outdir.join("Makefile"),
HashMap::from([
(&"/* REPLACE unit_srcs */".to_string(), &unit_files.join(" ")),
(
&"/* REPLACE unit_srcs */".to_string(),
&unit_files.join(" "),
),
(&"/* REPLACE pkgname */".to_string(), &self.pkgname),
]),
)?;
Expand All @@ -214,7 +214,7 @@ impl VelosiHwGenBackend for ArmFastModelsModule {
continue;
}

generate_unit_cpp(u, ast, &self.outdir)?;
generate_unit_cpp(u, ast, &self.pkgname, &self.outdir)?;
}

Ok(())
Expand Down
13 changes: 7 additions & 6 deletions lib/velosihwgen/src/fastmodels/registers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,15 @@

use crate::fastmodels::add_header_comment;
use crate::fastmodels::unit::state_class_name;
use crate::fastmodels::unit::unit_header_file;

use crate::VelosiHwGenError;
use crustal as C;
use std::ops::Deref;
use std::path::Path;
use velosiast::{VelosiAst, VelosiAstField, VelosiAstInterfaceField, VelosiAstUnit};

use super::unit::state_header_file;

pub fn registers_header_file(name: &str) -> String {
format!("{}_registers.hpp", name)
}
Expand Down Expand Up @@ -88,7 +90,7 @@ pub fn generate_register_header(
let rs = register_map(|r| r.clone(), u);

if !rs.is_empty() {
let state_h = unit_header_file(&u.ident_to_string());
let state_h = state_header_file(u.ident().as_str());
s.new_include(&state_h, false);
}

Expand Down Expand Up @@ -176,16 +178,15 @@ pub fn generate_register_impl(
))
.push_param(cparam);

let field_access_expr =
C::Expr::field_access(&stvar, r.ident());
let field_access_expr = C::Expr::field_access(&stvar, r.ident());

let m = c
.new_method("do_read", C::Type::new_uint(64))
.set_override();
m.body()
.fn_call(
"Logging::debug",
vec![C::Expr::new_str("Register::do_read()")],
vec![C::Expr::new_str(&format!("{rcn}::do_read()"))],
)
.raw(format!(
"auto st = static_cast<{} *>(this->get_state())",
Expand All @@ -202,7 +203,7 @@ pub fn generate_register_impl(
m.body()
.fn_call(
"Logging::debug",
vec![C::Expr::new_str("Register::do_write()")],
vec![C::Expr::new_str(&format!("{rcn}::do_write()"))],
)
.raw(format!(
"auto st = static_cast<{} *>(this->get_state())",
Expand Down
162 changes: 121 additions & 41 deletions lib/velosihwgen/src/fastmodels/unit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,11 @@ use velosiast::{
use C::Scope;

use crate::fastmodels::add_header_comment;
use crate::fastmodels::registers::register_class_name;
use crate::VelosiHwGenError;

use super::registers::registers_header_file;

pub fn unit_header_file(name: &str) -> String {
format!("{}_unit.hpp", name)
}
Expand All @@ -62,6 +65,10 @@ pub fn state_class_name(name: &str) -> String {
format!("{}State", unit_class_name(name))
}

pub fn state_header_file(name: &str) -> String {
format!("{}_state.hpp", name)
}

pub fn state_field_class_name(unit: &str, name: &str) -> String {
format!(
"{}{}{}StateField",
Expand Down Expand Up @@ -498,27 +505,25 @@ fn add_translate_method_segment(

body.return_expr(C::Expr::bfalse());
} else {
let offset_mask = body
.new_variable("offset_mask", C::Type::new_uint64())
.to_expr();
body.assign(
offset_mask.clone(),
C::Expr::Raw(format!("((uint64_t)1 << {:#x}) - 1", segment.inbitwidth)),
src_var.clone(),
C::Expr::binop(
src_var.clone(),
"&",
C::Expr::new_num(if segment.inbitwidth == 64 {
0xffffffffffffffff
} else {
(1 << segment.inbitwidth) - 1
}),
),
);

// should always be dealing with paddrs
// return the expression
// no next translation unit, simply set the return value with the expression
body.new_comment("return the result of the translation");
// calculate the value
body.assign(
base_var.clone(),
C::Expr::binop(
expr_to_cpp(tbody, &params),
"+",
C::Expr::binop(src_var, "&", offset_mask),
),
);
body.assign(base_var.clone(), expr_to_cpp(tbody, &params));
// assign it to the deref return value
body.assign(C::Expr::deref(&dst_addr), base_var);
// return true
Expand Down Expand Up @@ -916,6 +921,30 @@ fn add_method_maybe(c: &mut C::Class, tm: &VelosiAstMethod, params: &HashSet<&st
}
}

fn add_state_header(unit: &VelosiAstUnit, _pkgname: &str, outdir: &Path) {
let mut scope = C::Scope::new();

let header_guard = format!("{}_STATE_HPP_", unit.ident().to_uppercase());
let guard = scope.new_ifdef(&header_guard);
let s = guard.guard().then_scope();

add_header_comment(s, unit.ident(), "generated implementation");

s.new_comment("system includes");
s.new_include("string.h", true);
s.new_include("stddef.h", true);
s.new_include("assert.h", true);
s.new_comment("framework includes");
s.new_include("framework/types.hpp", false);
s.new_include("framework/state_base.hpp", false);
s.new_include("framework/state_field_base.hpp", false);

add_state_classes(s, unit);

scope.set_filename(&state_header_file(unit.ident()));
scope.to_file(outdir, true).expect("failed to write file");
}

fn add_state_classes(s: &mut Scope, unit: &VelosiAstUnit) {
let scn = state_class_name(unit.ident());

Expand All @@ -924,21 +953,25 @@ fn add_state_classes(s: &mut Scope, unit: &VelosiAstUnit) {
None => Vec::<Rc<VelosiAstStateField>>::new(),
};

for f in state_fields.clone() {
for f in &state_fields {
let sfcn = state_field_class_name(unit.ident(), f.ident());
let f_c = s
.new_class(&sfcn)
.set_base("StateFieldBase", C::Visibility::Public);

let (base, add_ptw_bus) = match f.as_ref() {
VelosiAstStateField::Memory(_) => ("MemoryStateFieldBase", true),
VelosiAstStateField::Register(_) => ("RegisterStateFieldBase", false),
};

let f_c = s.new_class(&sfcn).set_base(base, C::Visibility::Public);

let sf_offset = unit
.interface()
.and_then(|i: Rc<VelosiAstInterface>| i.fields_map.get(&f.ident_to_string()).cloned())
.and_then(|i_f| match i_f.as_ref() {
.map(|i_f| match i_f.as_ref() {
VelosiAstInterfaceField::Mmio(VelosiAstInterfaceMmioField { offset, .. })
| VelosiAstInterfaceField::Memory(VelosiAstInterfaceMemoryField {
offset, ..
}) => Some(offset.clone() * 8),
_ => Some(0),
}) => *offset * 8,
_ => 0,
});

let offset = match sf_offset {
Expand All @@ -962,17 +995,17 @@ fn add_state_classes(s: &mut Scope, unit: &VelosiAstUnit) {
C::Type::new_class("pv::RandomContextTransactionGenerator *"),
));

cons.push_parent_initializer(C::Expr::fn_call(
"StateFieldBase",
vec![
C::Expr::new_str(f.ident()),
C::Expr::new_num(offset),
C::Expr::Raw(String::from("base")),
C::Expr::Raw(String::from("ptw_pvbus")),
C::Expr::new_num(f.size() * 8),
C::Expr::new_num(0),
],
));
let mut init_args = vec![
C::Expr::new_str(f.ident()),
C::Expr::new_num(offset),
C::Expr::Raw(String::from("base")),
C::Expr::new_num(f.size() * 8),
C::Expr::new_num(0),
];
if add_ptw_bus {
init_args.push(C::Expr::Raw(String::from("ptw_pvbus")));
}
cons.push_parent_initializer(C::Expr::fn_call(base, init_args));

for sl in &f.layout_as_slice().to_vec() {
cons.body().method_call(
Expand Down Expand Up @@ -1078,14 +1111,57 @@ fn add_interface_class(s: &mut Scope, unit: &VelosiAstUnit) {

c.new_attribute("_state", state_ptr_type.clone());

// adding the registers here
if let Some(iface) = unit.interface() {
for f in iface.fields().iter() {
match f.as_ref() {
VelosiAstInterfaceField::Memory(_field) => (), /* no-op */
VelosiAstInterfaceField::Register(_field) => unimplemented!(), /* can't handle this */
VelosiAstInterfaceField::Mmio(field) => {
let rcn = register_class_name(field.ident());
let fieldname = format!("_{}", &field.ident());
let ty = C::Type::new_class(&rcn);
c.new_attribute(&fieldname, ty);
}
VelosiAstInterfaceField::Instruction(_field) => unimplemented!(), /* can't handle this */
}
}
}

let cons = c.new_constructor();

let m = cons.new_param("state", state_ptr_type);

let pa = C::Expr::from_method_param(m);

cons.push_parent_initializer(C::Expr::fn_call("InterfaceBase", vec![pa.clone()]));
cons.push_initializer("_state", pa);
cons.push_initializer("_state", pa.clone());

if let Some(iface) = unit.interface() {
for f in iface.fields().iter() {
match f.as_ref() {
VelosiAstInterfaceField::Memory(_field) => (), /* no-op */
VelosiAstInterfaceField::Register(_field) => unimplemented!(), /* can't handle this */
VelosiAstInterfaceField::Mmio(field) => {
let fieldname = format!("_{}", field.ident());
let rcn = register_class_name(field.ident());
cons.push_initializer(
fieldname.as_str(),
C::Expr::fn_call(&rcn, vec![pa.clone()]),
);

let this = C::Expr::this();
let field = C::Expr::field_access(&this, &fieldname);
cons.body().method_call(
C::Expr::this(),
"add_register",
vec![C::Expr::addr_of(&field)],
);
}
VelosiAstInterfaceField::Instruction(_field) => unimplemented!(), /* can't handle this */
}
}
}
}

fn add_unit_class(s: &mut Scope, unit: &VelosiAstUnit, ast: &VelosiAst) {
Expand Down Expand Up @@ -1188,15 +1264,16 @@ fn add_unit_class(s: &mut Scope, unit: &VelosiAstUnit, ast: &VelosiAst) {
pub fn generate_unit_cpp(
unit: &VelosiAstUnit,
ast: &VelosiAst,
pkgname: &str,
outdir: &Path,
) -> Result<(), VelosiHwGenError> {
let mut hs = C::Scope::new();
let mut scope = C::Scope::new();

let header_guard = format!("{}_UNIT_HPP_", unit.ident().to_uppercase());
let guard = hs.new_ifdef(&header_guard);
hs = guard.guard().then_scope().clone();
let guard = scope.new_ifdef(&header_guard);
let hs = guard.guard().then_scope();

add_header_comment(&mut hs, unit.ident(), "generated implementation");
add_header_comment(hs, unit.ident(), "generated implementation");

hs.new_comment("system includes");
hs.new_include("string.h", true);
Expand All @@ -1215,13 +1292,16 @@ pub fn generate_unit_cpp(
hs.new_comment("translation unit specific includes");
hs.new_include(&unit_header_file(&u.to_string()), false);
}
hs.new_include(&state_header_file(unit.ident().as_str()), false);
hs.new_include(&registers_header_file(pkgname), false);

add_state_classes(&mut hs, unit);
add_interface_class(&mut hs, unit);
add_unit_class(&mut hs, unit, ast);
add_state_header(unit, pkgname, outdir);
// add_state_classes(&mut hs, unit);
add_interface_class(hs, unit);
add_unit_class(hs, unit, ast);

hs.set_filename(&unit_header_file(unit.ident()));
hs.to_file(outdir, true)?;
scope.set_filename(&unit_header_file(unit.ident()));
scope.to_file(outdir, true)?;

let mut is = C::Scope::new();
is.new_include(&unit_header_file(unit.ident()), false);
Expand Down