Skip to content

Commit 75c533e

Browse files
committed
Instance array is supported in dataflow analyzer and AST code generator.
1 parent 1867a62 commit 75c533e

File tree

10 files changed

+126
-51
lines changed

10 files changed

+126
-51
lines changed

pyverilog/ast_code_generator/codegen.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -746,18 +746,31 @@ def visit_DelayStatement(self, node):
746746
rslt = template.render(template_dict)
747747
return rslt
748748

749-
def visit_Instance(self, node):
749+
def visit_InstanceList(self, node):
750750
filename = getfilename(node)
751751
template = self.env.get_template(filename)
752-
portlist = [ self.visit(port) for port in node.portlist ]
753752
parameterlist = [ self.visit(param) for param in node.parameterlist ]
753+
instances = [ self.visit(instance) for instance in node.instances ]
754754
template_dict = {
755755
'module' : node.module,
756+
'parameterlist' : parameterlist,
757+
'len_parameterlist' : len(parameterlist),
758+
'instances' : instances,
759+
'len_instances' : len(instances),
760+
}
761+
rslt = template.render(template_dict)
762+
return rslt
763+
764+
def visit_Instance(self, node):
765+
filename = getfilename(node)
766+
template = self.env.get_template(filename)
767+
array = '' if node.array is None else self.visit(node.array)
768+
portlist = [ self.visit(port) for port in node.portlist ]
769+
template_dict = {
756770
'name' : node.name,
771+
'array' : array,
757772
'portlist' : portlist,
758773
'len_portlist' : len(portlist),
759-
'parameterlist' : parameterlist,
760-
'len_parameterlist' : len(parameterlist),
761774
}
762775
rslt = template.render(template_dict)
763776
return rslt

pyverilog/ast_code_generator/list_ast.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ Initial
8787
WaitStatement
8888
ForeverStatement
8989
DelayStatement
90+
InstanceList
9091
Instance
9192
ParamArg
9293
PortArg
Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,5 @@
1-
{{ module }}
2-
{%- if len_parameterlist > 0 %}
3-
#({% for param in parameterlist %}
4-
{{ param }}{%- if loop.index < len_parameterlist -%}, {%- endif -%}
5-
{% endfor %}
6-
)
7-
{%- endif %}
8-
{{ name }}
1+
{{ name }}{{ array }}
92
({% for port in portlist %}
103
{{ port }}{%- if loop.index < len_portlist -%}, {%- endif -%}
114
{% endfor %}
12-
);
5+
)
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{{ module }}
2+
{%- if len_parameterlist > 0 %}
3+
#({% for param in parameterlist %}
4+
{{ param }}{%- if loop.index < len_parameterlist -%}, {%- endif -%}
5+
{% endfor %}
6+
)
7+
{%- endif %}
8+
{%- for instance in instances %}
9+
{{ instance }}{%- if loop.index < len_instances -%}, {%- endif -%}
10+
{%- endfor -%};

pyverilog/dataflow/bindvisitor.py

Lines changed: 52 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -135,25 +135,29 @@ def visit_Task(self, node):
135135
self.generic_visit(node)
136136
self.frames.unsetTaskDef()
137137

138-
def _visit_Instance_primitive(self, node):
139-
primitive_type = primitives[node.module]
140-
left = node.portlist[0].argname
141-
right = None
142-
if primitive_type == None:
143-
right = Partselect(node.portlist[1].argname, IntConst('0'), IntConst('0'))
144-
elif primitive_type == Unot:
145-
right = Ulnot(Partselect(node.portlist[1].argname, IntConst('0'), IntConst('0')))
146-
else:
147-
concat_list = [Partselect(p.argname, IntConst('0'), IntConst('0')) for p in node.portlist[1:]]
148-
right = primitive_type(Concat(concat_list))
149-
self.addBind(left, right, bindtype='assign')
138+
def visit_InstanceList(self, node):
139+
for i in node.instances:
140+
self.visit(i)
150141

151142
def visit_Instance(self, node):
152-
if node.module in primitives:
153-
self._visit_Instance_primitive(node)
154-
return
143+
if node.array: return self._visit_Instance_array(node)
144+
nodename = node.name
145+
return self._visit_Instance_body(node, nodename)
146+
147+
def _visit_Instance_array(self, node):
148+
current = self.frames.getCurrent()
149+
msb = self.optimize(self.getTree(node.array.msb, current)).value
150+
lsb = self.optimize(self.getTree(node.array.lsb, current)).value
151+
num_of_pins = msb + 1 - lsb
152+
153+
for i in range(lsb, msb+1):
154+
nodename = node.name + '_' + str(i)
155+
self._visit_Instance_body(node, nodename, arrayindex=i)
155156

156-
current = self.stackInstanceFrame(node.name, node.module)
157+
def _visit_Instance_body(self, node, nodename, arrayindex=None):
158+
if node.module in primitives: return self._visit_Instance_primitive(node, arrayindex)
159+
160+
current = self.stackInstanceFrame(nodename, node.module)
157161

158162
scope = self.frames.getCurrent()
159163

