From c9d6f22d6ec3e1b513a81001114337ec24693ea8 Mon Sep 17 00:00:00 2001 From: ryosuke fukatnai Date: Sun, 22 Feb 2015 17:33:20 +0900 Subject: [PATCH 1/3] =?UTF-8?q?4'sd=E3=81=AE=E3=82=88=E3=81=86=E3=81=AA?= =?UTF-8?q?=E3=82=B3=E3=83=BC=E3=83=89=E3=82=92=E8=A7=A3=E9=87=88=E3=81=A7?= =?UTF-8?q?=E3=81=8D=E3=81=AA=E3=81=84=E3=81=9F=E3=82=81=E4=BF=AE=E6=95=B4?= =?UTF-8?q?=E3=80=82lexer=E5=86=85=E3=81=AEtoken=E8=A7=A3=E9=87=88?= =?UTF-8?q?=E3=82=92=E3=81=99=E3=82=8B=E9=A0=86=E7=95=AA=E3=82=92=E5=85=A5?= =?UTF-8?q?=E3=82=8C=E6=9B=BF=E3=81=88=E3=81=9F=E3=81=A0=E3=81=91=E3=80=82?= =?UTF-8?q?=20casex=E6=96=87=E3=81=AB=E3=81=A4=E3=81=84=E3=81=A6case?= =?UTF-8?q?=E6=96=87=E3=81=A8=E5=90=8C=E6=A7=98=E3=81=AB=E8=A7=A3=E9=87=88?= =?UTF-8?q?=E3=81=99=E3=82=8B=E6=A9=9F=E8=83=BD=E3=81=AE=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 上記確認テストの追加。 --- pyverilog/testcode/casex.v | 24 ++++++++ pyverilog/testcode/signed.v | 18 ++++++ pyverilog/testcode/test_sd.py | 108 ++++++++++++++++++++++++++++++++++ pyverilog/vparser/ast.py | 17 +++--- pyverilog/vparser/lexer.py | 41 +++++++------ pyverilog/vparser/parser.py | 42 +++++++------ 6 files changed, 207 insertions(+), 43 deletions(-) create mode 100644 pyverilog/testcode/casex.v create mode 100644 pyverilog/testcode/signed.v create mode 100644 pyverilog/testcode/test_sd.py diff --git a/pyverilog/testcode/casex.v b/pyverilog/testcode/casex.v new file mode 100644 index 0000000..2f2ce32 --- /dev/null +++ b/pyverilog/testcode/casex.v @@ -0,0 +1,24 @@ +module TOP(CLK, RST, LED); + input CLK, RST; + output [7:0] LED; + reg [7:0] cnt; + always @(posedge CLK) begin + if(RST) begin + cnt <= 0; + end else begin + casex(cnt) + 'b00: begin + cnt <= cnt + 1; + end + 'b1x: begin + cnt <= 0; + end + default: begin + cnt <= cnt + 1; + end + endcase + end + end + assign LED = cnt; +endmodule + diff --git a/pyverilog/testcode/signed.v b/pyverilog/testcode/signed.v new file mode 100644 index 0000000..4bd8514 --- /dev/null +++ b/pyverilog/testcode/signed.v @@ -0,0 +1,18 @@ +//`default_nettype none + +module TOP(CLK, RST); + input CLK, RST; + reg [7:0] cnt; + + + always @(posedge CLK or negedge RST) begin + if(RST) begin + cnt <= 'd0; + end else begin + cnt <= cnt + 1'sd1; + end + end + + +endmodule + diff --git a/pyverilog/testcode/test_sd.py b/pyverilog/testcode/test_sd.py new file mode 100644 index 0000000..02ed63f --- /dev/null +++ b/pyverilog/testcode/test_sd.py @@ -0,0 +1,108 @@ +#------------------------------------------------------------------------------- +# test_sd.py +# +# Lexical analyzer +# +# Copyright (C) 2015, ryosuke fukatani +# License: Apache 2.0 +#------------------------------------------------------------------------------- + + +import sys +import os +import subprocess + +sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) ) + +from pyverilog.dataflow.dataflow_analyzer import * +import unittest + + +class TestSequenceFunctions(unittest.TestCase): + def setUp(self): + path_clone = sys.path + pop_target = [] + for i,path in enumerate(path_clone): + if path == 'C:\\Python27\\lib\\site-packages\\pyverilog-0.9.0-py2.7.egg': + pop_target.append(i) + for i in reversed(pop_target): + sys.path.pop(i) + reload(pyverilog.dataflow.dataflow_analyzer) + + def test_signed(self): + terms, binddict = self.dataflow_wrapper("signed.v") + self.assertEqual(binddict.values()[0][0].tostr(), + "(Bind dest:TOP.cnt tree:(Branch Cond:(Terminal TOP.RST) True:(IntConst 'd0) False:(Operator Plus Next:(Terminal TOP.cnt),(IntConst 1'sd1))))") + + def test_casex(self): + self.dataflow_wrapper("casex.v") + + def dataflow_wrapper(self,code_file): + + from optparse import OptionParser + + optparser = OptionParser() + optparser.add_option("-v","--version",action="store_true",dest="showversion", + default=False,help="Show the version") + optparser.add_option("-I","--include",dest="include",action="append", + default=[],help="Include path") + optparser.add_option("-D",dest="define",action="append", + default=[],help="Macro Definition") + optparser.add_option("-t","--top",dest="topmodule", + default="TOP",help="Top module, Default=TOP") + optparser.add_option("--nobind",action="store_true",dest="nobind", + default=False,help="No binding traversal, Default=False") + optparser.add_option("--noreorder",action="store_true",dest="noreorder", + default=False,help="No reordering of binding dataflow, Default=False") + + filelist = {code_file} + options = optparser.get_default_values() + + + for f in filelist: + if not os.path.exists(f): raise IOError("file not found: " + f) + + verilogdataflowanalyzer = VerilogDataflowAnalyzer(filelist, options.topmodule, + noreorder=options.noreorder, + nobind=options.nobind, + preprocess_include=options.include, + preprocess_define=options.define) + verilogdataflowanalyzer.generate() + + directives = verilogdataflowanalyzer.get_directives() + print('Directive:') + for dr in directives: + print(dr) + + instances = verilogdataflowanalyzer.getInstances() + print('Instance:') + for ins in instances: + print(ins) + + if options.nobind: + print('Signal:') + signals = verilogdataflowanalyzer.getSignals() + for sig in signals: + print(sig) + + print('Const:') + consts = verilogdataflowanalyzer.getConsts() + for con in consts: + print(con) + + else: + terms = verilogdataflowanalyzer.getTerms() + print('Term:') + for tk, tv in sorted(terms.items(), key=lambda x:len(x[0])): + print(tv.tostr()) + + binddict = verilogdataflowanalyzer.getBinddict() + print('Bind:') + for bk, bv in sorted(binddict.items(), key=lambda x:len(x[0])): + for bvi in bv: + print(bvi.tostr()) + + return terms, binddict + +if __name__ == '__main__': + unittest.main() diff --git a/pyverilog/vparser/ast.py b/pyverilog/vparser/ast.py index 8a78d6f..62fc4a6 100644 --- a/pyverilog/vparser/ast.py +++ b/pyverilog/vparser/ast.py @@ -1,9 +1,10 @@ #------------------------------------------------------------------------------- # ast.py -# +# # Verilog HDL AST classes with Pyverilog # # Copyright (C) 2013, Shinya Takamaeda-Yamazaki +# edited by ryosuke fukatani # License: Apache 2.0 #------------------------------------------------------------------------------- @@ -47,7 +48,7 @@ def __hash__(self): s = hash(tuple([getattr(self, a) for a in self.attr_names])) c = hash(self.children()) return hash((s, c)) - + ################################################################################ class Source(Node): attr_names = ('name',) @@ -171,7 +172,7 @@ def children(self): nodelist = [] if self.width: nodelist.append(self.width) return tuple(nodelist) - + class Input(Variable): pass class Output(Variable): pass class Inout(Variable): pass @@ -347,11 +348,11 @@ class Power(Operator): pass class Times(Operator): pass class Divide(Operator): pass class Mod(Operator): pass -################################################################################ +################################################################################ # Level 3 class Plus(Operator): pass class Minus(Operator): pass -################################################################################ +################################################################################ # Level 4 class Sll(Operator): pass class Srl(Operator): pass @@ -510,6 +511,8 @@ def children(self): if self.caselist: nodelist.extend(self.caselist) return tuple(nodelist) +class CasexStatement(CaseStatement): pass + class Case(Node): attr_names = () def __init__(self, cond, statement): @@ -540,7 +543,7 @@ def children(self): if self.statement: nodelist.append(self.statement) return tuple(nodelist) -class EventStatement(Node): +class EventStatement(Node): attr_names = () def __init__(self, senslist): self.senslist = senslist @@ -589,7 +592,7 @@ def children(self): if self.parameterlist: nodelist.extend(self.parameterlist) if self.instances: nodelist.extend(self.instances) return tuple(nodelist) - + class Instance(Node): attr_names = ('name', 'module') def __init__(self, module, name, portlist, parameterlist, array=None): diff --git a/pyverilog/vparser/lexer.py b/pyverilog/vparser/lexer.py index fb1ccad..4979fb0 100644 --- a/pyverilog/vparser/lexer.py +++ b/pyverilog/vparser/lexer.py @@ -1,9 +1,12 @@ #------------------------------------------------------------------------------- # lexer.py -# +# # Lexical analyzer # # Copyright (C) 2013, Shinya Takamaeda-Yamazaki +# +# edited by ryosuke fukatani +# # License: Apache 2.0 #------------------------------------------------------------------------------- @@ -45,9 +48,9 @@ def token(self): 'MODULE', 'ENDMODULE', 'BEGIN', 'END', 'GENERATE', 'ENDGENERATE', 'GENVAR', 'FUNCTION', 'ENDFUNCTION', 'TASK', 'ENDTASK', 'INPUT', 'INOUT', 'OUTPUT', 'TRI', 'REG', 'WIRE', 'INTEGER', 'REAL', 'SIGNED', - 'PARAMETER', 'LOCALPARAM', + 'PARAMETER', 'LOCALPARAM', 'ASSIGN', 'ALWAYS', 'SENS_OR', 'POSEDGE', 'NEGEDGE', 'INITIAL', - 'IF', 'ELSE', 'FOR', 'WHILE', 'CASE', 'ENDCASE', 'DEFAULT', + 'IF', 'ELSE', 'FOR', 'WHILE', 'CASE', 'CASEX', 'ENDCASE', 'DEFAULT', 'WAIT', 'FOREVER', 'DISABLE', 'FORK', 'JOIN', ) @@ -62,7 +65,7 @@ def token(self): 'PLUS','MINUS','POWER','TIMES','DIVIDE','MOD', 'NOT', 'OR', 'NOR', 'AND', 'NAND', 'XOR', 'XNOR', 'LOR', 'LAND', 'LNOT', - 'LSHIFTA', 'RSHIFTA', 'LSHIFT', 'RSHIFT', + 'LSHIFTA', 'RSHIFTA', 'LSHIFT', 'RSHIFT', 'LT', 'GT', 'LE', 'GE', 'EQ', 'NE', 'EQL', 'NEL', 'COND', # ? 'EQUALS', @@ -78,7 +81,7 @@ def token(self): 'INTNUMBER_OCT', 'SIGNED_INTNUMBER_OCT', 'INTNUMBER_BIN', 'SIGNED_INTNUMBER_BIN', 'LPAREN','RPAREN', 'LBRACKET', 'RBRACKET', 'LBRACE', 'RBRACE', - 'DELAY', 'DOLLER', + 'DELAY', 'DOLLER', ) skipped = ( @@ -188,7 +191,7 @@ def t_COMMENTOUT(self, t): octal_escape = r"""([0-7]{1,3})""" hex_escape = r"""(x[0-9a-fA-F]+)""" escape_sequence = r"""(\\("""+simple_escape+'|'+octal_escape+'|'+hex_escape+'))' - string_char = r"""([^"\\\n]|"""+escape_sequence+')' + string_char = r"""([^"\\\n]|"""+escape_sequence+')' string_literal = '"'+string_char+'*"' identifier = r"""(([a-zA-Z_])([a-zA-Z_0-9$])*)|((\\\S)(\S)*)""" @@ -201,38 +204,38 @@ def t_STRING_LITERAL(self, t): def t_FLOATNUMBER(self, t): return t - @TOKEN(bin_number) - def t_INTNUMBER_BIN(self, t): - return t - @TOKEN(signed_bin_number) def t_SIGNED_INTNUMBER_BIN(self, t): return t - @TOKEN(octal_number) - def t_INTNUMBER_OCT(self, t): + @TOKEN(bin_number) + def t_INTNUMBER_BIN(self, t): return t @TOKEN(signed_octal_number) def t_SIGNED_INTNUMBER_OCT(self, t): return t - @TOKEN(hex_number) - def t_INTNUMBER_HEX(self, t): - return t + @TOKEN(octal_number) + def t_INTNUMBER_OCT(self, t): + return t @TOKEN(signed_hex_number) def t_SIGNED_INTNUMBER_HEX(self, t): return t - @TOKEN(decimal_number) - def t_INTNUMBER_DEC(self, t): - return t + @TOKEN(hex_number) + def t_INTNUMBER_HEX(self, t): + return t @TOKEN(signed_decimal_number) def t_SIGNED_INTNUMBER_DEC(self, t): return t + @TOKEN(decimal_number) + def t_INTNUMBER_DEC(self, t): + return t + @TOKEN(identifier) def t_ID(self, t): t.type = self.reserved.get(t.value, 'ID') @@ -258,7 +261,7 @@ def _find_tok_column(self, token): if self.lexer.lexdata[i] == '\n': break i -= 1 return (token.lexpos - i) + 1 - + def _make_tok_location(self, token): return (token.lineno, self._find_tok_column(token)) diff --git a/pyverilog/vparser/parser.py b/pyverilog/vparser/parser.py index cf83b51..7a46535 100644 --- a/pyverilog/vparser/parser.py +++ b/pyverilog/vparser/parser.py @@ -1,9 +1,10 @@ #------------------------------------------------------------------------------- # parser.py -# +# # Parser # # Copyright (C) 2013, Shinya Takamaeda-Yamazaki +# edited by ryosuke fukatani # License: Apache 2.0 #------------------------------------------------------------------------------- @@ -51,7 +52,7 @@ def __init__(self): #self.parser = ply.yacc.yacc(module=self) ## Use this if you want to build the parser using LALR(1) instead of SLR self.parser = ply.yacc.yacc(module=self, method="LALR") - + def _lexer_error_func(self, msg, line, column): self._parse_error(msg, self._coord(line, column)) @@ -60,7 +61,7 @@ def get_directives(self): def get_default_nettype(self): return self.lexer.get_default_nettype() - + # Returns AST def parse(self, text, debug=0): return self.parser.parse(text, lexer=self.lexer, debug=debug) @@ -325,7 +326,7 @@ def p_ioport_portname(self, p): def p_width(self,p): 'width : LBRACKET expression COLON expression RBRACKET' - p[0] = Width(p[2], p[4]) + p[0] = Width(p[2], p[4]) def p_length(self,p): 'length : LBRACKET expression COLON expression RBRACKET' @@ -784,7 +785,7 @@ def p_expression_lesseq(self, p): def p_expression_greatereq(self, p): 'expression : expression GE expression' p[0] = GreaterEq(p[1], p[3]) - + ###################################################################### # Level 7 def p_expression_eq(self, p): @@ -893,7 +894,7 @@ def p_concatlist_one(self, p): def p_repeat(self, p): 'repeat : LBRACE expression concat RBRACE' - p[0] = Repeat(p[3], p[2]) + p[0] = Repeat(p[3], p[2]) def p_partselect(self, p): 'partselect : identifier LBRACKET expression COLON expression RBRACKET' @@ -1047,6 +1048,7 @@ def p_sens_all_paren(self, p): def p_basic_statement(self, p): """basic_statement : if_statement | case_statement + | casex_statement | for_statement | while_statement | event_statement @@ -1247,6 +1249,10 @@ def p_case_statement(self, p): 'case_statement : CASE LPAREN case_comp RPAREN casecontent_statements ENDCASE' p[0] = CaseStatement(p[3], p[5]) + def p_casex_statement(self, p): + 'casex_statement : CASEX LPAREN case_comp RPAREN casecontent_statements ENDCASE' + p[0] = CasexStatement(p[3], p[5]) + def p_case_comp(self, p): 'case_comp : expression' p[0] = p[1] @@ -1328,11 +1334,11 @@ def p_instance_or(self, p): def p_instance_bodylist(self, p): 'instance_bodylist : instance_bodylist COMMA instance_body' p[0] = p[1] + (p[3],) - + def p_instance_bodylist_one(self, p): 'instance_bodylist : instance_body' p[0] = (p[1],) - + def p_instance_body(self, p): 'instance_body : ID LPAREN instance_ports RPAREN' p[0] = (p[1], p[3], None) @@ -1358,11 +1364,11 @@ def p_instance_or_noname(self, p): def p_instance_bodylist_noname(self, p): 'instance_bodylist_noname : instance_bodylist_noname COMMA instance_body_noname' p[0] = p[1] + (p[3],) - + def p_instance_bodylist_one_noname(self, p): 'instance_bodylist_noname : instance_body_noname' p[0] = (p[1],) - + def p_instance_body_noname(self, p): 'instance_body_noname : LPAREN instance_ports RPAREN' p[0] = ('', p[2], None) @@ -1475,7 +1481,7 @@ def p_generate_items_one(self, p): p[0] = (p[1],) def p_generate_item(self, p): - """generate_item : standard_item + """generate_item : standard_item | generate_if | generate_for """ @@ -1582,6 +1588,7 @@ def p_function_calc(self, p): | for_statement | while_statement | case_statement + | casex_statement | block | namedblock """ @@ -1641,6 +1648,7 @@ def p_task_calc(self, p): | for_statement | while_statement | case_statement + | casex_statement | block | namedblock """ @@ -1684,11 +1692,11 @@ def p_single_statement_disable(self, p): 'single_statement : disable SEMICOLON' p[0] = SingleStatement(p[1]) - ## fix me: to support task-call-statement + ## fix me: to support task-call-statement #def p_single_statement_taskcall(self, p): # 'single_statement : functioncall SEMICOLON' # p[0] = SingleStatement(p[1]) - + #def p_single_statement_taskcall_empty(self, p): # 'single_statement : taskcall SEMICOLON' # p[0] = SingleStatement(p[1]) @@ -1707,7 +1715,7 @@ def p_error(self, p): print("Syntax error") if p: self._parse_error( - 'before: %s' % p.value, + 'before: %s' % p.value, self._coord(p.lineno)) else: self._parse_error('At end of input', '') @@ -1744,7 +1752,7 @@ def preprocess(self): rm = 'rm -f ' + self.preprocess_output subprocess.call(rm, shell=True) return text - + def parse(self, preprocess_output='preprocess.output', debug=0): text = self.preprocess() ast = self.parser.parse(text, debug=debug) @@ -1766,7 +1774,7 @@ def showVersion(): print(VERSION) print(USAGE) sys.exit() - + optparser = OptionParser() optparser.add_option("-v","--version",action="store_true",dest="showversion", default=False,help="Show the version") @@ -1786,7 +1794,7 @@ def showVersion(): if len(filelist) == 0: showVersion() - codeparser = VerilogCodeParser(filelist, + codeparser = VerilogCodeParser(filelist, preprocess_include=options.include, preprocess_define=options.define) ast = codeparser.parse() From 7442143009587f6df4db323b90621e261c215ef5 Mon Sep 17 00:00:00 2001 From: ryosuke fukatani Date: Thu, 26 Feb 2015 23:14:22 +0900 Subject: [PATCH 2/3] =?UTF-8?q?=E7=B4=B0=E3=81=8B=E3=81=84=E3=83=90?= =?UTF-8?q?=E3=82=B0=E4=BF=AE=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit always @(posedge CLK or posedge RST) begin if(RST) begin cnt[1:0] <= 0; end else begin cnt[1] <= SEND; cnt[0] <= 0; end end のようなコードで正しいバインドが生成できるように。 --- pyverilog/dataflow/dataflow.py | 35 +++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/pyverilog/dataflow/dataflow.py b/pyverilog/dataflow/dataflow.py index 30877b1..41d53fa 100644 --- a/pyverilog/dataflow/dataflow.py +++ b/pyverilog/dataflow/dataflow.py @@ -1,9 +1,10 @@ #------------------------------------------------------------------------------- # dataflow.py -# +# # Basic classes of Data flow nodes # # Copyright (C) 2013, Shinya Takamaeda-Yamazaki +# modified by ryoduke fukatani # License: Apache 2.0 #------------------------------------------------------------------------------- @@ -47,7 +48,7 @@ def __repr__(self): pass def tostr(self): pass def tocode(self, dest='dest'): return self.__repr__() def tolabel(self): return self.__repr__() - def children(self): + def children(self): nodelist = [] return tuple(nodelist) def __eq__(self, other): @@ -69,8 +70,8 @@ def __repr__(self): return ret[:-1] def tostr(self): ret = '(Terminal ' - for n in self.name: - ret += str(n) + '.' + for n in self.name: + ret += str(n) + '.' return ret[0:-1] + ')' def tocode(self, dest='dest'): #ret = '' @@ -207,7 +208,7 @@ def __eq__(self, other): return self.operator == other.operator and self.nextnodes == other.nextnodes def __hash__(self): return hash((self.operator, tuple(self.nextnodes))) - + class DFPartselect(DFNotTerminal): attr_names = () def __init__(self, var, msb, lsb): @@ -312,8 +313,8 @@ def __repr__(self): return 'Branch' def tostr(self): ret = '(Branch' - if self.condnode is not None: ret += ' Cond:' + self.condnode.tostr() - if self.truenode is not None: ret += ' True:' + self.truenode.tostr() + if self.condnode is not None: ret += ' Cond:' + self.condnode.tostr() + if self.truenode is not None: ret += ' True:' + self.truenode.tostr() if self.falsenode is not None: ret += ' False:'+ self.falsenode.tostr() ret += ')' return ret @@ -334,7 +335,7 @@ def _tocode_always(self, dest='dest', always='clockedge'): ret = 'if(' if self.condnode is not None: ret += self.condnode.tocode(dest) ret += ') begin\n' - if self.truenode is not None: + if self.truenode is not None: if isinstance(self.truenode, DFBranch): ret += self.truenode.tocode(dest, always=always) elif always == 'clockedge': @@ -342,7 +343,7 @@ def _tocode_always(self, dest='dest', always='clockedge'): elif always == 'combination': ret += dest + ' = ' + self.truenode.tocode(dest) + ';\n' ret += 'end\n' - if self.falsenode is not None: + if self.falsenode is not None: ret += 'else begin\n' if isinstance(self.falsenode, DFBranch): ret += self.falsenode.tocode(dest, always=always) @@ -462,7 +463,7 @@ def __repr__(self): return 'Delay' def tostr(self): ret = '(Delay ' - if self.nextnode is not None: ret += self.nextnode.tostr() + if self.nextnode is not None: ret += self.nextnode.tostr() ret += ')' return ret def tocode(self, dest='dest'): @@ -522,8 +523,8 @@ def __repr__(self): return str(self.name) def tostr(self): ret = '(Term name:' + str(self.name) + ' type:' + str(self.termtype) - if self.msb is not None: ret += ' msb:' + self.msb.tostr() - if self.lsb is not None: ret += ' lsb:' + self.lsb.tostr() + if self.msb is not None: ret += ' msb:' + self.msb.tostr() + if self.lsb is not None: ret += ' lsb:' + self.lsb.tostr() if self.lenmsb is not None: ret += ' lenmsb:' + self.lenmsb.tostr() if self.lenlsb is not None: ret += ' lenlsb:' + self.lenlsb.tostr() ret += ')' @@ -641,7 +642,7 @@ def _localparam(self): code = 'localparam ' + dest code += ' = ' + self.tree.tocode(dest) + ';\n' return code - + def _assign(self): dest = self.getdest() code = 'assign ' + dest @@ -652,10 +653,10 @@ def _always_clockedge(self): dest = self.getdest() code = 'always @(' if self.alwaysinfo.clock_edge is not None and self.alwaysinfo.clock_name is not None: - code += self.alwaysinfo.clock_edge + ' ' + code += self.alwaysinfo.clock_edge + ' ' code += util.toFlatname(self.alwaysinfo.clock_name) if self.alwaysinfo.reset_edge is not None and self.alwaysinfo.reset_name is not None: - code += ' or ' + code += ' or ' code += self.alwaysinfo.reset_edge + ' ' code += util.toFlatname(self.alwaysinfo.reset_name) code += ') begin\n' @@ -681,7 +682,7 @@ def _always_combination(self): code += 'end\n' code += '\n' return code - + def isClockEdge(self): if self.alwaysinfo is None: return False return self.alwaysinfo.isClockEdge() @@ -752,7 +753,7 @@ def setBind(self, name, bind): currentbindlist = self.binddict[name] c_i = 0 for c in currentbindlist: - if c.msb == bind.msb and c.msb == bind.msb and c.ptr == bind.ptr: + if c.msb == bind.msb and c.lsb == bind.lsb and c.ptr == bind.ptr: self.binddict[name][c_i].tree = bind.tree return c_i += 1 From bdb4d7375c3dffa2af9e09e5055f1c3198e699dd Mon Sep 17 00:00:00 2001 From: ryosuke fukatani Date: Sun, 1 Mar 2015 23:18:53 +0900 Subject: [PATCH 3/3] Modified bugs about $signed and $unsigned to work makeDFtree for both tasks and to parse $signed task. --- pyverilog/dataflow/bindvisitor.py | 204 +++++++++++++++--------------- pyverilog/testcode/signed_task.v | 14 ++ pyverilog/testcode/test_sd.py | 7 +- pyverilog/vparser/parser.py | 6 +- 4 files changed, 127 insertions(+), 104 deletions(-) create mode 100644 pyverilog/testcode/signed_task.v diff --git a/pyverilog/dataflow/bindvisitor.py b/pyverilog/dataflow/bindvisitor.py index 1ad7d83..97ce6d8 100644 --- a/pyverilog/dataflow/bindvisitor.py +++ b/pyverilog/dataflow/bindvisitor.py @@ -1,6 +1,6 @@ #------------------------------------------------------------------------------- # bindvisitor.py -# +# # Binding visitor # # Copyright (C) 2013, Shinya Takamaeda-Yamazaki @@ -138,28 +138,28 @@ def visit_Task(self, node): def visit_InstanceList(self, node): for i in node.instances: self.visit(i) - + def visit_Instance(self, node): if node.array: return self._visit_Instance_array(node) nodename = node.name return self._visit_Instance_body(node, nodename) - + def _visit_Instance_array(self, node): if node.name == '': raise verror.FormatError("Module %s requires an instance name" % node.module) - + current = self.frames.getCurrent() msb = self.optimize(self.getTree(node.array.msb, current)).value lsb = self.optimize(self.getTree(node.array.lsb, current)).value num_of_pins = msb + 1 - lsb - + for i in range(lsb, msb+1): nodename = node.name + '_' + str(i) self._visit_Instance_body(node, nodename, arrayindex=i) - + def _visit_Instance_body(self, node, nodename, arrayindex=None): if node.module in primitives: return self._visit_Instance_primitive(node, arrayindex) - + if nodename == '': raise verror.FormatError("Module %s requires an instance name" % node.module) @@ -173,7 +173,7 @@ def _visit_Instance_body(self, node, nodename, arrayindex=None): value = self.optimize(self.getTree(param.argname, current)) paramname = paramnames[paramnames_i] if param.paramname is None else param.paramname if paramname not in paramnames: - raise verror.FormatError("No such parameter: %s in %s" % + raise verror.FormatError("No such parameter: %s in %s" % (paramname, nodename)) name = scope + ScopeLabel(paramname, 'signal') self.setConstant(name, value) @@ -211,7 +211,7 @@ def _visit_Instance_primitive(self, node, arrayindex=None): [Pointer(p.argname, IntConst(str(arrayindex))) for p in node.portlist[1:]]) right = primitive_type(Concat(concat_list)) self.addBind(left, right, bindtype='assign') - + def visit_Initial(self, node): pass #label = self.labels.get( self.frames.getLabelKey('initial') ) @@ -227,8 +227,8 @@ def visit_Always(self, node): generate=self.frames.isGenerate(), always=True) - (clock_name, clock_edge, - reset_name, reset_edge, + (clock_name, clock_edge, + reset_name, reset_edge, senslist) = self._createAlwaysinfo(node, current) self.frames.setAlwaysInfo(clock_name, clock_edge, @@ -317,10 +317,10 @@ def _if_true(self, node): current = self.stackNextFrame(label, 'if', frametype='ifthen', condition=node.cond, - functioncall=self.frames.isFunctioncall(), + functioncall=self.frames.isFunctioncall(), taskcall=self.frames.isTaskcall(), - generate=self.frames.isGenerate(), - always=self.frames.isAlways(), + generate=self.frames.isGenerate(), + always=self.frames.isAlways(), initial=self.frames.isInitial()) self.copyPreviousNonblockingAssign(current + ScopeLabel(label, 'if')) @@ -334,8 +334,8 @@ def _if_false(self, node, label): label = self._toELSE(label) current = self.stackNextFrame(label, 'if', frametype='ifelse', - condition=node.cond, - functioncall=self.frames.isFunctioncall(), + condition=node.cond, + functioncall=self.frames.isFunctioncall(), taskcall=self.frames.isTaskcall(), generate=self.frames.isGenerate(), always=self.frames.isAlways(), @@ -365,15 +365,15 @@ def _case(self, comp, caselist, myframes): label = self.labels.get( self.frames.getLabelKey('if') ) current = self.stackNextFrame(label, 'if', frametype='ifthen', - condition=cond, - functioncall=self.frames.isFunctioncall(), + condition=cond, + functioncall=self.frames.isFunctioncall(), taskcall=self.frames.isTaskcall(), - generate=self.frames.isGenerate(), - always=self.frames.isAlways(), + generate=self.frames.isGenerate(), + always=self.frames.isAlways(), initial=self.frames.isInitial()) self.copyPreviousNonblockingAssign(current + ScopeLabel(label, 'if')) - + myframes.append( self.frames.getCurrent() ) if case.statement is not None: @@ -384,14 +384,14 @@ def _case(self, comp, caselist, myframes): label = self._toELSE(label) current = self.stackNextFrame(label, 'if', - frametype='ifelse', - condition=cond, - functioncall=self.frames.isFunctioncall(), + frametype='ifelse', + condition=cond, + functioncall=self.frames.isFunctioncall(), taskcall=self.frames.isTaskcall(), - generate=self.frames.isGenerate(), - always=self.frames.isAlways(), + generate=self.frames.isGenerate(), + always=self.frames.isAlways(), initial=self.frames.isInitial()) - + self.copyPreviousNonblockingAssign(current + ScopeLabel(label, 'if')) myframes.append( current + ScopeLabel(label, 'if') ) @@ -424,11 +424,11 @@ def visit_ForStatement(self, node): ## main-statement current = self.stackNextFrame(label, 'for', - frametype='for', - functioncall=self.frames.isFunctioncall(), + frametype='for', + functioncall=self.frames.isFunctioncall(), taskcall=self.frames.isTaskcall(), - generate=self.frames.isGenerate(), - always=self.frames.isAlways(), + generate=self.frames.isGenerate(), + always=self.frames.isAlways(), initial=self.frames.isInitial(), loop=loop, loop_iter=self.frames.getForIter()) @@ -464,11 +464,11 @@ def visit_WhileStatement(self, node): ## main-statement current = self.stackNextFrame(label, 'while', - frametype='while', - functioncall=self.frames.isFunctioncall(), + frametype='while', + functioncall=self.frames.isFunctioncall(), taskcall=self.frames.isTaskcall(), - generate=self.frames.isGenerate(), - always=self.frames.isAlways(), + generate=self.frames.isGenerate(), + always=self.frames.isAlways(), initial=self.frames.isInitial(), loop=loop) @@ -496,7 +496,7 @@ def visit_Block(self, node): functioncall=self.frames.isFunctioncall(), taskcall=self.frames.isTaskcall(), generate=self.frames.isGenerate(), - always=self.frames.isAlways(), + always=self.frames.isAlways(), initial=self.frames.isInitial()) self.generic_visit(node) @@ -520,7 +520,7 @@ def visit_NonblockingSubstitution(self, node): def visit_SystemCall(self, node): print("Warning: Isolated system call is not supported: %s" % node.syscall) - + ############################################################################ def optimize(self, node): return self.optimizer.optimize(node) @@ -532,9 +532,9 @@ def stackInstanceFrame(self, instname, modulename): return current def stackNextFrame(self, label, scopetype, - frametype='none', - alwaysinfo=None, condition=None, - module=False, functioncall=False, taskcall=False, + frametype='none', + alwaysinfo=None, condition=None, + module=False, functioncall=False, taskcall=False, generate=False, always=False, initial=False, loop=None, loop_iter=None): current = self.frames.getCurrent() scopelabel = ScopeLabel(label, scopetype, loop) @@ -543,7 +543,7 @@ def stackNextFrame(self, label, scopetype, current = self.frames.addFrame(scopelabel, frametype=frametype, alwaysinfo=alwaysinfo, condition=condition, - module=module, functioncall=functioncall, taskcall=taskcall, + module=module, functioncall=functioncall, taskcall=taskcall, generate=generate, always=always, initial=initial, loop=loop, loop_iter=loop_iter) self.frames.setCurrent(nextscope) @@ -561,7 +561,7 @@ def copyFrameInfo(self, current): self.dataflow.addTerm(name, term) for name, definitions in self.frames.getConsts(current).items(): - if len(definitions) > 1: + if len(definitions) > 1: raise verror.FormatError("Multiple definitions for Constant") for definition in definitions: cterm = self.makeConstantTerm(name, definition, current) @@ -619,8 +619,8 @@ def copyPreviousNonblockingAssign(self, scope): condlist, flowlist = self.getCondflow(scope) alwaysinfo = bind.alwaysinfo raw_tree = bind.tree - new_bind = self.makeBind(name, msb, lsb, ptr, part_msb, part_lsb, - raw_tree, condlist, flowlist, + new_bind = self.makeBind(name, msb, lsb, ptr, part_msb, part_lsb, + raw_tree, condlist, flowlist, alwaysinfo=alwaysinfo) self.dataflow.addBind(name, new_bind) @@ -665,7 +665,7 @@ def getBindlist(self, name): return self.dataflow.getBindlist(name) def renameVar(self, name): - renamedvar = (name[:-1] + + renamedvar = (name[:-1] + ScopeLabel('_rn' + str(self.renamecnt) + '_' + name[-1].scopename, 'signal')) self.renamecnt += 1 @@ -703,7 +703,7 @@ def searchScopeConstantDefinition(self, blocklabel, name, current): matchedchain = self.frames.searchMatchedScopeChain(currentmodule, localchain) constdef = self.frames.getConstantDefinition(matchedchain, name) return constdef - + def searchScopeTerminal(self, blocklabel, name, current): currentmodule = self.getModuleScopeChain(current) localchain = currentmodule + self.toScopeChain(blocklabel, current) @@ -745,7 +745,7 @@ def searchScopeTaskPorts(self, blocklabel, name, current): if self.dataflow.hasTask(varname): return self.dataflow.getTaskPorts(varname) raise verror.DefinitionError('No such task: %s' % varname) - + def searchTerminal(self, name, scope): if len(scope) == 0: return None varname = scope + ScopeLabel(name, 'signal') @@ -829,7 +829,7 @@ def addBind(self, left, right, alwaysinfo=None, bindtype=None): def addInstanceParameterBind(self, param, name=None): lscope = self.frames.getCurrent() rscope = lscope[:-1] - paramname = name if param.paramname is None else param.paramname + paramname = name if param.paramname is None else param.paramname dst = self.getDestinations(paramname, lscope) self.addDataflow(dst, param.argname, lscope, rscope, None, 'parameter') @@ -887,7 +887,7 @@ def addDataflow_blocking(self, dst, right, lscope, rscope, alwaysinfo): else: self.resetConstant(name) - ############################################################################ + ############################################################################ def getCondflow(self, scope): condlist = self.getCondlist(scope) condlist = self.resolveCondlist(condlist, scope) @@ -900,7 +900,7 @@ def getCondlist(self, scope): while s is not None: frame = self.frames.dict[s] cond = frame.getCondition() - if cond is not None: + if cond is not None: ret.append(self.makeDFTree(cond, self.reduceIfScope(s))) if frame.isModule(): break if frame.isFunctioncall(): break @@ -941,7 +941,7 @@ def makeDFTree(self, node, scope): raise verror.DefinitionError('No such signal: %s' % node.name) return DFTerminal(name) name = self.searchTerminal(node.name, scope) - if name is None: + if name is None: raise verror.DefinitionError('No such signal: %s' % node.name) return DFTerminal(name) @@ -988,8 +988,8 @@ def makeDFTree(self, node, scope): var_df = self.makeDFTree(node.var, scope) ptr_df = self.makeDFTree(node.ptr, scope) - if (isinstance(var_df, DFTerminal) and - (signaltype.isRegArray(self.getTermtype(var_df.name)) or + if (isinstance(var_df, DFTerminal) and + (signaltype.isRegArray(self.getTermtype(var_df.name)) or signaltype.isWireArray(self.getTermtype(var_df.name)))): return DFPointer(var_df, ptr_df) return DFPartselect(var_df, ptr_df, copy.deepcopy(ptr_df)) @@ -1021,8 +1021,8 @@ def makeDFTree(self, node, scope): self.frames.setCurrent(scope) current = self.frames.addFrame( - ScopeLabel(label, 'functioncall'), - functioncall=True, generate=self.frames.isGenerate(), + ScopeLabel(label, 'functioncall'), + functioncall=True, generate=self.frames.isGenerate(), always=self.frames.isAlways()) varname = self.frames.getCurrent() + ScopeLabel(func.name,'signal') @@ -1033,7 +1033,7 @@ def makeDFTree(self, node, scope): funcargs = node.args if len(funcports) != len(funcargs): - raise verror.FormatError("%s takes exactly %d arguments. (%d given)" % + raise verror.FormatError("%s takes exactly %d arguments. (%d given)" % (func.name.name, len(funcports), len(funcargs))) for port in funcports: self.addTerm( Wire(port.name, port.width) ) @@ -1060,7 +1060,7 @@ def makeDFTree(self, node, scope): current = self.frames.addFrame( ScopeLabel(label, 'taskcall'), - taskcall=True, generate=self.frames.isGenerate(), + taskcall=True, generate=self.frames.isGenerate(), always=self.frames.isAlways()) varname = self.frames.getCurrent() + ScopeLabel(task.name,'signal') @@ -1069,7 +1069,7 @@ def makeDFTree(self, node, scope): taskargs = node.args if len(taskports) != len(taskargs): - raise verror.FormatError("%s takes exactly %d arguments. (%d given)" % + raise verror.FormatError("%s takes exactly %d arguments. (%d given)" % (task.name.name, len(taskports), len(taskargs))) for port in taskports: self.addTerm( Wire(port.name, port.width) ) @@ -1089,9 +1089,9 @@ def makeDFTree(self, node, scope): if isinstance(node, SystemCall): if node.syscall == 'unsigned': - return self.makeDFTree(node.args[0]) + return self.makeDFTree(node.args[0], scope) if node.syscall == 'signed': - return self.makeDFTree(node.args[0]) + return self.makeDFTree(node.args[0], scope) return DFIntConst('0') raise verror.FormatError("unsupported AST node type: %s %s" % @@ -1115,19 +1115,19 @@ def removeOverwrappedCondition(self, tree, current_bindlist, scope): msb, lsb = self.getTermWidth(tree.name) merged_tree = self.getFitTree(current_bindlist, msb, lsb) condlist, flowlist = self.getCondflow(scope) - (merged_tree, - rest_condlist, - rest_flowlist, + (merged_tree, + rest_condlist, + rest_flowlist, match_flowlist) = self.diffBranchTree(merged_tree, condlist, flowlist) return replace.replaceUndefined(merged_tree, tree.name) def resolveBlockingAssign(self, tree, scope): if tree is None: return None - if isinstance(tree, DFConstant): + if isinstance(tree, DFConstant): return tree - if isinstance(tree, DFEvalValue): + if isinstance(tree, DFEvalValue): return tree if isinstance(tree, DFTerminal): @@ -1170,19 +1170,19 @@ def resolveBlockingAssign(self, tree, scope): resolved_lsb = self.resolveBlockingAssign(tree.lsb, scope) resolved_var = self.resolveBlockingAssign(tree.var, scope) if isinstance(resolved_var, DFBranch): - return reorder.insertPartselect(resolved_var, + return reorder.insertPartselect(resolved_var, resolved_msb, resolved_lsb) return DFPartselect(resolved_var, resolved_msb, resolved_lsb) if isinstance(tree, DFPointer): resolved_ptr = self.resolveBlockingAssign(tree.ptr, scope) - if (isinstance(tree.var, DFTerminal) and + if (isinstance(tree.var, DFTerminal) and signaltype.isRegArray(self.getTermtype(tree.var.name))): current_bindlist = self.frames.getBlockingAssign(tree.var.name, scope) if len(current_bindlist) == 0: return DFPointer(tree.var, resolved_ptr) new_tree = DFPointer(tree.var, resolved_ptr) for bind in current_bindlist: - new_tree = DFBranch(DFOperator((bind.ptr, resolved_ptr), 'Eq'), + new_tree = DFBranch(DFOperator((bind.ptr, resolved_ptr), 'Eq'), bind.tree, new_tree) print(("Warning: " "Overwrting Blocking Assignment with Reg Array is not supported")) @@ -1201,7 +1201,7 @@ def getFitTree(self, bindlist, msb, lsb): for bind in bindlist: if bind.msb is None and bind.lsb is None: return bind.tree - if (self.optimize(bind.msb) == optimized_msb and + if (self.optimize(bind.msb) == optimized_msb and self.optimize(bind.lsb) == optimized_lsb): return bind.tree return self.getMergedTree(bindlist) @@ -1214,12 +1214,12 @@ def bindkey(x): lsb = 0 if x.lsb is None else x.lsb.value ptr = 0 if not isinstance(x.ptr, DFEvalValue) else x.ptr.value term = self.getTerm(x.dest) - length = (abs(self.optimize(term.msb).value - + length = (abs(self.optimize(term.msb).value - self.optimize(term.lsb).value) + 1) return ptr * length + lsb for bind in sorted(bindlist, key=bindkey): lsb = 0 if bind.lsb is None else bind.lsb.value - if last_ptr != (-1 if not isinstance(bind.ptr, DFEvalValue) + if last_ptr != (-1 if not isinstance(bind.ptr, DFEvalValue) else bind.ptr.value): continue if last_msb + 1 < lsb: @@ -1236,13 +1236,13 @@ def getDestinations(self, left, scope): part_offset = DFIntConst('0') for name, msb, lsb, ptr in reversed(dst): if len(dst) == 1: - ret.append((name, msb, lsb, ptr, None, None)) + ret.append((name, msb, lsb, ptr, None, None)) continue if msb is None and lsb is None: msb, lsb = self.getTermWidth(name) diff = reorder.reorder( DFOperator((msb, lsb), 'Minus') ) - part_lsb = part_offset + part_lsb = part_offset part_msb = reorder.reorder(DFOperator((part_offset, diff), 'Plus')) part_offset = reorder.reorder( DFOperator((part_msb, DFIntConst('1')), 'Plus')) @@ -1259,7 +1259,7 @@ def getDsts(self, left, scope): for n in left.list: dst.extend(list(self.getDsts(n, scope))) return tuple(dst) - ret = (self.getDst(left, scope),) + ret = (self.getDst(left, scope),) return ret def getDst(self, left, scope): @@ -1310,7 +1310,7 @@ def getDst(self, left, scope): if left.var.scope is not None: name = left.var.scope + ScopeLabel(left.var.name, 'signal') ptr = self.optimize(self.makeDFTree(left.ptr, scope)) - if (signaltype.isRegArray(self.getTermtype(name)) or + if (signaltype.isRegArray(self.getTermtype(name)) or signaltype.isWireArray(self.getTermtype(name))): return (name, None, None, ptr) return (name, ptr, copy.deepcopy(ptr), None) @@ -1319,25 +1319,25 @@ def getDst(self, left, scope): (str(type(left)), str(left))) ############################################################################ - def setDataflow(self, dst, raw_tree, condlist, flowlist, + def setDataflow(self, dst, raw_tree, condlist, flowlist, alwaysinfo=None, bindtype=None): for name, msb, lsb, ptr, part_msb, part_lsb in dst: bind = self.makeBind(name, msb, lsb, ptr, part_msb, part_lsb, - raw_tree, condlist, flowlist, + raw_tree, condlist, flowlist, num_dst=len(dst), - alwaysinfo=alwaysinfo, + alwaysinfo=alwaysinfo, bindtype=bindtype) self.dataflow.addBind(name, bind) if alwaysinfo is not None: self.setNonblockingAssign(name, dst, raw_tree, - msb, lsb, ptr, + msb, lsb, ptr, part_msb, part_lsb, alwaysinfo) - - def setDataflow_rename(self, dst, raw_tree, condlist, flowlist, + + def setDataflow_rename(self, dst, raw_tree, condlist, flowlist, scope, alwaysinfo=None): renamed_dst = self.getRenamedDst(dst) self.setRenamedTree(renamed_dst, raw_tree, alwaysinfo) @@ -1382,20 +1382,20 @@ def setRenamedTree(self, renamed_dst, raw_tree, alwaysinfo): msb, lsb = self.getTermWidth(name) self.setConstantTerm(name, Term(name, set(['Rename']), msb, lsb)) - def setRenamedFlow(self, dst, renamed_dst, condlist, flowlist, + def setRenamedFlow(self, dst, renamed_dst, condlist, flowlist, scope, alwaysinfo=None): term_i = 0 for name, msb, lsb, ptr, part_msb, part_lsb in dst: renamed_term = DFTerminal(renamed_dst[term_i][0]) - renamed_bind = self.makeBind(name, msb, lsb, ptr, part_msb, part_lsb, - renamed_term, condlist, flowlist, + renamed_bind = self.makeBind(name, msb, lsb, ptr, part_msb, part_lsb, + renamed_term, condlist, flowlist, num_dst=len(dst), alwaysinfo=alwaysinfo) self.dataflow.addBind(name, renamed_bind) self.frames.setBlockingAssign(name, renamed_bind, scope) term_i+=1 - ############################################################################ - def makeBind(self, name, msb, lsb, ptr, part_msb, part_lsb, + ############################################################################ + def makeBind(self, name, msb, lsb, ptr, part_msb, part_lsb, raw_tree, condlist, flowlist, num_dst=1, alwaysinfo=None, bindtype=None): @@ -1407,8 +1407,8 @@ def makeBind(self, name, msb, lsb, ptr, part_msb, part_lsb, if len(current_bindlist) > 0: for current_bind in current_bindlist: - if ( current_bind.msb == msb and - current_bind.lsb == lsb and + if ( current_bind.msb == msb and + current_bind.lsb == lsb and current_bind.ptr == ptr ): current_tree = current_bind.tree current_msb = current_bind.msb @@ -1421,12 +1421,12 @@ def makeBind(self, name, msb, lsb, ptr, part_msb, part_lsb, rest_flowlist = flowlist match_flowlist = () - if ( current_msb == msb and - current_lsb == lsb and + if ( current_msb == msb and + current_lsb == lsb and current_ptr == ptr ): - (rest_tree, - rest_condlist, - rest_flowlist, + (rest_tree, + rest_condlist, + rest_flowlist, match_flowlist) = self.diffBranchTree(current_tree, condlist, flowlist) add_tree = self.makeBranchTree(rest_condlist, rest_flowlist, raw_tree) @@ -1436,7 +1436,7 @@ def makeBind(self, name, msb, lsb, ptr, part_msb, part_lsb, tree = reorder.reorder( self.appendBranchTree(current_tree, match_flowlist, add_tree)) - + if num_dst > 1: tree = reorder.reorder( DFPartselect(tree, part_msb, part_lsb)) @@ -1446,13 +1446,13 @@ def makeBind(self, name, msb, lsb, ptr, part_msb, part_lsb, def diffBranchTree(self, tree, condlist, flowlist, matchflowlist=()): if len(condlist) == 0: return (tree, condlist, flowlist, matchflowlist) - if not isinstance(tree, DFBranch): + if not isinstance(tree, DFBranch): return (tree, condlist, flowlist, matchflowlist) if condlist[0] != tree.condnode: return (tree, condlist, flowlist, matchflowlist) if flowlist[0]: return self.diffBranchTree( - tree.truenode, condlist[1:], flowlist[1:], + tree.truenode, condlist[1:], flowlist[1:], matchflowlist+(flowlist[0],)) else: return self.diffBranchTree( @@ -1466,12 +1466,12 @@ def makeBranchTree(self, condlist, flowlist, node): else: return DFBranch(condlist[0], None, node) else: if flowlist[0]: return DFBranch( - condlist[0], + condlist[0], self.makeBranchTree(condlist[1:], flowlist[1:], node), None) else: return DFBranch( - condlist[0], - None, + condlist[0], + None, self.makeBranchTree(condlist[1:], flowlist[1:], node)) def appendBranchTree(self, base, pos, tree): @@ -1482,9 +1482,9 @@ def appendBranchTree(self, base, pos, tree): else: if pos[0]: return DFBranch( base.condnode, - self.appendBranchTree(base.truenode, pos[1:], tree), + self.appendBranchTree(base.truenode, pos[1:], tree), base.falsenode) else: return DFBranch( - base.condnode, - base.truenode, + base.condnode, + base.truenode, self.appendBranchTree(base.falsenode, pos[1:], tree)) diff --git a/pyverilog/testcode/signed_task.v b/pyverilog/testcode/signed_task.v new file mode 100644 index 0000000..5d1aed3 --- /dev/null +++ b/pyverilog/testcode/signed_task.v @@ -0,0 +1,14 @@ +module TOP(CLK, RST); + input CLK, RST; + reg [7:0] cnt; + + always @(posedge CLK or negedge RST) begin + if(RST) begin + cnt <= $signed(cnt); + end else begin + cnt <= $unsigned(cnt); + end + end + + +endmodule diff --git a/pyverilog/testcode/test_sd.py b/pyverilog/testcode/test_sd.py index 02ed63f..d71e772 100644 --- a/pyverilog/testcode/test_sd.py +++ b/pyverilog/testcode/test_sd.py @@ -1,7 +1,7 @@ #------------------------------------------------------------------------------- # test_sd.py # -# Lexical analyzer +# # # Copyright (C) 2015, ryosuke fukatani # License: Apache 2.0 @@ -34,6 +34,11 @@ def test_signed(self): self.assertEqual(binddict.values()[0][0].tostr(), "(Bind dest:TOP.cnt tree:(Branch Cond:(Terminal TOP.RST) True:(IntConst 'd0) False:(Operator Plus Next:(Terminal TOP.cnt),(IntConst 1'sd1))))") + def test_signed_task(self): + terms, binddict = self.dataflow_wrapper("signed_task.v") + self.assertEqual(binddict.values()[0][0].tostr(), + "(Bind dest:TOP.cnt tree:(Branch Cond:(Terminal TOP.RST) True:(Terminal TOP.cnt) False:(Terminal TOP.cnt)))") + def test_casex(self): self.dataflow_wrapper("casex.v") diff --git a/pyverilog/vparser/parser.py b/pyverilog/vparser/parser.py index 7a46535..2be418b 100644 --- a/pyverilog/vparser/parser.py +++ b/pyverilog/vparser/parser.py @@ -4,7 +4,7 @@ # Parser # # Copyright (C) 2013, Shinya Takamaeda-Yamazaki -# edited by ryosuke fukatani +# modified by ryosuke fukatani # License: Apache 2.0 #------------------------------------------------------------------------------- @@ -1534,6 +1534,10 @@ def p_systemcall(self, p): 'systemcall : DOLLER ID LPAREN sysargs RPAREN' p[0] = SystemCall(p[2], p[4]) + def p_systemcall_signed(self, p):#for $signed system task + 'systemcall : DOLLER SIGNED LPAREN sysargs RPAREN' + p[0] = SystemCall(p[2], p[4]) + def p_sysargs(self, p): 'sysargs : sysargs COMMA sysarg' p[0] = p[1] + (p[3],)