diff --git a/src/codegen_fallback.rs b/src/codegen_fallback.rs index 375113c..c4e3f2f 100644 --- a/src/codegen_fallback.rs +++ b/src/codegen_fallback.rs @@ -51,11 +51,12 @@ struct CodeGenerationContext<'g, 'out, Stream: std::fmt::Write> { program_text: &'out mut Stream, use_latency: bool, + + needed_untils : FlatAlloc } fn wire_name_with_latency(wire: &RealWire, absolute_latency: i64, use_latency: bool) -> String { assert!(wire.absolute_latency <= absolute_latency); - assert!(wire.needed_until >= absolute_latency); if use_latency && (wire.absolute_latency != absolute_latency) { format!("{}_D{}", wire.name, absolute_latency) @@ -109,12 +110,12 @@ impl<'g, 'out, Stream: std::fmt::Write> CodeGenerationContext<'g, 'out, Stream> result } - fn add_latency_registers(&mut self, w: &RealWire) -> Result<(), std::fmt::Error> { + fn add_latency_registers(&mut self, wire_id: WireID, w: &RealWire) -> Result<(), std::fmt::Error> { if self.use_latency { // Can do 0 iterations, when w.needed_until == w.absolute_latency. Meaning it's only needed this cycle assert!(w.absolute_latency != CALCULATE_LATENCY_LATER); - assert!(w.needed_until != CALCULATE_LATENCY_LATER); - for i in w.absolute_latency..w.needed_until { + assert!(self.needed_untils[wire_id] != CALCULATE_LATENCY_LATER); + for i in w.absolute_latency..self.needed_untils[wire_id] { let from = wire_name_with_latency(w, i, self.use_latency); let to = wire_name_with_latency(w, i + 1, self.use_latency); @@ -148,11 +149,11 @@ impl<'g, 'out, Stream: std::fmt::Write> CodeGenerationContext<'g, 'out, Stream> writeln!(self.program_text, ");\n")?; for (_id, port) in self.instance.interface_ports.iter_valids() { let port_wire = &self.instance.wires[port.wire]; - self.add_latency_registers(port_wire)?; + self.add_latency_registers(port.wire, port_wire)?; } // Then output all declarations, and the wires we can already assign - for (_id, w) in &self.instance.wires { + for (wire_id, w) in &self.instance.wires { // For better readability of output Verilog if self.can_inline(w) { continue; @@ -217,7 +218,7 @@ impl<'g, 'out, Stream: std::fmt::Write> CodeGenerationContext<'g, 'out, Stream> } } } - self.add_latency_registers(w)?; + self.add_latency_registers(wire_id, w)?; } // Output all submodules @@ -320,6 +321,7 @@ pub fn gen_verilog_code(md: &Module, instance: &InstantiatedModule, use_latency: instance, program_text: &mut program_text, use_latency, + needed_untils: instance.compute_needed_untils() }; ctx.write_verilog_code().unwrap(); diff --git a/src/instantiation/execute.rs b/src/instantiation/execute.rs index fa8a19f..4f29941 100644 --- a/src/instantiation/execute.rs +++ b/src/instantiation/execute.rs @@ -425,7 +425,6 @@ impl<'fl, 'l> InstantiationContext<'fl, 'l> { typ: value.typ, name: self.unique_name_producer.get_unique_name(""), absolute_latency: CALCULATE_LATENCY_LATER, - needed_until: CALCULATE_LATENCY_LATER, }) } fn get_wire_or_constant_as_wire( @@ -481,7 +480,6 @@ impl<'fl, 'l> InstantiationContext<'fl, 'l> { typ: ConcreteType::Unknown, name: self.unique_name_producer.get_unique_name(format!("{}_{}", submod_instance.name, port_data.name)), absolute_latency: CALCULATE_LATENCY_LATER, - needed_until: CALCULATE_LATENCY_LATER, }); let name_refs = if let Some(sp) = port_name_span { @@ -564,7 +562,6 @@ impl<'fl, 'l> InstantiationContext<'fl, 'l> { domain, source, absolute_latency: CALCULATE_LATENCY_LATER, - needed_until: CALCULATE_LATENCY_LATER, })) } fn extend_condition( @@ -586,7 +583,6 @@ impl<'fl, 'l> InstantiationContext<'fl, 'l> { right: additional_condition, }, absolute_latency: CALCULATE_LATENCY_LATER, - needed_until: CALCULATE_LATENCY_LATER, }) } else { additional_condition @@ -641,7 +637,6 @@ impl<'fl, 'l> InstantiationContext<'fl, 'l> { domain: wire_decl.typ.domain.unwrap_physical(), source, absolute_latency, - needed_until: CALCULATE_LATENCY_LATER, }); SubModuleOrWire::Wire(wire_id) }) @@ -782,7 +777,6 @@ impl<'fl, 'l> InstantiationContext<'fl, 'l> { right: condition_wire, }, absolute_latency: CALCULATE_LATENCY_LATER, - needed_until: CALCULATE_LATENCY_LATER, }); let else_cond = self.extend_condition( condition, diff --git a/src/instantiation/latency_count.rs b/src/instantiation/latency_count.rs index e560943..df7a345 100644 --- a/src/instantiation/latency_count.rs +++ b/src/instantiation/latency_count.rs @@ -130,6 +130,25 @@ impl RealWireDataSource { } } +impl InstantiatedModule { + /// Is used to add implicit registers to wires that are used longer than one cycle. + /// + /// If needed only the same cycle it is generated, then this is equal to [RealWire::absolute_latency]. + pub fn compute_needed_untils(&self) -> FlatAlloc { + let mut result = self.wires.map(|(id, w)| w.absolute_latency); + + for (_id, w) in &self.wires { + w.source.iter_sources_with_min_latency(|other, _| { + let nu = &mut result[other]; + + *nu = max(*nu, w.absolute_latency); + }); + } + + result + } +} + impl<'fl, 'l> InstantiationContext<'fl, 'l> { fn make_wire_to_latency_map(&self) -> WireToLatencyMap { const PLACEHOLDER: usize = usize::MAX; @@ -338,23 +357,6 @@ impl<'fl, 'l> InstantiationContext<'fl, 'l> { }; } - // Compute needed_untils - for (_id, w) in &mut self.wires { - w.needed_until = w.absolute_latency; - } - let mut_wires_ref: *mut _ = &mut self.wires; - for (_id, w) in &self.wires { - w.source.iter_sources_with_min_latency(|other, _| { - // SAFETY: Need some unsafe code to modify needed_until while iterating through the wires - // We write to needed_until everywhere, and for the information we need we never read needed_until - unsafe { - let nu = &mut (*mut_wires_ref)[other].needed_until; - - *nu = max(*nu, w.absolute_latency); - } - }); - } - // Finally update interface absolute latencies for (_id, port) in self.interface_ports.iter_valids_mut() { port.absolute_latency = self.wires[port.wire].absolute_latency; diff --git a/src/instantiation/mod.rs b/src/instantiation/mod.rs index 486122c..8e1f135 100644 --- a/src/instantiation/mod.rs +++ b/src/instantiation/mod.rs @@ -95,10 +95,6 @@ pub struct RealWire { pub domain: DomainID, /// Before latency counting, non i64::MIN values specify specified latency pub absolute_latency: i64, - /// Is used to add implicit registers to wires that are used longer than one cycle. - /// - /// If needed only the same cycle it is generated, then this is equal to [RealWire::absolute_latency]. - pub needed_until: i64, } #[derive(Debug)] diff --git a/verilog_output/.gitignore b/verilog_output/.gitignore index e88a29a..ffcd310 100644 --- a/verilog_output/.gitignore +++ b/verilog_output/.gitignore @@ -2,3 +2,5 @@ *.sv *.vhdl *.vh +# Any build directories created by Verilator or other tools +**/