Compare commits
6 Commits
eca62daf30
...
5faead9fc6
Author | SHA1 | Date |
---|---|---|
|
5faead9fc6 | 3 weeks ago |
|
f56effc197 | 3 weeks ago |
|
858f752842 | 3 weeks ago |
|
3d983f0b5d | 3 weeks ago |
|
df70909542 | 3 weeks ago |
|
86ecdca0e9 | 3 weeks ago |
@ -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;
|
||||||
|
}
|
Loading…
Reference in new issue