mirror of
https://github.com/annoyatron255/yosys4gal.git
synced 2024-12-22 18:52:23 +00:00
wip: newtype nodeindex
This commit is contained in:
parent
0be535bfcb
commit
2ad9a1d157
|
@ -1,5 +1,5 @@
|
||||||
use crate::pcf::PcfFile;
|
use crate::pcf::PcfFile;
|
||||||
use crate::yosys_parser::{GalOLMC, GalSop, Graph, NamedPort, Net, Node};
|
use crate::yosys_parser::{GalOLMC, GalSop, Graph, NamedPort, Net, Node, NodeIdx};
|
||||||
use galette::blueprint::Blueprint;
|
use galette::blueprint::Blueprint;
|
||||||
use galette::chips::Chip;
|
use galette::chips::Chip;
|
||||||
use log::info;
|
use log::info;
|
||||||
|
@ -26,10 +26,10 @@ pub enum MappingError {
|
||||||
// attempt to map graph into blueprint
|
// 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: usize) -> Result<GalSop, MappingError> {
|
fn get_sop_for_olmc(graph: &Graph, olmc_idx: NodeIdx) -> Result<GalSop, MappingError> {
|
||||||
let input = graph.get_node_port_conns(olmc_idx, "A");
|
let input = graph.get_node_port_conns(olmc_idx, "A");
|
||||||
assert_eq!(input.len(), 1, "OLMC input should have one netadjpair");
|
assert_eq!(input.len(), 1, "OLMC input should have one netadjpair");
|
||||||
let other_node = input[0].get_other(olmc_idx);
|
let other_node = input[0].get_other(olmc_idx).ok_or(MappingError::Unknown)?;
|
||||||
let sop = graph
|
let sop = graph
|
||||||
.get_node(other_node.0)
|
.get_node(other_node.0)
|
||||||
.ok_or(MappingError::MissingSOP)?;
|
.ok_or(MappingError::MissingSOP)?;
|
||||||
|
@ -40,7 +40,7 @@ fn get_sop_for_olmc(graph: &Graph, olmc_idx: usize) -> Result<GalSop, MappingErr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn map_remaining_olcm(graph: &Graph, olmc: usize, unused: Vec<(usize, usize)>) -> Result<usize, MappingError> {
|
fn map_remaining_olcm(graph: &Graph, olmc: NodeIdx, unused: Vec<(usize, usize)>) -> Result<usize, MappingError> {
|
||||||
// (index, size)
|
// (index, size)
|
||||||
let mut chosen_row: Option<(usize, usize)> = None;
|
let mut chosen_row: Option<(usize, usize)> = None;
|
||||||
// FIXME: implement.
|
// FIXME: implement.
|
||||||
|
@ -64,7 +64,7 @@ fn map_remaining_olcm(graph: &Graph, olmc: usize, unused: Vec<(usize, usize)>) -
|
||||||
// at the end, if we have chosen a row, we can swap it in.
|
// at the end, if we have chosen a row, we can swap it in.
|
||||||
match chosen_row {
|
match chosen_row {
|
||||||
Some((row, size)) => {
|
Some((row, size)) => {
|
||||||
info!("mapping {olmc} size {sopsize} to row {row} with size {size}");
|
info!("mapping {olmc:?} size {sopsize} to row {row} with size {size}");
|
||||||
Ok(row)
|
Ok(row)
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
|
@ -73,8 +73,6 @@ fn map_remaining_olcm(graph: &Graph, olmc: usize, unused: Vec<(usize, usize)>) -
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
struct GALMapEntry(GalOLMC, usize); // data and the entry in the graph
|
|
||||||
|
|
||||||
pub fn graph_convert(graph: &Graph, pcf: PcfFile, chip: Chip) -> anyhow::Result<Blueprint> {
|
pub fn graph_convert(graph: &Graph, pcf: PcfFile, chip: Chip) -> anyhow::Result<Blueprint> {
|
||||||
let mut bp = Blueprint::new(chip);
|
let mut bp = Blueprint::new(chip);
|
||||||
|
@ -82,9 +80,9 @@ pub fn graph_convert(graph: &Graph, pcf: PcfFile, chip: Chip) -> anyhow::Result<
|
||||||
// phase one: OLMC mapping
|
// phase one: OLMC mapping
|
||||||
// start by finding the constraints.
|
// start by finding the constraints.
|
||||||
//
|
//
|
||||||
let mut olmcmap: Vec<Option<usize>> = vec![None; chip.num_olmcs()];
|
let mut olmcmap: Vec<Option<NodeIdx>> = vec![None; chip.num_olmcs()];
|
||||||
|
|
||||||
let mut deferrals: Vec<usize> = Vec::new();
|
let mut deferrals: Vec<NodeIdx> = Vec::new();
|
||||||
|
|
||||||
// For all the OLMCs in the graph, we either map it directly since it's constrained to a pin,
|
// For all the OLMCs in the graph, we either map it directly since it's constrained to a pin,
|
||||||
// or we defer it to later.
|
// or we defer it to later.
|
||||||
|
@ -110,11 +108,11 @@ pub fn graph_convert(graph: &Graph, pcf: PcfFile, chip: Chip) -> anyhow::Result<
|
||||||
.pin_to_olmc(pin.try_into()?)
|
.pin_to_olmc(pin.try_into()?)
|
||||||
.ok_or(MappingError::Unknown)?;
|
.ok_or(MappingError::Unknown)?;
|
||||||
// TODO: check size of row vs size of SOP
|
// TODO: check size of row vs size of SOP
|
||||||
info!("Found a real pin to map: Mapping node {o} onto row {olmc_row}");
|
info!("Found a real pin to map: Mapping node {o:?} onto row {olmc_row}");
|
||||||
olmcmap[olmc_row] = Some(o);
|
olmcmap[olmc_row] = Some(o);
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
info!("No port found, deferring placement for {o}");
|
info!("No port found, deferring placement for {o:?}");
|
||||||
deferrals.push(o)
|
deferrals.push(o)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
use crate::pcf::PcfFile;
|
use crate::pcf::PcfFile;
|
||||||
use galette::gal::Pin;
|
use galette::gal::Pin;
|
||||||
use log::error;
|
|
||||||
use log::info;
|
use log::info;
|
||||||
use serde::{de::Error, Deserialize, Deserializer, Serialize};
|
use serde::{de::Error, Deserialize, Deserializer, Serialize};
|
||||||
use serde_with::{serde_as, BoolFromInt};
|
use serde_with::{serde_as, BoolFromInt};
|
||||||
use std::collections::hash_map::Iter;
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::str;
|
use std::str;
|
||||||
|
|
||||||
|
@ -228,13 +226,18 @@ 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);
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct NetAdjPair {
|
pub struct NetAdjPair {
|
||||||
pub net: Net,
|
pub net: Net,
|
||||||
idx1: usize,
|
idx1: NodeIdx,
|
||||||
port1: String,
|
port1: String,
|
||||||
port2: String,
|
port2: String,
|
||||||
idx2: usize,
|
idx2: NodeIdx,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for NetAdjPair {
|
impl PartialEq for NetAdjPair {
|
||||||
|
@ -270,21 +273,23 @@ impl NetAdjPair {
|
||||||
pub fn uses_net(&self, net: &Net) -> bool {
|
pub fn uses_net(&self, net: &Net) -> bool {
|
||||||
net == &self.net
|
net == &self.net
|
||||||
}
|
}
|
||||||
pub fn uses_nodeport(&self, idx: usize, port: &str) -> bool {
|
pub fn uses_nodeport(&self, idx: NodeIdx, port: &str) -> bool {
|
||||||
(self.idx1 == idx && self.port1 == port) || (self.idx2 == idx && self.port2 == port)
|
(self.idx1 == idx && self.port1 == port) || (self.idx2 == idx && self.port2 == port)
|
||||||
}
|
}
|
||||||
pub fn get_other(&self, my_idx: usize) -> (usize, &str) {
|
pub fn get_other(&self, my_idx: NodeIdx) -> Option<(NodeIdx, &str)> {
|
||||||
if my_idx == self.idx1 {
|
if my_idx == self.idx1 {
|
||||||
(self.idx2, &self.port2)
|
Some((self.idx2, &self.port2))
|
||||||
} else if my_idx == self.idx2 {
|
} else if my_idx == self.idx2 {
|
||||||
(self.idx1, &self.port1)
|
Some((self.idx1, &self.port1))
|
||||||
} else {
|
} else {
|
||||||
(usize::MAX, "")
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A Node is an entry in our graph. A node has inputs and outputs.
|
/// A Node is an entry in our graph. A node has a set of connections that can be
|
||||||
|
/// read with `get_ports`. You can also see if a node accesses a given net with
|
||||||
|
/// `port_for_net`
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub enum Node {
|
pub enum Node {
|
||||||
Input(GalInput),
|
Input(GalInput),
|
||||||
|
@ -312,23 +317,29 @@ impl Node {
|
||||||
// Self::Olmc(go) => go.connections.input.to_vec(),
|
// Self::Olmc(go) => go.connections.input.to_vec(),
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
pub fn get_ports(&self) -> HashMap<String, Vec<Net>> {
|
|
||||||
|
// Returns the hashmap of String (connection name) to a list of nets.
|
||||||
|
pub fn get_connections(&self) -> HashMap<String, Vec<Net>> {
|
||||||
match self {
|
match self {
|
||||||
Self::Olmc(ol) => ol.connections.clone(),
|
Self::Olmc(ol) => ol.connections.clone(),
|
||||||
Self::Input(i) => i.connections.clone(),
|
Self::Input(i) => i.connections.clone(),
|
||||||
Self::Sop(s) => s.connections.clone(),
|
Self::Sop(s) => s.connections.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the connection that contains this net, if any.
|
||||||
pub fn port_for_net(&self, net: &Net) -> Option<String> {
|
pub fn port_for_net(&self, net: &Net) -> Option<String> {
|
||||||
for (port, nets) in self.get_ports() {
|
for (port, nets) in self.get_connections() {
|
||||||
if nets.contains(net) {
|
if nets.contains(net) {
|
||||||
return Some(port.to_string());
|
return Some(port.to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get every net that this node uses.
|
||||||
pub fn get_nets(&self) -> Vec<Net> {
|
pub fn get_nets(&self) -> Vec<Net> {
|
||||||
self.get_ports()
|
self.get_connections()
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|(_, nets)| nets.clone())
|
.flat_map(|(_, nets)| nets.clone())
|
||||||
.collect()
|
.collect()
|
||||||
|
@ -373,8 +384,8 @@ impl Graph {
|
||||||
let node2_port = node2.port_for_net(&net).expect("how");
|
let node2_port = node2.port_for_net(&net).expect("how");
|
||||||
let adj = NetAdjPair {
|
let adj = NetAdjPair {
|
||||||
net: net.clone(),
|
net: net.clone(),
|
||||||
idx1,
|
idx1: NodeIdx(idx1),
|
||||||
idx2,
|
idx2: NodeIdx(idx2),
|
||||||
port1: node1_port,
|
port1: node1_port,
|
||||||
port2: node2_port,
|
port2: node2_port,
|
||||||
};
|
};
|
||||||
|
@ -388,11 +399,11 @@ impl Graph {
|
||||||
}
|
}
|
||||||
/// Find all nodes that are attached to this net in any way.
|
/// Find all nodes that are attached to this net in any way.
|
||||||
/// Note that this is an expensive operation since it can't currently use the adjlist.
|
/// Note that this is an expensive operation since it can't currently use the adjlist.
|
||||||
pub fn find_nodes(&self, net: &Net) -> Vec<usize> {
|
pub fn find_nodes_on_net(&self, net: &Net) -> Vec<NodeIdx> {
|
||||||
let mut res = Vec::new();
|
let mut res = Vec::new();
|
||||||
for (idx, node) in self.nodelist.iter().enumerate() {
|
for (idx, node) in self.nodelist.iter().enumerate() {
|
||||||
if node.get_nets().contains(net) {
|
if node.get_nets().contains(net) {
|
||||||
res.push(idx);
|
res.push(NodeIdx(idx));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
res
|
res
|
||||||
|
@ -400,12 +411,12 @@ impl Graph {
|
||||||
|
|
||||||
/// Retrieve a node from the node index
|
/// Retrieve a node from the node index
|
||||||
/// TODO: make a newtype for the index.
|
/// TODO: make a newtype for the index.
|
||||||
pub fn get_node(&self, idx: usize) -> Option<&Node> {
|
pub fn get_node(&self, idx: NodeIdx) -> Option<&Node> {
|
||||||
self.nodelist.get(idx)
|
self.nodelist.get(idx.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// find the connections from the given node/port
|
// find the connections from the given node/port
|
||||||
pub fn get_node_port_conns(&self, nodeidx: usize, port: &str) -> Vec<&NetAdjPair> {
|
pub fn get_node_port_conns(&self, nodeidx: NodeIdx, port: &str) -> Vec<&NetAdjPair> {
|
||||||
self.adjlist
|
self.adjlist
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|adj| adj.uses_nodeport(nodeidx, port))
|
.filter(|adj| adj.uses_nodeport(nodeidx, port))
|
||||||
|
@ -414,12 +425,12 @@ impl Graph {
|
||||||
|
|
||||||
// TODO: get rid of this or refactor somehow?????
|
// TODO: get rid of this or refactor somehow?????
|
||||||
// VERY BAD
|
// VERY BAD
|
||||||
pub fn get_olmc_idx(&self) -> Vec<usize> {
|
pub fn get_olmc_idx(&self) -> Vec<NodeIdx> {
|
||||||
self.nodelist
|
self.nodelist
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.filter_map(|(idx, node)| match node {
|
.filter_map(|(idx, node)| match node {
|
||||||
Node::Olmc(_) => Some(idx),
|
Node::Olmc(_) => Some(NodeIdx(idx)),
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
|
|
Loading…
Reference in a new issue