diff --git a/src/kyupy/verilog.py b/src/kyupy/verilog.py index 43f5118..10cf9dd 100644 --- a/src/kyupy/verilog.py +++ b/src/kyupy/verilog.py @@ -6,7 +6,7 @@ It supports only a subset of Verilog. from collections import namedtuple -from lark import Lark, Transformer +from lark import Lark, Transformer, Tree from . import log, readtext from .circuit import Circuit, Node, Line @@ -45,7 +45,7 @@ class VerilogTransformer(Transformer): def name(args): s = args[0].value if s[0] == '\\': - s = s[1:-1] + s = s[1:].replace(' ','') return s @staticmethod @@ -99,7 +99,7 @@ class VerilogTransformer(Transformer): c.io_nodes[positions[name]] = n if sd.kind == 'input': Line(c, n, Node(c, name)) - for s1, s2 in assignments: # pass 1.5: process signal assignments + def assign_wire(s1, s2): if s1 in c.forks: assert s2 not in c.forks, 'assignment between two driven signals' Line(c, c.forks[s1], Node(c, s2)) @@ -110,6 +110,12 @@ class VerilogTransformer(Transformer): cnode = Node(c, f'__const{s2[3]}_{const_count}__', f'__const{s2[3]}__') const_count += 1 Line(c, cnode, Node(c, s1)) + for s1, s2 in assignments: # pass 1.5: process signal assignments + if isinstance(s2, Tree) and s2.data == 'concatenation': + for target, source in zip(self._signal_declarations[s1].names, s2.children): + assign_wire(target, source) + else: + assign_wire(s1, s2) for stmt in args[2:]: # pass 2: connect signals to readers if isinstance(stmt, Instantiation): for p, s in stmt.pins.items(): @@ -143,7 +149,7 @@ class VerilogTransformer(Transformer): def start(args): return args[0] if len(args) == 1 else args -GRAMMAR = """ +GRAMMAR = r""" start: (module)* module: "module" name parameters ";" (_statement)* "endmodule" parameters: "(" [ _namelist ] ")" @@ -153,16 +159,19 @@ GRAMMAR = """ inout: "inout" range? _namelist ";" tri: "tri" range? _namelist ";" wire: "wire" range? _namelist ";" - assign: "assign" name "=" name ";" + assign: "assign" lvalue "=" _expression ";" instantiation: name name "(" [ pin ( "," pin )* ] ")" ";" pin: "." name "(" name? ")" - range: "[" /[0-9]+/ ":" /[0-9]+/ "]" - + range: "[" /[0-9]+/ (":" /[0-9]+/)? "]" + ?lvalue: name range? + _expression: name | concatenation + concatenation: "{" _namelist "}" _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 ) - COMMENT: "//" /[^\\n]*/ - %ignore ( /\\r?\\n/ | COMMENT )+ - %ignore /[\\t \\f]+/ + name: ( /[a-z_][a-z0-9_\[\]]*/i | /\\[^\t \r\n]+[\t \r\n](\[[0-9]+\])?/i | /1'b0/i | /1'b1/i ) + %import common.NEWLINE + COMMENT: /\/\*(\*(?!\/)|[^*])*\*\// | /\(\*(\*(?!\))|[^*])*\*\)/ | "//" /(.)*/ NEWLINE + %ignore ( /\r?\n/ | COMMENT )+ + %ignore /[\t \f]+/ """