diff --git a/compiler/src/fitter.rs b/compiler/src/fitter.rs index 209666b..ff3c6ef 100644 --- a/compiler/src/fitter.rs +++ b/compiler/src/fitter.rs @@ -1,3 +1,4 @@ +use std::error::Error; use std::str::from_utf8; use crate::pcf::PcfFile; @@ -6,6 +7,7 @@ use crate::yosys_parser::{ }; use galette::blueprint::{Blueprint, PinMode}; use galette::chips::Chip; +use galette::errors; use log::{debug, error, info, warn}; use thiserror::Error; @@ -31,6 +33,9 @@ pub enum MappingError { #[error("Unknown error")] Unknown, + + #[error("galette error")] + Galette(#[from] galette::errors::ErrorCode), } // attempt to map graph into blueprint @@ -248,7 +253,7 @@ fn valid_inputs(chip: Chip) -> Vec { } } -pub fn graph_convert(graph: &Graph, pcf: PcfFile, chip: Chip) -> anyhow::Result { +pub fn graph_convert(graph: &Graph, pcf: &PcfFile, chip: Chip) -> Result { let mut bp = Blueprint::new(chip); let valid_inp = valid_inputs(chip); @@ -303,7 +308,7 @@ pub fn graph_convert(graph: &Graph, pcf: PcfFile, chip: Chip) -> anyhow::Result< .lookup(&pcf) .ok_or(MappingError::MissingConstraint(port.clone()))?; let olmc_row = chip - .pin_to_olmc(pin.try_into()?) + .pin_to_olmc(pin as usize) .ok_or(MappingError::Unknown)?; // TODO: check size of row vs size of SOP // FIXME: -0 to size if registered, if comb, size - 1 @@ -335,7 +340,7 @@ pub fn graph_convert(graph: &Graph, pcf: PcfFile, chip: Chip) -> anyhow::Result< } // at this point, we should have mapped let num_mapped = olmcmap.iter().filter(|x| x.is_some()).count(); - info!("Mapped {num_mapped} OLMCS, {} deferred", deferrals.len()); + info!("Mapped {num_mapped} OLMCS, {} deferred", deferrals.len()); // to map the deferred ones, we need to find the smallest SOP that is still large enough for // it. diff --git a/compiler/src/main.rs b/compiler/src/main.rs index 79a2999..f1f97c9 100644 --- a/compiler/src/main.rs +++ b/compiler/src/main.rs @@ -1,20 +1,23 @@ +mod fitter; pub mod pcf; pub mod yosys_parser; -mod fitter; -use clap::{Parser, Subcommand, ValueEnum, Args}; +use crate::fitter::{graph_convert, MappingError}; +use crate::pcf::{parse_pcf, PcfFile}; +use crate::yosys_parser::{Graph, YosysDoc}; +use anyhow::{bail, Result}; +use clap::{Args, Parser, Subcommand, ValueEnum}; +use env_logger; +use galette::blueprint::Blueprint; +use galette::chips::Chip; use galette::gal_builder::build; use galette::writer::{make_jedec, Config}; -use crate::pcf::parse_pcf; -use crate::yosys_parser::{YosysDoc, Graph}; -use crate::fitter::graph_convert; -use anyhow::{bail, Result}; use serde_json::from_slice; +use std::fs::{self, File}; use std::io::Write; use std::path::PathBuf; -use galette::chips::Chip; -use std::fs::{self, File}; -use env_logger; +use std::process::Command; +use log::{info, warn}; #[derive(Parser)] struct Cli { @@ -38,7 +41,7 @@ struct ValidateArgs { #[derive(ValueEnum, Debug, Clone)] enum ChipType { GAL16V8, - GAL22V10 + GAL22V10, } impl ChipType { @@ -50,7 +53,6 @@ impl ChipType { } } - #[derive(Args)] struct SynthArgs { #[arg(required = true, value_hint = clap::ValueHint::DirPath)] @@ -59,11 +61,10 @@ struct SynthArgs { constraints: PathBuf, #[arg(value_enum, long, default_value_t=ChipType::GAL16V8)] - chip: ChipType + chip: ChipType, } - -fn validate(v: ValidateArgs) -> Result<()>{ +fn validate(v: ValidateArgs) -> Result<()> { let f = fs::read(v.file)?; let data: YosysDoc = from_slice(f.as_slice())?; @@ -80,31 +81,45 @@ fn validate(v: ValidateArgs) -> Result<()>{ Ok(()) } +fn load_to_graph( + netlist: &PathBuf, + pcf: &PcfFile, + chip: Chip, +) -> Result { + info!("loading netlist..."); + let f = fs::read(netlist).unwrap(); -fn synth(s: SynthArgs) -> Result<()> { - let f = fs::read(s.netlist)?; - - let data: YosysDoc = from_slice(f.as_slice())?; + let data: YosysDoc = from_slice(f.as_slice()).unwrap(); let g = Graph::from(data); - let res = g.validate().map_err(|x| x.to_string()); - if let Err(e) = res { - bail!(e); - } + g.validate().map_err(|x| x.to_string()).unwrap(); println!("Validation Complete!"); println!("Stats:"); println!("Nodes: {}", g.nodelist.len()); println!("Edges: {}", g.adjlist.len()); + graph_convert(&g, pcf, chip) +} + +fn synth(s: SynthArgs) -> Result<()> { // load the pcf let pcf_file = &fs::read(s.constraints)?; let pcf_string = std::str::from_utf8(pcf_file)?; let pcf = parse_pcf(pcf_string); - let res = graph_convert(&g, pcf, s.chip.to_galette())?; + let mut res = load_to_graph(&s.netlist, &pcf, s.chip.to_galette()); + + while let Err(MappingError::SopTooBig { ref name, sop_size, wanted_size }) = res { + warn!("Sop too large, attempting to split {name}. cur={sop_size} want={wanted_size}"); + let yosys = Command::new("yosys").args(["split_sop.tcl"]); + + res = load_to_graph(&s.netlist, &pcf, s.chip.to_galette()); + } + + let bp = res?; + + let mut gal = build(&bp)?; - let mut gal = build(&res)?; - if matches!(s.chip, ChipType::GAL16V8) { gal.set_mode(galette::gal::Mode::Registered); } @@ -113,18 +128,18 @@ fn synth(s: SynthArgs) -> Result<()> { gen_pin: false, gen_fuse: false, gen_chip: false, - jedec_sec_bit: false + jedec_sec_bit: false, }; let mut file = File::create("output.jed")?; let jed = make_jedec(&config, &gal); file.write_all(jed.as_bytes())?; - + Ok(()) } -fn main() -> Result<()>{ +fn main() -> Result<()> { let args = Cli::parse(); env_logger::init(); match args.command { diff --git a/compiler/src/yosys_parser.rs b/compiler/src/yosys_parser.rs index fd10235..261efc4 100644 --- a/compiler/src/yosys_parser.rs +++ b/compiler/src/yosys_parser.rs @@ -517,7 +517,8 @@ impl From for Graph { YosysCell::Sop(s) => Node::Sop(s), YosysCell::OLMC(n) => Node::Olmc(n), }; - newcell.set_name(&cell_name); + let fully_qualified_name = format!("{mod_name}/{cell_name}"); + newcell.set_name(&fully_qualified_name); g.nodelist.push(newcell); } for (port_name, port) in module.ports {