diff --git a/pyverilog/dataflow/bindvisitor.py b/pyverilog/dataflow/bindvisitor.py index 94b06eb..81ae1fb 100644 --- a/pyverilog/dataflow/bindvisitor.py +++ b/pyverilog/dataflow/bindvisitor.py @@ -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 @@ -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 @@ -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): diff --git a/pyverilog/utils/scope.py b/pyverilog/utils/scope.py index 2dcba0d..4334e7e 100644 --- a/pyverilog/utils/scope.py +++ b/pyverilog/utils/scope.py @@ -1,6 +1,6 @@ #------------------------------------------------------------------------------- # scope.py -# +# # classes for definition of scope # # Copyright (C) 2013, Shinya Takamaeda-Yamazaki @@ -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', ) @@ -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: diff --git a/testcode/reset.v b/testcode/reset.v new file mode 100644 index 0000000..216da39 --- /dev/null +++ b/testcode/reset.v @@ -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 \ No newline at end of file diff --git a/tests/dataflow_test/test_reset.py b/tests/dataflow_test/test_reset.py new file mode 100644 index 0000000..ecd8c4e --- /dev/null +++ b/tests/dataflow_test/test_reset.py @@ -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()