Compare commits

...

6 Commits

@ -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

@ -0,0 +1,185 @@
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;
pub fn binary_op(
cell: &Cell,
text_id: &str,
parent_address: u32,
next_address: &mut u32,
next_position: &mut Vector3<i32>,
wires: &mut Vec<lw::Wire>,
connection_map: &mut ConnectionMap,
) -> Vec<lw::Component> {
// All binary RTL cells have two input ports \A and \B 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"];
// Set to a non-zero value if the input \B is signed and therefore should be sign-extended when needed.
let b_signed = cell.parameters["B_SIGNED"] > 0;
// The width of the input port \B.
let b_width = cell.parameters["B_WIDTH"];
// The width of the output port \Y.
let y_width = cell.parameters["Y_WIDTH"];
assert!(a_width == b_width, "Different widths not yet supported");
assert!(!a_signed && !b_signed, "Signed not yet supported");
assert!(
a_width == y_width,
"Different widths of input and output not yet supported"
);
let mut components = vec![];
let height = max(max(a_width, b_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_a = lw::Input::new(cell.inputs["A"][i_bit] as i32);
let input_b = lw::Input::new(cell.inputs["B"][i_bit] as i32);
let output_state_id = cell.outputs["Y"][i_bit] as lw::Int;
let output = lw::Output::new(output_state_id);
if text_id == "Custom.OrGate" {
let input_a = lw::Input::new(cell.inputs["A"][0] as lw::Int);
let input_b = lw::Input::new(cell.inputs["B"][0] as lw::Int);
let output_a = lw::Output::new(output_state_id);
let output_b = lw::Output::new(output_state_id);
let peg = lw::Input::new(output_state_id);
let buffer_a = lw::Component {
address: *next_address,
parent,
numeric_id: COMPONENT_MAP["MHG.Buffer_WithOutput"],
position: *next_position_within,
rotation: quaternion::id(),
inputs: vec![input_a],
outputs: vec![output_a],
custom_data: vec![],
};
let buffer_b = lw::Component {
address: *next_address + 1,
parent,
numeric_id: COMPONENT_MAP["MHG.Buffer_WithOutput"],
position: vec3_add(*next_position_within, [SQUARE, 0, 0]),
rotation: quaternion::id(),
inputs: vec![input_b],
outputs: vec![output_b],
custom_data: vec![],
};
let peg = lw::Component {
address: *next_address + 2,
parent,
numeric_id: COMPONENT_MAP["MHG.Peg"],
position: vec3_add(*next_position_within, [0, 0, 2 * SQUARE]),
rotation: quaternion::id(),
inputs: vec![peg],
outputs: vec![],
custom_data: vec![],
};
*next_address += 3;
connection_map.insert(
Connection {
cell_index: cell.index,
port_name: "A",
bit_index: i_bit,
},
lw::PegAddress::input(buffer_a.address, 0),
);
connection_map.insert(
Connection {
cell_index: cell.index,
port_name: "B",
bit_index: i_bit,
},
lw::PegAddress::input(buffer_b.address, 0),
);
connection_map.insert(
Connection {
cell_index: cell.index,
port_name: "Y",
bit_index: i_bit,
},
lw::PegAddress::input(peg.address, 0),
);
wires.push(lw::Wire {
first_point: lw::PegAddress::output(buffer_a.address, 0),
second_point: lw::PegAddress::input(peg.address, 0),
circuit_state_id: output_state_id,
wire_rotation: 0.0,
});
wires.push(lw::Wire {
first_point: lw::PegAddress::output(buffer_b.address, 0),
second_point: lw::PegAddress::input(peg.address, 0),
circuit_state_id: output_state_id,
wire_rotation: 0.0,
});
components.push(buffer_a);
components.push(buffer_b);
components.push(peg);
} else {
let component = lw::Component {
address: *next_address,
parent,
numeric_id: COMPONENT_MAP[text_id],
position: *next_position_within,
rotation: quaternion::id(),
inputs: vec![input_a, input_b],
outputs: vec![output],
custom_data: vec![],
};
*next_address += 1;
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: "B",
bit_index: i_bit,
},
lw::PegAddress::input(component.address, 1),
);
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_position[2] += 4 * SQUARE;
return components;
}

@ -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<i32>,
components: &mut Vec<lw::Component>,
wires: &mut Vec<lw::Wire>,
connection_map: &mut ConnectionMap,
layer_builder: impl Fn(
usize,
&mut u32,
u32,
&mut Vector3<i32>,
&mut Vec<lw::Component>,
&mut Vec<lw::Wire>,
&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);
}
}

