|
|
|
@ -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.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;
|
|
|
|
|
input_ports.extend(input_port(
|
|
|
|
|
&input.bits,
|
|
|
|
|
&input.name,
|
|
|
|
|
board_address,
|
|
|
|
|
&mut next_address,
|
|
|
|
|
&mut next_input_position,
|
|
|
|
|
&mut connection_map,
|
|
|
|
|
));
|
|
|
|
|
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.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;
|
|
|
|
|
output_ports.extend(output_port(
|
|
|
|
|
&output.bits,
|
|
|
|
|
&output.name,
|
|
|
|
|
board_address,
|
|
|
|
|
&mut next_address,
|
|
|
|
|
&mut next_output_position,
|
|
|
|
|
&mut connection_map,
|
|
|
|
|
));
|
|
|
|
|
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];
|
|
|
|
|
}
|
|
|
|
|