diff --git a/plugins/hdl/parselib/grammar.py b/plugins/hdl/parselib/grammar.py index 13a64d2e..8712c4ea 100644 --- a/plugins/hdl/parselib/grammar.py +++ b/plugins/hdl/parselib/grammar.py @@ -63,6 +63,8 @@ | continuestmt | hwait | hslice + | portbinding + | hnamedsensvar continuestmt: "hContinue" "NONAME" "NOLIST" // hvarinitlist can be empty @@ -78,7 +80,7 @@ ?htobool: ("hBuiltinFunction" "to_bool" | "hNoop" "to_bool") "[" harrayref "]" htouint: "hBuiltinFunction" "to_uint" "[" (syscread|hvarref|hslice) "]" - htoint: "hBuiltinFunction" "to_int" "[" (syscread|hvarref|hslice) "]" + htoint: "hBuiltinFunction" "to_int" "[" (syscread|hvarref|hslice|harrayref) "]" htolong: "hBuiltinFunction" "to_long" "[" (syscread|hvarref|hslice) "]" htoulong: "hBuiltinFunction" "to_ulong" "[" (syscread|hvarref|hslice) "]" hnoop: "hNoop" "NONAME" "NOLIST" @@ -94,11 +96,10 @@ // first component is the id of the module (in parent?) // second component is initialization list // third component is port binding list - hmodinitblock: "hModinitblock" ID "[" hcstmt* portbindinglist* hsenslist*"]" + hmodinitblock: "hModinitblock" ID "[" vardecl* hcstmt* hsenslist*"]" | "hModinitblock" ID "NOLIST" - // Port Bindings - portbindinglist: "hPortbindings" ID "[" portbinding* "]" + portbindinglist: "hCStmt" "NONAME" "[" portbinding* "]" // hPortbinding u_dut [ // hVarref avg_out NOLIST // hVarref dut_avg NOLIST @@ -108,11 +109,13 @@ | "hPortbinding" ID "[" hvarref hbindingref "]" | "hPortbinding" ID "[" hbindingarrayref hbindingarrayref "]" | "hPortbinding" ID "[" hvarref hbindingarrayref "]" + | "hPortbinding" ID "[" hfieldaccess (hvarref|hbinop) "]" + | "hPortbinding" ID "[" hbinop (hvarref|hbinop) "]" // TODO: replace portbinding with succinct syntax hbindingref: "hVarref" ID "[" hliteral "]" // compared array ref in normal expressions // we use a more restrictive form here - hbindingarrayref: "hBinop" "ARRAYSUBSCRIPT" "[" (hvarref|hbindingarrayref) (hliteral|hbinop) "]" + hbindingarrayref: "hBinop" "ARRAYSUBSCRIPT" "[" (hfieldaccess | hvarref|hbindingarrayref) (hvarref|hliteral|hbinop) "]" // This is solely for maintaining the semicolon @@ -125,7 +128,7 @@ dostmt: "hDoStmt" "NONAME" "[" expression stmt "]" // for(forinit; forcond; forpostcond) stmts - forstmt: "hForStmt" "NONAME" "[" forinit forcond forpostcond forbody "]" + forstmt: "hForStmt" "NONAME" "[" forinit forcond forpostcond forbody? "]" forinit: "hPortsigvarlist" "NONAME" "[" vardeclinit "]" | vardeclinit | hnoop @@ -162,6 +165,7 @@ | "hSenslist" ID "NOLIST" hsensvar : "hSensvar" "NONAME" "[" (hsensedge|expression|hvalchange) ("hNoop" | "hBuiltinFunction") npa "NOLIST" ("hNoop" npa "NOLIST")* "]" | hasync + hnamedsensvar : "hSensvar" ID "[" (hsensedge|expression|hvalchange) ("hNoop" | "hBuiltinFunction") npa "NOLIST" ("hNoop" npa "NOLIST")* "]" hasync : "hSensvar" "ASYNC" "[" expression hliteral "]" hvalchange: "hNoop" "value_changed_event" "[" expression "]" diff --git a/plugins/hdl/parselib/transforms/function_info_pass.py b/plugins/hdl/parselib/transforms/function_info_pass.py index b9e1207a..b4cbe059 100644 --- a/plugins/hdl/parselib/transforms/function_info_pass.py +++ b/plugins/hdl/parselib/transforms/function_info_pass.py @@ -291,7 +291,6 @@ def new_phantom_var_name(self, tpe): return phantom_var def __extract_name_from_method_args(self, arg_node, arg_tpe): - dprint(arg_node, arg_tpe) if is_tree_type(arg_node, 'hvarref'): return arg_node.children[0] elif is_tree_types(arg_node, ['hliteral', 'hbinop', 'hmethodcall', 'syscread', 'hunop', 'hslice']): diff --git a/plugins/hdl/parselib/transforms/literal_expansion.py b/plugins/hdl/parselib/transforms/literal_expansion.py index dfee5d52..6b76a5c9 100644 --- a/plugins/hdl/parselib/transforms/literal_expansion.py +++ b/plugins/hdl/parselib/transforms/literal_expansion.py @@ -1,9 +1,10 @@ import warnings +import lark from lark import Token from parselib.transforms import TopDown -from ..utils import dprint, is_tree_type +from ..utils import dprint, is_tree_type, get_ids_in_tree from ..grammar import UnexpectedHCodeStructureError @@ -16,9 +17,24 @@ def __init__(self, structure): self.port_binding_module = None self.field_access = None + def _get_port_binding_moduel(self, tree): + """ + Get the name of the module that corresponds + to this port-binding + """ + if type(tree) == lark.Tree: + if tree.children[0] != 'NONAME': + res = str(self.structure[self.current_module][tree.children[0]]) + else: + ids = get_ids_in_tree(tree) + res = str(self.structure[self.current_module][ids[0]]) + else: + res = str(self.structure[self.current_module][tree.children[0]]) + return res + def portbinding(self, tree): self.is_port_binding = True - self.port_binding_module = str(self.structure[self.current_module][tree.children[0]]) + self.port_binding_module = self._get_port_binding_moduel(tree) self.__push_up(tree) self.is_port_binding = False self.port_binding_module = None diff --git a/plugins/hdl/parselib/transforms/verilog_tranlation.py b/plugins/hdl/parselib/transforms/verilog_tranlation.py index 413670bd..1e30b95f 100644 --- a/plugins/hdl/parselib/transforms/verilog_tranlation.py +++ b/plugins/hdl/parselib/transforms/verilog_tranlation.py @@ -27,6 +27,7 @@ def __init__(self): self.__current_scope_type = [None] self.is_in_thread = False self.thread_comb = False + self.non_thread_comb_signals = set() def get_current_scope_type(self): """denotes one of four types of scope: loop, switch, branch, None @@ -163,7 +164,14 @@ def blkassign(self, tree): elif type(r) == Tree and r.data == 'harrayref': r = r.children[3] + # FIXME: this handling of shared signal across thread/comb block should be fixed + if 'thread' not in current_proc and '#function#' not in current_proc: + self.non_thread_comb_signals.add(l) + res = '{} {} {}'.format(l, op, r) + + if 'thread' in current_proc and l in self.non_thread_comb_signals: + res = '' return res def syscwrite(self, tree): @@ -389,9 +397,17 @@ def f_concat(x): if x[1].data == 'expression_in_stmt': # logging.warning('Expression as a statement may not have an effect. On line: {}'.format(x[1].line)) x = (x[0], x[1].children[0], x[2]) + res = str(x[0]) + str(x[1]) + str(x[2]) + elif x[1].data == 'portbinding': + ch = x[1].children + assignment = f"{ch[0]}.{ch[1]} = {ch[2]}" + res = ''.join([x[0], assignment, x[2]]) + elif x[1].data == 'hnamedsensvar': + res = f'{x[0]} /* always {x[1].children[1]} */ {x[2]}' else: assert False, 'Unrecognized construct: {}'.format(x[1]) - res = str(x[0]) + str(x[1]) + str(x[2]) + else: + res = ''.join(x) return res except Exception as e: print(x[0]) @@ -505,7 +521,12 @@ def forstmt(self, tree): new_children.extend(self.visit(t) for t in tree.children[3:]) self.dec_indent() - for_init, for_cond, for_post, for_body = new_children + if len(new_children) == 3: + warnings.warn("empty for loop") + for_init, for_cond, for_post = new_children + for_body = '' + else: + for_init, for_cond, for_post, for_body = new_children ind = self.get_current_ind_prefix() res = ind + 'for ({};{};{}) begin\n'.format(for_init, for_cond, for_post) @@ -946,7 +967,11 @@ def __generate_hthread_block(self, tree, is_sync): sense_list = self.get_sense_list() assert thread_name in sense_list, "Process name {} is not in module {}".format(proc_name, self.current_module) if is_sync: - res = ind + 'always @({}) begin: {}\n'.format(' or '.join(self.get_sense_list()[thread_name]), proc_name) + sense_list = self.get_sense_list()[thread_name] + if 'posedge clk' not in sense_list: + warnings.warn("Clock not detected in senstivity list, adding one by default") + sense_list = ['posedge clk'] + sense_list + res = ind + 'always @({}) begin: {}\n'.format(' or '.join(sense_list), proc_name) else: res = ind + 'always @(*) begin: {}\n'.format(proc_name) self.inc_indent() @@ -996,6 +1021,10 @@ def hmodule(self, tree): portbindings = ch elif ch.data == 'hsenslist': senslist.append(ch) + elif ch.data == 'vardecl': + initblock = ch + elif ch.data == 'hnamedsensevar': + senslist.append(ch) else: raise ValueError(ch.pretty()) if initblock: