Bunches more SystemVerilog syntax.

This commit is contained in:
Stephen Williams 2012-03-09 18:54:05 -08:00
parent 8c2e4a0892
commit da743c3b2c
4 changed files with 285 additions and 91 deletions

285
parse.y
View File

@ -265,6 +265,41 @@ static void current_task_set_statement(const YYLTYPE&loc, vector<Statement*>*s)
current_task->set_statement(tmp);
}
static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>*s)
{
if (s == 0) {
/* if the statement list is null, then the parser
detected the case that there are no statements in the
task. If this is System Verilog, handle it as an
an empty block. */
if (!gn_system_verilog()) {
yyerror(loc, "error: Support for empty functions requires SystemVerilog.");
}
PBlock*tmp = new PBlock(PBlock::BL_SEQ);
FILE_NAME(tmp, loc);
current_function->set_statement(tmp);
return;
}
/* The parser assures that there is a non-empty vector. */
assert(s && !s->empty());
/* A vector of 1 is handled as a simple statement. */
if (s->size() == 1) {
current_function->set_statement((*s)[0]);
return;
}
if (!gn_system_verilog()) {
yyerror(loc, "error: Function body with multiple statements requires SystemVerilog.");
}
PBlock*tmp = new PBlock(PBlock::BL_SEQ);
FILE_NAME(tmp, loc);
tmp->set_statement(*s);
current_function->set_statement(tmp);
}
%}
%union {
@ -447,7 +482,7 @@ static void current_task_set_statement(const YYLTYPE&loc, vector<Statement*>*s)
%type <flag> from_exclude
%type <number> number pos_neg_number
%type <flag> signing unsigned_signed_opt signed_unsigned_opt
%type <flag> K_automatic_opt K_packed_opt K_reg_opt K_virtual_opt
%type <flag> K_automatic_opt K_packed_opt K_reg_opt K_static_opt K_virtual_opt
%type <flag> udp_reg_opt edge_operator
%type <drive> drive_strength drive_strength_opt dr_strength0 dr_strength1
%type <letter> udp_input_sym udp_output_sym
@ -495,8 +530,8 @@ static void current_task_set_statement(const YYLTYPE&loc, vector<Statement*>*s)
%type <pform_name> hierarchy_identifier
%type <expr> assignment_pattern expression expr_primary expr_mintypmax
%type <expr> dynamic_array_new inc_or_dec_expression lpvalue
%type <expr> branch_probe_expression
%type <expr> class_new dynamic_array_new inc_or_dec_expression inside_expression lpvalue
%type <expr> branch_probe_expression streaming_concatenation
%type <expr> delay_value delay_value_simple
%type <exprs> delay1 delay3 delay3_opt delay_value_list
%type <exprs> expression_list_with_nuls expression_list_proper
@ -526,7 +561,7 @@ static void current_task_set_statement(const YYLTYPE&loc, vector<Statement*>*s)
%type <event_expr> event_expression
%type <event_statement> event_control
%type <statement> statement statement_or_null compressed_statement
%type <statement> loop_statement for_step
%type <statement> loop_statement for_step jump_statement
%type <statement_list> statement_or_null_list statement_or_null_list_opt
%type <statement> analog_statement
@ -543,7 +578,7 @@ static void current_task_set_statement(const YYLTYPE&loc, vector<Statement*>*s)
%token K_TAND
%right K_PLUS_EQ K_MINUS_EQ K_MUL_EQ K_DIV_EQ K_MOD_EQ K_AND_EQ K_OR_EQ
%right K_XOR_EQ K_LS_EQ K_RS_EQ K_RSS_EQ
%right '?' ':'
%right '?' ':' K_inside
%left K_LOR
%left K_LAND
%left '|'
@ -609,6 +644,11 @@ class_declaration /* IEEE1800-2005: A.1.2 */
}
;
class_constraint /* IEEE1800-2005: A.1.8 */
: constraint_prototype
| constraint_declaration
;
class_identifier
: IDENTIFIER
{ // Create a synthetic typedef for the class name so that the
@ -690,7 +730,7 @@ class_item /* IEEE1800-2005: A.1.8 */
be K_super ("this.new" makes little sense) but that would
cause a conflict. */
| method_qualifier_opt K_function K_new '(' tf_port_list_opt ')' ';'
implicit_class_handle '.' K_new '(' ')'
implicit_class_handle '.' K_new '(' expression_list_with_nuls ')'
statement_or_null_list_opt
K_endfunction endnew_opt
{ yyerror(@3, "sorry: Class constructors not supported yet.");
@ -708,6 +748,11 @@ class_item /* IEEE1800-2005: A.1.8 */
| method_qualifier_opt function_declaration
/* Class constraints... */
| class_constraint
/* Here are some error matching rules to help recover from various
syntax errors within a class declaration. */
@ -739,6 +784,65 @@ class_item_qualifier /* IEEE1800-2005 A.1.8 */
| K_local
;
class_new /* IEEE1800-2005 A.2.4 */
: K_new '(' ')'
{ yyerror(@1, "sorry: class_new not implemented yet.");
$$ = 0;
}
| K_new '(' expression_list_proper ')'
{ yyerror(@1, "sorry: class_new not implemented yet.");
$$ = 0;
}
;
constraint_block_item /* IEEE1800-2005 A.1.9 */
: constraint_expression
;
constraint_block_item_list
: constraint_block_item_list constraint_block_item
| constraint_block_item
;
constraint_block_item_list_opt
:
| constraint_block_item_list
;
constraint_declaration /* IEEE1800-2005: A.1.9 */
: K_static_opt K_constraint IDENTIFIER '{' constraint_block_item_list_opt '}'
{ yyerror(@2, "sorry: Constraint declarations not supported.") }
/* Error handling rules... */
| K_static_opt K_constraint IDENTIFIER '{' error '}'
{ yyerror(@4, "error: Errors in the constraint block item list."); }
;
constraint_expression /* IEEE1800-2005 A.1.9 */
: expression ';'
| expression K_dist '{' '}' ';'
| expression K_TRIGGER constraint_set
| K_if '(' expression ')' constraint_set %prec less_than_K_else
| K_if '(' expression ')' constraint_set K_else constraint_set
| K_foreach '(' IDENTIFIER '[' loop_variables ']' ')' constraint_set
;
constraint_expression_list /* */
: constraint_expression_list constraint_expression
| constraint_expression
;
constraint_prototype /* IEEE1800-2005: A.1.9 */
: K_static_opt K_constraint IDENTIFIER ';'
{ yyerror(@2, "sorry: Constraint prototypes not supported.") }
;
constraint_set /* IEEE1800-2005 A.1.9 */
: constraint_expression
| '{' constraint_expression_list '}'
;
data_type /* IEEE1800-2005: A.2.2.1 */
: integer_vector_type unsigned_signed_opt range_opt
{ vector_type_t*tmp = new vector_type_t($1, $2, $3);
@ -830,24 +934,11 @@ function_declaration /* IEEE1800-2005: A.2.6 */
{ assert(current_function == 0);
current_function = pform_push_function_scope(@1, $4, $2);
}
function_item_list statement_or_null_list
function_item_list statement_or_null_list_opt
K_endfunction
{ current_function->set_ports($7);
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.");
}
}
current_function_set_statement($8? @8 : @4, $8);
pform_pop_scope();
current_function = 0;
}
@ -869,24 +960,11 @@ function_declaration /* IEEE1800-2005: A.2.6 */
}
'(' tf_port_list_opt ')' ';'
block_item_decls_opt
statement_or_null_list
statement_or_null_list_opt
K_endfunction
{ current_function->set_ports($7);
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.");
}
}
current_function_set_statement($11? @11 : @4, $11);
pform_pop_scope();
current_function = 0;
if ($7==0 && !gn_system_verilog()) {
@ -965,6 +1043,13 @@ inc_or_dec_expression /* IEEE1800-2005: A.4.3 */
}
;
inside_expression /* IEEE1800-2005 A.8.3 */
: expression K_inside '{' open_range_list '}'
{ yyerror(@2, "sorry: \"inside\" expressions not supported yet.");
$$ = 0;
}
;
integer_vector_type /* IEEE1800-2005: A.2.2.1 */
: K_reg { $$ = IVL_VT_LOGIC; }
| K_bit { $$ = IVL_VT_BOOL; }
@ -972,6 +1057,21 @@ integer_vector_type /* IEEE1800-2005: A.2.2.1 */
| K_bool { $$ = IVL_VT_BOOL; } /* Icarus Verilog xtypes extension */
;
jump_statement /* IEEE1800-2005: A.6.5 */
: K_break ';'
{ yyerror(@1, "sorry: break statements not supported.");
$$ = 0;
}
| K_return ';'
{ yyerror(@1, "sorry: return statements not supported.");
$$ = 0;
}
| K_return expression ';'
{ yyerror(@1, "sorry: return statements not supported.");
$$ = 0;
}
;
/* Loop statements are kinds of statements. */
loop_statement /* IEEE1800-2005: A.6.8 */
@ -1084,13 +1184,6 @@ variable_decl_assignment /* IEEE1800-2005 A.2.3 */
delete[]$1;
$$ = tmp;
}
| IDENTIFIER '[' '$' ']'
{ decl_assignment_t*tmp = new decl_assignment_t;
tmp->name = lex_strings.make($1);
yyerror("sorry: Queue dimensions not yet supported here.");
delete[]$1;
$$ = tmp;
}
;
@ -1135,6 +1228,11 @@ number : BASED_NUMBER
based_size = 0; }
;
open_range_list /* IEEE1800-2005 A.2.11 */
: open_range_list ',' value_range
| value_range
;
port_direction /* IEEE1800-2005 A.1.3 */
: K_input { $$ = NetNet::PINPUT; }
| K_output { $$ = NetNet::POUTPUT; }
@ -1203,6 +1301,33 @@ statement_or_null /* IEEE1800-2005: A.6.4 */
{ $$ = 0; }
;
stream_expression
: expression
;
stream_expression_list
: stream_expression_list ',' stream_expression
| stream_expression
;
stream_operator
: K_LS
| K_RS
;
streaming_concatenation /* IEEE1800-2005: A.8.1 */
: '{' stream_operator '{' stream_expression_list '}' '}'
{ /* streaming concatenation is a SystemVerilog thing. */
if (gn_system_verilog()) {
yyerror(@2, "sorry: Streaming concatenation not supported.");
$$ = 0;
} else {
yyerror(@2, "error: Streaming concatenation requires SystemVerilog");
$$ = 0;
}
}
;
/* The task declaration rule matches the task declaration
header, then pushes the function scope. This causes the
definitions in the task_body to take on the scope of the task
@ -1350,7 +1475,8 @@ tf_port_item /* IEEE1800-2005: A.2.7 */
port_declaration_context.sign_flag = true;
delete port_declaration_context.range;
port_declaration_context.range = copy_range(range_stub);
svector<PWire*>*tmp = pform_make_task_ports(@3, $1, IVL_VT_LOGIC, true,
svector<PWire*>*tmp = pform_make_task_ports(@3, use_port_type,
IVL_VT_LOGIC, true,
range_stub,
list_from_identifier($3), true);
$$ = tmp;
@ -1424,7 +1550,7 @@ tf_port_item /* IEEE1800-2005: A.2.7 */
FILE_NAME($2, @3);
}
port_declaration_context.data_type = $2;
tmp = pform_make_task_ports(@3, $1, $2, ilist);
tmp = pform_make_task_ports(@3, use_port_type, $2, ilist);
}
$$ = tmp;
if ($4) {
@ -1437,12 +1563,6 @@ tf_port_item /* IEEE1800-2005: A.2.7 */
}
}
| port_direction_opt data_type_or_implicit IDENTIFIER '[' '$' ']'
{ yyerror(@5, "sorry: Queues not supported here.");
delete[]$3;
$$ = 0;
}
/* Rules to match error cases... */
| port_direction_opt data_type_or_implicit IDENTIFIER error
@ -1495,6 +1615,13 @@ tf_port_list /* IEEE1800-2005: A.2.7 */
;
value_range /* IEEE1800-2005: A.8.3 */
: expression
{ }
| '[' expression ':' expression ']'
{ }
;
variable_dimension /* IEEE1800-2005: A.2.5 */
: '[' expression ':' expression ']'
{ list<index_component_t> *tmp = new list<index_component_t>;
@ -1529,6 +1656,20 @@ variable_dimension /* IEEE1800-2005: A.2.5 */
tmp->push_back(index);
$$ = tmp;
}
| '[' '$' ']'
{ // SystemVerilog queue
list<index_component_t> *tmp = new list<index_component_t>;
index_component_t index;
index.msb = 0;
index.lsb = 0;
if (gn_system_verilog()) {
yyerror("sorry: Dynamic array ranges not supported.");
} else {
yyerror("error: Queue declarations require System Verilog.");
}
tmp->push_back(index);
$$ = tmp;
}
;
/* Verilog-2001 supports attribute lists, which can be attached to a
@ -2310,6 +2451,8 @@ expression
{ $$ = $1; }
| inc_or_dec_expression
{ $$ = $1; }
| inside_expression
{ $$ = $1; }
| '+' expr_primary %prec UNARY_PREC
{ $$ = $2; }
| '-' expr_primary %prec UNARY_PREC
@ -2678,6 +2821,11 @@ expr_primary
$$ = 0;
}
| implicit_class_handle '.' hierarchy_identifier
{ yyerror(@1, "sorry: Implicit class handles (this/super) are not supported.");
$$ = 0;
}
/* Many of the VAMS built-in functions are available as builtin
functions with $system_function equivalents. */
@ -2881,6 +3029,16 @@ expr_primary
yyerrok;
}
| '{' '}'
{ // This is the empty queue syntax.
if (gn_system_verilog()) {
yyerror(@1, "sorry: Expty queue expressions not supported.");
} else {
yyerror(@1, "error: Concatenations are not allowed to be empty.");
}
$$ = 0;
}
/* Cast expressions are primaries */
| DEC_NUMBER '\'' '(' expression ')'
@ -2901,6 +3059,14 @@ expr_primary
| assignment_pattern
{ $$ = $1; }
/* SystemVerilog supports streaming concatenation */
| streaming_concatenation
{ $$ = $1; }
| K_null
{ yyerror("sorry: null expressions not supported yet.");
$$ = 0;
}
;
/* A function_item_list borrows the task_port_item run to match
@ -3533,6 +3699,11 @@ lpvalue
delete $2;
$$ = tmp;
}
| streaming_concatenation
{ yyerror(@1, "sorry: streaming concatenation not supported in l-values.");
$$ = 0;
}
;
@ -5338,6 +5509,8 @@ statement /* This is roughly statement_item in the LRM */
| loop_statement { $$ = $1; }
| jump_statement { $$ = $1; }
| K_case '(' expression ')' case_items K_endcase
{ PCase*tmp = new PCase(NetCase::EQ, $3, $5);
FILE_NAME(tmp, @1);
@ -5495,6 +5668,15 @@ statement /* This is roughly statement_item in the LRM */
$$ = tmp;
}
/* The class new and dynamic array new expressions are special, so
sit in rules of their own. */
| lpvalue '=' class_new ';'
{ PAssign*tmp = new PAssign($1,$3);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| K_wait '(' expression ')' statement_or_null
{ PEventStatement*tmp;
PEEvent*etmp = new PEEvent(PEEvent::POSITIVE, $3);
@ -5980,4 +6162,5 @@ udp_primitive
K_automatic_opt: K_automatic { $$ = true; } | { $$ = false;} ;
K_packed_opt : K_packed { $$ = true; } | { $$ = false; } ;
K_reg_opt : K_reg { $$ = true; } | { $$ = false; } ;
K_static_opt : K_static { $$ = true; } | { $$ = false; } ;
K_virtual_opt : K_virtual { $$ = true; } | { $$ = false; } ;

View File

@ -2075,39 +2075,6 @@ void pform_makewire(const vlltype&li,
}
}
void pform_set_port_type(perm_string name, NetNet::PortType pt,
const char*file, unsigned lineno)
{
PWire*cur = pform_get_wire_in_scope(name);
if (cur == 0) {
cur = new PWire(name, NetNet::IMPLICIT, NetNet::PIMPLICIT, IVL_VT_NO_TYPE);
FILE_NAME(cur, file, lineno);
pform_put_wire_in_scope(name, cur);
}
switch (cur->get_port_type()) {
case NetNet::PIMPLICIT:
if (! cur->set_port_type(pt))
VLerror("error setting port direction.");
break;
case NetNet::NOT_A_PORT:
cerr << file << ":" << lineno << ": error: "
<< "port " << name << " is not in the port list."
<< endl;
error_count += 1;
break;
default:
cerr << file << ":" << lineno << ": error: "
<< "port " << name << " already has a port declaration."
<< endl;
error_count += 1;
break;
}
}
/*
* This function is called by the parser to create task ports. The
* resulting wire (which should be a register) is put into a list to
@ -2155,6 +2122,7 @@ svector<PWire*>*pform_make_task_ports(const struct vlltype&loc,
list<perm_string>*names,
bool isint)
{
assert(pt != NetNet::PIMPLICIT && pt != NetNet::NOT_A_PORT);
assert(names);
svector<PWire*>*res = new svector<PWire*>(0);
for (list<perm_string>::iterator cur = names->begin()
@ -2513,12 +2481,48 @@ extern void pform_module_specify_path(PSpecPath*obj)
pform_cur_module->specify_paths.push_back(obj);
}
static void pform_set_port_type(perm_string name, NetNet::PortType pt,
const char*file, unsigned lineno)
{
PWire*cur = pform_get_wire_in_scope(name);
if (cur == 0) {
cur = new PWire(name, NetNet::IMPLICIT, NetNet::PIMPLICIT, IVL_VT_NO_TYPE);
FILE_NAME(cur, file, lineno);
pform_put_wire_in_scope(name, cur);
}
switch (cur->get_port_type()) {
case NetNet::PIMPLICIT:
if (! cur->set_port_type(pt))
VLerror("error setting port direction.");
break;
case NetNet::NOT_A_PORT:
cerr << file << ":" << lineno << ": error: "
<< "port " << name << " is not in the port list."
<< endl;
error_count += 1;
break;
default:
cerr << file << ":" << lineno << ": error: "
<< "port " << name << " already has a port declaration."
<< endl;
error_count += 1;
break;
}
}
void pform_set_port_type(const struct vlltype&li,
list<perm_string>*names,
list<index_component_t>*range,
bool signed_flag,
NetNet::PortType pt)
{
assert(pt != NetNet::PIMPLICIT && pt != NetNet::NOT_A_PORT);
for (list<perm_string>::iterator cur = names->begin()
; cur != names->end() ; ++ cur ) {
perm_string txt = *cur;
@ -2636,6 +2640,11 @@ void pform_set_data_type(const struct vlltype&li, data_type_t*data_type, list<pe
return;
}
if (class_type_t*class_type = dynamic_cast<class_type_t*> (data_type)) {
VLerror(li, "sorry: Class types not supported.");
return;
}
assert(0);
}

View File

@ -282,8 +282,7 @@ extern void pform_set_port_type(const struct vlltype&li,
list<index_component_t>*range,
bool signed_flag,
NetNet::PortType);
extern void pform_set_port_type(perm_string nm, NetNet::PortType pt,
const char*file, unsigned lineno);
extern void pform_set_reg_idx(perm_string name, PExpr*l, PExpr*r);
extern void pform_set_reg_integer(list<perm_string>*names);

View File

@ -577,7 +577,10 @@ void PAssign::dump(ostream&out, unsigned ind) const
if (delay_) out << "#" << *delay_ << " ";
if (count_) out << "repeat(" << *count_ << ") ";
if (event_) out << *event_ << " ";
out << *rval() << ";" << " /* " << get_fileline() << " */" << endl;
PExpr*rexpr = rval();
if (rexpr) out << *rval() << ";";
else out << "<no rval>;";
out << " /* " << get_fileline() << " */" << endl;
}
void PAssignNB::dump(ostream&out, unsigned ind) const