|
|
@ -65,6 +65,16 @@ class VerilogTransformer(Transformer): |
|
|
|
if len(args) > 1 and isinstance(args[1], range): |
|
|
|
if len(args) > 1 and isinstance(args[1], range): |
|
|
|
l = [f'{args[0]}[{i}]' for i in args[1]] |
|
|
|
l = [f'{args[0]}[{i}]' for i in args[1]] |
|
|
|
return l if len(l) > 1 else l[0] |
|
|
|
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: |
|
|
|
else: |
|
|
|
return args[0] |
|
|
|
return args[0] |
|
|
|
|
|
|
|
|
|
|
@ -82,20 +92,24 @@ class VerilogTransformer(Transformer): |
|
|
|
if isinstance(args[0], range): |
|
|
|
if isinstance(args[0], range): |
|
|
|
rnge = args[0] |
|
|
|
rnge = args[0] |
|
|
|
args = args[1:] |
|
|
|
args = args[1:] |
|
|
|
for sd in [SignalDeclaration(kind, signal, rnge) for signal in args]: |
|
|
|
return [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 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def input(self, args): self.declaration("input", args) |
|
|
|
def input(self, args): return self.declaration("input", args) |
|
|
|
def output(self, args): self.declaration("output", args) |
|
|
|
def output(self, args): return self.declaration("output", args) |
|
|
|
def inout(self, args): self.declaration("input", args) # just treat as input |
|
|
|
def inout(self, args): return self.declaration("input", args) # just treat as input |
|
|
|
def wire(self, args): self.declaration("wire", args) |
|
|
|
def wire(self, args): return self.declaration("wire", args) |
|
|
|
|
|
|
|
|
|
|
|
def module(self, args): |
|
|
|
def module(self, args): |
|
|
|
c = Circuit(args[0]) |
|
|
|
c = Circuit(args[0]) |
|
|
|
positions = {} |
|
|
|
positions = {} |
|
|
|
pos = 0 |
|
|
|
pos = 0 |
|
|
|
const_count = 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 intf_sig in args[1].children: |
|
|
|
for name in self._signal_declarations[intf_sig].names: |
|
|
|
for name in self._signal_declarations[intf_sig].names: |
|
|
|
positions[name] = pos |
|
|
|
positions[name] = pos |
|
|
@ -107,7 +121,7 @@ class VerilogTransformer(Transformer): |
|
|
|
for p, s in stmt.pins.items(): |
|
|
|
for p, s in stmt.pins.items(): |
|
|
|
if self.tlib.pin_is_output(n.kind, p): |
|
|
|
if self.tlib.pin_is_output(n.kind, p): |
|
|
|
Line(c, (n, self.tlib.pin_index(stmt.type, p)), Node(c, s)) |
|
|
|
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])) |
|
|
|
assignments.append((stmt.children[0], stmt.children[1])) |
|
|
|
for sd in self._signal_declarations.values(): |
|
|
|
for sd in self._signal_declarations.values(): |
|
|
|
if sd.kind == 'output' or sd.kind == 'input': |
|
|
|
if sd.kind == 'output' or sd.kind == 'input': |
|
|
@ -117,17 +131,6 @@ class VerilogTransformer(Transformer): |
|
|
|
c.io_nodes[positions[name]] = n |
|
|
|
c.io_nodes[positions[name]] = n |
|
|
|
if sd.kind == 'input': |
|
|
|
if sd.kind == 'input': |
|
|
|
Line(c, n, Node(c, name)) |
|
|
|
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 |
|
|
|
for target, source in assignments: # pass 1.5: process signal assignments |
|
|
|
target_sigs = [] |
|
|
|
target_sigs = [] |
|
|
|
if not isinstance(target, list): target = [target] |
|
|
|
if not isinstance(target, list): target = [target] |
|
|
@ -144,7 +147,16 @@ class VerilogTransformer(Transformer): |
|
|
|
else: |
|
|
|
else: |
|
|
|
source_sigs.append(s) |
|
|
|
source_sigs.append(s) |
|
|
|
for t, s in zip(target_sigs, source_sigs): |
|
|
|
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 |
|
|
|
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(): |
|
|
@ -195,7 +207,7 @@ GRAMMAR = r""" |
|
|
|
sigsel: name range? | concat |
|
|
|
sigsel: name range? | concat |
|
|
|
concat: "{" sigsel ( "," sigsel )* "}" |
|
|
|
concat: "{" sigsel ( "," sigsel )* "}" |
|
|
|
_namelist: name ( "," name )* |
|
|
|
_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 |
|
|
|
%import common.NEWLINE |
|
|
|
COMMENT: /\/\*(\*(?!\/)|[^*])*\*\// | /\(\*(\*(?!\))|[^*])*\*\)/ | "//" /(.)*/ NEWLINE |
|
|
|
COMMENT: /\/\*(\*(?!\/)|[^*])*\*\// | /\(\*(\*(?!\))|[^*])*\*\)/ | "//" /(.)*/ NEWLINE |
|
|
|
%ignore ( /\r?\n/ | COMMENT )+ |
|
|
|
%ignore ( /\r?\n/ | COMMENT )+ |
|
|
|