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