Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
mapping progress
Browse files Browse the repository at this point in the history
5aji committed Apr 4, 2024
1 parent ea1ee09 commit 393ffa3
Showing 1 changed file with 86 additions and 34 deletions.
120 changes: 86 additions & 34 deletions src/yosys_parser.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use crate::gal::Pin;
use crate::pcf::PcfFile;
use itertools::Itertools;
use log::info;
use serde::{de::Error, Deserialize, Deserializer, Serialize};
use serde_with::{serde_as, BoolFromInt};
use std::collections::HashMap;
use log::info;
use std::str;

// Custom deserializer for the strange string of binary
@@ -24,7 +24,7 @@ where
u32::from_str_radix(s.as_str(), 2).map_err(D::Error::custom)
}

#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "UPPERCASE")]
pub struct SoPParameters {
#[serde(deserialize_with = "from_binstr")]
@@ -34,21 +34,21 @@ pub struct SoPParameters {
pub width: u32,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct SoPConnections {
#[serde(rename = "A")]
pub inputs: Vec<Net>,
#[serde(rename = "Y")]
pub output: [Net; 1], // sop Y has exactly one output
}

#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct SoPCell {
pub parameters: SoPParameters,
pub connections: SoPConnections,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct DffConnections {
#[serde(rename = "C")]
pub clock: [Net; 1],
@@ -58,19 +58,19 @@ pub struct DffConnections {
pub output: [Net; 1],
}

#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct DffCell {
connections: DffConnections,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "UPPERCASE")]
pub struct NotConnections {
pub a: [Net; 1],
pub y: [Net; 1],
}

#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct NotCell {
connections: NotConnections,
}
@@ -202,31 +202,53 @@ impl YosysDoc {
* hits.
*/



/// NamedPort is our internal representation of a port.
#[derive(Debug)]
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct NamedPort {
name: String,
bits: Vec<Net>,
upto: bool,
net: Net,
}

use std::cmp::Ordering;
impl NamedPort {
fn new(name: &str, p: ModPort) -> Self {
fn new(name: &str, net: &Net) -> Self {
NamedPort {
name: name.to_owned(),
bits: p.bits.clone(),
upto: p.upto,
net: net.clone(),
}
}

/// Takes a module port, and splits into N NamedPorts, where the name
/// is converted to match the pcf format <name>[index] if there is more than
/// one bit in the port
fn new_split(base_name: &str, port: ModPort) -> Vec<NamedPort> {
match port.bits.len().cmp(&1) {
Ordering::Greater => port
.bits
.iter()
.enumerate()
.map(|(idx, n)| {
NamedPort::new(&format!("{base_name}[{idx}]"), n)
})
.collect(),
Ordering::Equal => {
vec![NamedPort::new(base_name, &port.bits[0])]
}
_ => panic!("no bits on this port!"),
}
}
/// Retrieves the port mapping for this port, given a PCF file.
pub fn lookup(&self, pcf: &PcfFile) -> u32 {
//NOTE: since NamedPort is exactly (1) pin, we always use the pin case.
// When constructing, if we have a port with multiple bits, we split it (see `new_split`)
pcf.pin(&self.name).expect("missing constraint")
}
}

type NetAdjPair = (usize, usize, Net);


/// A Node is an entry in our graph. A node has inputs and outputs.
#[derive(Debug)]
#[derive(Debug, PartialEq, Clone)]
pub enum Node {
Input(NamedPort),
Output(NamedPort),
@@ -238,12 +260,12 @@ pub enum Node {
impl Node {
/* These functions are a little odd. We invert the input/output bits. CHIP inputs, are viewed
* as outputs internally, likewise we view the outputs of the chip as inputs (to be driven
* internally. So get_outputs returns values on input_cells, since those are driven already.
* internally. So get_outputs returns values on input_cells, since those are driven already.
* Likewise we reverse this for get_inputs, since the chip's outputs are our inputs.
*/
fn get_outputs(&self) -> Vec<Net> {
match self {
Self::Input(i) => i.bits.clone(),
Self::Input(i) => vec![i.net.clone()],
Self::Output(_) => Vec::new(),
Self::Sop(s) => s.connections.output.to_vec(),
Self::Not(n) => n.connections.y.to_vec(),
@@ -253,7 +275,7 @@ impl Node {
fn get_inputs(&self) -> Vec<Net> {
match self {
Self::Input(_) => Vec::new(),
Self::Output(o) => o.bits.clone(),
Self::Output(o) => vec![o.net.clone()],
Self::Sop(s) => s.connections.inputs.to_vec(),
Self::Not(n) => n.connections.a.to_vec(),
Self::Dff(d) => d.connections.input.to_vec(),
@@ -271,27 +293,54 @@ impl Graph {
pub fn generate_adjacency(&mut self) {
self.adjlist.clear();
for (idx, node) in self.nodelist.iter().enumerate() {
for net in node.get_outputs() { // for each output attached to the node.
for net in node.get_outputs() {
// for each output attached to the node.
// find all node idndexes that have our net as an input.
let edges = self
.nodelist
.iter()
.enumerate()
.filter(|&(_, x)| x.get_inputs().contains(&net)) // only get nodes that have
// us as their input.
// us as their input.
.map(|(i, _)| (idx, i, net.clone())); // convert into edge pair with our main.

self.adjlist.extend(edges);
}
}
}
/// Looks up the nodes attached to a given net. Returns a pair of results,
/// (Vec<&Node>, &Node). The first element is the vectors that use this net as an input.
/// The second element is the node that outputs to this net.
pub fn net_lookup(&self, net: &Net) -> (Vec<&Node>, &Node) {
self.adjlist.iter().filter(|_x| true);
todo!("hi");
// find all nodes that are for this net.
let mut inputs: Vec<&Node> = Vec::new();
let mut output: Option<&Node> = None;
let links: Vec<&NetAdjPair> = self.adjlist.iter().filter(|(_, _, n)| n == net).collect();
if links.is_empty() {
panic!("no links for this net!");
}
for (out, inp, _) in links {
match output {
None => output = Some(self.nodelist.get(*out).unwrap()),
Some(old) => {
// check
if old != self.nodelist.get(*out).unwrap() {
panic!("multiple drivers for this net!");
}
}
}
inputs.push(self.nodelist.get(*inp).unwrap())
}

(inputs, output.unwrap())
}
fn validate(&self) -> Result<(), String> {

let nets: Vec<&Net> = self.adjlist.iter().map(|(_,_,n)| n).unique().collect_vec();
let nets: Vec<&Net> = self
.adjlist
.iter()
.map(|(_, _, n)| n)
.unique()
.collect_vec();
// back-travel
// find output ports, find their drivers
// output port -> Vec<Net> -> Vec<(Net,Pin)>
@@ -309,18 +358,22 @@ impl From<YosysDoc> for Graph {
info!("Processing module {}", mod_name);
for (port_name, port) in module.ports {
info!("Processing port {}", port_name);
let newport = match port {
Port::Input(m) => Node::Input(NamedPort::new(&port_name, m)),
Port::Output(m) => Node::Output(NamedPort::new(&port_name, m)),


// this routine monomorphizes the ports. basically it takes a port named `counter`
// and maps it into counter[0], counter[1], etc
let newport: Vec<Node> = match port {
Port::Input(m) => NamedPort::new_split(&port_name, m).iter().map(|x| Node::Input(x.clone())).collect(),
Port::Output(m) => NamedPort::new_split(&port_name, m).iter().map(|x| Node::Output(x.clone())).collect(),
};
g.nodelist.push(newport);
g.nodelist.extend(newport);
}
for (cell_name, cell) in module.cells {
info!("Processing cell {}", cell_name);
let newcell = match cell {
YosysCell::DffCell(d) => Node::Dff(d),
YosysCell::SoPCell(s) => Node::Sop(s),
YosysCell::NotCell(n) => Node::Not(n)
YosysCell::NotCell(n) => Node::Not(n),
};
g.nodelist.push(newcell);
}
@@ -330,10 +383,9 @@ impl From<YosysDoc> for Graph {
}
}


/*
* This graph is too general as it stands. we cannot map individual input pins
* like we can with our output pins. Also, i have no way of finding a specific
* like we can with our output pins. Also, i have no way of finding a specific
* node in the graph.
*/

0 comments on commit 393ffa3

Please sign in to comment.