Compare commits

...

3 Commits

@ -1 +1 @@
Subproject commit 9801e5d6c87db31a616de50195110266ed00c15c Subproject commit 5c4ba463240312b81d43ed3e284aabf560d38520

@ -1,3 +1,4 @@
mod router;
mod verilog; mod verilog;
use std::f32::consts::PI; use std::f32::consts::PI;
@ -89,11 +90,32 @@ fn main() {
return; return;
}; };
for module in modules { for module_name in modules {
let result = compile_module(&module, &files); let result = compile_module(&module_name, &files);
println!("{}: {:?}", module, result);
let module = match result {
Ok(module) => module,
Err(err) => {
println!("Error while compiling module {}: {:?}", module_name, err);
return;
} }
};
let result = write_subassembly(); let result = router::route(module);
let (components, wires) = match result {
Ok(pair) => pair,
Err(err) => {
println!("Error while routing module {}: {:?}", module_name, err);
return;
}
};
let result = create_subassembly(
module_name,
&Path::new("output/"),
&components,
&wires,
);
println!("{:?}", result); println!("{:?}", result);
} }
}

@ -0,0 +1,220 @@
use std::{collections::HashMap, f32::consts::PI};
use logicworld_subassembly::{lw, COMPONENT_MAP};
use vecmath::{vec3_add, Vector3};
use crate::verilog::{Cell, Error, Module};
#[derive(Default, Debug)]
struct Net {
/// Index of cell that is outputting into this net (or None, if it's the module input)
connected_output: Option<(usize, String)>,
/// Indicies and names of ports of cells whose inputs are connected to this net
connected_inputs: Vec<(usize, String)>,
}
pub fn route(module: Module) -> Result<(Vec<lw::Component>, Vec<lw::Wire>), Error> {
let mut net_list: HashMap<usize, Net> = HashMap::new();
for input in &module.inputs {
println!("Input {}: {:?} ", input.name, input.bits);
for bit in &input.bits {
net_list.insert(*bit, Net::default());
}
}
for output in &module.outputs {
println!("Output {}: {:?} ", output.name, output.bits);
for bit in &output.bits {
net_list.insert(
*bit,
Net {
connected_output: None,
connected_inputs: Vec::with_capacity(0),
},
);
}
}
for (i, cell) in module.cells.iter().enumerate() {
// println!(
// "Cell {} - {}: in={:?} out={:?}",
// i, cell.cell_type, cell.inputs, cell.outputs
// );
for (key, bits) in &cell.inputs {
for bit in bits {
net_list
.entry(*bit)
.or_insert(Net::default())
.connected_inputs
.push((i, key.to_owned()));
}
}
for (key, bits) in &cell.outputs {
for bit in bits {
net_list
.entry(*bit)
.or_insert(Net::default())
.connected_output = Some((i, key.to_owned()));
}
}
}
for (key, value) in &net_list {
println!("Net {}: {:?}", key, value);
}
let board = lw::Component {
address: 1,
parent: 0,
numeric_id: COMPONENT_MAP["MHG.CircuitBoard"],
position: [0, 0, 0],
rotation: quaternion::euler_angles(0.0, -PI / 2.0, 0.0),
inputs: vec![],
outputs: vec![],
custom_data: lw::CircuitBoard::default()
.with_size(5, 10)
.with_color(100, 25, 25)
.custom_data(),
};
let board_address = board.address;
let mut next_address = board_address + 1;
let mut next_position = [150 + 1 * 300, 150, 150 + 1 * 300];
let mut wires: Vec<lw::Wire> = vec![];
let mut components = vec![board];
components.extend(
module
.cells
.iter()
.map(|cell| {
println!("{:?}", cell);
let component = match cell.cell_type.as_str() {
"$and" => Ok(basic_gate(
cell,
"MHG.AndGate",
board_address,
&mut next_address,
&mut next_position,
)),
"$xor" => Ok(basic_gate(
cell,
"MHG.XorGate",
board_address,
&mut next_address,
&mut next_position,
)),
"$or" => Ok(or_gate(
cell,
board_address,
&mut next_address,
&mut next_position,
&mut wires,
)),
_ => Err(Error::UnsupportedCell),
};
return component;
})
.collect::<Result<Vec<Vec<lw::Component>>, Error>>()?
.into_iter()
.flatten()
.collect::<Vec<_>>(),
);
return Ok((components, wires));
}
fn basic_gate(
cell: &Cell,
text_id: &str,
parent_address: u32,
next_address: &mut u32,
next_position: &mut Vector3<i32>,
) -> 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);
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_a, input_b],
outputs: vec![output],
custom_data: vec![],
};
*next_address += 1;
next_position[2] += 3 * 300;
return vec![component];
}
fn or_gate(
cell: &Cell,
parent_address: u32,
next_address: &mut u32,
next_position: &mut Vector3<i32>,
wires: &mut Vec<lw::Wire>,
) -> 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_state_id = cell.outputs["Y"][0] as i32;
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: parent_address,
numeric_id: COMPONENT_MAP["MHG.Buffer_WithOutput"],
position: *next_position,
rotation: quaternion::id(),
inputs: vec![input_a],
outputs: vec![output_a],
custom_data: vec![],
};
let buffer_b = lw::Component {
address: *next_address + 1,
parent: parent_address,
numeric_id: COMPONENT_MAP["MHG.Buffer_WithOutput"],
position: vec3_add(*next_position, [300, 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: parent_address,
numeric_id: COMPONENT_MAP["MHG.Peg"],
position: vec3_add(*next_position, [0, 0, 2 * 300]),
rotation: quaternion::id(),
inputs: vec![peg],
outputs: vec![],
custom_data: vec![],
};
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,
});
*next_address += 3;
next_position[2] += 5 * 300;
return vec![buffer_a, buffer_b, peg];
}

