diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..378c09b --- /dev/null +++ b/.travis.yml @@ -0,0 +1,16 @@ +language: python +python: + - 2.7 + - 3.4 +env: + - EXE_TRAVIS=1 +cache: apt +before_install: + - sudo apt-get install iverilog + - sudo apt-get install graphviz + - pip install pygraphviz jinja2 +before_script: + - pip freeze +script: +# - export EXE_TRAVIS=1 + - make \ No newline at end of file diff --git a/Makefile b/Makefile index 26b2a2c..b144d54 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,7 @@ .PHONY: all all: + export PYTHON=python3 + export PYTHON27=python2.7 make -C ./pyverilog .PHONY: clean diff --git a/pyverilog/ast_code_generator/Makefile b/pyverilog/ast_code_generator/Makefile index 8b99863..88788b4 100644 --- a/pyverilog/ast_code_generator/Makefile +++ b/pyverilog/ast_code_generator/Makefile @@ -1,4 +1,8 @@ -PYTHON=python3 +ifndef EXE_TRAVIS + PYTHON=python3 +else + PYTHON=python +endif #OPT=-m pdb #OPT=-m cProfile -s time #OPT=-m cProfile -o profile.rslt diff --git a/pyverilog/controlflow/Makefile b/pyverilog/controlflow/Makefile index 2c0d51c..3f268d4 100644 --- a/pyverilog/controlflow/Makefile +++ b/pyverilog/controlflow/Makefile @@ -1,3 +1,8 @@ +ifndef EXE_TRAVIS + PYTHON=python3 +else + PYTHON=python +endif PYTHON=python3 #PYTHON=python2.7 #OPT=-m pdb diff --git a/pyverilog/dataflow/Makefile b/pyverilog/dataflow/Makefile index b250e29..cccdc29 100644 --- a/pyverilog/dataflow/Makefile +++ b/pyverilog/dataflow/Makefile @@ -1,4 +1,8 @@ -PYTHON=python3 +ifndef EXE_TRAVIS + PYTHON=python3 +else + PYTHON=python +endif #PYTHON=python2.7 PYTHON27=python2.7 #OPT=-m pdb @@ -42,11 +46,18 @@ subset: .PHONY: codegen codegen: - $(PYTHON) $(OPT) $(CODEGEN) $(SRCS) $(TOP) $(TARGETS) $(CODEGEN_OPT) + $(PYTHON) $(OPT) $(CODEGEN) $(SRCS) $(TOP) $(TARGETS) $(CODEGEN_OPT) .PHONY: graphgen graphgen: - $(PYTHON27) $(OPT) $(GRAPHGEN) $(SRCS) $(TOP) $(TARGETS) $(GRAPHGEN_OPT) +ifdef EXE_TRAVIS +ifdef EXE_GRAPHGEN + python --version + $(PYTHON) $(OPT) $(GRAPHGEN) $(SRCS) $(TOP) $(TARGETS) $(GRAPHGEN_OPT) +endif +else + $(PYTHON27) $(OPT) $(GRAPHGEN) $(SRCS) $(TOP) $(TARGETS) $(GRAPHGEN_OPT) +endif .PHONY: clean clean: diff --git a/pyverilog/dataflow/bindvisitor.py b/pyverilog/dataflow/bindvisitor.py index 81ae1fb..7ed2f89 100644 --- a/pyverilog/dataflow/bindvisitor.py +++ b/pyverilog/dataflow/bindvisitor.py @@ -229,10 +229,10 @@ def visit_Always(self, node): (clock_name, clock_edge, clock_bit, reset_name, reset_edge, reset_bit, - senslist) = self._createAlwaysinfo(node, current) + senslist, load_const_dict) = self._createAlwaysinfo(node, current) self.frames.setAlwaysInfo(clock_name, clock_edge, clock_bit, - reset_name, reset_edge, reset_bit, senslist) + reset_name, reset_edge, reset_bit, senslist, load_const_dict) self.generic_visit(node) self.frames.setCurrent(current) @@ -255,29 +255,33 @@ def _createAlwaysinfo(self, node, scope): reset_edge = None reset_name = None reset_bit = None + reset_sig = None + is_sync_reset = True + r_finder = self.reset_finder(node, self.frames.current, self.dataflow) - #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))) + if str(r_finder._has_if_branch(node)) and any(r_finder.load_const_dict.values()): + reset_sig, reset_edge, reset_bit = r_finder.get_rst_info() + reset_name = self.searchTerminal(reset_sig, scope) for l in node.sens_list.list: if l.sig is None: continue - if isinstance(l.sig, pyverilog.vparser.ast.Pointer): + if isinstance(l.sig, Pointer): signame = self._get_signal_name(l.sig.var) bit = int(l.sig.ptr.value) else: signame = self._get_signal_name(l.sig) bit = 0 - if signaltype.isClock(signame): + + if signame == reset_sig and bit == reset_bit: + if l.type == reset_edge: + is_sync_reset = False + else: + raise verror.FormatError('Illegal reset polarity') + elif not clock_name: #First signal which is not reset is regard as clock. clock_name = self.searchTerminal(signame, scope) clock_edge = l.type clock_bit = bit - elif signaltype.isReset(signame): - reset_name = self.searchTerminal(signame, scope) - reset_edge = l.type - reset_bit = bit else: senslist.append(l) @@ -286,135 +290,10 @@ def _createAlwaysinfo(self, node, scope): if reset_edge is not None and len(senslist) > 0: raise verror.FormatError('Illegal sensitivity list') - 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 + if is_sync_reset: + reset_edge = 'sync' + return (clock_name, clock_edge, clock_bit, reset_name, reset_edge, reset_bit, + senslist, r_finder.load_const_dict) def visit_IfStatement(self, node): if self.frames.isFunctiondef() and not self.frames.isFunctioncall(): return @@ -495,7 +374,6 @@ def visit_CaseStatement(self, node): start_frame = self.frames.getCurrent() caseframes = [] self._case(node.comp, node.caselist, caseframes) - #self._case(node.comp, tuple(reversed(list(node.caselist))), caseframes) self.frames.setCurrent(start_frame) for f in caseframes: self.copyBlockingAssigns(f, start_frame) @@ -662,7 +540,7 @@ def visit_Assign(self, node): self.addBind(node.left, node.right, bindtype='assign') def visit_BlockingSubstitution(self, node): - self.addBind(node.left, node.right, self.frames.getAlwaysStatus(), 'blocking') + self.addBind(node.left, node.right, self.frames.getAlwaysStatus(node.left), 'blocking') def visit_NonblockingSubstitution(self, node): if self.frames.isForpre() or self.frames.isForpost(): @@ -670,7 +548,7 @@ def visit_NonblockingSubstitution(self, node): "in for-statement")) if self.frames.isFunctioncall(): raise verror.FormatError("Non Blocking Substitution is not allowed in function") - self.addBind(node.left, node.right, self.frames.getAlwaysStatus(), 'nonblocking') + self.addBind(node.left, node.right, self.frames.getAlwaysStatus(node.left), 'nonblocking') def visit_SystemCall(self, node): print("Warning: Isolated system call is not supported: %s" % node.syscall) @@ -1646,3 +1524,147 @@ def appendBranchTree(self, base, pos, tree): base.condnode, base.truenode, self.appendBranchTree(base.falsenode, pos[1:], tree)) + + class reset_finder(object): + def __init__(self, node, current, dataflow): + self.current = current + self.dataflow = dataflow + self.is_posedge = 'posedge' + self.rst_bit = 0 + self.rst_name = None + self.load_const_dict = {} + self._walk_in_first_ifbranch(node) + self._make_rst_info(node) + + def _walk_in_first_ifbranch(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): + self._walk_in_first_ifbranch(node.statement) + elif isinstance(node, Block): + for statement in node.statements: + self._walk_in_first_ifbranch(statement) + elif isinstance(node, IfStatement): + self._walk_in_first_ifbranch(node.true_statement) + elif isinstance(node, NonblockingSubstitution): + self.load_const_dict[node.left] = self._is_const(node.right) + else: + raise Exception('Pyverilog unknown error') + + def _is_const(self, node): + if 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 + elif hasattr(node, 'children'): + for child in node.children(): + if not self._is_const(child): + return False + else: + return True + elif isinstance(node, Rvalue): + self._is_const(node.var) + elif hasattr(node, 'value'): + return True + else: + raise Exception('Pyverilog unknown error') + + def get_is_const_subed(self): + return self.const_substituted + + def get_scopechain(self, node): + assert isinstance(node, Identifier), 'Node type should be Identifier.' + scope_list = self.current.get_module_list() + [util.ScopeLabel(str(node)),] + return util.ScopeChain(scope_list) + + def _make_rst_info(self, node): + """ [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): + self._make_rst_info(node.statement) + elif isinstance(node, Block): + self._make_rst_info(node.statements[0]) + elif isinstance(node, IfStatement): + self._make_rst_info(node.cond) + elif isinstance(node, Ulnot): + self.is_posedge = 'negedge' if self.is_posedge == 'posedge' else 'posedge' + self._make_rst_info(node.children()[0]) + elif isinstance(node, Pointer): + if isinstance(node.ptr, Identifier): + ptr_chain = self.get_scopechain(node.ptr) + if 'Parameter' in self.dataflow.terms[ptr_chain].termtype: + self.rst_bit = self.dataflow.binddict[ptr_chain][0].tree.eval() + self._make_rst_info(node.var) + else: + self.is_posedge = None + self.rst_name = None + self.rst_bit = None + elif hasattr(node.ptr, 'value'): + self.rst_bit = int(node.ptr.value) + self._make_rst_info(node.var) + elif isinstance(node, Identifier): + self.rst_name = str(node) + + 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 get_rst_info(self): + return self.rst_name, self.is_posedge, self.rst_bit \ No newline at end of file diff --git a/pyverilog/dataflow/visit.py b/pyverilog/dataflow/visit.py index 074d24f..784e808 100644 --- a/pyverilog/dataflow/visit.py +++ b/pyverilog/dataflow/visit.py @@ -1,6 +1,6 @@ #------------------------------------------------------------------------------- # visit.py -# +# # Basic classes for binding tree analysis # # Copyright (C) 2013, Shinya Takamaeda-Yamazaki @@ -127,7 +127,7 @@ def update(self, table): self.dict.update(table) def getDict(self): return self.dict - + class SignalTable(VariableTable): pass class ConstTable(VariableTable): pass class GenvarTable(VariableTable): pass @@ -271,6 +271,7 @@ def __init__(self, name, previous, frametype='none', self.frametype = frametype self.alwaysinfo = alwaysinfo + self.load_const_dict = {} self.condition = condition self.module = module @@ -304,6 +305,8 @@ def isIfelse(self): def getAlwaysInfo(self): return self.alwaysinfo + def getLoadConstDict(self): + return self.load_const_dict def getCondition(self): return self.condition @@ -324,9 +327,10 @@ def setNext(self, nextframe): self.next.append(nextframe) def setAlwaysInfo(self, clock_name, clock_edge, clock_bit, - reset_name, reset_edge, reset_bit, senslist): + reset_name, reset_edge, reset_bit, senslist, load_const_dict): self.alwaysinfo = AlwaysInfo(clock_name, clock_edge, clock_bit, reset_name, reset_edge, reset_bit, senslist) + self.load_const_dict = load_const_dict def addSignal(self, node): self.variables.addSignal(node.name, node) @@ -383,7 +387,7 @@ def setBlockingAssign(self, dst, bind): self.blockingassign[dst][c_i].tree = bind.tree return self.blockingassign[dst] = current + (bind,) - + def getBlockingAssign(self, dst): if dst in self.blockingassign: return self.blockingassign[dst] return () @@ -504,9 +508,10 @@ def getForIter(self): return self.for_iter def setAlwaysInfo(self, clock_name, clock_edge, clock_bit, - reset_name, reset_edge, reset_bit, senslist): + reset_name, reset_edge, reset_bit, senslist, load_const_dict): self.dict[self.current].setAlwaysInfo(clock_name, clock_edge, clock_bit, - reset_name, reset_edge, reset_bit, senslist) + reset_name, reset_edge, reset_bit, + senslist, load_const_dict) def setCurrent(self, current): self.current = current @@ -536,7 +541,7 @@ def addSignal(self, var): self.dict[self.current].addTaskPort(var) return self.dict[self.current].addSignal(var) - + def addConst(self, var): self.dict[self.current].addConst(var) def addGenvar(self, var): @@ -560,7 +565,7 @@ def getAllInstances(self): if dk[-1].scopetype == 'module': ret.append( (dk, self.dict[dk].getModuleName()) ) return tuple(ret) - + def getAllSignals(self): ret = collections.OrderedDict() for dk, dv in self.dict.items(): @@ -623,7 +628,7 @@ def getGenerateConditions(self): ptr = self.dict[ptr].previous return tuple(reversed(ret)) - def getAlwaysStatus(self): + def getAlwaysStatus(self, left_value): ptr = self.current frame = self.dict[ptr] alwaysinfo = frame.getAlwaysInfo() @@ -631,11 +636,33 @@ def getAlwaysStatus(self): if frame.isFunctioncall(): return None if frame.isTaskcall(): return None if not frame.isAlways(): return None - if alwaysinfo is not None: return alwaysinfo + if alwaysinfo is not None: + if left_value in frame.load_const_dict.keys() and frame.load_const_dict[left_value]: + return alwaysinfo + elif alwaysinfo.reset_edge != 'sync': + raise verror.FormatError('Illegal sensitivity list') + #ex. + #As follows, RST is reset signal for reg1 but clock for reg2. + #This is rearded as illegal sensitivity list. + +# always @(posedge CLK or posedge RST) begin +# if(RST) begin +# reg1 <= 8'd0; +# end else begin +# reg1 <= 8'd0; +# reg2 <= 8'd1; +# end +# end + else: + return self.to_noreset(alwaysinfo) ptr = self.dict[ptr].previous frame = self.dict[ptr] alwaysinfo = frame.getAlwaysInfo() - + + def to_noreset(self, alwaysinfo): + return AlwaysInfo(alwaysinfo.clock_name, alwaysinfo.clock_edge, alwaysinfo.clock_bit, + None, None, None, alwaysinfo.senslist) + def setBlockingAssign(self, dst, bind, scope): self.dict[scope].setBlockingAssign(dst, bind) @@ -700,7 +727,7 @@ def searchMatchedScopeChain(self, currentchain, targetchain): return ScopeChain( [currentchain[skiplength]] ) + rslt return None - if (currentchain[skiplength].scopetype == 'for' and + if (currentchain[skiplength].scopetype == 'for' and targetchain[0].scopetype == 'for'): if currentchain[skiplength].scopeloop != targetchain[0].scopeloop: return None @@ -710,7 +737,7 @@ def searchMatchedScopeChain(self, currentchain, targetchain): rslt = self.searchMatchedScopeChain(nextframe, targetchain[1:]) if rslt is not None: return ScopeChain( [currentchain[skiplength]] ) + rslt - + return None for nextframe in self.dict[currentchain].getNext(): diff --git a/testcode/irregular_reset0.v b/testcode/irregular_reset0.v new file mode 100644 index 0000000..087a5c7 --- /dev/null +++ b/testcode/irregular_reset0.v @@ -0,0 +1,15 @@ +module TOP0(CLK, RST); + input CLK, RST; + reg [7:0] cnt8; + + //no reset because condition is too complex + always @(posedge CLK or posedge RST) begin + if(RST && RST) begin + cnt8 <= 0; + end else begin + cnt8 <= 8'd1; + end + end + +endmodule + diff --git a/testcode/irregular_reset1.v b/testcode/irregular_reset1.v new file mode 100644 index 0000000..7f42388 --- /dev/null +++ b/testcode/irregular_reset1.v @@ -0,0 +1,16 @@ +module TOP1(CLK, RST); + input CLK, RST; + reg [7:0] cnt3,cnt1; + + + //no reset because variable is loaded + always @(posedge CLK or posedge RST) begin + if(RST) begin + cnt3 <= cnt1[0]; + end else begin + cnt3 <= 8'd1; + end + end + + +endmodule diff --git a/testcode/irregular_reset2.v b/testcode/irregular_reset2.v new file mode 100644 index 0000000..1b0aeab --- /dev/null +++ b/testcode/irregular_reset2.v @@ -0,0 +1,12 @@ +module TOP2(CLK, RST); + input CLK, RST; + reg [7:0] cnt4; + parameter zero = 0; + + // no reset because it has no if branch. + always @(posedge CLK or posedge RST) begin + cnt4 <= 0; + end + +endmodule + diff --git a/testcode/irregular_reset3.v b/testcode/irregular_reset3.v new file mode 100644 index 0000000..665995f --- /dev/null +++ b/testcode/irregular_reset3.v @@ -0,0 +1,15 @@ +module TOP3(CLK, RST); + input CLK, RST; + reg [7:0] cnt6,cnt1; + parameter zero = 0; + + //no reset because variable is loaded. + always @(posedge CLK or posedge RST) begin + if(RST) begin + cnt6 <= 7'd0 + cnt1[1:0]; + end else begin + cnt6 <= 8'd1; + end + end + +endmodule diff --git a/testcode/irregular_reset4.v b/testcode/irregular_reset4.v new file mode 100644 index 0000000..cf1a4b4 --- /dev/null +++ b/testcode/irregular_reset4.v @@ -0,0 +1,16 @@ +module TOP4(CLK, RST); + input CLK, RST; + reg [7:0] reg1,reg2; + parameter zero = 0; + + //Illegal! not reset for reg2. + always @(posedge CLK or posedge RST) begin + if(RST) begin + reg1 <= 8'd0; + end else begin + reg1 <= 8'd0; + reg2 <= 8'd1; + end + end + +endmodule diff --git a/testcode/reset.v b/testcode/reset.v index 216da39..773a687 100644 --- a/testcode/reset.v +++ b/testcode/reset.v @@ -19,19 +19,6 @@ module TOP(CLK, RST); 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 @@ -42,32 +29,17 @@ module TOP(CLK, RST); 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 + //reset for cnt7 only always @(posedge CLK) begin if(!RST) begin cnt7 <= 0; end else begin + cnt6 <= 8'd1; 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 diff --git a/testcode/vectoradd.v b/testcode/vectoradd.v index 014bc8e..e392135 100644 --- a/testcode/vectoradd.v +++ b/testcode/vectoradd.v @@ -38,7 +38,7 @@ module TOP(CLK, RST_X, localparam ST_WRITEWAIT = 8; localparam ST_DONE = 9; - always @(posedge CLK or negedge RST_X) begin + always @(posedge CLK) begin if(!RST_X) begin state <= ST_INIT; cnt0 <= 0; diff --git a/tests/ast_code_generator_test/Makefile b/tests/ast_code_generator_test/Makefile index 9f1fc58..aefe078 100644 --- a/tests/ast_code_generator_test/Makefile +++ b/tests/ast_code_generator_test/Makefile @@ -1,7 +1,8 @@ TEST=*.py ARGS= - -PYTHON=python3 +if [ -z "${PYTHON}" ];then + PYTHON=python3 +fi #PYTHON=python #OPT=-m pdb #OPT=-m cProfile -s time diff --git a/tests/dataflow_test/test_reset.py b/tests/dataflow_test/test_reset.py index ecd8c4e..6dc641d 100644 --- a/tests/dataflow_test/test_reset.py +++ b/tests/dataflow_test/test_reset.py @@ -6,6 +6,17 @@ codedir = '../../testcode/' expected = """\ +TOP.cnt1: sync TOP.RST[0]posedge TOP.CLK[0] +TOP.cnt10: sync TOP.RST[0]posedge TOP.CLK[0] +TOP.cnt2: posedge TOP.RST[0]posedge TOP.CLK[0] +TOP.cnt5: posedge TOP.RST[0]posedge TOP.CLK[0] +TOP.cnt6: None None[None]posedge TOP.CLK[0] +TOP.cnt7: sync TOP.RST[0]posedge TOP.CLK[0] +TOP.sub.CLK: [] [] +TOP.sub.RST: [] [] +TOP.sub.cnt9: sync TOP.sub.RST[0]posedge TOP.sub.CLK[0] +TOP.sub.zero: [] [] +TOP.zero: [] [] """ def test(): @@ -22,26 +33,27 @@ def test(): 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()) + ']') + directives = analyzer.get_directives() + instances = analyzer.getInstances() + terms = analyzer.getTerms() + binddict = analyzer.getBinddict() + sens_info = [] + for tk in sorted(binddict.keys(), key=lambda x:str(x)): + sens_info.append(str(tk) + ': ') + reset_info = (str(binddict[tk][0].getResetEdge()) + ' ' + + str(binddict[tk][0].getResetName())+ + '[' + str(binddict[tk][0].getResetBit()) +']') + clock_info = (str(binddict[tk][0].getClockEdge()) + ' ' + + str(binddict[tk][0].getClockName()) + + '[' + str(binddict[tk][0].getClockBit()) + ']') + sens_info.append(reset_info + clock_info) + sens_info.append('\n') + + rslt = ''.join(sens_info) + + print(rslt) + assert(expected == rslt) if __name__ == '__main__': diff --git a/tests/dataflow_test/test_reset_irrregular.py b/tests/dataflow_test/test_reset_irrregular.py new file mode 100644 index 0000000..19a545f --- /dev/null +++ b/tests/dataflow_test/test_reset_irrregular.py @@ -0,0 +1,39 @@ +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 +import pyverilog.utils.verror as verror + +codedir = '../../testcode/' + + +def test(): + filelist = [(codedir + 'irregular_reset0.v'), + (codedir + 'irregular_reset1.v'), + (codedir + 'irregular_reset2.v'), + (codedir + 'irregular_reset3.v'), + (codedir + 'irregular_reset4.v')] + + topmodule = 'TOP' + noreorder = False + nobind = False + include = None + define = None + + for i, file in enumerate(filelist): + topmodule = 'TOP' + str(i) + analyzer = VerilogDataflowAnalyzer(filelist, topmodule, + noreorder=noreorder, + nobind=nobind, + preprocess_include=include, + preprocess_define=define) + try: + analyzer.generate() + except verror.FormatError: + del analyzer + else: + raise Exception('Irregal reset code is passed.@' + file) + + +if __name__ == '__main__': + test()