@ -0,0 +1,73 @@
use std::f32::consts::PI;
use logicworld_subassembly::{lw, COMPONENT_MAP};
use vecmath::{vec3_add, Vector3};
use crate::cells::builder;
use crate::router::{Connection, ConnectionMap, SQUARE};
pub fn input_port(
bits: &Vec<usize>,
port_name: &str,
parent_address: u32,
next_address: &mut u32,
next_position: &mut Vector3<lw::Int>,
connection_map: &mut ConnectionMap,
) -> Vec<lw::Component> {
let mut components = vec![];
let mut wires = vec![]; // discard
builder(
bits.len(),
parent_address,
next_address,
next_position,
&mut components,
&mut wires,
connection_map,
|i_bit, next_address, parent, next_position_within, components, _wires, connection_map| {
let bit_id = bits[i_bit];
let label = lw::Component {
address: *next_address,
parent,
numeric_id: COMPONENT_MAP["MHG.PanelLabel"],
position: *next_position_within,
rotation: quaternion::euler_angles(0.0, -PI / 2.0, 0.0),
inputs: vec![],
outputs: vec![],
custom_data: lw::Label::new(&format!("{}[{}]", port_name, i_bit))
.with_size(2.0)
.custom_data(),
};
*next_address += 1;
let peg = lw::Component {
address: *next_address,
parent,
numeric_id: COMPONENT_MAP["MHG.Peg"],
position: vec3_add(*next_position_within, [0, 0, SQUARE]),
rotation: quaternion::id(),
inputs: vec![lw::Input::new(bit_id as lw::Int)],
outputs: vec![],
custom_data: vec![],
};
connection_map.insert(
Connection {
cell_index: bit_id,
port_name: "input",
bit_index: 0,
},
lw::PegAddress::input(peg.address, 0),
);
components.push(label);
components.push(peg);
*next_address += 1;
},
);
next_position[0] += SQUARE / 3; // third of a square
return components;
}

@ -0,0 +1,12 @@
mod builder;
use builder::builder;
pub mod unary_op;
pub mod binary_op;
pub mod input_port;
pub mod output_port;
pub use unary_op::unary_op;
pub use binary_op::binary_op;
pub use output_port::output_port;
pub use input_port::input_port;

@ -0,0 +1,73 @@
use std::f32::consts::PI;
use logicworld_subassembly::{lw, COMPONENT_MAP};
use vecmath::{vec3_add, Vector3};
use crate::cells::builder;
use crate::router::{Connection, ConnectionMap, SQUARE};
pub fn output_port(
bits: &Vec<usize>,
port_name: &str,
parent_address: u32,
next_address: &mut u32,
next_position: &mut Vector3<lw::Int>,
connection_map: &mut ConnectionMap,
) -> Vec<lw::Component> {
let mut components = vec![];
let mut wires = vec![]; // discard
builder(
bits.len(),
parent_address,
next_address,
next_position,
&mut components,
&mut wires,
connection_map,
|i_bit, next_address, parent, next_position_within, components, _wires, connection_map| {
let bit_id = bits[i_bit];
let label = lw::Component {
address: *next_address,
parent,
numeric_id: COMPONENT_MAP["MHG.PanelLabel"],
position: vec3_add(*next_position_within, [0, 0, SQUARE]),
rotation: quaternion::euler_angles(0.0, -PI / 2.0, 0.0),
inputs: vec![],
outputs: vec![],
custom_data: lw::Label::new(&format!("{}[{}]", port_name, i_bit))
.with_size(2.0)
.custom_data(),
};
*next_address += 1;
let peg = lw::Component {
address: *next_address,
parent,
numeric_id: COMPONENT_MAP["MHG.Peg"],
position: *next_position_within,
rotation: quaternion::id(),
inputs: vec![lw::Input::new(bit_id as lw::Int)],
outputs: vec![],
custom_data: vec![],
};
connection_map.insert(
Connection {
cell_index: bit_id,
port_name: "output",
bit_index: 0,
},
lw::PegAddress::input(peg.address, 0),
);
components.push(label);
components.push(peg);
*next_address += 1;
},
);
next_position[0] += SQUARE / 3; // third of a square
return components;
}

