use itertools::Itertools;
use crate::{
ast::{
AttributeList, ComplexAttri, ComplexParseError, ComplexWrapper, GroupComments,
GroupFn, SimpleAttri,
},
expression::logic,
ArcStr, GroupSet,
};
#[derive(Debug, Clone, Default)]
#[derive(liberty_macros::Group)]
#[mut_set::derive::item(
sort,
macro(derive(Debug, Clone,Default);)
)]
#[derive(serde::Serialize, serde::Deserialize)]
pub struct Sensitization {
#[id]
#[liberty(name)]
pub name: ArcStr,
#[liberty(comments)]
pub comments: GroupComments<Self>,
#[liberty(undefined)]
pub undefined: AttributeList,
#[liberty(complex)]
pub pin_names: Vec<ArcStr>,
#[liberty(complex(type = Vec))]
pub vector: Vec<SensitizationVector>,
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
#[derive(serde::Serialize, serde::Deserialize)]
pub struct SensitizationVector {
id: usize,
states: Vec<logic::Static>,
}
impl ComplexAttri for SensitizationVector {
#[inline]
fn parse(v: &[&str]) -> Result<Self, ComplexParseError> {
let mut i = v.iter();
let id: usize = match i.next() {
Some(&s) => match s.parse() {
Ok(f) => f,
Err(e) => return Err(ComplexParseError::Int(e)),
},
None => return Err(ComplexParseError::LengthDismatch),
};
let states = match i.next() {
Some(&s) => match s
.split_ascii_whitespace()
.map(str::parse)
.collect::<Result<Vec<logic::Static>, _>>()
{
Ok(states) => states,
Err(_) => return Err(ComplexParseError::UnsupportedWord),
},
None => return Err(ComplexParseError::LengthDismatch),
};
if i.next().is_some() {
return Err(ComplexParseError::LengthDismatch);
}
Ok(Self { id, states })
}
#[inline]
fn to_wrapper(&self) -> ComplexWrapper {
let mut buffer = itoa::Buffer::new();
vec![vec![
ArcStr::from(buffer.format(self.id)),
self
.states
.iter()
.map(|state| match state {
logic::Static::UnInit(logic::UnInit::HighImpedance) => "Z",
logic::Static::UnInit(logic::UnInit::Unknown(_)) => "X",
logic::Static::Level(logic::Level::High) => "1",
logic::Static::Level(logic::Level::Low) => "0",
})
.join(" ")
.into(),
]]
}
}
#[cfg(test)]
mod test_sensitization {
use super::*;
#[test]
fn sensitization() {
let (sense, _, _) = crate::ast::test_parse_group::<Sensitization>(
r#"(sensitization_nand2) {
pin_names ( IN1, IN2, OUT1 );
vector ( 1, "0 0 1" );
vector ( 2, "0 X 1" );
vector ( 3, "Z 0 1" );
vector ( 4, "1 1 0" );
}"#,
);
assert_eq!(
sense.vector,
vec![
SensitizationVector {
id: 1,
states: vec![
logic::Static::Level(logic::Level::Low),
logic::Static::Level(logic::Level::Low),
logic::Static::Level(logic::Level::High),
]
},
SensitizationVector {
id: 2,
states: vec![
logic::Static::Level(logic::Level::Low),
logic::Static::UnInit(logic::UnInit::Unknown(None)),
logic::Static::Level(logic::Level::High),
]
},
SensitizationVector {
id: 3,
states: vec![
logic::Static::UnInit(logic::UnInit::HighImpedance),
logic::Static::Level(logic::Level::Low),
logic::Static::Level(logic::Level::High),
]
},
SensitizationVector {
id: 4,
states: vec![
logic::Static::Level(logic::Level::High),
logic::Static::Level(logic::Level::High),
logic::Static::Level(logic::Level::Low),
]
}
]
);
let (sense1, _, _) = crate::ast::test_parse_group::<Sensitization>(
r#"(sensitization_nand2) {
vector ( 1, "0 0 1" );
vector ( 2, "0 X 9" );
vector ( 3, "Z 0 1" );
vector ( 4, "1 1 0" );
}"#,
);
assert!(sense1.undefined.len() == 1);
}
}
impl GroupFn for Sensitization {}
#[derive(Debug, Clone, Default)]
#[mut_set::derive::item(
sort,
macro(derive(Debug, Clone,Default);)
)]
#[derive(serde::Serialize, serde::Deserialize)]
pub struct VoltageMap {
#[id]
pub name: ArcStr,
pub voltage: f64,
}
impl ComplexAttri for VoltageMap {
#[inline]
fn parse(v: &[&str]) -> Result<Self, ComplexParseError> {
let mut i = v.iter();
let name = match i.next() {
Some(&s) => ArcStr::from(s),
None => return Err(ComplexParseError::LengthDismatch),
};
let voltage = match i.next() {
Some(&s) => match s.parse() {
Ok(f) => f,
Err(e) => {
return Err(ComplexParseError::Float(
ordered_float::ParseNotNanError::ParseFloatError(e),
))
}
},
None => return Err(ComplexParseError::LengthDismatch),
};
if i.next().is_some() {
return Err(ComplexParseError::LengthDismatch);
}
Ok(Self { name, voltage })
}
#[inline]
fn to_wrapper(&self) -> ComplexWrapper {
let mut buffer = ryu::Buffer::new();
vec![vec![self.name.clone(), ArcStr::from(buffer.format(self.voltage))]]
}
}
#[derive(Debug, Clone, Default)]
#[derive(liberty_macros::Group)]
#[mut_set::derive::item(
sort,
macro(derive(Debug, Clone, Default);)
)]
#[derive(serde::Serialize, serde::Deserialize)]
pub struct InputVoltage {
#[id]
#[liberty(name)]
pub name: ArcStr,
#[liberty(comments)]
pub comments: GroupComments<Self>,
#[liberty(undefined)]
pub undefined: AttributeList,
#[liberty(simple)]
pub vil: ArcStr,
#[liberty(simple)]
pub vih: ArcStr,
#[liberty(simple)]
pub vimin: ArcStr,
#[liberty(simple)]
pub vimax: ArcStr,
}
impl GroupFn for InputVoltage {}
#[derive(Debug, Clone, Default)]
#[derive(liberty_macros::Group)]
#[mut_set::derive::item(
sort,
macro(derive(Debug, Clone, Default);)
)]
#[derive(serde::Serialize, serde::Deserialize)]
pub struct OutputVoltage {
#[id]
#[liberty(name)]
pub name: ArcStr,
#[liberty(comments)]
pub comments: GroupComments<Self>,
#[liberty(undefined)]
pub undefined: AttributeList,
#[liberty(simple)]
pub vol: ArcStr,
#[liberty(simple)]
pub voh: ArcStr,
#[liberty(simple)]
pub vomin: ArcStr,
#[liberty(simple)]
pub vomax: ArcStr,
}
impl GroupFn for OutputVoltage {}
#[derive(Debug, Clone, Copy)]
#[derive(Hash, PartialEq, Eq, Default)]
#[derive(Ord, PartialOrd)]
#[derive(strum_macros::EnumString, strum_macros::EnumIter, strum_macros::Display)]
#[derive(serde::Serialize, serde::Deserialize)]
pub enum DelayModel {
#[default]
#[strum(serialize = "table_lookup")]
TableLookup,
}
impl SimpleAttri for DelayModel {}
#[derive(Debug, Clone, derivative::Derivative)]
#[derivative(Default)]
#[derive(liberty_macros::Group)]
#[mut_set::derive::item(
sort,
macro(derive(Debug, Clone);
derive(derivative::Derivative);
derivative(Default);),
attr_filter(derivative;)
)]
#[derive(serde::Serialize, serde::Deserialize)]
pub struct OperatingConditions {
#[id]
#[liberty(name)]
pub name: ArcStr,
#[liberty(comments)]
pub comments: GroupComments<Self>,
#[liberty(undefined)]
pub undefined: AttributeList,
#[liberty(simple(type = Option))]
pub calc_mode: Option<ArcStr>,
#[liberty(simple(type = Option))]
pub parameteri: Option<f64>,
#[liberty(simple)]
pub process: f64,
#[liberty(simple(type = Option))]
pub process_label: Option<ArcStr>,
#[liberty(simple)]
pub temperature: f64,
#[liberty(simple(type = Option))]
pub tree_type: Option<TreeType>,
#[liberty(simple)]
#[derivative(Default(value = "5.0"))]
pub voltage: f64,
}
impl GroupFn for OperatingConditions {}
#[derive(Debug, Clone, Copy)]
#[derive(Hash, PartialEq, Eq)]
#[derive(Ord, PartialOrd)]
#[derive(strum_macros::EnumString, strum_macros::EnumIter, strum_macros::Display)]
#[derive(serde::Serialize, serde::Deserialize)]
pub enum TreeType {
#[strum(serialize = "best_case_tree")]
BestCaseTree,
#[strum(serialize = "balanced_tree")]
BalancedTree,
#[strum(serialize = "worst_case_tree")]
WorstCaseTree,
}
impl SimpleAttri for TreeType {}
#[derive(Debug, Clone)]
#[mut_set::derive::item(
sort,
macro(derive(Debug, Clone);)
)]
#[derive(serde::Serialize, serde::Deserialize)]
pub struct Define {
#[id]
pub attribute_name: ArcStr,
#[id]
pub group_name: ArcStr,
pub attribute_type: AttributeType,
}
#[derive(Debug, Clone, Copy)]
#[derive(Hash, PartialEq, Eq)]
#[derive(Ord, PartialOrd)]
#[derive(strum_macros::EnumString, strum_macros::EnumIter, strum_macros::Display)]
#[derive(serde::Serialize, serde::Deserialize)]
pub enum AttributeType {
#[strum(serialize = "Boolean", serialize = "boolean")]
Boolean,
#[strum(serialize = "string")]
String,
#[strum(serialize = "integer")]
Integer,
#[strum(serialize = "float")]
Float,
}
impl ComplexAttri for Define {
#[inline]
fn parse(v: &[&str]) -> Result<Self, ComplexParseError> {
let mut i = v.iter();
let attribute_name = match i.next() {
Some(&s) => ArcStr::from(s),
None => return Err(ComplexParseError::LengthDismatch),
};
let group_name = match i.next() {
Some(&s) => ArcStr::from(s),
None => return Err(ComplexParseError::LengthDismatch),
};
let attribute_type = match i.next() {
Some(&s) => match s.parse() {
Ok(f) => f,
Err(_) => return Err(ComplexParseError::UnsupportedWord),
},
None => return Err(ComplexParseError::LengthDismatch),
};
if i.next().is_some() {
return Err(ComplexParseError::LengthDismatch);
}
Ok(Self { attribute_name, group_name, attribute_type })
}
#[inline]
fn to_wrapper(&self) -> ComplexWrapper {
vec![vec![
self.attribute_name.clone(),
self.group_name.clone(),
self.attribute_type.to_string().into(),
]]
}
}
#[derive(Debug, Clone)]
#[mut_set::derive::item(
sort,
macro(derive(Debug, Clone);)
)]
#[derive(serde::Serialize, serde::Deserialize)]
pub struct DefineCellArea {
#[id]
pub area_name: ArcStr,
pub resource_type: ResourceType,
}
#[derive(Debug, Clone, Copy)]
#[derive(Hash, PartialEq, Eq)]
#[derive(Ord, PartialOrd)]
#[derive(strum_macros::EnumString, strum_macros::EnumIter, strum_macros::Display)]
#[derive(serde::Serialize, serde::Deserialize)]
pub enum ResourceType {
#[strum(serialize = "pad_slots")]
PadSlots,
#[strum(serialize = "pad_input_driver_sites")]
PadInputDriverSites,
#[strum(serialize = "pad_output_driver_sites")]
PadOutputDriverSites,
#[strum(serialize = "pad_driver_sites")]
PadDriverSites,
}
impl ComplexAttri for DefineCellArea {
#[inline]
fn parse(v: &[&str]) -> Result<Self, ComplexParseError> {
let mut i = v.iter();
let area_name = match i.next() {
Some(&s) => ArcStr::from(s),
None => return Err(ComplexParseError::LengthDismatch),
};
let resource_type = match i.next() {
Some(&s) => match s.parse() {
Ok(f) => f,
Err(_) => return Err(ComplexParseError::UnsupportedWord),
},
None => return Err(ComplexParseError::LengthDismatch),
};
if i.next().is_some() {
return Err(ComplexParseError::LengthDismatch);
}
Ok(Self { area_name, resource_type })
}
#[inline]
fn to_wrapper(&self) -> ComplexWrapper {
vec![vec![self.area_name.clone(), self.resource_type.to_string().into()]]
}
}
#[derive(Debug, Clone)]
#[mut_set::derive::item(
sort,
macro(derive(Debug, Clone);)
)]
#[derive(serde::Serialize, serde::Deserialize)]
pub struct DefineGroup {
#[id]
pub group: ArcStr,
#[id]
pub parent_name: ArcStr,
}
impl ComplexAttri for DefineGroup {
#[inline]
fn parse(v: &[&str]) -> Result<Self, ComplexParseError> {
let mut i = v.iter();
let group = match i.next() {
Some(&s) => ArcStr::from(s),
None => return Err(ComplexParseError::LengthDismatch),
};
let parent_name = match i.next() {
Some(&s) => ArcStr::from(s),
None => return Err(ComplexParseError::LengthDismatch),
};
if i.next().is_some() {
return Err(ComplexParseError::LengthDismatch);
}
Ok(Self { group, parent_name })
}
#[inline]
fn to_wrapper(&self) -> ComplexWrapper {
vec![vec![self.group.clone(), self.parent_name.clone()]]
}
}
#[derive(Debug, Clone, Default)]
#[derive(liberty_macros::Group)]
#[mut_set::derive::item(
sort,
macro(derive(Debug, Clone,Default);)
)]
#[derive(serde::Serialize, serde::Deserialize)]
pub struct WireLoad {
#[id]
#[liberty(name)]
pub name: ArcStr,
#[liberty(comments)]
pub comments: GroupComments<Self>,
#[liberty(undefined)]
pub undefined: AttributeList,
#[liberty(simple)]
pub area: f64,
#[liberty(simple)]
pub capacitance: f64,
#[liberty(simple)]
pub resistance: f64,
#[liberty(simple)]
pub slope: f64,
#[liberty(complex(type = Set))]
pub fanout_length: GroupSet<FanoutLength>,
}
impl GroupFn for WireLoad {}
#[derive(Debug, Clone, Default, Copy)]
#[mut_set::derive::item(
sort,
macro(derive(Debug, Clone, Default, Copy);)
)]
#[derive(serde::Serialize, serde::Deserialize)]
pub struct FanoutLength {
#[id]
pub fanout: u32,
pub length: f64,
pub average_capacitance: Option<f64>,
pub standard_deviation: Option<f64>,
pub number_of_nets: Option<u32>,
}
impl ComplexAttri for FanoutLength {
#[inline]
fn parse(v: &[&str]) -> Result<Self, ComplexParseError> {
let mut i = v.iter();
let fanout = match i.next() {
Some(&s) => match s.parse() {
Ok(f) => f,
Err(e) => return Err(ComplexParseError::Int(e)),
},
None => return Err(ComplexParseError::LengthDismatch),
};
let length = match i.next() {
Some(&s) => match s.parse() {
Ok(f) => f,
Err(e) => {
return Err(ComplexParseError::Float(
ordered_float::ParseNotNanError::ParseFloatError(e),
))
}
},
None => return Err(ComplexParseError::LengthDismatch),
};
let average_capacitance = i.next().and_then(|s| s.parse().ok());
let standard_deviation = i.next().and_then(|s| s.parse().ok());
let number_of_nets = i.next().and_then(|s| s.parse().ok());
if i.next().is_some() {
return Err(ComplexParseError::LengthDismatch);
}
Ok(Self {
fanout,
length,
average_capacitance,
standard_deviation,
number_of_nets,
})
}
#[inline]
fn to_wrapper(&self) -> ComplexWrapper {
let mut buffer_f = ryu::Buffer::new();
let mut buffer_i = itoa::Buffer::new();
match (self.average_capacitance, self.standard_deviation, self.number_of_nets) {
(Some(average_capacitance), Some(standard_deviation), Some(number_of_nets)) => {
vec![vec![
ArcStr::from(buffer_i.format(self.fanout)),
ArcStr::from(buffer_f.format(self.length)),
ArcStr::from(buffer_f.format(average_capacitance)),
ArcStr::from(buffer_f.format(standard_deviation)),
ArcStr::from(buffer_i.format(number_of_nets)),
]]
}
_ => {
vec![vec![
ArcStr::from(buffer_i.format(self.fanout)),
ArcStr::from(buffer_f.format(self.length)),
]]
}
}
}
}
#[derive(Debug, Clone, Default)]
#[derive(liberty_macros::Group)]
#[mut_set::derive::item(
sort,
macro(derive(Debug, Clone,Default);)
)]
#[derive(serde::Serialize, serde::Deserialize)]
pub struct WireLoadSection {
#[id]
#[liberty(name)]
pub name: ArcStr,
#[liberty(comments)]
pub comments: GroupComments<Self>,
#[liberty(undefined)]
pub undefined: AttributeList,
#[liberty(complex)]
pub wire_load_from_area: (f64, f64, ArcStr),
}
impl GroupFn for WireLoadSection {}