From df8a58f57b01df6b5031e992eb92e21488ddcdaf Mon Sep 17 00:00:00 2001 From: Stefan Holst Date: Sun, 2 Nov 2025 20:44:04 +0900 Subject: [PATCH] generate proper simprims in bench parser --- src/kyupy/bench.py | 36 +++++++++++++++++++++++++++++++++--- src/kyupy/sim.py | 5 ++++- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/src/kyupy/bench.py b/src/kyupy/bench.py index a4a514b..fb80598 100644 --- a/src/kyupy/bench.py +++ b/src/kyupy/bench.py @@ -10,7 +10,11 @@ Besides loading these benchmarks, this module is also useful for easily construc from lark import Lark, Transformer from .circuit import Circuit, Node, Line -from . import readtext +from . import readtext, batchrange + +def treeify(l, max_degree=4): + if len(l) <= max_degree: return l + return treeify([l[bo:bo+bs] for bo, bs in batchrange(len(l), max_degree)]) class BenchTransformer(Transformer): @@ -25,9 +29,35 @@ class BenchTransformer(Transformer): def interface(self, args): self.c.io_nodes.extend(args[0]) + def _cell_tree_inner(self, name, kind, inner_kind, drivers): + cell = Node(self.c, name, f'{kind}{len(drivers)}') + fork = self.c.get_or_add_fork(name) + Line(self.c, cell, fork) + for i, d in enumerate(drivers): + while isinstance(d, list) and len(d) == 1: d = d[0] + if isinstance(d, list): + d = self._cell_tree_inner(f'{name}~{i}', inner_kind, inner_kind, d) + Line(self.c, d, cell) + return fork + + def cell_tree(self, name, kind, drivers): + root_kind = kind.upper() + inner_kind = root_kind + if root_kind == 'NAND': inner_kind = 'AND' + if root_kind == 'NOR': inner_kind = 'OR' + if root_kind == 'XNOR': inner_kind = 'XOR' + return self._cell_tree_inner(name, root_kind, inner_kind, treeify(drivers)) + def assignment(self, args): - name, cell_type, drivers = args - cell = Node(self.c, str(name), str(cell_type)) + name, kind, drivers = args + if kind.upper() in ('AND', 'NAND', 'OR', 'NOR', 'XOR', 'XNOR'): + self.cell_tree(name, kind, drivers) + return + if kind.upper().startswith('BUF'): + kind = 'BUF1' + elif kind.upper().startswith('INV') or kind.upper().startswith('NOT'): + kind = 'INV1' + cell = Node(self.c, str(name), str(kind)) Line(self.c, cell, self.c.get_or_add_fork(str(name))) for d in drivers: Line(self.c, d, cell) diff --git a/src/kyupy/sim.py b/src/kyupy/sim.py index 765a394..471c0b3 100644 --- a/src/kyupy/sim.py +++ b/src/kyupy/sim.py @@ -4,6 +4,7 @@ from bisect import bisect, insort_left import numpy as np +from . import log from .circuit import Circuit BUF1 = np.uint16(0b1010_1010_1010_1010) @@ -199,6 +200,8 @@ class SimOps: for l in level_lines: n = l.driver + if len(n.ins) > 4: + log.warn(f'too many input pins: {n}') in_idxs = [n.ins[x].index if len(n.ins) > x and n.ins[x] is not None else self.zero_idx for x in [0,1,2,3]] if n in ppio2idx: in_idxs[0] = self.ppi_offset + ppio2idx[n] @@ -223,7 +226,7 @@ class SimOps: sp = prims[2] break if sp is None: - print('unknown cell type', kind) + log.warn(f'ignored cell of unknown type: {n}') else: level_ops.append((sp, l.index, *in_idxs, *a_ctrl[l]))