From 3fe5e7361e80a62cd0077d9877026f92b53281ac Mon Sep 17 00:00:00 2001 From: Lennart Van Hirtum Date: Fri, 6 Dec 2024 14:38:28 +0100 Subject: [PATCH] Extract some shared functionality between SV and VHDL --- src/codegen/mod.rs | 16 +++-------- src/codegen/shared.rs | 45 +++++++++++++++++++++++++++++++ src/codegen/system_verilog.rs | 37 +++----------------------- src/codegen/vhdl.rs | 50 +++++++++-------------------------- 4 files changed, 64 insertions(+), 84 deletions(-) create mode 100644 src/codegen/shared.rs diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 0847cb6..4991523 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -1,5 +1,6 @@ pub mod system_verilog; pub mod vhdl; +mod shared; pub use system_verilog::VerilogCodegenBackend; pub use vhdl::VHDLCodegenBackend; @@ -12,7 +13,7 @@ pub trait CodeGenBackend { fn file_extension(&self) -> &str; fn output_dir_name(&self) -> &str; fn comment(&self) -> &str; - fn codegen(&self, md: &Module, instance: &InstantiatedModule) -> String; + fn codegen(&self, md: &Module, instance: &InstantiatedModule, use_latency: bool) -> String; fn make_output_file(&self, name: &str) -> File { let mut path = PathBuf::with_capacity(name.len() + self.output_dir_name().len() + self.file_extension().len() + 2); @@ -40,7 +41,7 @@ pub trait CodeGenBackend { return; // Continue } println!("Instantiating success: {inst_name}"); - let code = self.codegen(md, &inst); + let code = self.codegen(md, &inst, true); // hardcode use_latency = true for now. Maybe forever, we'll see write!(out_file, "{} {inst_name}\n{code}", self.comment()).unwrap(); } @@ -88,14 +89,3 @@ pub trait CodeGenBackend { } } } - -fn mangle(str: &str) -> String { - let mut result = String::with_capacity(str.len()); - for c in str.chars() { - if c.is_whitespace() || c == ':' { - continue; - } - result.push(if c.is_alphanumeric() { c } else { '_' }); - } - result -} diff --git a/src/codegen/shared.rs b/src/codegen/shared.rs new file mode 100644 index 0000000..29a6383 --- /dev/null +++ b/src/codegen/shared.rs @@ -0,0 +1,45 @@ +//! Shared utilities + +use std::borrow::Cow; + +use crate::{instantiation::RealWire, linker::get_builtin_type, TypeUUID}; + + +pub fn mangle(str: &str) -> String { + let mut result = String::with_capacity(str.len()); + for c in str.chars() { + if c.is_whitespace() || c == ':' { + continue; + } + result.push(if c.is_alphanumeric() { c } else { '_' }); + } + result +} + +pub fn get_type_name_size(id: TypeUUID) -> u64 { + if id == get_builtin_type("int") { + 32 // TODO concrete int sizes + } else if id == get_builtin_type("bool") { + 1 + } else { + println!("TODO Named Structs Size"); + 1 // todo!() // Named structs are not implemented yet + } +} + +pub fn wire_name_with_latency(wire: &RealWire, absolute_latency: i64, use_latency: bool) -> Cow { + assert!(wire.absolute_latency <= absolute_latency); + if use_latency && (wire.absolute_latency != absolute_latency) { + if absolute_latency < 0 { + Cow::Owned(format!("_{}_N{}", wire.name, -absolute_latency)) + } else { + Cow::Owned(format!("_{}_D{}", wire.name, absolute_latency)) + } + } else { + Cow::Borrowed(&wire.name) + } +} + +pub fn wire_name_self_latency(wire: &RealWire, use_latency: bool) -> Cow { + wire_name_with_latency(wire, wire.absolute_latency, use_latency) +} diff --git a/src/codegen/system_verilog.rs b/src/codegen/system_verilog.rs index f404701..9c271d8 100644 --- a/src/codegen/system_verilog.rs +++ b/src/codegen/system_verilog.rs @@ -8,9 +8,9 @@ use crate::flattening::{DeclarationPortInfo, Instruction, Module, Port}; use crate::instantiation::{ InstantiatedModule, RealWire, RealWireDataSource, RealWirePathElem, CALCULATE_LATENCY_LATER, }; -use crate::{linker::get_builtin_type, typing::concrete_type::ConcreteType, value::Value}; +use crate::{typing::concrete_type::ConcreteType, value::Value}; -use super::mangle; +use super::shared::*; #[derive(Debug)] pub struct VerilogCodegenBackend; @@ -25,19 +25,8 @@ impl super::CodeGenBackend for VerilogCodegenBackend { fn comment(&self) -> &str { "//" } - fn codegen(&self, md: &Module, instance: &InstantiatedModule) -> String { - gen_verilog_code(md, instance, true) - } -} - -fn get_type_name_size(id: TypeUUID) -> u64 { - if id == get_builtin_type("int") { - 32 // TODO concrete int sizes - } else if id == get_builtin_type("bool") { - 1 - } else { - println!("TODO Named Structs Size"); - 1 // todo!() // Named structs are not implemented yet + fn codegen(&self, md: &Module, instance: &InstantiatedModule, use_latency: bool) -> String { + gen_verilog_code(md, instance, use_latency) } } @@ -67,24 +56,6 @@ fn typ_to_declaration(mut typ: &ConcreteType, var_name: &str) -> String { } } -fn wire_name_with_latency(wire: &RealWire, absolute_latency: i64, use_latency: bool) -> Cow { - assert!(wire.absolute_latency <= absolute_latency); - - if use_latency && (wire.absolute_latency != absolute_latency) { - if absolute_latency < 0 { - Cow::Owned(format!("_{}_N{}", wire.name, -absolute_latency)) - } else { - Cow::Owned(format!("_{}_D{}", wire.name, absolute_latency)) - } - } else { - Cow::Borrowed(&wire.name) - } -} - -fn wire_name_self_latency(wire: &RealWire, use_latency: bool) -> Cow { - wire_name_with_latency(wire, wire.absolute_latency, use_latency) -} - struct CodeGenerationContext<'g, 'out, Stream: std::fmt::Write> { md: &'g Module, instance: &'g InstantiatedModule, diff --git a/src/codegen/vhdl.rs b/src/codegen/vhdl.rs index 5acb406..ec17773 100644 --- a/src/codegen/vhdl.rs +++ b/src/codegen/vhdl.rs @@ -1,13 +1,14 @@ -use super::mangle; + use crate::{ flattening::{DeclarationPortInfo, Instruction}, - instantiation::RealWire, - linker::{get_builtin_type, IsExtern}, + linker::IsExtern, typing::concrete_type::ConcreteType, - FlatAlloc, InstantiatedModule, Module, TypeUUID, WireIDMarker, + FlatAlloc, InstantiatedModule, Module, WireIDMarker, }; use std::ops::Deref; -use std::{borrow::Cow, fmt::Write}; +use std::fmt::Write; + +use super::shared::*; #[derive(Debug)] pub struct VHDLCodegenBackend; @@ -22,47 +23,19 @@ impl super::CodeGenBackend for VHDLCodegenBackend { fn comment(&self) -> &str { "--" } - fn codegen(&self, md: &Module, instance: &InstantiatedModule) -> String { - gen_vhdl_code(md, instance) - } -} - -fn wire_name_with_latency(wire: &RealWire, absolute_latency: i64) -> Cow { - assert!(wire.absolute_latency <= absolute_latency); - - if wire.absolute_latency != absolute_latency { - if absolute_latency < 0 { - Cow::Owned(format!("_{}_N{}", wire.name, -absolute_latency)) - } else { - Cow::Owned(format!("_{}_D{}", wire.name, absolute_latency)) - } - } else { - Cow::Borrowed(&wire.name) + fn codegen(&self, md: &Module, instance: &InstantiatedModule, use_latency: bool) -> String { + gen_vhdl_code(md, instance, use_latency) } } -fn wire_name_self_latency(wire: &RealWire) -> Cow { - wire_name_with_latency(wire, wire.absolute_latency) -} - struct CodeGenerationContext<'g, 'out, Stream: std::fmt::Write> { md: &'g Module, instance: &'g InstantiatedModule, program_text: &'out mut Stream, + use_latency: bool, needed_untils: FlatAlloc, } -fn get_type_name_size(id: TypeUUID) -> u64 { - if id == get_builtin_type("int") { - 32 // TODO concrete int sizes - } else if id == get_builtin_type("bool") { - 1 - } else { - println!("TODO Named Structs Size"); - 1 // todo!() // Named structs are not implemented yet - } -} - fn typ_to_declaration(mut typ: &ConcreteType) -> String { let mut array_string = String::new(); while let ConcreteType::Array(arr) = typ { @@ -174,7 +147,7 @@ impl<'g, 'out, Stream: std::fmt::Write> CodeGenerationContext<'g, 'out, Stream> return true; }) .map(|(_, wire)| { - let signal_name = wire_name_self_latency(wire); + let signal_name = wire_name_self_latency(wire, self.use_latency); let signal_type = typ_to_declaration(&wire.typ); format!(" signal {signal_name} : {signal_type}") }) @@ -191,13 +164,14 @@ impl<'g, 'out, Stream: std::fmt::Write> CodeGenerationContext<'g, 'out, Stream> } } -fn gen_vhdl_code(md: &Module, instance: &InstantiatedModule) -> String { +fn gen_vhdl_code(md: &Module, instance: &InstantiatedModule, use_latency: bool) -> String { todo!("VHDl codegen is unfinshed"); let mut program_text = String::new(); let mut ctx = CodeGenerationContext { md, instance, + use_latency, program_text: &mut program_text, needed_untils: instance.compute_needed_untils(), };