diff --git a/PTask.h b/PTask.h index df1dee628..b06375dfc 100644 --- a/PTask.h +++ b/PTask.h @@ -24,6 +24,7 @@ # include "svector.h" # include "StringHeap.h" # include +# include # include class Design; class NetScope; diff --git a/Statement.cc b/Statement.cc index 88581712f..415dffc12 100644 --- a/Statement.cc +++ b/Statement.cc @@ -105,11 +105,11 @@ PBlock::PBlock(BL_TYPE t) PBlock::~PBlock() { - for (unsigned idx = 0 ; idx < list_.count() ; idx += 1) + for (unsigned idx = 0 ; idx < list_.size() ; idx += 1) delete list_[idx]; } -void PBlock::set_statement(const svector&st) +void PBlock::set_statement(const vector&st) { list_ = st; } diff --git a/Statement.h b/Statement.h index f5c19d7b6..3f3c14010 100644 --- a/Statement.h +++ b/Statement.h @@ -20,6 +20,7 @@ */ # include +# include # include # include "ivl_target.h" # include "svector.h" @@ -167,7 +168,7 @@ class PBlock : public PScope, public Statement { BL_TYPE bl_type() const { return bl_type_; } - void set_statement(const svector&st); + void set_statement(const std::vector&st); virtual void dump(ostream&out, unsigned ind) const; virtual NetProc* elaborate(Design*des, NetScope*scope) const; @@ -176,7 +177,7 @@ class PBlock : public PScope, public Statement { private: const BL_TYPE bl_type_; - svectorlist_; + std::vectorlist_; }; class PCallTask : public Statement { diff --git a/elab_scope.cc b/elab_scope.cc index da9030141..2347f7ac2 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -1513,7 +1513,7 @@ void PBlock::elaborate_scope(Design*des, NetScope*scope) const elaborate_scope_events_(des, my_scope, events); } - for (unsigned idx = 0 ; idx < list_.count() ; idx += 1) + for (unsigned idx = 0 ; idx < list_.size() ; idx += 1) list_[idx] -> elaborate_scope(des, my_scope); } diff --git a/elab_sig.cc b/elab_sig.cc index c9758444f..77cab98fe 100644 --- a/elab_sig.cc +++ b/elab_sig.cc @@ -450,7 +450,7 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const /* Make sure the function has at least one input port. If it fails this test, print an error message. Keep going so we can find more errors. */ - if (ports_ == 0) { + if (ports_ == 0 && !gn_system_verilog()) { cerr << get_fileline() << ": error: Function " << fname << " has no ports." << endl; cerr << get_fileline() << ": : Functions must have" @@ -721,7 +721,7 @@ void PBlock::elaborate_sig(Design*des, NetScope*scope) const // elaborate_sig in the statements included in the // block. There may be named blocks in there. - for (unsigned idx = 0 ; idx < list_.count() ; idx += 1) + for (unsigned idx = 0 ; idx < list_.size() ; idx += 1) list_[idx] -> elaborate_sig(des, my_scope); } diff --git a/elaborate.cc b/elaborate.cc index 4d3cff6d0..28384e005 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -2562,13 +2562,13 @@ NetProc* PBlock::elaborate(Design*des, NetScope*scope) const // statement. There is no need to keep the block node. Also, // don't elide named blocks, because they might be referenced // elsewhere. - if ((list_.count() == 1) && (pscope_name() == 0)) { + if ((list_.size() == 1) && (pscope_name() == 0)) { assert(list_[0]); NetProc*tmp = list_[0]->elaborate(des, nscope); return tmp; } - for (unsigned idx = 0 ; idx < list_.count() ; idx += 1) { + for (unsigned idx = 0 ; idx < list_.size() ; idx += 1) { assert(list_[idx]); NetProc*tmp = list_[idx]->elaborate(des, nscope); // If the statement fails to elaborate, then simply @@ -3879,6 +3879,7 @@ void PFunction::elaborate(Design*des, NetScope*scope) const assert(def); + ivl_assert(*this, statement_); NetProc*st = statement_->elaborate(des, scope); if (st == 0) { cerr << statement_->get_fileline() << ": error: Unable to elaborate " diff --git a/parse.y b/parse.y index a75c4f893..75ef78365 100644 --- a/parse.y +++ b/parse.y @@ -310,7 +310,7 @@ static long check_enum_seq_value(const YYLTYPE&loc, verinum *arg, bool zero_ok) PEventStatement*event_statement; Statement*statement; - svector*statement_list; + vector*statement_list; PTaskFuncArg function_type; @@ -454,7 +454,7 @@ static long check_enum_seq_value(const YYLTYPE&loc, verinum *arg, bool zero_ok) %type enum_data_type %type task_item task_item_list task_item_list_opt -%type task_port_item task_port_decl task_port_decl_list +%type task_port_item task_port_decl task_port_decl_list task_port_decl_list_opt %type function_item function_item_list %type port_name parameter_value_byname @@ -1651,6 +1651,16 @@ expr_primary delete[]$1; $$ = tmp; } + | hierarchy_identifier '(' ')' + { const vector empty; + PECallFunction*tmp = new PECallFunction(*$1, empty); + FILE_NAME(tmp, @1); + delete $1; + $$ = tmp; + if (!gn_system_verilog()) { + yyerror(@1, "error: Empty function argument list requires SystemVerilog."); + } + } /* Many of the VAMS built-in functions are available as builtin functions with $system_function equivalents. */ @@ -2854,11 +2864,24 @@ module_item { assert(current_function == 0); current_function = pform_push_function_scope(@1, $4, $2); } - function_item_list statement + function_item_list statement_list K_endfunction { current_function->set_ports($7); - current_function->set_statement($8); current_function->set_return($3); + assert($8 && $8->size() > 0); + if ($8->size() == 1) { + current_function->set_statement((*$8)[0]); + delete $8; + } else { + PBlock*tmp = new PBlock(PBlock::BL_SEQ); + FILE_NAME(tmp, @8); + tmp->set_statement( *$8 ); + current_function->set_statement(tmp); + delete $8; + if (!gn_system_verilog()) { + yyerror(@8, "error: Function body with multiple statements requres SystemVerilog."); + } + } pform_pop_scope(); current_function = 0; delete[]$4; @@ -2868,20 +2891,42 @@ module_item { assert(current_function == 0); current_function = pform_push_function_scope(@1, $4, $2); } - '(' task_port_decl_list ')' ';' + '(' task_port_decl_list_opt ')' ';' block_item_decls_opt - statement + statement_list K_endfunction { current_function->set_ports($7); - current_function->set_statement($11); current_function->set_return($3); + assert($11 && $11->size() > 0); + if ($11->size() == 1) { + current_function->set_statement((*$11)[0]); + delete $11; + } else { + PBlock*tmp = new PBlock(PBlock::BL_SEQ); + FILE_NAME(tmp, @11); + tmp->set_statement( *$11 ); + current_function->set_statement(tmp); + delete $11; + if (!gn_system_verilog()) { + yyerror(@11, "error: Function body with multiple statements requres SystemVerilog."); + } + } pform_pop_scope(); current_function = 0; delete[]$4; + if ($7==0 && !gn_system_verilog()) { + yyerror(@7, "error: Empty parenthesis syntax requires SystemVerilog."); + } } | K_function automatic_opt function_range_or_type_opt IDENTIFIER error K_endfunction - { + { /* */ + if (current_function) { + pform_pop_scope(); + current_function = 0; + } assert(current_function == 0); + yyerror(@1, "error: Syntax error defining function."); + yyerrok; delete[]$4; } @@ -4582,17 +4627,17 @@ compressed_statement ; statement_list - : statement_list statement - { svector*tmp = new svector(*$1, $2); - delete $1; - $$ = tmp; - } - | statement - { svector*tmp = new svector(1); - (*tmp)[0] = $1; - $$ = tmp; - } - ; + : statement_list statement + { vector*tmp = $1; + tmp->push_back($2); + $$ = tmp; + } + | statement + { vector*tmp = new vector(1); + tmp->at(0) = $1; + $$ = tmp; + } + ; statement_or_null : statement @@ -5007,6 +5052,11 @@ task_port_decl } ; +task_port_decl_list_opt + : task_port_decl_list { $$ = $1; } + | { $$ = 0; } + ; + task_port_decl_list : task_port_decl_list ',' task_port_decl { svector*tmp = new svector(*$1, *$3); diff --git a/pform_dump.cc b/pform_dump.cc index b5a4a380a..26621b327 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -591,7 +591,7 @@ void PBlock::dump(ostream&out, unsigned ind) const dump_wires_(out, ind+2); } - for (unsigned idx = 0 ; idx < list_.count() ; idx += 1) { + for (unsigned idx = 0 ; idx < list_.size() ; idx += 1) { if (list_[idx]) list_[idx]->dump(out, ind+2); else