Preparation for multi bit

master
D4VID 4 weeks ago
parent 9ce03c7779
commit 18ef7c2914

@ -1,6 +1,6 @@
module gates(
input a,b,c,d,
output wire out, out2
input [3:0] a,b,c,d,
output wire [3:0] out, out2
);
assign out = a & b | c;
assign out2 = a & b ^ d;

@ -5,17 +5,28 @@ use vecmath::{vec3_add, Vector3};
use crate::verilog::{Cell, Error, Module};
// https://yosyshq.readthedocs.io/projects/yosys/en/0.39/CHAPTER_CellLib.html
const SQUARE: lw::Int = 300;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
struct Connection<'a> {
cell_index: usize,
port_name: &'a str,
bit_index: usize,
}
#[derive(Default, Debug)]
struct Net<'a> {
/// Index of cell that is outputting into this net (or None, if it's the module input)
connected_output: Option<(usize, &'a str)>,
connected_output: Option<Connection<'a>>,
/// Indicies and names of ports of cells whose inputs are connected to this net
connected_inputs: Vec<(usize, &'a str)>,
connected_inputs: Vec<Connection<'a>>,
}
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();
@ -37,22 +48,30 @@ pub fn route(module: Module) -> Result<(Vec<lw::Component>, Vec<lw::Wire>), Erro
);
}
}
for (i, cell) in module.cells.iter().enumerate() {
for (i_cell, cell) in module.cells.iter().enumerate() {
for (key, bits) in &cell.inputs {
for bit in bits {
for (i_bit, bit) in bits.iter().enumerate() {
net_list
.entry(*bit)
.or_insert(Net::default())
.connected_inputs
.push((i, key));
.push(Connection {
cell_index: i_cell,
port_name: key,
bit_index: 0,
});
}
}
for (key, bits) in &cell.outputs {
for bit in bits {
for (i_bit, bit) in bits.iter().enumerate() {
net_list
.entry(*bit)
.or_insert(Net::default())
.connected_output = Some((i, key));
.connected_output = Some(Connection {
cell_index: i_cell,
port_name: key,
bit_index: 0,
});
}
}
}
@ -69,7 +88,7 @@ pub fn route(module: Module) -> Result<(Vec<lw::Component>, Vec<lw::Wire>), Erro
let mut input_ports: Vec<lw::Component> = vec![];
let mut output_ports: Vec<lw::Component> = vec![];
let mut connection_map: HashMap<(usize, &str), lw::PegAddress> = HashMap::new();
let mut connection_map: ConnectionMap = HashMap::new();
// the size of squares is 300 units
// 150, 150, 150 is the middle of the first square
@ -89,9 +108,9 @@ pub fn route(module: Module) -> Result<(Vec<lw::Component>, Vec<lw::Wire>), Erro
));
}
// align back to middle
next_input_position[0] += SQUARE/2;
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] += SQUARE / 2;
}
let mut next_position = vec3_add(origin, [1 * SQUARE, 0, 3 * SQUARE]);
@ -149,9 +168,9 @@ pub fn route(module: Module) -> Result<(Vec<lw::Component>, Vec<lw::Wire>), Erro
));
}
// align back to middle
next_output_position[0] += SQUARE/2;
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] += SQUARE / 2;
}
let board = lw::Component {
@ -177,10 +196,14 @@ pub fn route(module: Module) -> Result<(Vec<lw::Component>, Vec<lw::Wire>), Erro
components.extend(output_ports);
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((*id, "input"))];
// 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
})];
for input in &net.connected_inputs {
let input_address = &connection_map[input];
wires.push(lw::Wire {
@ -192,7 +215,11 @@ pub fn route(module: Module) -> Result<(Vec<lw::Component>, Vec<lw::Wire>), Erro
}
if net.connected_inputs.is_empty() {
let input_address = &connection_map[&(*id, "output")];
let input_address = &connection_map[&Connection {
cell_index: *id,
port_name: "output",
bit_index: 0, // TODO: figure out
}];
wires.push(lw::Wire {
first_point: output_address.clone(),
second_point: input_address.clone(),
@ -211,9 +238,8 @@ fn input_port(
parent_address: u32,
next_address: &mut u32,
next_position: &mut Vector3<lw::Int>,
connection_map: &mut HashMap<(usize, &str), lw::PegAddress>,
connection_map: &mut ConnectionMap,
) -> Vec<lw::Component> {
let label = lw::Component {
address: *next_address,
parent: parent_address,
@ -237,7 +263,14 @@ fn input_port(
outputs: vec![],
custom_data: vec![],
};
connection_map.insert((bit_id, "input"), lw::PegAddress::input(peg.address, 0));
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
@ -251,9 +284,8 @@ fn output_port(
parent_address: u32,
next_address: &mut u32,
next_position: &mut Vector3<lw::Int>,
connection_map: &mut HashMap<(usize, &str), lw::PegAddress>,
connection_map: &mut ConnectionMap,
) -> Vec<lw::Component> {
let label = lw::Component {
address: *next_address,
parent: parent_address,
@ -277,7 +309,14 @@ fn output_port(
outputs: vec![],
custom_data: vec![],
};
connection_map.insert((bit_id, "output"), lw::PegAddress::input(peg.address, 0));
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
@ -291,39 +330,78 @@ fn binary_op(
parent_address: u32,
next_address: &mut u32,
next_position: &mut Vector3<i32>,
connection_map: &mut HashMap<(usize, &str), lw::PegAddress>,
connection_map: &mut ConnectionMap,
) -> Vec<lw::Component> {
let input_a = lw::Input::new(cell.inputs["A"][0] as i32);
let input_b = lw::Input::new(cell.inputs["B"][0] as i32);
let output = lw::Output::new(cell.outputs["Y"][0] as i32);
// 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");
// let mut next_parent = parent_address;
let mut components = vec![];
for i in 0..a_width {
let input_a = lw::Input::new(cell.inputs["A"][i] as i32);
let input_b = lw::Input::new(cell.inputs["B"][i] as i32);
let output = lw::Output::new(cell.outputs["Y"][i] as i32);
let component = lw::Component {
address: *next_address,
parent: parent_address,
numeric_id: COMPONENT_MAP[text_id],
position: *next_position,
position: vec3_add(*next_position, [0, (i as lw::Int) * 2 * SQUARE, 0]),
rotation: quaternion::id(),
inputs: vec![input_a, input_b],
outputs: vec![output],
custom_data: vec![],
};
*next_address += 1;
connection_map.insert(
(cell.index, "A"),
Connection {
cell_index: cell.index,
port_name: "A",
bit_index: 0,
},
lw::PegAddress::input(component.address, 0),
);
connection_map.insert(
(cell.index, "B"),
Connection {
cell_index: cell.index,
port_name: "B",
bit_index: 0,
},
lw::PegAddress::input(component.address, 1),
);
connection_map.insert(
(cell.index, "Y"),
Connection {
cell_index: cell.index,
port_name: "Y",
bit_index: 0,
},
lw::PegAddress::output(component.address, 0),
);
components.push(component);
}
*next_address += 1;
next_position[2] += 3 * SQUARE;
return vec![component];
return components;
}
fn unary_op(
@ -332,7 +410,7 @@ fn unary_op(
parent_address: u32,
next_address: &mut u32,
next_position: &mut Vector3<i32>,
connection_map: &mut HashMap<(usize, &str), lw::PegAddress>,
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);
@ -348,11 +426,19 @@ fn unary_op(
};
connection_map.insert(
(cell.index, "A"),
Connection {
cell_index: cell.index,
port_name: "A",
bit_index: 0,
},
lw::PegAddress::input(component.address, 0),
);
connection_map.insert(
(cell.index, "Y"),
Connection {
cell_index: cell.index,
port_name: "Y",
bit_index: 0,
},
lw::PegAddress::output(component.address, 0),
);
@ -368,7 +454,7 @@ fn or_gate(
next_address: &mut u32,
next_position: &mut Vector3<lw::Int>,
wires: &mut Vec<lw::Wire>,
connection_map: &mut HashMap<(usize, &str), lw::PegAddress>,
connection_map: &mut ConnectionMap,
) -> Vec<lw::Component> {
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);
@ -409,14 +495,29 @@ fn or_gate(
};
connection_map.insert(
(cell.index, "A"),
Connection {
cell_index: cell.index,
port_name: "A",
bit_index: 0,
},
lw::PegAddress::input(buffer_a.address, 0),
);
connection_map.insert(
(cell.index, "B"),
Connection {
cell_index: cell.index,
port_name: "B",
bit_index: 0,
},
lw::PegAddress::input(buffer_b.address, 0),
);
connection_map.insert((cell.index, "Y"), lw::PegAddress::input(peg.address, 0));
connection_map.insert(
Connection {
cell_index: cell.index,
port_name: "Y",
bit_index: 0,
},
lw::PegAddress::input(peg.address, 0),
);
wires.push(lw::Wire {
first_point: lw::PegAddress::output(buffer_a.address, 0),

Loading…
Cancel
Save