From c86274e4a53c679be19a9e52a90ddcb7734cd86d Mon Sep 17 00:00:00 2001 From: Michael Maloney Date: Sun, 7 Jul 2024 14:14:58 +0000 Subject: [PATCH] A bit more Verilog output. --- examples/hello.vir | 1 + src/db/typecheckq.rs | 18 ++++++++++--- src/verilog.rs | 62 +++++++++++++++++++++++--------------------- 3 files changed, 47 insertions(+), 34 deletions(-) diff --git a/examples/hello.vir b/examples/hello.vir index 7482bd9..84e03f8 100644 --- a/examples/hello.vir +++ b/examples/hello.vir @@ -6,6 +6,7 @@ pub mod Top { out := reset; mod foo of Foo; + foo.in := reset; } mod Foo { diff --git a/src/db/typecheckq.rs b/src/db/typecheckq.rs index 4d633ea..b332595 100644 --- a/src/db/typecheckq.rs +++ b/src/db/typecheckq.rs @@ -22,6 +22,8 @@ pub trait TypecheckQ: StructureQ { fn method_sig(&self, typ: Type, method: Ident) -> VirdantResult; + fn bitwidth(&self, typ: Type) -> VirdantResult; + fn moddef_typecheck_wire(&self, moddef: Ident, target: Path) -> VirdantResult>; fn moddef_typecheck(&self, moddef: Ident) -> VirdantResult<()>; fn typecheck(&self) -> VirdantResult<()>; @@ -38,7 +40,6 @@ fn typecheck(db: &dyn TypecheckQ) -> VirdantResult<()> { } fn expr_typecheck(db: &dyn TypecheckQ, moddef: Ident, expr: Arc, typ: Type) -> VirdantResult> { - 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())?; @@ -98,7 +99,6 @@ fn expr_typecheck(db: &dyn TypecheckQ, moddef: Ident, expr: Arc, typ: } fn expr_typeinfer(db: &dyn TypecheckQ, moddef: Ident, expr: Arc) -> VirdantResult> { - eprintln!("expr_typeinfer {expr:?} in {moddef}"); match expr.as_ref() { ast::Expr::Reference(path) => { let typ = db.moddef_reference_type(moddef, path.clone())?; @@ -135,6 +135,18 @@ fn method_sig(db: &dyn TypecheckQ, typ: Type, method: Ident) -> VirdantResult VirdantResult { + 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> { let ast::Wire(target, _wire_type, expr) = db.moddef_wire(moddef.clone(), target)?; let typ = db.moddef_target_type(moddef.clone(), target)?; @@ -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); } @@ -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) { diff --git a/src/verilog.rs b/src/verilog.rs index 1bc3dfd..3edf710 100644 --- a/src/verilog.rs +++ b/src/verilog.rs @@ -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::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")?; @@ -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() { @@ -151,22 +159,6 @@ impl<'a> Verilog<'a> { Ok(()) } - /* - fn verilog_type(&mut self, typ: Arc) -> 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) -> VirdantResult { match expr.as_ref() { TypedExpr::Reference(typ, path) if path.is_local() => Ok(format!("{}", path)), @@ -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]") + } +}