Skip to content

Commit 95188ef

Browse files
committed
Provisional commit for issue #14. Implemented function for detecting reset from always block.
1 parent cdf85bd commit 95188ef

File tree

4 files changed

+282
-3
lines changed

4 files changed

+282
-3
lines changed

pyverilog/dataflow/bindvisitor.py

Lines changed: 134 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,11 @@ def _createAlwaysinfo(self, node, scope):
256256
reset_name = None
257257
reset_bit = None
258258

259+
#TODO unimplemented
260+
#print('load: ' + str(self._first_lvalue_is_const(node)))
261+
#print('if_branch: ' + str(self._has_if_branch(node)))
262+
#print('reset_info: ' + str(self._get_rst_info(node)))
263+
259264
for l in node.sens_list.list:
260265
if l.sig is None:
261266
continue
@@ -283,6 +288,134 @@ def _createAlwaysinfo(self, node, scope):
283288

284289
return (clock_name, clock_edge, clock_bit, reset_name, reset_edge, reset_bit, senslist)
285290

291+
#TODO This function is implemented for https://github.com/PyHDI/Pyverilog/issues/14.
292+
#Be incorporated into formally in lator commit.
293+
def _first_lvalue_is_const(self, node):
294+
""" [FUNCTIONS]
295+
Walk until lvalue and judge whether it is constant or not.
296+
297+
ex.
298+
if(RST)
299+
reg1 <= 1'd0: //const: judged as rst branch
300+
301+
if(RST)
302+
reg1 <= {1'd0, 1'd0}: //const: judged as rst branch
303+
304+
if(RST)
305+
reg1 <= reg2: //variable: judged as not rst branch
306+
307+
if(RST)
308+
reg1 <= {1'd0, reg2}: //variable: judged as not rst branch
309+
"""
310+
if isinstance(node, Always):
311+
return self._first_lvalue_is_const(node.statement)
312+
elif isinstance(node, Block):
313+
return self._first_lvalue_is_const(node.statements[0])
314+
elif isinstance(node, IfStatement):
315+
return self._first_lvalue_is_const(node.true_statement)
316+
elif isinstance(node, NonblockingSubstitution):
317+
print(node.left.var)# for debug
318+
return self._first_lvalue_is_const(node.right)
319+
elif isinstance(node, Identifier):
320+
node_chain = self.get_scopechain(node)
321+
if node_chain in self.dataflow.terms.keys():
322+
#Parameter is regard as constant.
323+
return 'Parameter' in self.dataflow.terms[node_chain].termtype
324+
return False
325+
elif hasattr(node, 'children'):
326+
for child in node.children():
327+
if not self._first_lvalue_is_const(child):
328+
return False
329+
return True
330+
elif isinstance(node, Rvalue):
331+
return self._first_lvalue_is_const(node.var)
332+
elif hasattr(node, 'value'):
333+
return True
334+
else:
335+
raise Exception('Pyverilog unknown error')
336+
337+
def get_scopechain(self, node):
338+
assert isinstance(node, Identifier), 'Node type should be Identifier.'
339+
scope_list = self.frames.current.get_module_list() + [util.ScopeLabel(str(node)),]
340+
return util.ScopeChain(scope_list)
341+
342+
#TODO This function is implemented for https://github.com/PyHDI/Pyverilog/issues/14.
343+
#Be incorporated into formally in lator commit.
344+
def _get_rst_info(self, node, rst_name='', is_posedge=True, rst_bit=0):
345+
""" [FUNCTIONS]
346+
get reset information from first if statement.
347+
348+
ex1.
349+
always @(posedge CLK or posedge RST) begin
350+
if(RST)
351+
reg1 <= 0;
352+
else
353+
reg1 <= !reg1;
354+
end
355+
->RST is posedge RST.
356+
357+
ex2.
358+
always @(posedge CLK or posedge RST) begin
359+
if(!RSTN[1])
360+
reg1 <= 0;
361+
else
362+
reg1 <= !reg1;
363+
end
364+
->RSTN[1] is negedge RST.
365+
366+
ex3.
367+
always @(posedge CLK or posedge RST) begin
368+
if(RST && RST2)
369+
reg1 <= 0;
370+
else
371+
reg1 <= !reg1;
372+
end
373+
-> reg1 has no reset. (too complex condition)
374+
"""
375+
if isinstance(node, Always):
376+
return self._get_rst_info(node.statement, rst_name, is_posedge, rst_bit)
377+
elif isinstance(node, Block):
378+
return self._get_rst_info(node.statements[0], rst_name, is_posedge, rst_bit)
379+
elif isinstance(node, IfStatement):
380+
return self._get_rst_info(node.cond, rst_name, is_posedge, rst_bit)
381+
elif isinstance(node, pyverilog.vparser.ast.Ulnot):
382+
is_posedge = not is_posedge
383+
return self._get_rst_info(node.children()[0], rst_name, is_posedge, rst_bit)
384+
elif isinstance(node, pyverilog.vparser.ast.Pointer):
385+
#TODO if identifier
386+
if isinstance(node.ptr, Identifier):
387+
ptr_chain = self.get_scopechain(node.ptr)
388+
if 'Parameter' in self.dataflow.terms[ptr_chain].termtype:
389+
rst_bit = self.dataflow.binddict[ptr_chain][0].tree.eval()
390+
return self._get_rst_info(node.var, rst_name, is_posedge, rst_bit)
391+
else:
392+
return (None, None, None)
393+
elif hasattr(node.ptr, 'value'):
394+
return self._get_rst_info(node.var, rst_name, is_posedge, int(node.ptr.value))
395+
elif isinstance(node, pyverilog.vparser.ast.Identifier):
396+
return (node, is_posedge, rst_bit)
397+
return (None, None, None)
398+
399+
#TODO This function is implemented for https://github.com/PyHDI/Pyverilog/issues/14.
400+
#Be incorporated into formally in lator commit.
401+
def _has_if_branch(self, node):
402+
""" [FUNCTIONS]
403+
Return always block have 'if branch' or not.
404+
ex.
405+
always @(posedge CLK or posedge RST) begin
406+
reg1 <= 0;
407+
end
408+
-> reg1 has no reset. (If statement isn't exists.)
409+
"""
410+
if isinstance(node, Always):
411+
return self._has_if_branch(node.statement)
412+
elif isinstance(node, Block):
413+
return self._has_if_branch(node.statements[0])
414+
elif isinstance(node, IfStatement):
415+
return True
416+
else:
417+
return False
418+
286419
def visit_IfStatement(self, node):
287420
if self.frames.isFunctiondef() and not self.frames.isFunctioncall(): return
288421
if self.frames.isTaskdef() and not self.frames.isTaskcall(): return
@@ -828,7 +961,7 @@ def addTerm(self, node, rscope=None):
828961
else:
829962
msb = DFIntConst('0') if node.width is None else self.makeDFTree(node.width.msb, scope)
830963
lsb = DFIntConst('0') if node.width is None else self.makeDFTree(node.width.lsb, scope)
831-
964+
832965
lenmsb = None
833966
lenlsb = None
834967
if isinstance(node, RegArray) or isinstance(node, WireArray):

