Skip to content

Commit

Permalink
A bit more Verilog output.
Browse files Browse the repository at this point in the history
  • Loading branch information
maloneymr committed Jul 7, 2024
1 parent a9862cf commit c86274e
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 34 deletions.
1 change: 1 addition & 0 deletions examples/hello.vir
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub mod Top {
out := reset;

mod foo of Foo;
foo.in := reset;
}

mod Foo {
Expand Down
18 changes: 14 additions & 4 deletions src/db/typecheckq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ pub trait TypecheckQ: StructureQ {

fn method_sig(&self, typ: Type, method: Ident) -> VirdantResult<MethodSig>;

fn bitwidth(&self, typ: Type) -> VirdantResult<Width>;

fn moddef_typecheck_wire(&self, moddef: Ident, target: Path) -> VirdantResult<Arc<TypedExpr>>;
fn moddef_typecheck(&self, moddef: Ident) -> VirdantResult<()>;
fn typecheck(&self) -> VirdantResult<()>;
Expand All @@ -38,7 +40,6 @@ fn typecheck(db: &dyn TypecheckQ) -> VirdantResult<()> {
}

fn expr_typecheck(db: &dyn TypecheckQ, moddef: Ident, expr: Arc<ast::Expr>, typ: Type) -> VirdantResult<Arc<TypedExpr>> {
eprintln!("expr_typecheck {expr:?} as {typ} in {moddef}");
match expr.as_ref() {
ast::Expr::Reference(path) => {
let actual_typ = db.moddef_reference_type(moddef, path.clone())?;
Expand Down Expand Up @@ -98,7 +99,6 @@ fn expr_typecheck(db: &dyn TypecheckQ, moddef: Ident, expr: Arc<ast::Expr>, typ:
}

fn expr_typeinfer(db: &dyn TypecheckQ, moddef: Ident, expr: Arc<ast::Expr>) -> VirdantResult<Arc<TypedExpr>> {
eprintln!("expr_typeinfer {expr:?} in {moddef}");
match expr.as_ref() {
ast::Expr::Reference(path) => {
let typ = db.moddef_reference_type(moddef, path.clone())?;
Expand Down Expand Up @@ -135,6 +135,18 @@ fn method_sig(db: &dyn TypecheckQ, typ: Type, method: Ident) -> VirdantResult<Me
}
}

fn bitwidth(db: &dyn TypecheckQ, typ: Type) -> VirdantResult<Width> {
match typ {
Type::Unknown => todo!(),
Type::Clock => Ok(1),
Type::Bool => Ok(1),
Type::Word(n) => Ok(n.into()),
Type::Vec(_, _) => todo!(),
Type::TypeRef(_) => todo!(),
Type::Other(_) => todo!(),
}
}

fn moddef_typecheck_wire(db: &dyn TypecheckQ, moddef: Ident, target: Path) -> VirdantResult<Arc<TypedExpr>> {
let ast::Wire(target, _wire_type, expr) = db.moddef_wire(moddef.clone(), target)?;
let typ = db.moddef_target_type(moddef.clone(), target)?;
Expand All @@ -146,7 +158,6 @@ fn moddef_typecheck(db: &dyn TypecheckQ, moddef: Ident) -> VirdantResult<()> {
let targets = db.moddef_wire_targets(moddef.clone())?;

for target in &targets {
eprintln!("typechecking {target}");
if let Err(e) = db.moddef_typecheck_wire(moddef.clone(), target.clone()) {
errors.add(e);
}
Expand Down Expand Up @@ -222,7 +233,6 @@ fn typecheck_wire(db: &dyn TypecheckQ, moddef: Ident, target: Path) -> VirdantRe
let ast::Wire(target, _wire_type, expr) = db.moddef_wire(moddef.clone(), target)?;
let expected_type = db.moddef_target_type(moddef.clone(), target.clone())?;
let ctx = db.moddef_full_context(moddef.clone())?;
dbg!(&ctx);
match &*expr {
ast::Expr::Reference(path) => {
if let Some(actual_type) = ctx.lookup(path) {
Expand Down
62 changes: 32 additions & 30 deletions src/verilog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,25 +93,31 @@ impl<'a> Verilog<'a> {

fn verilog_component(&mut self, moddef: Ident, component: Ident) -> VirdantResult<()> {
let component_ast = self.db.moddef_component_ast(moddef.clone(), component.clone())?;
let expr: Arc<TypedExpr> = TypedExpr::Word(Type::Word(1), ast::WordLit { width: Some(1), value: 0 }).into();
match component_ast.kind {
SimpleComponentKind::Incoming => (),
SimpleComponentKind::Outgoing => {
let expr = self.db.moddef_typecheck_wire(moddef.clone(), component.clone().as_path())?;
let ssa = self.verilog_expr(expr)?;
writeln!(self.writer, " assign {component} = {ssa};")?;
},
SimpleComponentKind::Node => {
let expr = self.db.moddef_typecheck_wire(moddef.clone(), component.clone().as_path())?;
let typ = expr.typ();
let ssa = self.verilog_expr(expr)?;
writeln!(self.writer, " wire [31:0] {component};")?;
let width_str = make_width_str(self.db, typ);
writeln!(self.writer, " wire {width_str} {component};")?;
writeln!(self.writer, " assign {component} = {ssa};")?;
},
SimpleComponentKind::Reg => {
let expr = self.db.moddef_typecheck_wire(moddef.clone(), component.clone().as_path())?;
let typ = expr.typ();
let width_str = make_width_str(self.db, typ);
let clk: String = todo!();
//let clock_ssa = self.verilog_expr(clk)?;
let connect_ssa = self.verilog_expr(expr)?;
let width = if let Type::Word(n) = expr.typ() { n } else { panic!() };
let max_bit = width - 1;
writeln!(self.writer, " reg [{max_bit}:0] {component};")?;
writeln!(self.writer, " reg {width_str} {component};")?;
writeln!(self.writer, " always @(posedge {clk}) begin")?;
writeln!(self.writer, " {component} <= {connect_ssa};")?;
writeln!(self.writer, " end")?;
Expand All @@ -121,21 +127,23 @@ impl<'a> Verilog<'a> {
}

fn verilog_submodule(&mut self, moddef: Ident, submodule: ast::Submodule) -> VirdantResult<()> {
let mut ports = self.db.moddef_port_names(submodule.moddef.clone())?;

/*
for Connect(path, _connect_type, expr) in &self.db.moddef_submodule_connects_typed(moddef.name.clone(), submodule.name.clone())? {
let gs = self.verilog_expr(&expr)?;
let parts = path.parts();
let name = parts[1];
writeln!(self.writer, " assign __TEMP_{sm}_{name} = {gs};", sm = submodule.name)?;
let ports = self.db.moddef_port_names(submodule.moddef.clone())?;

for port in &ports {
let typ = self.db.moddef_component_type(submodule.moddef.clone(), port.clone())?;
let width_str = make_width_str(self.db, typ);
writeln!(self.writer, " wire {width_str} __TEMP_{sm}_{port};", sm = submodule.name)?;
}

// let width = todo!(); // TODO
// for Wire(path, _wire_type, expr) in &self.db.moddef_typecheck_wire(moddef.name.clone(), submodule.name.clone())? {

for port in &ports {
writeln!(self.writer, " wire [31:0] __TEMP_{sm}_{port};", sm = submodule.name)?;
if let Ok(expr) = self.db.moddef_typecheck_wire(moddef.clone(), submodule.name.as_path().join(&port.clone().as_path())) {
let gs = self.verilog_expr(expr)?;
writeln!(self.writer, " assign __TEMP_{sm}_{port} = {gs};", sm = submodule.name)?;
}
}
*/


writeln!(self.writer, " {} {}(", submodule.moddef, submodule.name)?;
for (i, port) in ports.iter().enumerate() {
Expand All @@ -151,22 +159,6 @@ impl<'a> Verilog<'a> {
Ok(())
}

/*
fn verilog_type(&mut self, typ: Arc<Type>) -> VirdantResult<()> {
match typ.as_ref() {
Type::Clock => write!(self.writer, "!virdant.clock")?,
Type::Word(n) => write!(self.writer, "!virdant.word<{n}>")?,
Type::Vec(typ, n) => {
write!(self.writer, "!virdant.vec<")?;
self.verilog_type(typ.clone())?;
write!(self.writer, ", {n}>")?;
},
_ => todo!(),
}
Ok(())
}
*/

fn verilog_expr(&mut self, expr: Arc<TypedExpr>) -> VirdantResult<SsaName> {
match expr.as_ref() {
TypedExpr::Reference(typ, path) if path.is_local() => Ok(format!("{}", path)),
Expand Down Expand Up @@ -443,3 +435,13 @@ fn verilog_output() {
let mut stdout = std::io::stdout();
verilog.write(&mut stdout).unwrap();
}

fn make_width_str(db: &Db, typ: Type) -> String {
let n = db.bitwidth(typ.clone()).unwrap();
if n == 1 {
"".to_string()
} else {
let max_bit = n - 1;
format!("[{max_bit}:0]")
}
}

0 comments on commit c86274e

Please sign in to comment.