Browse Source

support concat, bus select, ISOL cells

devel
Stefan Holst 1 year ago
parent
commit
f8bf579be2
  1. 4
      src/kyupy/techlib.py
  2. 56
      src/kyupy/verilog.py
  3. 41
      tests/test_verilog.py

4
src/kyupy/techlib.py

@ -47,7 +47,9 @@ class TechLib:
('SDFF', ('QN',), 1), ('SDFF', ('QN',), 1),
('SDFF', ('CLK',), 3), ('SDFF', ('CLK',), 3),
('SDFF', ('RSTB', 'RN'), 4), ('SDFF', ('RSTB', 'RN'), 4),
('SDFF', ('SETB',), 5)]: ('SDFF', ('SETB',), 5),
('ISOL', ('ISO',), 0),
('ISOL', ('D',), 1)]:
if kind.startswith(prefix) and pin in pins: return index if kind.startswith(prefix) and pin in pins: return index
for index, pins in enumerate([('A1', 'IN1', 'A', 'S', 'INP', 'I', 'Q', 'QN', 'Y', 'Z', 'ZN'), for index, pins in enumerate([('A1', 'IN1', 'A', 'S', 'INP', 'I', 'Q', 'QN', 'Y', 'Z', 'ZN'),
('A2', 'IN2', 'B', 'CK', 'CLK', 'CO', 'SE'), ('A2', 'IN2', 'B', 'CK', 'CLK', 'CO', 'SE'),

56
src/kyupy/verilog.py

@ -44,9 +44,7 @@ class VerilogTransformer(Transformer):
@staticmethod @staticmethod
def name(args): def name(args):
s = args[0].value s = args[0].value
if s[0] == '\\': return s[1:-1] if s[0] == '\\' else s
s = s[1:].replace(' ','')
return s
@staticmethod @staticmethod
def instantiation(args): def instantiation(args):
@ -56,9 +54,25 @@ class VerilogTransformer(Transformer):
def range(self, args): def range(self, args):
left = int(args[0].value) left = int(args[0].value)
right = int(args[1].value) right = int(args[1].value) if len(args) > 1 else left
return range(left, right+1) if left <= right else range(left, right-1, -1) return range(left, right+1) if left <= right else range(left, right-1, -1)
def sigsel(self, args):
if len(args) > 1 and isinstance(args[1], range):
l = [f'{args[0]}[{i}]' for i in args[1]]
return l if len(l) > 1 else l[0]
else:
return args[0]
def concat(self, args):
sigs = []
for a in args:
if isinstance(a, list):
sigs += a
else:
sigs.append(a)
return sigs
def declaration(self, kind, args): def declaration(self, kind, args):
rnge = None rnge = None
if isinstance(args[0], range): if isinstance(args[0], range):
@ -110,12 +124,23 @@ class VerilogTransformer(Transformer):
cnode = Node(c, f'__const{s2[3]}_{const_count}__', f'__const{s2[3]}__') cnode = Node(c, f'__const{s2[3]}_{const_count}__', f'__const{s2[3]}__')
const_count += 1 const_count += 1
Line(c, cnode, Node(c, s1)) Line(c, cnode, Node(c, s1))
for s1, s2 in assignments: # pass 1.5: process signal assignments for target, source in assignments: # pass 1.5: process signal assignments
if isinstance(s2, Tree) and s2.data == 'concatenation': target_sigs = []
for target, source in zip(self._signal_declarations[s1].names, s2.children): if not isinstance(target, list): target = [target]
assign_wire(target, source) for s in target:
else: if s in self._signal_declarations:
assign_wire(s1, s2) target_sigs += self._signal_declarations[s].names
else:
target_sigs.append(s)
source_sigs = []
if not isinstance(source, list): source = [source]
for s in source:
if s in self._signal_declarations:
source_sigs += self._signal_declarations[s].names
else:
source_sigs.append(s)
for t, s in zip(target_sigs, source_sigs):
assign_wire(t, s)
for stmt in args[2:]: # pass 2: connect signals to readers for stmt in args[2:]: # pass 2: connect signals to readers
if isinstance(stmt, Instantiation): if isinstance(stmt, Instantiation):
for p, s in stmt.pins.items(): for p, s in stmt.pins.items():
@ -159,15 +184,14 @@ GRAMMAR = r"""
inout: "inout" range? _namelist ";" inout: "inout" range? _namelist ";"
tri: "tri" range? _namelist ";" tri: "tri" range? _namelist ";"
wire: "wire" range? _namelist ";" wire: "wire" range? _namelist ";"
assign: "assign" lvalue "=" _expression ";" assign: "assign" sigsel "=" sigsel ";"
instantiation: name name "(" [ pin ( "," pin )* ] ")" ";" instantiation: name name "(" [ pin ( "," pin )* ] ")" ";"
pin: "." name "(" name? ")" pin: "." name "(" sigsel? ")"
range: "[" /[0-9]+/ (":" /[0-9]+/)? "]" range: "[" /[0-9]+/ (":" /[0-9]+/)? "]"
?lvalue: name range? sigsel: name range? | concat
_expression: name | concatenation concat: "{" sigsel ( "," sigsel )* "}"
concatenation: "{" _namelist "}"
_namelist: name ( "," name )* _namelist: name ( "," name )*
name: ( /[a-z_][a-z0-9_\[\]]*/i | /\\[^\t \r\n]+[\t \r\n](\[[0-9]+\])?/i | /1'b0/i | /1'b1/i ) name: ( /[a-z_][a-z0-9_]*/i | /\\[^\t \r\n]+[\t \r\n]/i | /1'b0/i | /1'b1/i )
%import common.NEWLINE %import common.NEWLINE
COMMENT: /\/\*(\*(?!\/)|[^*])*\*\// | /\(\*(\*(?!\))|[^*])*\*\)/ | "//" /(.)*/ NEWLINE COMMENT: /\/\*(\*(?!\/)|[^*])*\*\// | /\(\*(\*(?!\))|[^*])*\*\)/ | "//" /(.)*/ NEWLINE
%ignore ( /\r?\n/ | COMMENT )+ %ignore ( /\r?\n/ | COMMENT )+

41
tests/test_verilog.py

@ -3,6 +3,43 @@ from kyupy import verilog
def test_b01(mydir): def test_b01(mydir):
with open(mydir / 'b01.v', 'r') as f: with open(mydir / 'b01.v', 'r') as f:
modules = verilog.parse(f.read()) c = verilog.parse(f.read())
assert modules is not None assert c is not None
assert verilog.load(mydir / 'b01.v') is not None assert verilog.load(mydir / 'b01.v') is not None
assert len(c.nodes) == 139
assert len(c.lines) == 203
stats = c.stats
assert stats['input'] == 6
assert stats['output'] == 3
assert stats['__seq__'] == 5
def test_b15(mydir):
c = verilog.load(mydir / 'b15_4ig.v.gz')
assert len(c.nodes) == 12067
assert len(c.lines) == 20731
stats = c.stats
assert stats['input'] == 40
assert stats['output'] == 71
assert stats['__seq__'] == 417
def test_gates(mydir):
c = verilog.load(mydir / 'gates.v')
assert len(c.nodes) == 10
assert len(c.lines) == 10
stats = c.stats
assert stats['input'] == 2
assert stats['output'] == 2
assert stats['__seq__'] == 0
def test_halton2(mydir):
c = verilog.load(mydir / 'rng_haltonBase2.synth_yosys.v')
assert len(c.nodes) == 146
assert len(c.lines) == 210
stats = c.stats
assert stats['input'] == 2
assert stats['output'] == 12
assert stats['__seq__'] == 12
Loading…
Cancel
Save