use crate::{
Ctx,
ast::{
Attributes, CodeFormatter, ComplexAttri, ComplexParseError, DefinedType,
GroupComments, GroupFn, GroupSet, Indentation, ParseScope, SimpleAttri,
},
common::{
items::{Formula, IdVector},
parse_f64,
},
expression::logic,
};
use core::fmt::{self, Write};
#[derive(Debug, Clone)]
#[derive(liberty_macros::Group)]
#[mut_set::derive::item]
#[derive(serde::Serialize, serde::Deserialize)]
#[serde(bound = "C::Other: serde::Serialize + serde::de::DeserializeOwned")]
pub struct Sensitization<C: Ctx> {
#[id(borrow = str)]
#[liberty(name)]
pub name: String,
#[liberty(comments)]
comments: GroupComments,
#[liberty(extra_ctx)]
pub extra_ctx: C::Other,
#[liberty(attributes)]
pub attributes: Attributes,
#[liberty(complex)]
pub pin_names: Vec<String>,
#[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>,
}
crate::ast::impl_self_builder!(SensitizationVector);
impl<C: Ctx> ComplexAttri<C> for SensitizationVector {
#[inline]
fn parse<'a, I: Iterator<Item = &'a &'a str>>(
mut iter: I,
_scope: &mut ParseScope<'_>,
) -> Result<Self, ComplexParseError> {
let id: usize = match iter.next() {
Some(&s) => lexical_core::parse(s.as_bytes())?,
None => return Err(ComplexParseError::LengthDismatch),
};
let states = match iter.next() {
Some(&s) => match s
.split_ascii_whitespace()
.map(|t| match t {
"1" => Ok(logic::Static::H),
"0" => Ok(logic::Static::L),
"X" => Ok(logic::Static::X),
"Z" => Ok(logic::Static::Z),
_ => Err(ComplexParseError::UnsupportedWord),
})
.collect::<Result<Vec<logic::Static>, _>>()
{
Ok(states) => states,
Err(_) => return Err(ComplexParseError::UnsupportedWord),
},
None => return Err(ComplexParseError::LengthDismatch),
};
if iter.next().is_some() {
return Err(ComplexParseError::LengthDismatch);
}
Ok(Self { id, states })
}
#[inline]
fn fmt_self<T: Write, I: Indentation>(
&self,
f: &mut CodeFormatter<'_, T, I>,
) -> fmt::Result {
f.write_num(self.id)?;
f.write_str(", ")?;
crate::ast::join_fmt(
self.states.iter(),
f,
|state, ff| {
write!(
ff,
"{}",
match state {
logic::Static::Z => "Z",
logic::Static::X => "X",
logic::Static::H => "1",
logic::Static::L => "0",
}
)
},
" ",
)
}
}
#[cfg(test)]
mod test_sensitization {
use super::*;
use crate::DefaultCtx;
#[test]
fn sensitization() {
let sense = crate::ast::test_parse_fmt::<Sensitization<DefaultCtx>>(
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" );
}"#,
r#"
liberty_db::library::items::Sensitization (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::L, logic::Static::L, logic::Static::H,]
},
SensitizationVector {
id: 2,
states: vec![logic::Static::L, logic::Static::X, logic::Static::H,]
},
SensitizationVector {
id: 3,
states: vec![logic::Static::Z, logic::Static::L, logic::Static::H,]
},
SensitizationVector {
id: 4,
states: vec![logic::Static::H, logic::Static::H, logic::Static::L,]
}
]
);
let sense1 = crate::ast::test_parse_fmt::<Sensitization<DefaultCtx>>(
r#"(sensitization_nand2) {
vector ( 1, "0 0 1" );
vector ( 2, "0 X 9" );
vector ( 3, "Z 0 1" );
vector ( 4, "1 1 0" );
}"#,
r#"
liberty_db::library::items::Sensitization (sensitization_nand2) {
| vector (1, "0 0 1");
| vector (3, "Z 0 1");
| vector (4, "1 1 0");
| vector (2, "0 X 9"); /* user defined attribute */
}"#,
);
assert!(sense1.attributes.len() == 1);
}
}
impl<C: Ctx> GroupFn<C> for Sensitization<C> {}
#[mut_set::derive::item]
#[derive(Debug, Clone, Default)]
#[derive(serde::Serialize, serde::Deserialize)]
pub struct VoltageMap {
#[id(borrow = str)]
pub name: String,
pub voltage: f64,
}
crate::ast::impl_self_builder!(VoltageMap);
impl<C: Ctx> ComplexAttri<C> for VoltageMap {
#[inline]
fn parse<'a, I: Iterator<Item = &'a &'a str>>(
mut iter: I,
_scope: &mut ParseScope<'_>,
) -> Result<Self, ComplexParseError> {
let name = match iter.next() {
Some(&s) => String::from(s),
None => return Err(ComplexParseError::LengthDismatch),
};
let voltage = match iter.next() {
Some(s) => parse_f64(s)?,
None => return Err(ComplexParseError::LengthDismatch),
};
if iter.next().is_some() {
return Err(ComplexParseError::LengthDismatch);
}
Ok(Self { name, voltage })
}
#[inline]
fn fmt_self<T: Write, I: Indentation>(
&self,
f: &mut CodeFormatter<'_, T, I>,
) -> fmt::Result {
write!(f, "{}, ", self.name)?;
f.write_num(self.voltage)
}
}
#[derive(Debug, Clone)]
#[derive(liberty_macros::Group)]
#[mut_set::derive::item]
#[derive(serde::Serialize, serde::Deserialize)]
#[serde(bound = "C::Other: serde::Serialize + serde::de::DeserializeOwned")]
pub struct InputVoltage<C: Ctx> {
#[id(borrow = str)]
#[liberty(name)]
pub name: String,
#[liberty(comments)]
comments: GroupComments,
#[liberty(extra_ctx)]
pub extra_ctx: C::Other,
#[liberty(attributes)]
pub attributes: Attributes,
#[liberty(simple)]
pub vil: Formula,
#[liberty(simple)]
pub vih: Formula,
#[liberty(simple)]
pub vimin: Formula,
#[liberty(simple)]
pub vimax: Formula,
}
impl<C: Ctx> GroupFn<C> for InputVoltage<C> {}
#[derive(Debug, Clone)]
#[derive(liberty_macros::Group)]
#[mut_set::derive::item]
#[derive(serde::Serialize, serde::Deserialize)]
#[serde(bound = "C::Other: serde::Serialize + serde::de::DeserializeOwned")]
pub struct OutputVoltage<C: Ctx> {
#[id(borrow = str)]
#[liberty(name)]
pub name: String,
#[liberty(comments)]
comments: GroupComments,
#[liberty(extra_ctx)]
pub extra_ctx: C::Other,
#[liberty(attributes)]
pub attributes: Attributes,
#[liberty(simple)]
pub vol: Formula,
#[liberty(simple)]
pub voh: Formula,
#[liberty(simple)]
pub vomin: Formula,
#[liberty(simple)]
pub vomax: Formula,
}
impl<C: Ctx> GroupFn<C> for OutputVoltage<C> {}
#[derive(Debug, Clone, Copy)]
#[derive(Hash, PartialEq, Eq, Default)]
#[derive(Ord, PartialOrd)]
#[derive(strum::EnumString, strum::EnumIter, strum::Display)]
#[derive(serde::Serialize, serde::Deserialize)]
pub enum DelayModel {
#[default]
#[strum(serialize = "table_lookup")]
TableLookup,
}
crate::ast::impl_self_builder!(DelayModel);
impl<C: Ctx> SimpleAttri<C> for DelayModel {
#[inline]
fn nom_parse<'a>(
i: &'a str,
scope: &mut ParseScope<'_>,
) -> crate::ast::SimpleParseRes<'a, Self> {
crate::ast::nom_parse_from_str::<C, _>(i, scope)
}
}
#[derive(Debug, Clone)]
#[derive(liberty_macros::Group)]
#[mut_set::derive::item]
#[derive(serde::Serialize, serde::Deserialize)]
#[serde(bound = "C::Other: serde::Serialize + serde::de::DeserializeOwned")]
pub struct OperatingConditions<C: Ctx> {
#[id(borrow = str)]
#[liberty(name)]
pub name: String,
#[liberty(comments)]
comments: GroupComments,
#[liberty(extra_ctx)]
pub extra_ctx: C::Other,
#[liberty(attributes)]
pub attributes: Attributes,
#[liberty(simple(type = Option))]
pub calc_mode: Option<String>,
#[liberty(simple(type = Option))]
pub parameteri: Option<f64>,
#[liberty(simple)]
pub process: f64,
#[liberty(simple(type = Option))]
pub process_label: Option<String>,
#[liberty(simple)]
pub temperature: f64,
#[liberty(simple(type = Option))]
pub tree_type: Option<TreeType>,
#[liberty(simple)]
#[liberty(default = 5.0)]
pub voltage: f64,
}
impl<C: Ctx> GroupFn<C> for OperatingConditions<C> {}
#[derive(Debug, Clone)]
#[derive(liberty_macros::Group)]
#[mut_set::derive::item]
#[derive(serde::Serialize, serde::Deserialize)]
#[serde(bound = "C::Other: serde::Serialize + serde::de::DeserializeOwned")]
pub struct FpgaIsd<C: Ctx> {
#[liberty(name)]
#[id(borrow = str)]
pub name: String,
#[liberty(comments)]
comments: GroupComments,
#[liberty(extra_ctx)]
pub extra_ctx: C::Other,
#[liberty(attributes)]
pub attributes: Attributes,
#[liberty(simple)]
pub drive: String,
#[liberty(simple)]
pub io_type: String,
#[liberty(simple(type = Option))]
pub slew: Option<FPGASlew>,
}
impl<C: Ctx> GroupFn<C> for FpgaIsd<C> {}
#[derive(Debug, Clone, Copy)]
#[derive(Hash, PartialEq, Eq)]
#[derive(Ord, PartialOrd)]
#[derive(strum::EnumString, strum::EnumIter, strum::Display)]
#[derive(serde::Serialize, serde::Deserialize)]
pub enum FPGASlew {
#[strum(serialize = "FAST")]
FAST,
#[strum(serialize = "SLOW")]
SLOW,
}
crate::ast::impl_self_builder!(FPGASlew);
impl<C: Ctx> SimpleAttri<C> for FPGASlew {
#[inline]
fn nom_parse<'a>(
i: &'a str,
scope: &mut ParseScope<'_>,
) -> crate::ast::SimpleParseRes<'a, Self> {
crate::ast::nom_parse_from_str::<C, _>(i, scope)
}
}
#[derive(Debug, Clone, Copy)]
#[derive(Hash, PartialEq, Eq)]
#[derive(Ord, PartialOrd)]
#[derive(strum::EnumString, strum::EnumIter, strum::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,
}
crate::ast::impl_self_builder!(TreeType);
impl<C: Ctx> SimpleAttri<C> for TreeType {
#[inline]
fn nom_parse<'a>(
i: &'a str,
scope: &mut ParseScope<'_>,
) -> crate::ast::SimpleParseRes<'a, Self> {
crate::ast::nom_parse_from_str::<C, _>(i, scope)
}
}
#[derive(Debug, Clone, Copy)]
#[derive(Hash, PartialEq, Eq)]
#[derive(Ord, PartialOrd)]
#[derive(strum::EnumString, strum::EnumIter, strum::Display)]
#[derive(serde::Serialize, serde::Deserialize)]
pub enum Technology {
#[strum(serialize = "cmos")]
Cmos,
}
crate::ast::impl_self_builder!(Technology);
impl<C: Ctx> ComplexAttri<C> for Technology {
#[inline]
fn parse<'a, I: Iterator<Item = &'a &'a str>>(
iter: I,
_scope: &mut ParseScope<'_>,
) -> Result<Self, ComplexParseError> {
let mut i = iter;
let v1: Self = match i.next() {
Some(&s) => s.parse()?,
None => return Err(ComplexParseError::LengthDismatch),
};
if i.next().is_some() {
return Err(ComplexParseError::LengthDismatch);
}
Ok(v1)
}
#[inline]
fn fmt_self<T: Write, I: Indentation>(
&self,
f: &mut CodeFormatter<'_, T, I>,
) -> fmt::Result {
write!(f, "{self}")
}
}
#[mut_set::derive::item]
#[derive(Debug, Clone, Default)]
#[derive(serde::Serialize, serde::Deserialize)]
pub struct Define {
#[id(borrow = str)]
pub attribute_name: String,
#[id(borrow = str)]
pub group_name: String,
pub attribute_type: AttributeType,
}
#[derive(Debug, Clone, Copy, Default)]
#[derive(Hash, PartialEq, Eq)]
#[derive(Ord, PartialOrd)]
#[derive(strum::EnumString, strum::EnumIter, strum::Display)]
#[derive(serde::Serialize, serde::Deserialize)]
pub enum AttributeType {
#[default]
#[strum(serialize = "Boolean", serialize = "boolean")]
Boolean,
#[strum(serialize = "string")]
String,
#[strum(serialize = "integer")]
Integer,
#[strum(serialize = "float")]
Float,
}
crate::ast::impl_self_builder!(Define);
impl<C: Ctx> ComplexAttri<C> for Define {
#[inline]
fn parse<'a, I: Iterator<Item = &'a &'a str>>(
mut iter: I,
scope: &mut ParseScope<'_>,
) -> Result<Self, ComplexParseError> {
let attribute_name = match iter.next() {
Some(&s) => String::from(s),
None => return Err(ComplexParseError::LengthDismatch),
};
let group_name = match iter.next() {
Some(&s) => String::from(s),
None => return Err(ComplexParseError::LengthDismatch),
};
let attribute_type = match iter.next() {
Some(&s) => s.parse()?,
None => return Err(ComplexParseError::LengthDismatch),
};
if iter.next().is_some() {
return Err(ComplexParseError::LengthDismatch);
}
let define_id = crate::ast::define_id(&scope.hasher, &group_name, &attribute_name);
_ = scope
.define_map
.insert(define_id, DefinedType::Simple(attribute_type));
Ok(Self { attribute_name, group_name, attribute_type })
}
#[inline]
fn fmt_self<T: Write, I: Indentation>(
&self,
f: &mut CodeFormatter<'_, T, I>,
) -> fmt::Result {
write!(f, "{}, {}, {}", self.attribute_name, self.group_name, self.attribute_type)
}
}
#[mut_set::derive::item]
#[derive(Debug, Clone, Default)]
#[derive(serde::Serialize, serde::Deserialize)]
pub struct DefineGroup {
#[id(borrow = str)]
pub group: String,
#[id(borrow = str)]
pub parent_name: String,
}
crate::ast::impl_self_builder!(DefineGroup);
impl<C: Ctx> ComplexAttri<C> for DefineGroup {
#[inline]
fn parse<'a, I: Iterator<Item = &'a &'a str>>(
mut iter: I,
scope: &mut ParseScope<'_>,
) -> Result<Self, ComplexParseError> {
let group = match iter.next() {
Some(&s) => String::from(s),
None => return Err(ComplexParseError::LengthDismatch),
};
let parent_name = match iter.next() {
Some(&s) => String::from(s),
None => return Err(ComplexParseError::LengthDismatch),
};
if iter.next().is_some() {
return Err(ComplexParseError::LengthDismatch);
}
let define_id = crate::ast::define_id(&scope.hasher, &parent_name, &group);
_ = scope.define_map.insert(define_id, DefinedType::Group);
Ok(Self { group, parent_name })
}
#[inline]
fn fmt_self<T: Write, I: Indentation>(
&self,
f: &mut CodeFormatter<'_, T, I>,
) -> fmt::Result {
write!(f, "{}, {}", self.group, self.parent_name)
}
}
#[mut_set::derive::item]
#[derive(Debug, Clone, Default)]
#[derive(serde::Serialize, serde::Deserialize)]
pub struct DefineCellArea {
#[id(borrow = str)]
pub area_name: String,
pub resource_type: ResourceType,
}
#[derive(Debug, Clone, Copy, Default)]
#[derive(Hash, PartialEq, Eq)]
#[derive(Ord, PartialOrd)]
#[derive(strum::EnumString, strum::EnumIter, strum::Display)]
#[derive(serde::Serialize, serde::Deserialize)]
pub enum ResourceType {
#[default]
#[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,
}
crate::ast::impl_self_builder!(DefineCellArea);
impl<C: Ctx> ComplexAttri<C> for DefineCellArea {
#[inline]
fn parse<'a, I: Iterator<Item = &'a &'a str>>(
mut iter: I,
_scope: &mut ParseScope<'_>,
) -> Result<Self, ComplexParseError> {
let area_name = match iter.next() {
Some(&s) => String::from(s),
None => return Err(ComplexParseError::LengthDismatch),
};
let resource_type = match iter.next() {
Some(&s) => match s.parse() {
Ok(f) => f,
Err(_) => return Err(ComplexParseError::UnsupportedWord),
},
None => return Err(ComplexParseError::LengthDismatch),
};
if iter.next().is_some() {
return Err(ComplexParseError::LengthDismatch);
}
Ok(Self { area_name, resource_type })
}
#[inline]
fn fmt_self<T: Write, I: Indentation>(
&self,
f: &mut CodeFormatter<'_, T, I>,
) -> fmt::Result {
write!(f, "{}, {}", self.area_name, self.resource_type)
}
}
#[derive(Debug, Clone)]
#[derive(liberty_macros::Group)]
#[mut_set::derive::item]
#[derive(serde::Serialize, serde::Deserialize)]
pub struct WireLoad<C: Ctx> {
#[id(borrow = str)]
#[liberty(name)]
pub name: String,
#[liberty(comments)]
comments: GroupComments,
#[liberty(extra_ctx)]
pub extra_ctx: C::Other,
#[liberty(attributes)]
pub attributes: Attributes,
#[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<C: Ctx> GroupFn<C> for WireLoad<C> {}
#[derive(Debug, Clone, Default, Copy)]
#[mut_set::derive::item]
#[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>,
}
crate::ast::impl_self_builder!(FanoutLength);
impl<C: Ctx> ComplexAttri<C> for FanoutLength {
#[inline]
fn parse<'a, I: Iterator<Item = &'a &'a str>>(
mut iter: I,
_scope: &mut ParseScope<'_>,
) -> Result<Self, ComplexParseError> {
let fanout = match iter.next() {
Some(&s) => lexical_core::parse(s.as_bytes())?,
None => return Err(ComplexParseError::LengthDismatch),
};
let length = match iter.next() {
Some(s) => parse_f64(s)?,
None => return Err(ComplexParseError::LengthDismatch),
};
let average_capacitance =
if let Some(s) = iter.next() { Some(parse_f64(s)?) } else { None };
let standard_deviation =
if let Some(s) = iter.next() { Some(parse_f64(s)?) } else { None };
let number_of_nets = if let Some(s) = iter.next() {
Some(lexical_core::parse(s.as_bytes())?)
} else {
None
};
if iter.next().is_some() {
return Err(ComplexParseError::LengthDismatch);
}
Ok(Self {
fanout,
length,
average_capacitance,
standard_deviation,
number_of_nets,
})
}
#[inline]
fn fmt_self<T: Write, I: Indentation>(
&self,
f: &mut CodeFormatter<'_, T, I>,
) -> fmt::Result {
f.write_num(self.fanout)?;
f.write_str(", ")?;
f.write_num(self.length)?;
if let (Some(average_capacitance), Some(standard_deviation), Some(number_of_nets)) =
(self.average_capacitance, self.standard_deviation, self.number_of_nets)
{
f.write_str(", ")?;
f.write_num(average_capacitance)?;
f.write_str(", ")?;
f.write_num(standard_deviation)?;
f.write_str(", ")?;
f.write_num(number_of_nets)?;
}
Ok(())
}
}
#[derive(Debug, Clone)]
#[derive(liberty_macros::Group)]
#[mut_set::derive::item]
#[derive(serde::Serialize, serde::Deserialize)]
pub struct WireLoadSection<C: Ctx> {
#[id(borrow = str)]
#[liberty(name)]
pub name: String,
#[liberty(comments)]
comments: GroupComments,
#[liberty(extra_ctx)]
pub extra_ctx: C::Other,
#[liberty(attributes)]
pub attributes: Attributes,
#[liberty(complex)]
pub wire_load_from_area: (f64, f64, String),
}
impl<C: Ctx> GroupFn<C> for WireLoadSection<C> {}
#[derive(Debug, Clone, Copy)]
#[derive(Hash, PartialEq, Eq)]
#[derive(Ord, PartialOrd, Default)]
#[derive(strum::EnumString, strum::EnumIter, strum::Display)]
#[derive(serde::Serialize, serde::Deserialize)]
pub enum BaseCurveType {
#[strum(serialize = "ccs_half_curve")]
#[default]
CcsHalfCurve,
#[strum(serialize = "ccs_timing_half_curve")]
CcsTimingHalfCurve,
}
crate::ast::impl_self_builder!(BaseCurveType);
impl<C: Ctx> SimpleAttri<C> for BaseCurveType {
#[inline]
fn nom_parse<'a>(
i: &'a str,
scope: &mut ParseScope<'_>,
) -> crate::ast::SimpleParseRes<'a, Self> {
crate::ast::nom_parse_from_str::<C, _>(i, scope)
}
}
#[derive(Debug, Clone)]
#[derive(liberty_macros::Group)]
#[mut_set::derive::item]
#[derive(serde::Serialize, serde::Deserialize)]
pub struct BaseCurves<C: Ctx> {
#[liberty(name)]
#[id(borrow = str)]
pub name: String,
#[liberty(comments)]
comments: GroupComments,
#[liberty(extra_ctx)]
pub extra_ctx: C::Other,
#[liberty(attributes)]
pub attributes: Attributes,
#[liberty(simple)]
pub base_curve_type: BaseCurveType,
#[liberty(complex)]
pub curve_x: Vec<f64>,
#[liberty(complex(type = Set))]
pub curve_y: GroupSet<IdVector>,
}
impl<C: Ctx> GroupFn<C> for BaseCurves<C> {}
#[cfg(test)]
mod test {
use crate::DefaultCtx;
#[test]
fn input_voltage() {
let g = crate::ast::test_parse_fmt::<super::InputVoltage<DefaultCtx>>(
r#"(cmos_schmitt) {
vil : 0.3 * VDD ;
vih : 0.7 * VDD ;
vimin : -0.5 ;
vimax : VDD + 0.5 ;
}"#,
r#"
liberty_db::library::items::InputVoltage (cmos_schmitt) {
| vil : 0.3 * VDD ;
| vih : 0.7 * VDD ;
| vimin : -0.5 ;
| vimax : VDD + 0.5 ;
}"#,
);
}
#[test]
fn base_curves() {
let g = crate::ast::test_parse_fmt::<super::BaseCurves<DefaultCtx>>(
r#"("nc_compact_ccs_curve_1") {
base_curve_type : "ccs_timing_half_curve";
curve_x("0.1000000, 0.2000000, 0.3000000, 0.4000000, 0.5000000, 0.6000000, 0.7000000, 0.8000000, 0.9000000");
curve_y(1, \
"0.9965371, 0.9930742, 0.9584770, 0.9165637, 0.8271961, 0.7425452, 0.6009643, 0.4459254, 0.2653107");
curve_y(2, \
"0.9887274, 0.9695129, 0.9443244, 0.9183546, 0.8705093, 0.8062681, 0.6984753, 0.5213233, 0.2657268");
curve_y(3, \
"0.9895478, 0.9774914, 0.9389569, 0.8934003, 0.8125975, 0.7144581, 0.5786802, 0.4298566, 0.2542494");
curve_y(4, \
"0.9944934, 0.9784088, 0.9620733, 0.9304195, 0.8888662, 0.8329558, 0.7240709, 0.5580780, 0.3037784");
curve_y(5, \
"0.9922672, 0.9664605, 0.9307680, 0.8888898, 0.8146837, 0.7076250, 0.5811826, 0.4366006, 0.2619239");
}"#,
r#"
liberty_db::library::items::BaseCurves (nc_compact_ccs_curve_1) {
| base_curve_type : ccs_timing_half_curve;
| curve_x ("0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9");
| curve_y (1, \
| | "0.9965371, 0.9930742, 0.958477, 0.9165637, 0.8271961, 0.7425452, 0.6009643, 0.4459254, 0.2653107");
| curve_y (2, \
| | "0.9887274, 0.9695129, 0.9443244, 0.9183546, 0.8705093, 0.8062681, 0.6984753, 0.5213233, 0.2657268");
| curve_y (3, \
| | "0.9895478, 0.9774914, 0.9389569, 0.8934003, 0.8125975, 0.7144581, 0.5786802, 0.4298566, 0.2542494");
| curve_y (4, \
| | "0.9944934, 0.9784088, 0.9620733, 0.9304195, 0.8888662, 0.8329558, 0.7240709, 0.558078, 0.3037784");
| curve_y (5, \
| | "0.9922672, 0.9664605, 0.930768, 0.8888898, 0.8146837, 0.707625, 0.5811826, 0.4366006, 0.2619239");
}"#,
);
}
}