@ -0,0 +1,86 @@
use std::cmp::max;
use logicworld_subassembly::{lw, COMPONENT_MAP};
use vecmath::Vector3;
use crate::cells::builder;
use crate::router::{Connection, ConnectionMap, SQUARE};
use crate::verilog::Cell;
pub fn unary_op(
cell: &Cell,
text_id: &str,
parent_address: u32,
next_address: &mut u32,
next_position: &mut Vector3<i32>,
wires: &mut Vec<lw::Wire>,
connection_map: &mut ConnectionMap,
) -> Vec<lw::Component> {
// 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"
);
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;
},
);
next_position[2] += 3 * SQUARE;
return components;
}

@ -1,5 +1,6 @@
mod router;
mod verilog;
mod cells;
use std::path::Path;

@ -1,19 +1,20 @@
use std::{cmp::max, collections::HashMap, f32::consts::PI, fmt::Debug};
use std::{collections::HashMap, f32::consts::PI, fmt::Debug};
use logicworld_subassembly::{lw, COMPONENT_MAP};
use vecmath::{vec3_add, Vector3};
use vecmath::vec3_add;
use crate::verilog::{Cell, Error, Module};
use crate::verilog::{Error, Module};
use crate::cells::*;
// https://yosyshq.readthedocs.io/projects/yosys/en/0.39/CHAPTER_CellLib.html
const SQUARE: lw::Int = 300;
pub const SQUARE: lw::Int = 300;
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
struct Connection<'a> {
cell_index: usize,
port_name: &'a str,
bit_index: usize,
pub struct Connection<'a> {
pub cell_index: usize,
pub port_name: &'a str,
pub bit_index: usize,
}
impl<'a> Debug for Connection<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
@ -34,7 +35,7 @@ struct Net<'a> {
connected_inputs: Vec<Connection<'a>>,
}
type ConnectionMap<'a> = HashMap<Connection<'a>, lw::PegAddress>;
pub type ConnectionMap<'a> = HashMap<Connection<'a>, lw::PegAddress>;
pub fn route(module: Module) -> Result<(Vec<lw::Component>, Vec<lw::Wire>), Error> {
let mut net_list: HashMap<usize, Net> = HashMap::new();
@ -106,20 +107,15 @@ pub fn route(module: Module) -> Result<(Vec<lw::Component>, Vec<lw::Wire>), Erro
let mut next_input_position = origin.clone();
for input in &module.inputs {
for bit in &input.bits {
input_ports.extend(input_port(
*bit,
&input.bits,
&input.name,
board_address,
&mut next_address,
&mut next_input_position,
&mut connection_map,
));
}
// align back to middle
next_input_position[0] += SQUARE / 2;
next_input_position[0] -= next_input_position[0] % SQUARE;
next_input_position[0] += SQUARE / 2;
next_input_position[0] += 3 * SQUARE;
}
let mut next_position = vec3_add(origin, [1 * SQUARE, 0, 3 * SQUARE]);
@ -170,20 +166,15 @@ pub fn route(module: Module) -> Result<(Vec<lw::Component>, Vec<lw::Wire>), Erro
let mut next_output_position = next_position.clone();
for output in &module.outputs {
for bit in &output.bits {
output_ports.extend(output_port(
*bit,
&output.bits,
&output.name,
board_address,
&mut next_address,
&mut next_output_position,
&mut connection_map,
));
}
// align back to middle
next_output_position[0] += SQUARE / 2;
next_output_position[0] -= next_output_position[0] % SQUARE;
next_output_position[0] += SQUARE / 2;
next_output_position[0] += 3 * SQUARE;
}
let board = lw::Component {
@ -211,11 +202,10 @@ pub fn route(module: Module) -> Result<(Vec<lw::Component>, Vec<lw::Wire>), Erro
for (id, net) in &net_list {
println!();
println!("{}: {:#?}", id, net);
println!("map; {:#?}", connection_map.keys());
let output_address = &connection_map[&net.connected_output.unwrap_or(Connection {
cell_index: *id,
port_name: "input",
bit_index: 0, // TODO: figure out
bit_index: 0,
})];
for input in &net.connected_inputs {
println!("input: {:?}", input);
@ -232,7 +222,7 @@ pub fn route(module: Module) -> Result<(Vec<lw::Component>, Vec<lw::Wire>), Erro
let input_address = &connection_map[&Connection {
cell_index: *id,
port_name: "output",
bit_index: 0, // TODO: figure out
bit_index: 0,
}];
wires.push(lw::Wire {
first_point: output_address.clone(),
@ -245,364 +235,3 @@ pub fn route(module: Module) -> Result<(Vec<lw::Component>, Vec<lw::Wire>), Erro
return Ok((components, wires));
}
fn input_port(
bit_id: usize,
port_name: &str,
parent_address: u32,
next_address: &mut u32,
next_position: &mut Vector3<lw::Int>,
connection_map: &mut ConnectionMap,
) -> Vec<lw::Component> {
let label = lw::Component {
address: *next_address,
parent: parent_address,
numeric_id: COMPONENT_MAP["MHG.PanelLabel"],
position: *next_position,
rotation: quaternion::euler_angles(0.0, -PI / 2.0, 0.0),
inputs: vec![],
outputs: vec![],
custom_data: lw::Label::new(port_name).with_size(2.0).custom_data(),
};
*next_address += 1;
let peg = lw::Component {
address: *next_address,
parent: parent_address,
numeric_id: COMPONENT_MAP["MHG.Peg"],
position: vec3_add(*next_position, [0, 0, SQUARE]),
rotation: quaternion::id(),
inputs: vec![lw::Input::new(bit_id as lw::Int)],
outputs: vec![],
custom_data: vec![],
};
connection_map.insert(
Connection {
cell_index: bit_id,
port_name: "input",
bit_index: 0,
},
lw::PegAddress::input(peg.address, 0),
);
*next_address += 1;
next_position[0] += SQUARE / 3; // third of a square
return vec![peg, label];
}
fn output_port(
bit_id: usize,
port_name: &str,
parent_address: u32,
next_address: &mut u32,
next_position: &mut Vector3<lw::Int>,
connection_map: &mut ConnectionMap,
) -> Vec<lw::Component> {
let label = lw::Component {
address: *next_address,
parent: parent_address,
numeric_id: COMPONENT_MAP["MHG.PanelLabel"],
position: vec3_add(*next_position, [0, 0, SQUARE]),
rotation: quaternion::euler_angles(0.0, -PI / 2.0, 0.0),
inputs: vec![],
outputs: vec![],
custom_data: lw::Label::new(port_name).with_size(2.0).custom_data(),
};
*next_address += 1;
let peg = lw::Component {
address: *next_address,
parent: parent_address,
numeric_id: COMPONENT_MAP["MHG.Peg"],
position: *next_position,
rotation: quaternion::id(),
inputs: vec![lw::Input::new(bit_id as lw::Int)],
outputs: vec![],
custom_data: vec![],
};
connection_map.insert(
Connection {
cell_index: bit_id,
port_name: "output",
bit_index: 0,
},
lw::PegAddress::input(peg.address, 0),
);
*next_address += 1;
next_position[0] += SQUARE / 3; // third of a square
return vec![peg, label];
}
fn binary_op(
cell: &Cell,
text_id: &str,
parent_address: u32,
next_address: &mut u32,
next_position: &mut Vector3<i32>,
wires: &mut Vec<lw::Wire>,
connection_map: &mut ConnectionMap,
) -> Vec<lw::Component> {
// All binary RTL cells have two input ports \A and \B 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"];
// Set to a non-zero value if the input \B is signed and therefore should be sign-extended when needed.
let b_signed = cell.parameters["B_SIGNED"] > 0;
// The width of the input port \B.
let b_width = cell.parameters["B_WIDTH"];
// The width of the output port \Y.
let y_width = cell.parameters["Y_WIDTH"];
assert!(a_width == b_width, "Different widths not yet supported");
assert!(!a_signed && !b_signed, "Signed not yet supported");
assert!(
a_width == y_width,
"Different widths of input and output not yet supported"
);
let mut next_parent = parent_address;
let mut components = vec![];
let height = max(max(a_width, b_width), y_width);
let mount = lw::Component {
address: *next_address,
parent: next_parent,
numeric_id: COMPONENT_MAP["MHG.Mount"],
position: *next_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;
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;
let input_a = lw::Input::new(cell.inputs["A"][i_bit] as i32);
let input_b = lw::Input::new(cell.inputs["B"][i_bit] as i32);
let output_state_id = cell.outputs["Y"][i_bit] as lw::Int;
let output = lw::Output::new(output_state_id);
if text_id == "Custom.OrGate" {
let input_a = lw::Input::new(cell.inputs["A"][0] as lw::Int);
let input_b = lw::Input::new(cell.inputs["B"][0] as lw::Int);
let output_a = lw::Output::new(output_state_id);
let output_b = lw::Output::new(output_state_id);
let peg = lw::Input::new(output_state_id);
let buffer_a = lw::Component {
address: *next_address,
parent: next_parent,
numeric_id: COMPONENT_MAP["MHG.Buffer_WithOutput"],
position: next_position_within,
rotation: quaternion::id(),
inputs: vec![input_a],
outputs: vec![output_a],
custom_data: vec![],
};
let buffer_b = lw::Component {
address: *next_address + 1,
parent: next_parent,
numeric_id: COMPONENT_MAP["MHG.Buffer_WithOutput"],
position: vec3_add(next_position_within, [SQUARE, 0, 0]),
rotation: quaternion::id(),
inputs: vec![input_b],
outputs: vec![output_b],
custom_data: vec![],
};
let peg = lw::Component {
address: *next_address + 2,
parent: next_parent,
numeric_id: COMPONENT_MAP["MHG.Peg"],
position: vec3_add(next_position_within, [0, 0, 2 * SQUARE]),
rotation: quaternion::id(),
inputs: vec![peg],
outputs: vec![],
custom_data: vec![],
};
connection_map.insert(
Connection {
cell_index: cell.index,
port_name: "A",
bit_index: i_bit,
},
lw::PegAddress::input(buffer_a.address, 0),
);
connection_map.insert(
Connection {
cell_index: cell.index,
port_name: "B",
bit_index: i_bit,
},
lw::PegAddress::input(buffer_b.address, 0),
);
connection_map.insert(
Connection {
cell_index: cell.index,
port_name: "Y",
bit_index: i_bit,
},
lw::PegAddress::input(peg.address, 0),
);
wires.push(lw::Wire {
first_point: lw::PegAddress::output(buffer_a.address, 0),
second_point: lw::PegAddress::input(peg.address, 0),
circuit_state_id: output_state_id,
wire_rotation: 0.0,
});
wires.push(lw::Wire {
first_point: lw::PegAddress::output(buffer_b.address, 0),
second_point: lw::PegAddress::input(peg.address, 0),
circuit_state_id: output_state_id,
wire_rotation: 0.0,
});
components.push(buffer_a);
components.push(buffer_b);
components.push(peg);
*next_address += 3;
} else {
let component = lw::Component {
address: *next_address,
parent: next_parent,
numeric_id: COMPONENT_MAP[text_id],
position: next_position_within,
rotation: quaternion::id(),
inputs: vec![input_a, input_b],
outputs: vec![output],
custom_data: vec![],
};
*next_address += 1;
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: "B",
bit_index: i_bit,
},
lw::PegAddress::input(component.address, 1),
);
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_parent = next_board.address;
components.push(mount);
components.push(next_board);
}
next_position[2] += 5 * SQUARE;
return components;
}
fn unary_op(
cell: &Cell,
text_id: &str,
parent_address: u32,
next_address: &mut u32,
next_position: &mut Vector3<i32>,
wires: &mut Vec<lw::Wire>,
connection_map: &mut ConnectionMap,
) -> Vec<lw::Component> {
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),
);
connection_map.insert(
Connection {
cell_index: cell.index,
port_name: "Y",
bit_index: 0,
},
lw::PegAddress::output(component.address, 0),
);
*next_address += 1;
next_position[2] += 3 * SQUARE;
return vec![component];
}

Loading…
Cancel
Save