Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 134 additions & 1 deletion pyverilog/dataflow/bindvisitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,11 @@ def _createAlwaysinfo(self, node, scope):
reset_name = None
reset_bit = None

#TODO unimplemented
#print('load: ' + str(self._first_lvalue_is_const(node)))
#print('if_branch: ' + str(self._has_if_branch(node)))
#print('reset_info: ' + str(self._get_rst_info(node)))

for l in node.sens_list.list:
if l.sig is None:
continue
Expand Down Expand Up @@ -283,6 +288,134 @@ def _createAlwaysinfo(self, node, scope):

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

#TODO This function is implemented for https://github.com/PyHDI/Pyverilog/issues/14.
#Be incorporated into formally in lator commit.
def _first_lvalue_is_const(self, node):
""" [FUNCTIONS]
Walk until lvalue and judge whether it is constant or not.

ex.
if(RST)
reg1 <= 1'd0: //const: judged as rst branch

if(RST)
reg1 <= {1'd0, 1'd0}: //const: judged as rst branch

if(RST)
reg1 <= reg2: //variable: judged as not rst branch

if(RST)
reg1 <= {1'd0, reg2}: //variable: judged as not rst branch
"""
if isinstance(node, Always):
return self._first_lvalue_is_const(node.statement)
elif isinstance(node, Block):
return self._first_lvalue_is_const(node.statements[0])
elif isinstance(node, IfStatement):
return self._first_lvalue_is_const(node.true_statement)
elif isinstance(node, NonblockingSubstitution):
print(node.left.var)# for debug
return self._first_lvalue_is_const(node.right)
elif isinstance(node, Identifier):
node_chain = self.get_scopechain(node)
if node_chain in self.dataflow.terms.keys():
#Parameter is regard as constant.
return 'Parameter' in self.dataflow.terms[node_chain].termtype
return False
elif hasattr(node, 'children'):
for child in node.children():
if not self._first_lvalue_is_const(child):
return False
return True
elif isinstance(node, Rvalue):
return self._first_lvalue_is_const(node.var)
elif hasattr(node, 'value'):
return True
else:
raise Exception('Pyverilog unknown error')

def get_scopechain(self, node):
assert isinstance(node, Identifier), 'Node type should be Identifier.'
scope_list = self.frames.current.get_module_list() + [util.ScopeLabel(str(node)),]
return util.ScopeChain(scope_list)

#TODO This function is implemented for https://github.com/PyHDI/Pyverilog/issues/14.
#Be incorporated into formally in lator commit.
def _get_rst_info(self, node, rst_name='', is_posedge=True, rst_bit=0):
""" [FUNCTIONS]
get reset information from first if statement.

ex1.
always @(posedge CLK or posedge RST) begin
if(RST)
reg1 <= 0;
else
reg1 <= !reg1;
end
->RST is posedge RST.

ex2.
always @(posedge CLK or posedge RST) begin
if(!RSTN[1])
reg1 <= 0;
else
reg1 <= !reg1;
end
->RSTN[1] is negedge RST.

ex3.
always @(posedge CLK or posedge RST) begin
if(RST && RST2)
reg1 <= 0;
else
reg1 <= !reg1;
end
-> reg1 has no reset. (too complex condition)
"""
if isinstance(node, Always):
return self._get_rst_info(node.statement, rst_name, is_posedge, rst_bit)
elif isinstance(node, Block):
return self._get_rst_info(node.statements[0], rst_name, is_posedge, rst_bit)
elif isinstance(node, IfStatement):
return self._get_rst_info(node.cond, rst_name, is_posedge, rst_bit)
elif isinstance(node, pyverilog.vparser.ast.Ulnot):
is_posedge = not is_posedge
return self._get_rst_info(node.children()[0], rst_name, is_posedge, rst_bit)
elif isinstance(node, pyverilog.vparser.ast.Pointer):
#TODO if identifier
if isinstance(node.ptr, Identifier):
ptr_chain = self.get_scopechain(node.ptr)
if 'Parameter' in self.dataflow.terms[ptr_chain].termtype:
rst_bit = self.dataflow.binddict[ptr_chain][0].tree.eval()
return self._get_rst_info(node.var, rst_name, is_posedge, rst_bit)
else:
return (None, None, None)
elif hasattr(node.ptr, 'value'):
return self._get_rst_info(node.var, rst_name, is_posedge, int(node.ptr.value))
elif isinstance(node, pyverilog.vparser.ast.Identifier):
return (node, is_posedge, rst_bit)
return (None, None, None)

#TODO This function is implemented for https://github.com/PyHDI/Pyverilog/issues/14.
#Be incorporated into formally in lator commit.
def _has_if_branch(self, node):
""" [FUNCTIONS]
Return always block have 'if branch' or not.
ex.
always @(posedge CLK or posedge RST) begin
reg1 <= 0;
end
-> reg1 has no reset. (If statement isn't exists.)
"""
if isinstance(node, Always):
return self._has_if_branch(node.statement)
elif isinstance(node, Block):
return self._has_if_branch(node.statements[0])
elif isinstance(node, IfStatement):
return True
else:
return False

