diff --git a/compiler/src/fitter.rs b/compiler/src/fitter.rs index f9541c0..2649310 100644 --- a/compiler/src/fitter.rs +++ b/compiler/src/fitter.rs @@ -1,5 +1,5 @@ use crate::pcf::PcfFile; -use crate::yosys_parser::{GalOLMC, GalSop, Graph, NamedPort, Net, Node, NodeIdx}; +use crate::yosys_parser::{GalOLMC, GalSop, Graph, NamedPort, Net, Node, NodeIdx, PortDirection}; use galette::blueprint::Blueprint; use galette::chips::Chip; use log::info; @@ -16,8 +16,8 @@ pub enum MappingError { #[error("Could not find the SOP input")] MissingSOP, - #[error("Could not find a sop to fit {0}")] - SopTooBig(usize), + #[error("Could not find a sop to fit SOP {0:?} of {1}")] + SopTooBig(String, usize), #[error("Unknown error")] Unknown, @@ -25,7 +25,7 @@ pub enum MappingError { // attempt to map graph into blueprint -/// Acquire the SOP associated with the OLMC. If it's +/// Acquire the SOP associated with the OLMC. If it's fn get_sop_for_olmc(graph: &Graph, olmc_idx: NodeIdx) -> Result { let input = graph.get_node_port_conns(olmc_idx, "A"); assert_eq!(input.len(), 1, "OLMC input should have one netadjpair"); @@ -40,47 +40,83 @@ fn get_sop_for_olmc(graph: &Graph, olmc_idx: NodeIdx) -> Result) -> Result { +fn map_remaining_olmc( + graph: &Graph, + olmc: NodeIdx, + unused: &Vec<(usize, usize)>, +) -> Result<(usize, usize), MappingError> { // (index, size) let mut chosen_row: Option<(usize, usize)> = None; // FIXME: implement. - let sopsize: usize = get_sop_for_olmc(graph, olmc)?.parameters.depth as usize; + let sop = get_sop_for_olmc(graph, olmc)?; + let sopsize: usize = sop.parameters.depth as usize; for (olmc_idx, size) in unused { match chosen_row { None => { - if size > sopsize { - chosen_row = Some((olmc_idx, size)); + if size > &sopsize { + chosen_row = Some((*olmc_idx, *size)); } } Some(r) => { // we do the comparison (size > SOP Size) - if size < r.1 && size > sopsize { - chosen_row = Some((olmc_idx, size)); + if size < &r.1 && size > &sopsize { + chosen_row = Some((*olmc_idx, *size)); } } } } // at the end, if we have chosen a row, we can swap it in. match chosen_row { - Some((row, size)) => { - info!("mapping {olmc:?} size {sopsize} to row {row} with size {size}"); - Ok(row) - }, - None => { - Err(MappingError::SopTooBig(sopsize)) + Some(x) => { + info!( + "mapping {olmc:?} size {sopsize} to row {} with size {}", + x.0, x.1 + ); + Ok(x) } - } + None => Err(MappingError::SopTooBig("TODO FIXME".to_string(), sopsize)), + } } +fn valid_inputs(chip: Chip) -> Vec { + match chip { + Chip::GAL16V8 => vec![ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 19, + ], + Chip::GAL22V10 => vec![ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + ], + _ => panic!("unsupported chip"), + } +} pub fn graph_convert(graph: &Graph, pcf: PcfFile, chip: Chip) -> anyhow::Result { let mut bp = Blueprint::new(chip); + // phase zero: input mapping. + let mut pinmap: Vec> = vec![None; chip.num_pins()]; + + let valid_inp = valid_inputs(chip); + let mut olmcmap: Vec> = vec![None; chip.num_olmcs()]; + + for port in &graph.ports { + let pin = port + .lookup(&pcf) + .ok_or(MappingError::MissingConstraint(port.clone()))?; + if valid_inp.contains(&pin) { + if let Some(olmcrow) = chip.pin_to_olmc(pin as usize) { + if port.direction == PortDirection::Input { + olmcmap[olmcrow] = Some(NodeIdx(usize::MAX)); + } // otherwise we do not care! + } + } else { + return Err(MappingError::Unknown.into()); + } + } + // phase one: OLMC mapping // start by finding the constraints. - // - let mut olmcmap: Vec> = vec![None; chip.num_olmcs()]; let mut deferrals: Vec = Vec::new(); @@ -108,7 +144,14 @@ pub fn graph_convert(graph: &Graph, pcf: PcfFile, chip: Chip) -> anyhow::Result< .pin_to_olmc(pin.try_into()?) .ok_or(MappingError::Unknown)?; // TODO: check size of row vs size of SOP + // FIXME: -0 to size if registered, if comb, size - 1 info!("Found a real pin to map: Mapping node {o:?} onto row {olmc_row}"); + + // check if OLMC row is already in use + if let Some(o) = olmcmap[olmc_row] { + info!("already exists in {o:?}"); + return Err(MappingError::Unknown.into()); + } olmcmap[olmc_row] = Some(o); } None => { @@ -124,14 +167,24 @@ pub fn graph_convert(graph: &Graph, pcf: PcfFile, chip: Chip) -> anyhow::Result< // to map remainders, we need to find the smallest SOP. // // Vec<(olmc_index,size)> - let unused_rows = olmcmap + let mut unused_rows = olmcmap .iter() - .enumerate() - .filter_map(|(i, x)| if !x.is_some() { Some(i) } else { None }) - .map(|i| (i, chip.num_rows_for_olmc(i))); - // find the smallest row that fits. + .enumerate() // get the index + .filter_map(|(i, x)| if x.is_none() { Some(i) } else { None }) // find the ones that are + .map(|i| (i, chip.num_rows_for_olmc(i))) + .collect(); - let olmc = deferrals[0]; + // find the smallest row that fits. + for olmc in deferrals { + let row = map_remaining_olmc(graph, olmc, &unused_rows)?; + // insert into the mapping + olmcmap[row.0] = Some(olmc); + // remove this row from the available rows + // i.e only keep those that are not equal to this row. + unused_rows.retain(|r| r != &row); + } + + // at this point, we have mapped every OLMC. Ok(bp) } diff --git a/compiler/src/yosys_parser.rs b/compiler/src/yosys_parser.rs index 033bc4a..7065588 100644 --- a/compiler/src/yosys_parser.rs +++ b/compiler/src/yosys_parser.rs @@ -64,9 +64,9 @@ pub struct GalSop { #[serde(rename_all = "UPPERCASE")] pub struct GALOLMCParameters { #[serde(deserialize_with = "bool_from_binstr")] - inverted: bool, + pub inverted: bool, #[serde(deserialize_with = "bool_from_binstr")] - registered: bool, + pub registered: bool, } #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] @@ -187,8 +187,8 @@ pub enum PortDirection { #[derive(Debug, Clone, PartialEq, PartialOrd)] pub struct NamedPort { pub name: String, - net: Net, - direction: PortDirection, + pub net: Net, + pub direction: PortDirection, } use std::cmp::Ordering; @@ -228,7 +228,7 @@ impl NamedPort { /// NodeIdx is an index into the node list to reference a specific node. #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] -pub struct NodeIdx(usize); +pub struct NodeIdx(pub usize); #[derive(Debug, Clone)]