pyverilog/utils/scope.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#-------------------------------------------------------------------------------
22
# scope.py
3-
#
3+
#
44
# classes for definition of scope
55
#
66
# Copyright (C) 2013, Shinya Takamaeda-Yamazaki
@@ -12,7 +12,7 @@
1212
import os
1313
import copy
1414

15-
scopetype_list_unprint = ('generate', 'always', 'function', #'functioncall',
15+
scopetype_list_unprint = ('generate', 'always', 'function', #'functioncall',
1616
'task', 'taskcall', 'initial', 'for', 'while', 'if')
1717
scopetype_list_print = ('module', 'block', 'signal', 'functioncall',)
1818
scopetype_list = scopetype_list_unprint + scopetype_list_print + ('any', )
@@ -88,6 +88,8 @@ def tocode(self):
8888
it = None
8989
ret = ret[:-1]
9090
return ''.join(ret)
91+
def get_module_list(self):
92+
return [scope for scope in self.scopechain if scope.scopetype == 'module']
9193
def __repr__(self):
9294
ret = ''
9395
for scope in self.scopechain:

testcode/reset.v

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
module TOP(CLK, RST);
2+
input CLK, RST;
3+
reg [7:0] cnt1,cnt2,cnt3,cnt4,cnt5,cnt6,cnt7,cnt8,cnt9,cnt10;
4+
parameter zero = 0;
5+
6+
//reset
7+
always @(posedge CLK) begin
8+
if(RST[0]) begin
9+
cnt1 <= 0;
10+
end else begin
11+
cnt1 <= 8'd1;
12+
end
13+
end
14+
15+
//reset
16+
always @(posedge CLK or posedge RST)
17+
if(RST)
18+
cnt2 <= 0;
19+
else
20+
cnt2 <= 8'd1;
21+
22+
//not reset
23+
always @(posedge CLK or posedge RST) begin
24+
if(RST) begin
25+
cnt3 <= cnt1[0];
26+
end else begin
27+
cnt3 <= 8'd1;
28+
end
29+
end
30+
31+
//not reset
32+
always @(posedge CLK or posedge RST) begin
33+
cnt4 <= 0;
34+
end
35+
36+
//reset
37+
always @(posedge CLK or posedge RST) begin
38+
if(RST) begin
39+
cnt5 <= {2'd0,6'd0};
40+
end else begin
41+
cnt5 <= 8'd1;
42+
end
43+
end
44+
45+
//not reset
46+
always @(posedge CLK or posedge RST) begin
47+
if(RST) begin
48+
cnt6 <= 7'd0 + cnt1[1:0];
49+
end else begin
50+
cnt6 <= 8'd1;
51+
end
52+
end
53+
54+
//reset
55+
always @(posedge CLK) begin
56+
if(!RST) begin
57+
cnt7 <= 0;
58+
end else begin
59+
cnt7 <= 8'd1;
60+
end
61+
end
62+
63+
//not reset
64+
always @(posedge CLK) begin
65+
if(RST && RST) begin
66+
cnt8 <= 0;
67+
end else begin
68+
cnt8 <= 8'd1;
69+
end
70+
end
71+
72+
always @(posedge CLK) begin
73+
if(RST[zero]) begin
74+
cnt10 <= 0;
75+
end else begin
76+
cnt10 <= 8'd1;
77+
end
78+
end
79+
80+
SUB sub(CLK,RST);
81+
82+
endmodule
83+
84+
module SUB(CLK, RST);
85+
input CLK, RST;
86+
reg [7:0] cnt9;
87+
parameter zero = 0;
88+
89+
always @(posedge CLK) begin
90+
if(RST) begin
91+
cnt9 <= zero;
92+
end else begin
93+
cnt9 <= 8'd1;
94+
end
95+
end
96+
endmodule

tests/dataflow_test/test_reset.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import os
2+
import sys
3+
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
4+
from pyverilog.dataflow.dataflow_analyzer import VerilogDataflowAnalyzer
5+
6+
codedir = '../../testcode/'
7+
8+
expected = """\
9+
"""
10+
11+
def test():
12+
filelist = [codedir + 'reset.v']
13+
topmodule = 'TOP'
14+
noreorder = False
15+
nobind = False
16+
include = None
17+
define = None
18+
19+
analyzer = VerilogDataflowAnalyzer(filelist, topmodule,
20+
noreorder=noreorder,
21+
nobind=nobind,
22+
preprocess_include=include,
23+
preprocess_define=define)
24+
analyzer.generate()
25+
#TODO Current version is for only display.
26+
## directives = analyzer.get_directives()
27+
## instances = analyzer.getInstances()
28+
## terms = analyzer.getTerms()
29+
## binddict = analyzer.getBinddict()
30+
##
31+
## output = []
32+
## output.append(list(binddict.values())[0][0].tostr())
33+
## output.append('\n')
34+
##
35+
## rslt = ''.join(output)
36+
##
37+
## print(rslt)
38+
## for key, verb in binddict.items():
39+
## if verb[0].getResetName() is None:
40+
## print(str(key) + ': None')
41+
## else:
42+
## print(str(key) + ': ' + verb[0].getResetEdge() + str(verb[0].getResetName()) +
43+
## '[' + str(verb[0].getResetBit()) + ']')
44+
45+
46+
47+
if __name__ == '__main__':
48+
test()

0 commit comments

Comments
 (0)