full constants support, fix signal declarations
This commit is contained in:
1 parent
80d26b6f0b
commit
39b8c1695b
1 file changed
+33
-21
+33
-21
@@ -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 )+
|
||||
|
||||
Reference in new issue
Block a user