1use compact_str::CompactString;
6use indexmap::{IndexMap, IndexSet};
7use std::ops::Range;
8
9#[derive(Default, Debug)]
12pub struct Liberty {
13 pub libs: Vec<(CompactString, Lib)>,
14}
15
16#[derive(Debug)]
22#[allow(dead_code)]
23#[readonly::make]
24pub struct Unparsed {
25 pub reason: &'static str,
27 pub keyword: CompactString,
29 pub span: Range<usize>
31}
32
33#[derive(Debug)]
37pub struct Lib {
38 pub cells: Vec<(CompactString, Cell)>,
40 pub units: Units,
47 pub lut_templates: IndexMap<CompactString, LUTTemplate>,
52 pub default_input_pin_cap: f32,
57 pub default_output_pin_cap: f32,
62 pub slew_derate: f32,
66 pub input_delay_threshold: [f32; 2],
70 pub output_delay_threshold: [f32; 2],
74 pub slew_threshold: [(f32, f32); 2],
78 pub unparsed: Vec<Unparsed>,
80}
81
82#[derive(Default, Debug)]
85pub struct Cell {
86 pub pins: Vec<(CompactString, Pin)>,
88 pub sequential_def: Option<SequentialDef>,
90 pub unparsed: Vec<Unparsed>,
92}
93
94#[derive(Debug)]
97pub enum SequentialDef {
98 FF(FFDef),
99 Latch(LatchDef),
100 StateTable(StateTableDef)
101}
102
103#[derive(Debug)]
104pub struct FFDef {
105 pub pin_v1: CompactString,
106 pub pin_v2: CompactString,
107 pub clocked_on: LogicExpr,
108 pub next_state: LogicExpr,
109 pub clear: Option<LogicExpr>,
110 pub preset: Option<LogicExpr>,
111 pub clear_preset_var1: Option<ClearPresetVar>,
112 pub clear_preset_var2: Option<ClearPresetVar>
113}
114
115#[derive(Debug)]
116pub struct LatchDef {
117 pub pin_v1: CompactString,
118 pub pin_v2: CompactString,
119 pub enable: Option<LogicExpr>, pub data_in: Option<LogicExpr>, pub clear: Option<LogicExpr>,
122 pub preset: Option<LogicExpr>,
123 pub clear_preset_var1: Option<ClearPresetVar>,
124 pub clear_preset_var2: Option<ClearPresetVar>
125}
126
127#[derive(Debug, Copy, Clone, PartialEq, Eq)]
129pub enum ClearPresetVar {
130 L, H, N, T, X
131}
132
133#[derive(Debug)]
134pub struct StateTableDef {
135 pub inputs: Vec<CompactString>,
136 pub internals: Vec<CompactString>,
137 pub rows: Vec<Vec<StateTableValue>>
138}
139
140#[derive(Debug, Copy, Clone, PartialEq, Eq)]
146pub enum StateTableValue {
147 L, H, N, X, LH, HL, R, F, NR, NF
148}
149
150#[derive(Debug, Clone)]
151pub struct LogicExpr {
152 pub compiled: Vec<LogicExprInst>
155}
156
157#[derive(Debug, Clone)]
163pub enum LogicExprInst {
164 PushVar(CompactString),
166 PushConst(bool),
168 Op(u8)
170}
171
172#[derive(Debug)]
175pub struct Pin {
176 pub direction: PinDirection,
178 pub function: Option<LogicExpr>,
180 pub cap_rf: [f32; 2],
182 pub timings: Vec<Timing>,
184 pub unparsed: Vec<Unparsed>,
186}
187
188#[derive(Debug)]
191pub struct Timing {
192 pub related_pin: CompactString,
194 pub typ: TimingType,
196 pub sense: TimingSense,
198 pub cell_rise: Option<LUT>,
199 pub cell_fall: Option<LUT>,
200 pub rise_transition: Option<LUT>,
201 pub fall_transition: Option<LUT>,
202 pub rise_constraint: Option<LUT>,
203 pub fall_constraint: Option<LUT>,
204 pub unparsed: Vec<Unparsed>,
206}
207
208#[derive(Debug, PartialEq, Eq, Copy, Clone)]
209pub enum LUTVariable {
210 Empty,
211 InputNetTransition,
212 TotalOutputNetCapacitance,
213 ConstrainedPinTransition,
214 RelatedPinTransition
215}
216
217#[derive(Debug)]
221pub struct LUTTemplate {
222 pub variables: [LUTVariable; 3],
223 pub units: [f32; 3],
224 pub indices: [Vec<f32>; 3],
225}
226
227#[derive(Debug)]
234pub struct LUT {
235 pub template: CompactString,
238 pub indices: [Vec<f32>; 3],
242 pub values: Vec<f32>,
244 pub values_unit: f32,
248}
249
250#[derive(Debug, PartialEq, Eq, Clone)]
251pub enum TimingType {
252 Combinational,
253 RisingEdge,
254 FallingEdge,
255 SetupRising,
256 HoldRising,
257 SetupFalling,
258 HoldFalling,
259 Unsupported(CompactString)
260}
261
262#[derive(Debug, PartialEq, Eq, Copy, Clone)]
263pub enum TimingSense {
264 PositiveUnate,
265 NegativeUnate,
266 NonUnate
267}
268
269#[derive(Debug, PartialEq, Eq, Clone)]
270pub enum PinDirection {
271 I, O,
272 Unsupported(CompactString),
273 Unspecified
274}
275
276#[derive(Debug)]
278pub struct Units {
279 pub time: f32,
280 pub voltage: f32,
281 pub current: f32,
282 pub power: f32,
283 pub cap: f32,
284 pub res: f32,
285}
286
287mod libertypest;
288
289impl Liberty {
290 pub fn parse_str(s: &str) -> Result<Liberty, String> {
292 libertypest::parse_liberty(s)
293 }
294
295 pub fn debug_report_unparsed(&self) -> (
297 IndexSet<&str>, IndexSet<&str>, IndexSet<&str>, IndexSet<&str>
298 ) {
299 let libwise = self.libs.iter()
300 .map(|(_, lib)| lib.unparsed.iter().map(|u| u.keyword.as_str()))
301 .flatten().collect::<IndexSet<&str>>();
302 if libwise.len() != 0 {
303 clilog::warn!(
304 W_LIB_UNPARSE, "{} unparsed library-wise items: {:?}",
305 libwise.len(), libwise);
306 }
307
308 let cellwise = self.libs.iter().map(
309 |(_, lib)| lib.cells.iter().map(|(_, c)| c.unparsed.iter().map(|u| u.keyword.as_str()))
310 .flatten()).flatten().collect::<IndexSet<&str>>();
311 if cellwise.len() != 0 {
312 clilog::warn!(
313 W_LIB_UNPARSE, "{} unparsed cell-wise items: {:?}",
314 cellwise.len(), cellwise);
315 }
316
317 let pinwise = self.libs.iter().map(
318 |(_, lib)| lib.cells.iter().map(
319 |(_, c)| c.pins.iter().map(|(_, p)| p.unparsed.iter().map(|u| u.keyword.as_str()))
320 .flatten()).flatten()).flatten().collect::<IndexSet<&str>>();
321 if pinwise.len() != 0 {
322 clilog::warn!(
323 W_LIB_UNPARSE, "{} unparsed pin-wise items: {:?}",
324 pinwise.len(), pinwise);
325 }
326
327 let timingwise = self.libs.iter().map(
328 |(_, lib)| lib.cells.iter().map(
329 |(_, c)| c.pins.iter().map(
330 |(_, p)| p.timings.iter().map(
331 |t| t.unparsed.iter().map(|u| u.keyword.as_str()))
332 .flatten()).flatten()).flatten()).flatten()
333 .collect::<IndexSet<&str>>();
334 if timingwise.len() != 0 {
335 clilog::warn!(
336 W_LIB_UNPARSE, "{} unparsed timing-wise items: {:?}",
337 timingwise.len(), timingwise);
338 }
339
340 (libwise, cellwise, pinwise, timingwise)
341 }
342}
343
344mod fmt;
345
346#[cfg(feature = "direction_provider")]
348mod direction_provider;
349#[cfg(feature = "direction_provider")]
350pub use direction_provider::LibDirectionProvider;
351