logiclib/
builder.rs

1//! The builder implementation.
2
3use 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    /// Build the logic library from a parsed liberty library.
13    pub fn from(liberty: &Liberty) -> LogicLib {
14        // deduplicate same logic cell in different library.
15        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        // calculate the flattened truth table size and offset
25        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        // compute and put the truth table entries
36        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        // completed.
44        LogicLib {
45            logic_cells: logic_cells.into_iter()
46                .map(|(name, (_, lc, _))| (name, lc)).collect(),
47            truthtable
48        }
49    }
50}
51
52impl LogicCell {
53    // Build the basic pin structure, and compute the truth table size.
54    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    // Fill in the table items.
87    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        // sort inputs by alphabetical order for simplicity
145        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        // two stages.
168        // includes very heavy constant index calculations,
169        // 4, 6; 5, 7; ...
170        // modify them with care.
171
172        // map rf sensitivity to non-u base
173        fn map_rf_nu_base(rf: bool) -> usize {
174            match rf { true => 6, false => 4 }
175        }
176        // map rf to base with u
177        fn map_rf_u_base(rf: bool) -> usize {
178            match rf { true => 7, false => 5 }
179        }
180        // map non-u base to logic value
181        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        // map u base to logic value.
189        // guaranteed to be a trivial one.
190        fn map_u_val(v: usize) -> LogicVal {
191            (v as u8).try_into().unwrap()
192        }
193        // map logic value to u base.
194        // guaranteed to be a trivial one.
195        fn map_val_u(lv: LogicVal) -> usize {
196            lv as u8 as usize
197        }
198        
199        // stage 1: calculate all non-U table items
200        // note our little-endian encoding. the related inputs
201        // reside in the lower part of encoding.
202        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        // `s` is a simplified encoding that does not have U's.
211        for s in 0..set_size {
212            // dump s (set index) into bits (b)
213            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            // load b into t (table index)
225            // note the reversed index: important for our
226            // little-endian encoding.
227            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; // table index computed.
234            // compute expr, with seq or not
235            match (seq, seq_int) {
236                (None, None) => {
237                    // directly evaluate a pure combinational
238                    // logic expression.
239                    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                    // evaluate sequential element to get
251                    // new internals.
252                    // (the sequential evaluation might call
253                    // other combinational evaluations inside.)
254                    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                    // evaluate pin function given inputs
268                    // and the determined new internals.
269                    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                                // use new internals.
277                                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        // stage 2: use a bitmask DP to calculate U's.
291        // s_u: masked (undetermined) positions
292        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                // transfrom s into a bit representation s_bit.
315                // non-first-u are U's.
316                // first-u is 0.
317                // others are assigned with their proper value.
318                let mut t = s;
319                // initialize with all internals.
320                // the orders do not matter.
321                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                        // do nothing
331                    }
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                // check if all assignments are equal to
343                // the L assignment (0).
344                // if yes, we propagate the L assigns (can be Us).
345                // if no, we give up and fill in Us.
346                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}