diff --git a/src/kyupy/verilog.py b/src/kyupy/verilog.py index 687435e..9336459 100644 --- a/src/kyupy/verilog.py +++ b/src/kyupy/verilog.py @@ -65,6 +65,16 @@ class VerilogTransformer(Transformer): 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] + elif "'" in args[0]: + width, rest = args[0].split("'") + width = int(width) + base, const = rest[0], rest[1:] + const = int(const, {'b': 2, 'd':10, 'h':16}[base.lower()]) + l = [] + for _ in range(width): + l.insert(0, "1'b1" if (const & 1) else "1'b0") + const >>= 1 + return l if len(l) > 1 else l[0] else: return args[0] @@ -82,20 +92,24 @@ class VerilogTransformer(Transformer): if isinstance(args[0], range): rnge = args[0] args = args[1:] - for sd in [SignalDeclaration(kind, signal, rnge) for signal in args]: - if kind != 'wire' or sd.basename not in self._signal_declarations: - self._signal_declarations[sd.basename] = sd + return [SignalDeclaration(kind, signal, rnge) for signal in args] - def input(self, args): self.declaration("input", args) - def output(self, args): self.declaration("output", args) - def inout(self, args): self.declaration("input", args) # just treat as input - def wire(self, args): self.declaration("wire", args) + def input(self, args): return self.declaration("input", args) + def output(self, args): return self.declaration("output", args) + def inout(self, args): return self.declaration("input", args) # just treat as input + def wire(self, args): return self.declaration("wire", args) def module(self, args): c = Circuit(args[0]) positions = {} pos = 0 const_count = 0 + self._signal_declarations = {} + for decls in args[2:]: # pass 0: collect signal declarations + if isinstance(decls, list): + if len(decls) > 0 and isinstance(decls[0], SignalDeclaration): + for decl in decls: + self._signal_declarations[decl.basename] = decl for intf_sig in args[1].children: for name in self._signal_declarations[intf_sig].names: positions[name] = pos @@ -107,7 +121,7 @@ class VerilogTransformer(Transformer): for p, s in stmt.pins.items(): if self.tlib.pin_is_output(n.kind, p): Line(c, (n, self.tlib.pin_index(stmt.type, p)), Node(c, s)) - elif stmt is not None and stmt.data == 'assign': + elif hasattr(stmt, 'data') and stmt.data == 'assign': assignments.append((stmt.children[0], stmt.children[1])) for sd in self._signal_declarations.values(): if sd.kind == 'output' or sd.kind == 'input': @@ -117,17 +131,6 @@ class VerilogTransformer(Transformer): c.io_nodes[positions[name]] = n if sd.kind == 'input': Line(c, n, Node(c, name)) - 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)) - elif s2 in c.forks: - assert s1 not in c.forks, 'assignment between two driven signals' - Line(c, c.forks[s2], Node(c, s1)) - elif s2.startswith("1'b"): - cnode = Node(c, f'__const{s2[3]}_{const_count}__', f'__const{s2[3]}__') - const_count += 1 - Line(c, cnode, Node(c, s1)) for target, source in assignments: # pass 1.5: process signal assignments target_sigs = [] if not isinstance(target, list): target = [target] @@ -144,7 +147,16 @@ class VerilogTransformer(Transformer): else: source_sigs.append(s) for t, s in zip(target_sigs, source_sigs): - assign_wire(t, s) + if t in c.forks: + assert s not in c.forks, 'assignment between two driven signals' + Line(c, c.forks[t], Node(c, s)) + elif s in c.forks: + assert t not in c.forks, 'assignment between two driven signals' + Line(c, c.forks[s], Node(c, t)) + elif s.startswith("1'b"): + cnode = Node(c, f'__const{s[3]}_{const_count}__', f'__const{s[3]}__') + const_count += 1 + Line(c, cnode, Node(c, t)) for stmt in args[2:]: # pass 2: connect signals to readers if isinstance(stmt, Instantiation): for p, s in stmt.pins.items(): @@ -195,7 +207,7 @@ GRAMMAR = r""" sigsel: name range? | concat concat: "{" sigsel ( "," sigsel )* "}" _namelist: name ( "," name )* - name: ( /[a-z_][a-z0-9_]*/i | /\\[^\t \r\n]+[\t \r\n]/i | /1'b0/i | /1'b1/i ) + name: ( /[a-z_][a-z0-9_]*/i | /\\[^\t \r\n]+[\t \r\n]/i | /[0-9]+'[bdh][0-9a-f]+/i ) %import common.NEWLINE COMMENT: /\/\*(\*(?!\/)|[^*])*\*\// | /\(\*(\*(?!\))|[^*])*\*\)/ | "//" /(.)*/ NEWLINE %ignore ( /\r?\n/ | COMMENT )+