From 0059acd5c2b646f85a25e7737faab26b5fcba56f Mon Sep 17 00:00:00 2001 From: matth2k Date: Wed, 2 Jul 2025 22:04:21 -0400 Subject: [PATCH 1/2] modify instantiable interface to relax port storage type --- examples/lut.rs | 4 ++-- examples/variants.rs | 4 ++-- src/circuit.rs | 30 +++++++++++++++++++++--------- src/netlist.rs | 25 ++++++++++++++++--------- 4 files changed, 41 insertions(+), 22 deletions(-) diff --git a/examples/lut.rs b/examples/lut.rs index 22e3ed6..ba56b99 100644 --- a/examples/lut.rs +++ b/examples/lut.rs @@ -35,11 +35,11 @@ impl Instantiable for Lut { &self.id } - fn get_input_ports(&self) -> &[Net] { + fn get_input_ports(&self) -> impl IntoIterator { &self.inputs } - fn get_output_ports(&self) -> &[Net] { + fn get_output_ports(&self) -> impl IntoIterator { std::slice::from_ref(&self.output) } diff --git a/examples/variants.rs b/examples/variants.rs index 5432785..b2a4b98 100644 --- a/examples/variants.rs +++ b/examples/variants.rs @@ -17,13 +17,13 @@ impl Instantiable for Gate { } } - fn get_input_ports(&self) -> &[Net] { + fn get_input_ports(&self) -> impl IntoIterator { match self { Gate::And(_, inputs, _) => inputs, } } - fn get_output_ports(&self) -> &[Net] { + fn get_output_ports(&self) -> impl IntoIterator { match self { Gate::And(_, _, output) => std::slice::from_ref(output), } diff --git a/src/circuit.rs b/src/circuit.rs index 5c78102..13363cf 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -220,10 +220,10 @@ pub trait Instantiable: Clone { fn get_name(&self) -> &Identifier; /// Returns the input ports of the primitive - fn get_input_ports(&self) -> &[Net]; + fn get_input_ports(&self) -> impl IntoIterator; /// Returns the output ports of the primitive - fn get_output_ports(&self) -> &[Net]; + fn get_output_ports(&self) -> impl IntoIterator; /// Returns `true` if the type intakes a parameter with this name. fn has_parameter(&self, id: &Identifier) -> bool; @@ -241,20 +241,32 @@ pub trait Instantiable: Clone { /// Returns the single output port of the primitive. fn get_single_output_port(&self) -> &Net { - if self.get_output_ports().len() > 1 { - panic!("Primitive has more than one output port"); - } - self.get_input_ports().first().unwrap() + self.get_input_ports() + .into_iter() + .next() + .expect("Primitive has no output ports") } /// Returns the output port at the given index. + /// # Panics + /// + /// If the index is out of bounds. fn get_output_port(&self, index: usize) -> &Net { - &self.get_output_ports()[index] + self.get_output_ports() + .into_iter() + .nth(index) + .expect("Index out of bounds for output ports") } - /// Returns the input port of the primitive at index `index`. + /// Returns the input port at the given index. + /// # Panics + /// + /// If the index is out of bounds. fn get_input_port(&self, index: usize) -> &Net { - &self.get_input_ports()[index] + self.get_input_ports() + .into_iter() + .nth(index) + .expect("Index out of bounds for output ports") } } diff --git a/src/netlist.rs b/src/netlist.rs index 2a7b8f8..aa9b1e0 100644 --- a/src/netlist.rs +++ b/src/netlist.rs @@ -39,11 +39,11 @@ impl Instantiable for Gate { &self.name } - fn get_input_ports(&self) -> &[Net] { + fn get_input_ports(&self) -> impl IntoIterator { &self.inputs } - fn get_output_ports(&self) -> &[Net] { + fn get_output_ports(&self) -> impl IntoIterator { &self.outputs } @@ -597,7 +597,7 @@ where /// Returns the number of input ports for this circuit node. pub fn get_num_input_ports(&self) -> usize { if let Some(inst_type) = self.get_instance_type() { - inst_type.get_input_ports().len() + inst_type.get_input_ports().into_iter().count() } else { 0 } @@ -1084,13 +1084,14 @@ where ) -> Result, String> { let nets = inst_type .get_output_ports() - .iter() + .into_iter() .map(|pnet| pnet.with_name(format!("{}_{}", inst_name, pnet.get_identifier()))) .collect::>(); - if operands.len() != inst_type.get_input_ports().len() { + let input_count = inst_type.get_input_ports().into_iter().count(); + if operands.len() != input_count { return Err(format!( "Expected {} operands, got {}", - inst_type.get_input_ports().len(), + input_count, operands.len() )); } @@ -1106,13 +1107,19 @@ where ) -> Result, String> { let nets = inst_type .get_output_ports() - .iter() + .into_iter() .map(|pnet| pnet.with_name(format!("{}_{}", inst_name, pnet.get_identifier()))) .collect::>(); let object = Object::Instance(nets, inst_name, inst_type); let index = self.objects.borrow().len(); let weak = Rc::downgrade(self); - let operands = vec![None; object.get_instance_type().unwrap().get_input_ports().len()]; + let input_count = object + .get_instance_type() + .unwrap() + .get_input_ports() + .into_iter() + .count(); + let operands = vec![None; input_count]; let owned_object = Rc::new(RefCell::new(OwnedObject { object, owner: weak, @@ -1857,7 +1864,7 @@ where writeln!(f, "{} (", inst_name.emit_name())?; let level = 4; let indent = " ".repeat(level); - for (idx, port) in inst_type.get_input_ports().iter().enumerate() { + for (idx, port) in inst_type.get_input_ports().into_iter().enumerate() { let port_name = port.get_identifier().emit_name(); if let Some(operand) = owned.operands[idx].as_ref() { let operand = match operand { From d88c09c02b886bae779bffd0d341291455ccd561 Mon Sep 17 00:00:00 2001 From: matth2k Date: Wed, 2 Jul 2025 22:07:30 -0400 Subject: [PATCH 2/2] add back missing panic --- src/circuit.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/circuit.rs b/src/circuit.rs index 13363cf..ae62405 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -241,10 +241,12 @@ pub trait Instantiable: Clone { /// Returns the single output port of the primitive. fn get_single_output_port(&self) -> &Net { - self.get_input_ports() - .into_iter() - .next() - .expect("Primitive has no output ports") + let mut iter = self.get_output_ports().into_iter(); + let ret = iter.next().expect("Primitive has no output ports"); + if iter.next().is_some() { + panic!("Primitive has more than one output port"); + } + ret } /// Returns the output port at the given index.