1use libertyparse::{ Liberty, Cell, Pin, PinDirection, SequentialDef };
4use ulib::UVec;
5use compact_str::CompactString;
6use indexmap::{ IndexMap, IndexSet };
7use super::{ LogicVal, LogicLib, LogicCell, LogicOutputPin };
8use super::{ combinational, sequential };
9use sequential::SequentialInterface;
10
11impl LogicLib {
12 pub fn from(liberty: &Liberty) -> LogicLib {
14 let cell_refs: IndexMap<&CompactString, &Cell> = liberty.libs.iter()
16 .map(|(_, lib)| lib.cells.iter().map(|(n, p)| (n, p)))
17 .flatten().collect();
18
19 let mut logic_cells = cell_refs.into_iter().map(|(name, cell)| {
20 let (logic_cell, seq) = LogicCell::build_pin_sizes(cell);
21 (name.clone(), (cell, logic_cell, seq))
22 }).collect::<Vec<_>>();
23
24 let mut truthtable_size = 0;
26 for (_, (_, lc, _)) in &mut logic_cells {
27 for (_, pin) in &mut lc.output_pins {
28 if let Ok(pin) = pin {
29 pin.table_start = truthtable_size;
30 truthtable_size += pin.table_size;
31 }
32 }
33 }
34
35 let mut truthtable = UVec::new_zeroed(truthtable_size,
37 ulib::Device::CPU);
38 let tt_ref = truthtable.as_mut();
39 for (_, (c, lc, seq)) in &logic_cells {
40 lc.build_pin_table(c, seq.as_ref(), tt_ref);
41 }
42
43 LogicLib {
45 logic_cells: logic_cells.into_iter()
46 .map(|(name, (_, lc, _))| (name, lc)).collect(),
47 truthtable
48 }
49 }
50}
51
52impl LogicCell {
53 fn build_pin_sizes(
55 cell: &Cell
56 ) -> (LogicCell, Option<SequentialInterface>) {
57 let inputs = cell.pins.iter().filter_map(|(n, p)| {
58 match p.direction {
59 PinDirection::I => Some(n),
60 _ => None
61 }
62 }).collect();
63 let seq = match &cell.sequential_def {
64 None => None,
65 Some(seq) => Some(SequentialInterface::from(seq))
66 };
67 (LogicCell {
68 output_pins: cell.pins.iter().filter_map(|(n, p)| {
69 match p.direction {
70 PinDirection::I => None,
71 PinDirection::O => Some((
72 n.clone(),
73 LogicOutputPin::build_size(
74 &inputs, seq.as_ref(), p)
75 )),
76 _ => Some((
77 n.clone(),
78 Err("unknown pin direction in liberty def")
79 ))
80 }
81 }).collect()
82 },
83 seq)
84 }
85
86 fn build_pin_table(
88 &self,
89 cell: &Cell,
90 seq: Option<&SequentialInterface>,
91 tab: &mut [LogicVal]
92 ) {
93 for (n, pin) in &cell.pins {
94 if let Some(Ok(lp)) = self.output_pins.get(n) {
95 lp.build_table(
96 pin,
97 cell.sequential_def.as_ref(),
98 seq,
99 &mut tab[
100 lp.table_start..
101 lp.table_start + lp.table_size]);
102 }
103 }
104 }
105}
106
107impl LogicOutputPin {
108 fn build_size(
109 all_cell_inputs: &IndexSet<&CompactString>,
110 seq_int: Option<&SequentialInterface>,
111 pin: &Pin
112 ) -> Result<LogicOutputPin, &'static str> {
113 let expr = match &pin.function {
114 Some(expr) => expr,
115 None => return Err("No function field in liberty")
116 };
117 let mut related_inputs = IndexMap::new();
118 let mut has_internal = false;
119 for name in combinational::all_idents(expr) {
120 if all_cell_inputs.contains(name) {
121 related_inputs.insert(name.clone(), false);
122 continue;
123 }
124 if let Some(seq_int) = seq_int {
125 if seq_int.internals.contains(name) {
126 has_internal = true;
127 continue;
128 }
129 }
130 clilog::error!(
131 LOGICLIB_FUNC_BADREF,
132 "Parsing logiclib: bad reference {}",
133 name);
134 return Err("Bad function reference")
135 }
136 let num_internals = if has_internal {
137 let seq_int = seq_int.unwrap();
138 for (name, rf_sens) in &seq_int.inputs {
139 related_inputs.insert((*name).clone(), *rf_sens);
140 }
141 seq_int.internals.len()
142 }
143 else { 0 };
144 related_inputs.sort_keys();
146
147 let table_size = related_inputs.iter()
148 .map(|(_, rf_s)| match rf_s { true => 7, false => 5 })
149 .product::<usize>()
150 * 4usize.pow(num_internals as u32) * (num_internals + 1);
151 Ok(LogicOutputPin {
152 related_inputs,
153 num_internals: num_internals.try_into().unwrap(),
154 table_size,
155 table_start: usize::MAX
156 })
157 }
158
159 fn build_table(
160 &self,
161 pin: &Pin,
162 seq: Option<&SequentialDef>,
163 seq_int: Option<&SequentialInterface>,
164 tab: &mut [LogicVal]
165 ) {
166 use LogicVal::*;
167 fn map_rf_nu_base(rf: bool) -> usize {
174 match rf { true => 6, false => 4 }
175 }
176 fn map_rf_u_base(rf: bool) -> usize {
178 match rf { true => 7, false => 5 }
179 }
180 fn map_nu_val(v: usize) -> LogicVal {
182 match v {
183 0 => L, 1 => H, 2 => X, 3 => Z,
184 4 => R, 5 => F,
185 _ => unreachable!()
186 }
187 }
188 fn map_u_val(v: usize) -> LogicVal {
191 (v as u8).try_into().unwrap()
192 }
193 fn map_val_u(lv: LogicVal) -> usize {
196 lv as u8 as usize
197 }
198
199 assert_eq!(tab.len(), self.table_size);
203 let internals_mul = 4usize.pow(self.num_internals as u32);
204 let set_size = self.related_inputs.iter()
205 .map(|(_, rf_s)| map_rf_nu_base(*rf_s))
206 .product::<usize>() * internals_mul;
207 let n_inputs = self.related_inputs.len();
208 let n_internals = self.num_internals as usize;
209 let mut b = vec![U; n_inputs + n_internals];
210 for s in 0..set_size {
212 let mut t = s;
214 for (i, (_, rf)) in self.related_inputs.iter().enumerate() {
215 let base = map_rf_nu_base(*rf);
216 b[i] = map_nu_val(t % base);
217 t /= base;
218 }
219 for i in 0..n_internals {
220 b[n_inputs + i] = map_nu_val(t % 4);
221 t /= 4;
222 }
223 assert_eq!(t, 0);
224 for i in (0..n_internals).rev() {
228 t = t * 4 + map_val_u(b[n_inputs + i]);
229 }
230 for (i, (_, rf)) in self.related_inputs.iter().enumerate().rev() {
231 t = t * map_rf_u_base(*rf) + map_val_u(b[i]);
232 }
233 let t = t; match (seq, seq_int) {
236 (None, None) => {
237 tab[t] = combinational::eval(
240 pin.function.as_ref().unwrap(),
241 &|name| {
242 b[self.related_inputs
243 .get_index_of(name).unwrap()]
244 },
245 false
246 );
247 }
248 (Some(seq), Some(seq_int)) => {
249 let tab_start = t * (n_internals + 1);
250 sequential::eval(
255 seq,
256 seq_int,
257 &|name| {
258 b[match self.related_inputs
259 .get_index_of(name) {
260 Some(i) => i,
261 None => n_inputs + seq_int.internals
262 .get_index_of(name).unwrap()
263 }]
264 },
265 &mut tab[tab_start + 1..tab_start + n_internals + 1]
266 );
267 tab[tab_start] = combinational::eval(
270 pin.function.as_ref().unwrap(),
271 &|name| {
272 match self.related_inputs
273 .get_index_of(name)
274 {
275 Some(i) => b[i],
276 None => tab[
278 tab_start + 1 + seq_int.internals
279 .get_index_of(name)
280 .unwrap()]
281 }
282 },
283 false
284 );
285 }
286 _ => panic!()
287 }
288 }
289
290 for s_u in 1..(1 << n_inputs) {
293 let first_u = (0..n_inputs)
294 .filter(|i| (s_u >> i & 1) != 0)
295 .next().unwrap();
296 let set_size = self.related_inputs.iter()
297 .enumerate()
298 .map(|(i, (_, rf_s))| {
299 if (s_u >> i & 1) != 0 { 1 }
300 else { map_rf_nu_base(*rf_s) }
301 })
302 .product::<usize>() * internals_mul;
303 let first_u_base = map_rf_u_base(
304 *self.related_inputs
305 .get_index(first_u).unwrap().1
306 );
307 let first_u_skip = self.related_inputs.iter()
308 .enumerate()
309 .take_while(|(i, _)| *i < first_u)
310 .map(|(_, (_, rf_s))| map_rf_u_base(*rf_s))
311 .product::<usize>();
312
313 for s in 0..set_size {
314 let mut t = s;
319 let mut s_bit = t % internals_mul;
322 t /= internals_mul;
323 for (i, (_, rf_s)) in self.related_inputs
324 .iter().enumerate().rev()
325 {
326 let s_bit_base = map_rf_u_base(*rf_s);
327 let s_base = map_rf_nu_base(*rf_s);
328 s_bit *= s_bit_base;
329 if i == first_u {
330 }
332 else if (s_u >> i & 1) != 0 {
333 s_bit += map_val_u(U);
334 }
335 else {
336 s_bit += map_val_u(map_nu_val(t % s_base));
337 t /= s_base;
338 }
339 }
340 assert_eq!(t, 0);
341
342 let mut all_eq = true;
347 let gslice = |s_bit: usize| -> std::ops::Range<usize> {
348 s_bit * (n_internals + 1)..
349 (s_bit + 1) * (n_internals + 1)
350 };
351 for first_to in 1..first_u_base {
352 if map_u_val(first_to) == U { continue }
353 let s_bit_first_to = s_bit +
354 first_to * first_u_skip;
355 if tab[gslice(s_bit)] != tab[gslice(s_bit_first_to)] {
356 all_eq = false;
357 break;
358 }
359 }
360 let s_bit_first_u = s_bit + map_val_u(U) * first_u_skip;
361 if all_eq {
362 tab.copy_within(gslice(s_bit), gslice(s_bit_first_u).start);
363 }
364 else {
365 tab[gslice(s_bit_first_u)].fill(U);
366 }
367 }
368 }
369 }
370}