def visit_IfStatement(self, node):
if self.frames.isFunctiondef() and not self.frames.isFunctioncall(): return
if self.frames.isTaskdef() and not self.frames.isTaskcall(): return
Expand Down Expand Up @@ -828,7 +961,7 @@ def addTerm(self, node, rscope=None):
else:
msb = DFIntConst('0') if node.width is None else self.makeDFTree(node.width.msb, scope)
lsb = DFIntConst('0') if node.width is None else self.makeDFTree(node.width.lsb, scope)

lenmsb = None
lenlsb = None
if isinstance(node, RegArray) or isinstance(node, WireArray):
Expand Down
6 changes: 4 additions & 2 deletions pyverilog/utils/scope.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#-------------------------------------------------------------------------------
# scope.py
#
#
# classes for definition of scope
#
# Copyright (C) 2013, Shinya Takamaeda-Yamazaki
Expand All @@ -12,7 +12,7 @@
import os
import copy

scopetype_list_unprint = ('generate', 'always', 'function', #'functioncall',
scopetype_list_unprint = ('generate', 'always', 'function', #'functioncall',
'task', 'taskcall', 'initial', 'for', 'while', 'if')
scopetype_list_print = ('module', 'block', 'signal', 'functioncall',)
scopetype_list = scopetype_list_unprint + scopetype_list_print + ('any', )
Expand Down Expand Up @@ -88,6 +88,8 @@ def tocode(self):
it = None
ret = ret[:-1]
return ''.join(ret)
def get_module_list(self):
return [scope for scope in self.scopechain if scope.scopetype == 'module']
def __repr__(self):
ret = ''
for scope in self.scopechain:
Expand Down
96 changes: 96 additions & 0 deletions testcode/reset.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
module TOP(CLK, RST);
input CLK, RST;
reg [7:0] cnt1,cnt2,cnt3,cnt4,cnt5,cnt6,cnt7,cnt8,cnt9,cnt10;
parameter zero = 0;

//reset
always @(posedge CLK) begin
if(RST[0]) begin
cnt1 <= 0;
end else begin
cnt1 <= 8'd1;
end
end

//reset
always @(posedge CLK or posedge RST)
if(RST)
cnt2 <= 0;
else
cnt2 <= 8'd1;

//not reset
always @(posedge CLK or posedge RST) begin
if(RST) begin
cnt3 <= cnt1[0];
end else begin
cnt3 <= 8'd1;
end
end

//not reset
always @(posedge CLK or posedge RST) begin
cnt4 <= 0;
end

//reset
always @(posedge CLK or posedge RST) begin
if(RST) begin
cnt5 <= {2'd0,6'd0};
end else begin
cnt5 <= 8'd1;
end
end

//not reset
always @(posedge CLK or posedge RST) begin
if(RST) begin
cnt6 <= 7'd0 + cnt1[1:0];
end else begin
cnt6 <= 8'd1;
end
end

//reset
always @(posedge CLK) begin
if(!RST) begin
cnt7 <= 0;
end else begin
cnt7 <= 8'd1;
end
end

//not reset
always @(posedge CLK) begin
if(RST && RST) begin
cnt8 <= 0;
end else begin
cnt8 <= 8'd1;
end
end

always @(posedge CLK) begin
if(RST[zero]) begin
cnt10 <= 0;
end else begin
cnt10 <= 8'd1;
end
end

SUB sub(CLK,RST);

endmodule

module SUB(CLK, RST);
input CLK, RST;
reg [7:0] cnt9;
parameter zero = 0;

always @(posedge CLK) begin
if(RST) begin
cnt9 <= zero;
end else begin
cnt9 <= 8'd1;
end
end
endmodule
48 changes: 48 additions & 0 deletions tests/dataflow_test/test_reset.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import os
import sys
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
from pyverilog.dataflow.dataflow_analyzer import VerilogDataflowAnalyzer

codedir = '../../testcode/'

expected = """\
"""

def test():
filelist = [codedir + 'reset.v']
topmodule = 'TOP'
noreorder = False
nobind = False
include = None
define = None

analyzer = VerilogDataflowAnalyzer(filelist, topmodule,
noreorder=noreorder,
nobind=nobind,
preprocess_include=include,
preprocess_define=define)
analyzer.generate()
#TODO Current version is for only display.
## directives = analyzer.get_directives()
## instances = analyzer.getInstances()
## terms = analyzer.getTerms()
## binddict = analyzer.getBinddict()
##
## output = []
## output.append(list(binddict.values())[0][0].tostr())
## output.append('\n')
##
## rslt = ''.join(output)
##
## print(rslt)
## for key, verb in binddict.items():
## if verb[0].getResetName() is None:
## print(str(key) + ': None')
## else:
## print(str(key) + ': ' + verb[0].getResetEdge() + str(verb[0].getResetName()) +
## '[' + str(verb[0].getResetBit()) + ']')



if __name__ == '__main__':
test()