use super::*;
use std::fmt::{ Display, Formatter, Result };
use itertools::Itertools;
use indexmap::IndexSet;
type NameMap<'i> = IndexSet<(&'i Arc<HierName>, Option<isize>)>;
impl Display for Direction {
#[inline]
fn fmt(&self, f: &mut Formatter) -> Result {
use Direction::*;
write!(f, "{}", match self {
I => "I", O => "O", B => "B"
})
}
}
impl Display for ParValue {
#[inline]
fn fmt(&self, f: &mut Formatter) -> Result {
use ParValue::*;
match self {
Single(a) => write!(f, "{}", a),
Three(a, b, c) => write!(f, "{}:{}:{}", a, b, c)
}
}
}
impl Display for SPEFConnAttr {
#[inline]
fn fmt(&self, f: &mut Formatter) -> Result {
if let Some((x, y)) = self.coords {
write!(f, " *C {} {}", x, y)?;
}
if let Some(v) = self.cap_load {
write!(f, " *L {}", v)?;
}
if let Some((v1, v2)) = self.slew {
write!(f, " *S {} {}", v1, v2)?;
}
if let Some(s) = &self.driving_cell {
write!(f, " *D {}", s)?;
}
Ok(())
}
}
struct BitIDFmt<'a>(isize, &'a SPEFHeader);
impl Display for BitIDFmt<'_> {
#[inline]
fn fmt(&self, f: &mut Formatter) -> Result {
write!(f, "{}{}{}",
self.1.bus_delimiter_left, self.0,
self.1.bus_delimiter_right)
}
}
struct HierNameFmt<'a>(&'a HierName, &'a SPEFHeader);
impl Display for HierNameFmt<'_> {
#[inline]
fn fmt(&self, f: &mut Formatter) -> Result {
write!(f, "{}", self.0.0.iter().format(
self.1.divider.encode_utf8(&mut [0; 1])))
}
}
impl HierName {
#[inline]
fn display<'a>(&'a self, header: &'a SPEFHeader) -> HierNameFmt {
HierNameFmt(self, header)
}
}
struct SPEFHierPortPinRefFmt<'a>(
&'a SPEFHierPortPinRef, &'a NameMap<'a>, &'a SPEFHeader);
impl Display for SPEFHierPortPinRefFmt<'_> {
#[inline]
fn fmt(&self, f: &mut Formatter) -> Result {
let SPEFHierPortPinRefFmt(r, nm, header) = self;
let raw_name = r.as_raw_name();
let mut need_bit_output = false;
if let Some(id) = nm.get_index_of(&raw_name) {
write!(f, "*{}", id + 1)?;
}
else {
write!(f, "{}", raw_name.0.display(header))?;
need_bit_output = true;
}
if let Some(pin) = &r.1 {
write!(f, "{}{}", header.delimiter, pin)?;
need_bit_output = true;
}
if need_bit_output{
if let Some(bit_id) = raw_name.1 {
write!(f, "{}", BitIDFmt(bit_id, header))?;
}
}
Ok(())
}
}
impl SPEFHierPortPinRef {
#[inline]
fn as_raw_name(&self) -> (&Arc<HierName>, Option<isize>) {
match &self.1 {
Some(_) => (&self.0, None),
None => (&self.0, self.2)
}
}
#[inline]
fn display<'a>(&'a self, nm: &'a NameMap<'a>, header: &'a SPEFHeader) -> SPEFHierPortPinRefFmt<'a> {
SPEFHierPortPinRefFmt(self, nm, header)
}
}
impl SPEFPort {
#[inline]
fn write_to_fmt(&self, f: &mut Formatter, nm: &NameMap, header: &SPEFHeader) -> Result {
writeln!(f, "{} {}{}",
self.name.display(nm, header),
self.direction, self.conn_attr)
}
}
impl SPEFNet {
#[inline]
fn write_to_fmt(&self, f: &mut Formatter, nm: &NameMap, header: &SPEFHeader) -> Result {
writeln!(f, "*D_NET {} {}",
self.name.display(nm, header),
self.total_cap)?;
writeln!(f, "*CONN")?;
for conn in &self.conns {
writeln!(f, "*{} {} {}{}",
if conn.name.1.is_some() { 'I' } else { 'P' },
conn.name.display(nm, header),
conn.direction, conn.conn_attr)?
}
writeln!(f, "*CAP")?;
for (id, cap) in self.caps.iter().enumerate() {
write!(f, "{} {}", id + 1, cap.a.display(nm, header))?;
if let Some(b) = &cap.b {
write!(f, " {}", b.display(nm, header))?;
}
writeln!(f, " {}", cap.val)?;
}
writeln!(f, "*RES")?;
for (id, res) in self.ress.iter().enumerate() {
writeln!(f, "{} {} {} {}",
id + 1,
res.a.display(nm, header),
res.b.display(nm, header),
res.val)?;
}
writeln!(f, "*END")?;
Ok(())
}
}
impl SPEF {
#[inline]
fn build_name_map(&self) -> NameMap {
let mut ret = NameMap::new();
ret.extend(self.top_ports.iter()
.map(|p| p.name.as_raw_name()));
ret.extend(self.nets.iter()
.map(|p| p.name.as_raw_name()));
for net in &self.nets {
ret.extend(net.conns.iter()
.map(|c| c.name.as_raw_name()));
ret.extend(net.caps.iter()
.map(|c| c.a.as_raw_name()));
ret.extend(net.caps.iter()
.filter_map(|c| c.b.as_ref()
.map(|b| b.as_raw_name())));
ret.extend(net.ress.iter()
.map(|r| r.a.as_raw_name()));
ret.extend(net.ress.iter()
.map(|r| r.b.as_raw_name()));
}
ret
}
#[inline]
fn write_name_map(&self, f: &mut Formatter, nm: &NameMap) -> Result {
if nm.len() == 0 {
return Ok(());
}
writeln!(f, "*NAME_MAP")?;
for (id, (name, bit_id)) in nm.iter().enumerate() {
write!(f, "*{} {}",
id + 1, name.display(&self.header))?;
if let Some(bit_id) = bit_id {
write!(f, "{}", BitIDFmt(*bit_id, &self.header))?;
}
writeln!(f)?;
}
Ok(())
}
#[inline]
fn write_header(&self, f: &mut Formatter) -> Result {
macro_rules! fmt_unit {
($v:expr, $($k:expr => $u:expr),+) => {{
let v = $v;
let mut best: Option<(&'static str, f32, f32)> = None;
$({
let v_div_log = (v / $u).ln().abs();
match best {
None => {
best = Some(($k, v_div_log, v / $u));
}
Some((_, w, _)) if w > v_div_log => {
best = Some(($k, v_div_log, v / $u));
}
_ => {}
}
})+;
let (best_unit, _, best_ratio) = best.unwrap();
format!("{} {}", best_ratio, best_unit)
}}
}
let h = &self.header;
write!(
f, "\
*SPEF {:?}
*DESIGN {:?}
*DATE {:?}
*VENDOR {:?}
*PROGRAM {:?}
*VERSION {:?}
*DESIGN_FLOW {:?}
*DIVIDER {}
*DELIMITER {}
*BUS_DELIMITER {} {}
*T_UNIT {}
*C_UNIT {}
*R_UNIT {}
*L_UNIT {}
",
h.edition, h.design, h.date, h.vendor, h.program,
h.version, h.design_flow.iter().format(" "),
h.divider, h.delimiter,
h.bus_delimiter_left, h.bus_delimiter_right,
fmt_unit!(h.time_unit, "NS" => 1e-9, "PS" => 1e-12),
fmt_unit!(h.cap_unit, "PF" => 1e-12, "FF" => 1e-15),
fmt_unit!(h.res_unit, "OHM" => 1., "KOHM" => 1e3),
fmt_unit!(h.induct_unit, "HENRY" => 1., "MH" => 1e-3, "UH" => 1e-6))
}
}
impl Display for SPEF {
fn fmt(&self, f: &mut Formatter) -> Result {
self.write_header(f)?;
writeln!(f)?;
let name_map = self.build_name_map();
self.write_name_map(f, &name_map)?;
writeln!(f)?;
if self.top_ports.len() != 0 {
writeln!(f, "*PORTS")?;
for port in &self.top_ports {
port.write_to_fmt(f, &name_map, &self.header)?;
}
writeln!(f)?;
}
for net in &self.nets {
net.write_to_fmt(f, &name_map, &self.header)?;
writeln!(f)?;
}
Ok(())
}
}