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):
|
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 )+
|
||||||
|
|||||||
Reference in new issue
Block a user