From 858f7528426c09a3ab9bbdf7e0437efa4adb4ece Mon Sep 17 00:00:00 2001 From: D4VID Date: Sat, 30 Aug 2025 17:52:31 +0200 Subject: [PATCH] Use layer builder for unary op --- verilog2logicworld/gates.v | 2 +- verilog2logicworld/src/cells/binary_op.rs | 87 +------------------- verilog2logicworld/src/cells/builder.rs | 90 +++++++++++++++++++++ verilog2logicworld/src/cells/mod.rs | 3 + verilog2logicworld/src/cells/unary_op.rs | 98 ++++++++++++++++------- 5 files changed, 162 insertions(+), 118 deletions(-) create mode 100644 verilog2logicworld/src/cells/builder.rs diff --git a/verilog2logicworld/gates.v b/verilog2logicworld/gates.v index acee0b6..7ebbebf 100644 --- a/verilog2logicworld/gates.v +++ b/verilog2logicworld/gates.v @@ -3,5 +3,5 @@ module gates( output wire [3:0] out, out2 ); assign out = a & b | c; - assign out2 = a & b ^ d; + assign out2 = ~(a & b ^ d); endmodule diff --git a/verilog2logicworld/src/cells/binary_op.rs b/verilog2logicworld/src/cells/binary_op.rs index a094064..55c0cb5 100644 --- a/verilog2logicworld/src/cells/binary_op.rs +++ b/verilog2logicworld/src/cells/binary_op.rs @@ -3,6 +3,7 @@ use std::cmp::max; use logicworld_subassembly::{lw, COMPONENT_MAP}; use vecmath::{vec3_add, Vector3}; +use crate::cells::builder; use crate::router::{Connection, ConnectionMap, SQUARE}; use crate::verilog::Cell; @@ -182,89 +183,3 @@ pub fn binary_op( return components; } - -pub fn builder( - height: usize, - parent_address: u32, - next_address: &mut u32, - position: &Vector3, - components: &mut Vec, - wires: &mut Vec, - connection_map: &mut ConnectionMap, - layer_builder: impl Fn( - usize, - &mut u32, - u32, - &mut Vector3, - &mut Vec, - &mut Vec, - &mut ConnectionMap, - ), -) { - let mount = lw::Component { - address: *next_address, - parent: parent_address, - numeric_id: COMPONENT_MAP["MHG.Mount"], - position: *position, - rotation: quaternion::id(), - inputs: vec![], - outputs: vec![], - custom_data: lw::Mount::new(8).custom_data(), - }; - let next_board = lw::Component { - address: *next_address + 1, - parent: mount.address, - numeric_id: COMPONENT_MAP["MHG.CircuitBoard"], - position: [-SQUARE / 2, 3 * SQUARE - SQUARE / 3, -SQUARE / 2], - rotation: quaternion::id(), - inputs: vec![], - outputs: vec![], - custom_data: lw::CircuitBoard::default().with_size(3, 2).custom_data(), - }; - - *next_address += 2; - - let mut next_parent = next_board.address; - components.push(mount); - components.push(next_board); - - for i_bit in 0..height { - let mut next_position_within = [SQUARE / 2, SQUARE / 2, SQUARE / 2]; - let mount = lw::Component { - address: *next_address, - parent: next_parent, - numeric_id: COMPONENT_MAP["MHG.Mount"], - position: next_position_within, - rotation: quaternion::id(), - inputs: vec![], - outputs: vec![], - custom_data: lw::Mount::new(8).custom_data(), - }; - let next_board = lw::Component { - address: *next_address + 1, - parent: mount.address, - numeric_id: COMPONENT_MAP["MHG.CircuitBoard"], - position: [-SQUARE / 2, 3 * SQUARE - SQUARE / 3, -SQUARE / 2], - rotation: quaternion::id(), - inputs: vec![], - outputs: vec![], - custom_data: lw::CircuitBoard::default().with_size(3, 2).custom_data(), - }; - *next_address += 2; - next_position_within[0] += SQUARE; - - layer_builder( - i_bit, - next_address, - next_parent, - &mut next_position_within, - components, - wires, - connection_map, - ); - - next_parent = next_board.address; - components.push(mount); - components.push(next_board); - } -} diff --git a/verilog2logicworld/src/cells/builder.rs b/verilog2logicworld/src/cells/builder.rs new file mode 100644 index 0000000..b5e7d85 --- /dev/null +++ b/verilog2logicworld/src/cells/builder.rs @@ -0,0 +1,90 @@ +use logicworld_subassembly::{lw, COMPONENT_MAP}; +use vecmath::Vector3; + +use crate::router::{ConnectionMap, SQUARE}; + +pub fn builder( + height: usize, + parent_address: u32, + next_address: &mut u32, + position: &Vector3, + components: &mut Vec, + wires: &mut Vec, + connection_map: &mut ConnectionMap, + layer_builder: impl Fn( + usize, + &mut u32, + u32, + &mut Vector3, + &mut Vec, + &mut Vec, + &mut ConnectionMap, + ), +) { + let mount = lw::Component { + address: *next_address, + parent: parent_address, + numeric_id: COMPONENT_MAP["MHG.Mount"], + position: *position, + rotation: quaternion::id(), + inputs: vec![], + outputs: vec![], + custom_data: lw::Mount::new(8).custom_data(), + }; + let next_board = lw::Component { + address: *next_address + 1, + parent: mount.address, + numeric_id: COMPONENT_MAP["MHG.CircuitBoard"], + position: [-SQUARE / 2, 3 * SQUARE - SQUARE / 3, -SQUARE / 2], + rotation: quaternion::id(), + inputs: vec![], + outputs: vec![], + custom_data: lw::CircuitBoard::default().with_size(3, 2).custom_data(), + }; + + *next_address += 2; + + let mut next_parent = next_board.address; + components.push(mount); + components.push(next_board); + + for i_bit in 0..height { + let mut next_position_within = [SQUARE / 2, SQUARE / 2, SQUARE / 2]; + let mount = lw::Component { + address: *next_address, + parent: next_parent, + numeric_id: COMPONENT_MAP["MHG.Mount"], + position: next_position_within, + rotation: quaternion::id(), + inputs: vec![], + outputs: vec![], + custom_data: lw::Mount::new(8).custom_data(), + }; + let next_board = lw::Component { + address: *next_address + 1, + parent: mount.address, + numeric_id: COMPONENT_MAP["MHG.CircuitBoard"], + position: [-SQUARE / 2, 3 * SQUARE - SQUARE / 3, -SQUARE / 2], + rotation: quaternion::id(), + inputs: vec![], + outputs: vec![], + custom_data: lw::CircuitBoard::default().with_size(3, 2).custom_data(), + }; + *next_address += 2; + next_position_within[0] += SQUARE; + + layer_builder( + i_bit, + next_address, + next_parent, + &mut next_position_within, + components, + wires, + connection_map, + ); + + next_parent = next_board.address; + components.push(mount); + components.push(next_board); + } +} diff --git a/verilog2logicworld/src/cells/mod.rs b/verilog2logicworld/src/cells/mod.rs index a472f19..d7ae14d 100644 --- a/verilog2logicworld/src/cells/mod.rs +++ b/verilog2logicworld/src/cells/mod.rs @@ -1,3 +1,6 @@ +mod builder; +use builder::builder; + pub mod unary_op; pub use unary_op::unary_op; diff --git a/verilog2logicworld/src/cells/unary_op.rs b/verilog2logicworld/src/cells/unary_op.rs index 38e12f8..c9fd7db 100644 --- a/verilog2logicworld/src/cells/unary_op.rs +++ b/verilog2logicworld/src/cells/unary_op.rs @@ -1,8 +1,11 @@ +use std::cmp::max; + use logicworld_subassembly::{lw, COMPONENT_MAP}; use vecmath::Vector3; -use crate::verilog::Cell; +use crate::cells::builder; use crate::router::{Connection, ConnectionMap, SQUARE}; +use crate::verilog::Cell; pub fn unary_op( cell: &Cell, @@ -10,41 +13,74 @@ pub fn unary_op( parent_address: u32, next_address: &mut u32, next_position: &mut Vector3, - _wires: &mut Vec, + wires: &mut Vec, connection_map: &mut ConnectionMap, ) -> Vec { - let input = lw::Input::new(cell.inputs["A"][0] as i32); - let output = lw::Output::new(cell.outputs["Y"][0] as i32); - let component = lw::Component { - address: *next_address, - parent: parent_address, - numeric_id: COMPONENT_MAP[text_id], - position: *next_position, - rotation: quaternion::id(), - inputs: vec![input], - outputs: vec![output], - custom_data: vec![], - }; - - connection_map.insert( - Connection { - cell_index: cell.index, - port_name: "A", - bit_index: 0, - }, - lw::PegAddress::input(component.address, 0), + // All unary RTL cells have one input port \A and one output port \Y. They also have the following parameters: + + // Set to a non-zero value if the input \A is signed and therefore should be sign-extended when needed. + let a_signed = cell.parameters["A_SIGNED"] > 0; + + // The width of the input port \A. + let a_width = cell.parameters["A_WIDTH"]; + + // The width of the output port \Y. + let y_width = cell.parameters["Y_WIDTH"]; + + assert!(!a_signed, "Signed not yet supported"); + assert!( + a_width == y_width, + "Different widths of input and output not yet supported" ); - connection_map.insert( - Connection { - cell_index: cell.index, - port_name: "Y", - bit_index: 0, + + let mut components = vec![]; + + let height = max(a_width, y_width); + + builder( + height, + parent_address, + next_address, + next_position, + &mut components, + wires, + connection_map, + |i_bit, next_address, parent, next_position_within, components, _wires, connection_map| { + let input = lw::Input::new(cell.inputs["A"][i_bit] as i32); + let output = lw::Output::new(cell.outputs["Y"][i_bit] as i32); + let component = lw::Component { + address: *next_address, + parent, + numeric_id: COMPONENT_MAP[text_id], + position: *next_position_within, + rotation: quaternion::id(), + inputs: vec![input], + outputs: vec![output], + custom_data: vec![], + }; + + connection_map.insert( + Connection { + cell_index: cell.index, + port_name: "A", + bit_index: i_bit, + }, + lw::PegAddress::input(component.address, 0), + ); + connection_map.insert( + Connection { + cell_index: cell.index, + port_name: "Y", + bit_index: i_bit, + }, + lw::PegAddress::output(component.address, 0), + ); + + components.push(component); + *next_address += 1; }, - lw::PegAddress::output(component.address, 0), ); - - *next_address += 1; next_position[2] += 3 * SQUARE; - return vec![component]; + return components; }