@ -28,15 +28,17 @@ pub struct Port {
#[derive(Default)] #[derive(Default)]
pub struct Module { pub struct Module {
inputs: Vec<Port>, pub inputs: Vec<Port>,
outputs: Vec<Port>, pub outputs: Vec<Port>,
pub cells: Vec<Cell>,
} }
#[derive(Debug)] #[derive(Debug)]
pub struct Cell<'a> { pub struct Cell {
pub cell_type: String, pub cell_type: String,
pub parameters: HashMap<&'a str, usize>, pub parameters: HashMap<String, usize>,
pub connections: HashMap<&'a str, Vec<usize>>, pub inputs: HashMap<String, Vec<usize>>,
pub outputs: HashMap<String, Vec<usize>>,
} }
impl From<io::Error> for Error { impl From<io::Error> for Error {
@ -55,7 +57,7 @@ pub fn get_modules(files: &[&str]) -> Result<Vec<String>, Error> {
return Ok(module_names); return Ok(module_names);
} }
pub fn compile_module(module_name: &str, files: &[&str]) -> Result<(), Error> { pub fn compile_module(module_name: &str, files: &[&str]) -> Result<Module, Error> {
let json = run_yosys("proc; flatten; wreduce; opt; fsm; opt; memory -nomap -nordff; opt; muxpack; peepopt; async2sync; wreduce; opt -mux_bool", Some(module_name), files)?; let json = run_yosys("proc; flatten; wreduce; opt; fsm; opt; memory -nomap -nordff; opt; muxpack; peepopt; async2sync; wreduce; opt -mux_bool", Some(module_name), files)?;
let compiled_module = &json["modules"][module_name]; let compiled_module = &json["modules"][module_name];
let ports_json = &compiled_module["ports"]; let ports_json = &compiled_module["ports"];
@ -83,40 +85,49 @@ pub fn compile_module(module_name: &str, files: &[&str]) -> Result<(), Error> {
} }
} }
let cells = &compiled_module["cells"]; module.cells = compiled_module["cells"]
.entries()
for (_, cell) in cells.entries() { .map(|(_, cell)| resolve_cell(cell))
let cell = resolve_cell(cell)?; .collect::<Result<_, _>>()?;
println!("{:?}", cell);
}
return Ok(()); return Ok(module);
} }
pub fn resolve_cell(cell: &JsonValue) -> Result<Cell, Error> { pub fn resolve_cell(cell: &JsonValue) -> Result<Cell, Error> {
let json_parameters = &cell["parameters"]; let json_parameters = &cell["parameters"];
let mut parameters: HashMap<&str, usize> = HashMap::new(); let mut parameters: HashMap<String, usize> = HashMap::new();
for (key, value) in json_parameters.entries() { for (key, value) in json_parameters.entries() {
parameters.insert( parameters.insert(
key, key.to_owned(),
usize::from_str_radix(value.as_str().ok_or(Error::BadJson)?, 2) usize::from_str_radix(value.as_str().ok_or(Error::BadJson)?, 2)
.map_err(|_| Error::BadJson)?, .map_err(|_| Error::BadJson)?,
); );
} }
let json_connections = &cell["connections"]; let json_connections = &cell["connections"];
let mut connections: HashMap<&str, Vec<usize>> = HashMap::new(); let json_port_directions = &cell["port_directions"];
let mut inputs: HashMap<String, Vec<usize>> = HashMap::new();
let mut outputs: HashMap<String, Vec<usize>> = HashMap::new();
for (key, bits) in json_connections.entries() { for (key, bits) in json_connections.entries() {
let JsonValue::Array(arr) = bits else { let JsonValue::Array(arr) = bits else {
return Err(Error::BadJson); return Err(Error::BadJson);
}; };
let direction = json_port_directions[key].as_str().ok_or(Error::BadJson)?;
let connection_bits: Vec<usize> = arr let connection_bits: Vec<usize> = arr
.iter() .iter()
.map(|x| x.as_usize().ok_or(Error::BadJson)) .map(|x| x.as_usize().ok_or(Error::BadJson))
.collect::<Result<_, _>>()?; .collect::<Result<_, _>>()?;
connections.insert(key, connection_bits); match direction {
"input" => {
inputs.insert(key.to_owned(), connection_bits);
}
"output" => {
outputs.insert(key.to_owned(), connection_bits);
}
_ => return Err(Error::BadJson),
}
} }
let cell_type = cell["type"].as_str().ok_or(Error::BadJson)?.to_owned(); let cell_type = cell["type"].as_str().ok_or(Error::BadJson)?.to_owned();
@ -124,7 +135,8 @@ pub fn resolve_cell(cell: &JsonValue) -> Result<Cell, Error> {
return Ok(Cell { return Ok(Cell {
cell_type, cell_type,
parameters, parameters,
connections, inputs,
outputs,
}); });
} }
@ -162,8 +174,6 @@ fn run_yosys(
let mut file_contents = String::new(); let mut file_contents = String::new();
file.read_to_string(&mut file_contents)?; file.read_to_string(&mut file_contents)?;
println!("{}", file_contents);
let root = json::parse(&file_contents).map_err(|_| Error::InvalidJson)?; let root = json::parse(&file_contents).map_err(|_| Error::InvalidJson)?;
return Ok(root); return Ok(root);

Loading…
Cancel
Save