SystemVerilog has more lax rules for function declarations.

Allow empty parameter lists
Allow lists of statements instead of simple statements.
This commit is contained in:
Stephen Williams 2011-09-17 12:10:05 -07:00
parent 1d02f89a09
commit f0bf64271b
8 changed files with 82 additions and 29 deletions

View File

@ -24,6 +24,7 @@
# include "svector.h"
# include "StringHeap.h"
# include <string>
# include <vector>
# include <list>
class Design;
class NetScope;

View File

@ -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<Statement*>&st)
void PBlock::set_statement(const vector<Statement*>&st)
{
list_ = st;
}

View File

@ -20,6 +20,7 @@
*/
# include <string>
# include <vector>
# include <list>
# 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<Statement*>&st);
void set_statement(const std::vector<Statement*>&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_;
svector<Statement*>list_;
std::vector<Statement*>list_;
};
class PCallTask : public Statement {

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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 "

88
parse.y
View File

@ -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*>*statement_list;
vector<Statement*>*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_type> enum_data_type
%type <wires> task_item task_item_list task_item_list_opt
%type <wires> task_port_item task_port_decl task_port_decl_list
%type <wires> task_port_item task_port_decl task_port_decl_list task_port_decl_list_opt
%type <wires> function_item function_item_list
%type <named_pexpr> port_name parameter_value_byname
@ -1651,6 +1651,16 @@ expr_primary
delete[]$1;
$$ = tmp;
}
| hierarchy_identifier '(' ')'
{ const vector<PExpr*> 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<Statement*>*tmp = new svector<Statement*>(*$1, $2);
delete $1;
$$ = tmp;
}
| statement
{ svector<Statement*>*tmp = new svector<Statement*>(1);
(*tmp)[0] = $1;
$$ = tmp;
}
;
: statement_list statement
{ vector<Statement*>*tmp = $1;
tmp->push_back($2);
$$ = tmp;
}
| statement
{ vector<Statement*>*tmp = new vector<Statement*>(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<PWire*>*tmp = new svector<PWire*>(*$1, *$3);

View File

@ -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