Compare commits

...

2 Commits

@ -1 +1 @@
Subproject commit 373860674228f199c57344be19a4e32c759371e9
Subproject commit 9801e5d6c87db31a616de50195110266ed00c15c

@ -1,13 +1,14 @@
mod verilog;
use std::f32::consts::PI;
use std::io;
use std::path::Path;
use logicworld_subassembly::create_subassembly;
use logicworld_subassembly::lw;
use logicworld_subassembly::lw::PegAddress;
use logicworld_subassembly::COMPONENT_MAP;
use verilog::run_yosys;
use verilog::compile_module;
use verilog::get_modules;
fn write_subassembly() -> io::Result<()> {
let components = vec![
@ -21,14 +22,14 @@ fn write_subassembly() -> io::Result<()> {
outputs: vec![],
custom_data: lw::CircuitBoard::default()
.with_color(0, 100, 50)
.with_size(5, 10)
.with_size(5, 13)
.custom_data(),
},
lw::Component {
address: 2,
parent: 1,
numeric_id: COMPONENT_MAP["MHG.AndGate"],
position: [150+1*300, 150, 150+2*300],
position: [150 + 1 * 300, 150, 150 + 7 * 300],
rotation: quaternion::id(),
inputs: vec![lw::Input::new(1), lw::Input::new(2), lw::Input::new(3)],
outputs: vec![lw::Output::new(4)],
@ -38,16 +39,32 @@ fn write_subassembly() -> io::Result<()> {
address: 3,
parent: 1,
numeric_id: COMPONENT_MAP["MHG.XorGate"],
position: [150+1*300, 150, 150+5*300],
position: [150 + 1 * 300, 150, 150 + 10 * 300],
rotation: quaternion::id(),
inputs: vec![lw::Input::new(5), lw::Input::new(4)],
outputs: vec![lw::Output::new(6)],
custom_data: vec![],
},
lw::Component {
address: 4,
parent: 1,
numeric_id: COMPONENT_MAP["MHG.PanelLabel"],
position: [150 + 3 * 300, 150, 150 + 1 * 300],
rotation: quaternion::euler_angles(0.0, -PI / 2.0, 0.0),
inputs: vec![],
outputs: vec![],
custom_data: lw::Label::new("Lmao")
.mono()
.with_size(2.5)
.with_color(0, 100, 250)
.with_align(lw::HorizontalAlign::Right, lw::VerticalAlign::Bottom)
.with_dimensions(4, 3)
.custom_data(),
},
];
let wires = vec![lw::Wire {
first_point: PegAddress::output(2, 0),
second_point: PegAddress::input(3, 1),
first_point: lw::PegAddress::output(2, 0),
second_point: lw::PegAddress::input(3, 1),
circuit_state_id: 4,
wire_rotation: 0.0,
}];
@ -63,11 +80,19 @@ fn write_subassembly() -> io::Result<()> {
}
fn main() {
let result = run_yosys("proc;", None, &["gates.v"]);
let files = ["gates.v"];
let result = get_modules(&files);
println!("{:?}", result);
let result = run_yosys("proc; flatten; wreduce; opt; fsm; opt; memory -nomap -nordff; opt; muxpack; peepopt; async2sync; wreduce; opt -mux_bool", Some("$abstract\\gates"), &["gates.v"]);
println!("{:?}", result);
let Ok(modules) = result else {
println!("Error while getting modules: {:?}", result);
return;
};
for module in modules {
let result = compile_module(&module, &files);
println!("{}: {:?}", module, result);
}
let result = write_subassembly();
println!("{:?}", result);

@ -1,7 +1,11 @@
use std::{
fs::File, io::{self, Read}, process::{Command, Stdio}
collections::HashMap,
fs::File,
io::{self, Read},
process::{Command, Stdio},
};
use json::JsonValue;
use tempfile::tempdir;
#[derive(Debug)]
@ -13,6 +17,26 @@ pub enum Error {
Execute,
IO(io::Error),
InvalidJson,
BadJson,
UnsupportedCell,
}
pub struct Port {
pub name: String,
pub bits: Vec<usize>,
}
#[derive(Default)]
pub struct Module {
inputs: Vec<Port>,
outputs: Vec<Port>,
}
#[derive(Debug)]
pub struct Cell<'a> {
pub cell_type: String,
pub parameters: HashMap<&'a str, usize>,
pub connections: HashMap<&'a str, Vec<usize>>,
}
impl From<io::Error> for Error {
@ -21,18 +45,106 @@ impl From<io::Error> for Error {
}
}
pub fn run_yosys(yosys_command: &str, module: Option<&str>, files: &[&str]) -> Result<(), Error> {
pub fn get_modules(files: &[&str]) -> Result<Vec<String>, Error> {
let json = run_yosys("proc;", None, files)?;
// module names in this step have a "$abstract\" prefix
let module_names = json["modules"]
.entries()
.map(|(key, _)| key[10..].to_string())
.collect();
return Ok(module_names);
}
pub fn compile_module(module_name: &str, files: &[&str]) -> Result<(), 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 compiled_module = &json["modules"][module_name];
let ports_json = &compiled_module["ports"];
let mut module = Module::default();
for (name, value) in ports_json.entries() {
let JsonValue::Array(arr) = &value["bits"] else {
return Err(Error::BadJson);
};
let port = Port {
name: name.to_owned(),
bits: arr
.iter()
.map(|x| x.as_usize().ok_or(Error::BadJson))
.collect::<Result<_, _>>()?,
};
match value["direction"].as_str() {
Some("input") => {
module.inputs.push(port);
}
Some("output") => {
module.outputs.push(port);
}
_ => return Err(Error::BadJson),
}
}
let cells = &compiled_module["cells"];
for (_, cell) in cells.entries() {
let cell = resolve_cell(cell)?;
println!("{:?}", cell);
}
return Ok(());
}
pub fn resolve_cell(cell: &JsonValue) -> Result<Cell, Error> {
let json_parameters = &cell["parameters"];
let mut parameters: HashMap<&str, usize> = HashMap::new();
for (key, value) in json_parameters.entries() {
parameters.insert(
key,
usize::from_str_radix(value.as_str().ok_or(Error::BadJson)?, 2)
.map_err(|_| Error::BadJson)?,
);
}
let json_connections = &cell["connections"];
let mut connections: HashMap<&str, Vec<usize>> = HashMap::new();
for (key, bits) in json_connections.entries() {
let JsonValue::Array(arr) = bits else {
return Err(Error::BadJson);
};
let connection_bits: Vec<usize> = arr
.iter()
.map(|x| x.as_usize().ok_or(Error::BadJson))
.collect::<Result<_, _>>()?;
connections.insert(key, connection_bits);
}
let cell_type = cell["type"].as_str().ok_or(Error::BadJson)?.to_owned();
return Ok(Cell {
cell_type,
parameters,
connections,
});
}
fn run_yosys(
yosys_command: &str,
module: Option<&str>,
files: &[&str],
) -> Result<JsonValue, Error> {
let tmp = tempdir().map_err(|_| Error::TempDir)?;
let tmp_file_path = tmp.path().join("modules.json");
let tmp_file_path = tmp.path().join("yosys-output.json");
let mut command = Command::new("yosys");
command.args(["-o", tmp_file_path.to_str().unwrap(), "-p", yosys_command]);
command.args(files);
if let Some(module) = module {
command.args(["-r", module]);
}
command.args(files);
let result = command
.stdout(Stdio::null())
.status()
@ -52,9 +164,7 @@ pub fn run_yosys(yosys_command: &str, module: Option<&str>, files: &[&str]) -> R
println!("{}", file_contents);
let object = json::parse(&file_contents).map_err(|_| Error::InvalidJson)?;
let root = json::parse(&file_contents).map_err(|_| Error::InvalidJson)?;
println!("{:?}", object["modules"]);
return Ok(());
return Ok(root);
}

Loading…
Cancel
Save