@@ -164,7 +168,7 @@ def visit_Instance(self, node):
164168
paramname = paramnames[paramnames_i] if param.paramname is None else param.paramname
165169
if paramname not in paramnames:
166170
raise verror.FormatError("No such parameter: %s in %s" %
167-
(paramname, node.name))
171+
(paramname, nodename))
168172
name = scope + ScopeLabel(paramname, 'signal')
169173
self.setConstant(name, value)
170174
definition = Parameter(paramname, str(value.value))
@@ -175,15 +179,33 @@ def visit_Instance(self, node):
175179
for ioport_i, port in enumerate(node.portlist):
176180
if port.portname is not None and not (port.portname in ioports):
177181
raise verror.FormatError("No such port: %s in %s" %
178-
(port.argname.name, node.name))
179-
self.addInstancePortBind(port, ioports[ioport_i])
182+
(port.argname.name, nodename))
183+
self.addInstancePortBind(port, ioports[ioport_i], arrayindex)
180184

181185
new_current = self.frames.getCurrent()
182186
self.copyFrameInfo(new_current)
183187

184188
self.visit(self.moduleinfotable.getDefinition(node.module))
185189
self.frames.setCurrent(current)
186190

191+
def _visit_Instance_primitive(self, node, arrayindex=None):
192+
primitive_type = primitives[node.module]
193+
left = node.portlist[0].argname
194+
if arrayindex is not None:
195+
left = Pointer(left, IntConst(str(arrayindex)))
196+
right = None
197+
if primitive_type == None:
198+
right = (Pointer(node.portlist[1].argname, IntConst('0')) if arrayindex is None else
199+
Pointer(node.portlist[1].argname, IntConst(str(arrayindex))))
200+
elif primitive_type == Unot:
201+
right = (Ulnot(Pointer(node.portlist[1].argname, IntConst('0'))) if arrayindex is None else
202+
Ulnot(Pointer(node.portlist[1].argname, IntConst(str(arrayindex)))))
203+
else:
204+
concat_list = ([Pointer(p.argname, IntConst('0')) for p in node.portlist[1:]] if arrayindex is None else
205+
[Pointer(p.argname, IntConst(str(arrayindex))) for p in node.portlist[1:]])
206+
right = primitive_type(Concat(concat_list))
207+
self.addBind(left, right, bindtype='assign')
208+
187209
def visit_Initial(self, node):
188210
pass
189211
#label = self.labels.get( self.frames.getLabelKey('initial') )
@@ -806,11 +828,10 @@ def addInstanceParameterBind(self, param, name=None):
806828

807829
self.addDataflow(dst, param.argname, lscope, rscope, None, 'parameter')
808830

809-
def addInstancePortBind(self, port, instportname=None):
831+
def addInstancePortBind(self, port, instportname=None, arrayindex=None):
810832
lscope = self.frames.getCurrent()
811833
rscope = lscope[:-1]
812834
portname = instportname if port.portname is None else port.portname
813-
814835
ldst = self.getDestinations(portname, lscope)
815836
if ldst[0][0] is None:
816837
raise verror.DefinitionError('No such port: %s' % portname)
@@ -819,15 +840,21 @@ def addInstancePortBind(self, port, instportname=None):
819840
for t in termtype:
820841
if t == 'Input':
821842
if port.argname is None: continue
822-
self.addDataflow(ldst, port.argname, lscope, rscope)
843+
portarg = (port.argname if arrayindex is None else
844+
Pointer(port.argname, IntConst(str(arrayindex))))
845+
self.addDataflow(ldst, portarg, lscope, rscope)
823846
elif t == 'Output':
824847
if port.argname is None: continue
825-
rdst = self.getDestinations(port.argname, rscope)
848+
portarg = (port.argname if arrayindex is None else
849+
Pointer(port.argname, IntConst(str(arrayindex))))
850+
rdst = self.getDestinations(portarg, rscope)
826851
self.addDataflow(rdst, portname, rscope, lscope)
827852
elif t == 'Inout':
828853
if port.argname is None: continue
829-
self.addDataflow(ldst, port.argname, lscope, rscope)
830-
rdst = self.getDestinations(port.argname, rscope)
854+
portarg = (port.argname if arrayindex is None else
855+
Pointer(port.argname, IntConst(str(arrayindex))))
856+
self.addDataflow(ldst, portarg, lscope, rscope)
857+
rdst = self.getDestinations(portarg, rscope)
831858
self.addDataflow(rdst, portname, rscope, lscope)
832859

833860
############################################################################

pyverilog/dataflow/modulevisitor.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ def visit_Always(self, node):
6060
def visit_Initial(self, node):
6161
pass
6262

63+
def visit_InstanceList(self, node):
64+
pass
65+
6366
def visit_Instance(self, node):
6467
pass
6568

pyverilog/dataflow/signalvisitor.py

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,10 +116,28 @@ def visit_Initial(self, node):
116116
#self.generic_visit(node)
117117
#self.frames.setCurrent(current)
118118

119+
def visit_InstanceList(self, node):
120+
for i in node.instances:
121+
self.visit(i)
122+
119123
def visit_Instance(self, node):
120-
if node.module in primitives: return
124+
if node.array: return self._visit_Instance_array(node)
125+
nodename = node.name
126+
return self._visit_Instance_body(node, nodename)
127+
128+
def _visit_Instance_array(self, node):
129+
current = self.frames.getCurrent()
130+
msb = self.optimize(self.getTree(node.array.msb, current)).value
131+
lsb = self.optimize(self.getTree(node.array.lsb, current)).value
121132

122-
current = self.stackInstanceFrame(node.name, node.module)
133+
for i in range(lsb, msb+1):
134+
nodename = node.name + '_' + str(i)
135+
self._visit_Instance_body(node, nodename)
136+
137+
def _visit_Instance_body(self, node, nodename):
138+
if node.module in primitives: return self._visit_Instance_primitive(node)
139+
140+
current = self.stackInstanceFrame(nodename, node.module)
123141

124142
self.setInstanceSimpleConstantTerms()
125143

@@ -130,7 +148,7 @@ def visit_Instance(self, node):
130148
paramname = paramnames[paramnames_i] if param.paramname is None else param.paramname
131149
if paramname not in paramnames:
132150
raise verror.FormatError("No such parameter: %s in %s" %
133-
(paramname, node.name))
151+
(paramname, nodename))
134152
value = self.optimize(self.getTree(param.argname, current))
135153
name, definition = self.searchConstantDefinition(scope, paramname)
136154
self.setConstant(name, value)
@@ -141,6 +159,9 @@ def visit_Instance(self, node):
141159
self.visit(self.moduleinfotable.getDefinition(node.module))
142160
self.frames.setCurrent(current)
143161

162+
def _visit_Instance_primitive(self, node):
163+
pass
164+
144165
def visit_Always(self, node):
145166
label = self.labels.get( self.frames.getLabelKey('always') )
146167
current = self.frames.addFrame(ScopeLabel(label, 'always'),

pyverilog/testcode/instance_array.v

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ module TOP
33
input [3:0] VAL,
44
output [3:0] LED0,
55
output [3:0] LED1,
6-
output [3:0] LED2
6+
output [3:0] LED2,
7+
output [3:0] LED3,
8+
input [3:0] in0, in1, in2
79
);
810

911
SUB
@@ -17,7 +19,9 @@ module TOP
1719
# (.MODE(0))
1820
inst_sub4[3:0] (VAL, LED1),
1921
inst_sub5[3:0] (VAL, LED2);
20-
22+
23+
and U0[3:0] (LED3, in0, in1, in2);
24+
2125
endmodule
2226

2327
module SUB #

pyverilog/vparser/ast.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -579,12 +579,15 @@ def children(self):
579579
return tuple(nodelist)
580580

581581
class InstanceList(Node):
582-
attr_names = ()
583-
def __init__(self, list):
584-
self.list = list
582+
attr_names = ('module',)
583+
def __init__(self, module, parameterlist, instances):
584+
self.module = module
585+
self.parameterlist = parameterlist
586+
self.instances = instances
585587
def children(self):
586588
nodelist = []
587-
if self.list: nodelist.extend(self.list)
589+
if self.parameterlist: nodelist.extend(self.parameterlist)
590+
if self.instances: nodelist.extend(self.instances)
588591
return tuple(nodelist)
589592

590593
class Instance(Node):
@@ -597,9 +600,9 @@ def __init__(self, module, name, portlist, parameterlist, array=None):
597600
self.array = array
598601
def children(self):
599602
nodelist = []
600-
if self.portlist: nodelist.extend(self.portlist)
601-
if self.parameterlist: nodelist.extend(self.parameterlist)
602603
if self.array: nodelist.append(self.array)
604+
if self.parameterlist: nodelist.extend(self.parameterlist)
605+
if self.portlist: nodelist.extend(self.portlist)
603606
return tuple(nodelist)
604607

605608
class ParamArg(Node):

pyverilog/vparser/parser.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1316,14 +1316,14 @@ def p_instance(self, p):
13161316
instancelist = []
13171317
for instance_name, instance_ports, instance_array in p[3]:
13181318
instancelist.append( Instance(p[1], instance_name, instance_ports, p[2], instance_array) )
1319-
p[0] = InstanceList( tuple(instancelist) )
1319+
p[0] = InstanceList(p[1], p[2], tuple(instancelist))
13201320

13211321
def p_instance_or(self, p):
13221322
'instance : SENS_OR parameterlist instance_bodylist SEMICOLON'
13231323
instancelist = []
13241324
for instance_name, instance_ports, instance_array in p[3]:
13251325
instancelist.append( Instance(p[1], instance_name, instance_ports, p[2], instance_array) )
1326-
p[0] = InstanceList( tuple(instancelist) )
1326+
p[0] = InstanceList(p[1], p[2], tuple(instancelist))
13271327

13281328
def p_instance_bodylist(self, p):
13291329
'instance_bodylist : instance_bodylist COMMA instance_body'

0 commit comments

Comments
 (0)