Merge pull request #609 from larsclausen/sv-omit-param-keyword

Allow omitting `parameter` in module parameter port list
This commit is contained in:
Stephen Williams 2022-02-13 08:13:11 -08:00 committed by GitHub
commit 13aa782be2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 186 additions and 89 deletions

View File

@ -0,0 +1,30 @@
// Check that all parameters in a parameter port list after a `localparam` get
// elaborated as localparams, until the next `parameter`. Check that this is the
// case even when the data type of the parameter is redefined.
module a #(
parameter A = 1, B = 2,
localparam C = 3, real D = 4,
parameter E = 5
);
initial begin
if (A == 10 && B == 20 && C == 3 && D == 4 && E == 50) begin
$display("PASSED");
end else begin
$display("FAILED");
end
end
endmodule
module b;
a #(
.A(10),
.B(20),
.D(40), // This will cause an error
.E(50)
) i_a();
endmodule

View File

@ -0,0 +1,17 @@
// Tests that it possible to omit the initial `parameter` keyword in a parameter
// port list in SystemVerilog. In Verilog this is not allowed and should result
// in an error.
module a #(A = 1);
initial begin
if (A == 10) begin
$display("PASSED");
end else begin
$display("FAILED");
end
end
endmodule
module test;
a #(.A(10)) i_a();
endmodule

View File

@ -0,0 +1,17 @@
// Tests that it possible to omit the initial `parameter` keyword in a parameter
// port list in SystemVerilog. In Verilog this is not allowed and should result
// in an error.
module a #(integer A = 1);
initial begin
if (A == 10) begin
$display("PASSED");
end else begin
$display("FAILED");
end
end
endmodule
module test;
a #(.A(10.1)) i_a();
endmodule

View File

@ -0,0 +1,17 @@
// Tests that it possible to omit the `parameter` keyword in a parameter port
// list before changing the parameter type in SystemVerilog. In Verilog this is
// not allowed and should result in an error.
module a #(parameter real A = 1.0, integer B = 2);
initial begin
if (A == 10.1 && B == 20) begin
$display("PASSED");
end else begin
$display("FAILED");
end
end
endmodule
module test;
a #(.A(10.1), .B(20)) i_a();
endmodule

View File

@ -0,0 +1,8 @@
// Check that implicit type in a parameter port list without `parameter`
// generates an error.
module test #([7:0] A = 1);
initial begin
$display("FAILED");
end
endmodule

View File

@ -0,0 +1,8 @@
// Check that implicit type in a parameter port list without `parameter`
// generates an error.
module test #(signed A = 1);
initial begin
$display("FAILED");
end
endmodule

View File

@ -0,0 +1,8 @@
// Check that declaring changing the parameter type to an implicit type without
// the `parameter` keyword results in an error.
module test #(parameter real A = 1.0, signed B = 2);
initial begin
$display("FAILED");
end
endmodule

View File

@ -78,6 +78,9 @@ br_gh567 normal ivltests
check_constant_3 normal ivltests check_constant_3 normal ivltests
function4 normal ivltests function4 normal ivltests
parameter_in_generate1 normal ivltests parameter_in_generate1 normal ivltests
parameter_omit1 normal ivltests
parameter_omit2 normal ivltests
parameter_omit3 normal ivltests
pr1963962 normal ivltests gold=pr1963962-fsv.gold pr1963962 normal ivltests gold=pr1963962-fsv.gold
pr3015421 CE ivltests gold=pr3015421-fsv.gold pr3015421 CE ivltests gold=pr3015421-fsv.gold
resetall normal,-Wtimescale ivltests gold=resetall-fsv.gold resetall normal,-Wtimescale ivltests gold=resetall-fsv.gold

View File

@ -302,6 +302,7 @@ l_equiv_const normal,-g2005-sv ivltests
line_directive normal,-g2009,-I./ivltests ivltests gold=line_directive.gold line_directive normal,-g2009,-I./ivltests ivltests gold=line_directive.gold
localparam_implicit normal,-g2005-sv ivltests localparam_implicit normal,-g2005-sv ivltests
localparam_implicit2 CE,-g2005-sv ivltests localparam_implicit2 CE,-g2005-sv ivltests
localparam_implicit3 CE,-g2005-sv ivltests
localparam_query normal,-g2005-sv ivltests localparam_query normal,-g2005-sv ivltests
localparam_type2 normal,-g2009 ivltests localparam_type2 normal,-g2009 ivltests
logical_short_circuit normal,-g2012 ivltests logical_short_circuit normal,-g2012 ivltests

View File

@ -696,6 +696,12 @@ param_test4 normal ivltests
param_times normal ivltests # param has multiplication. param_times normal ivltests # param has multiplication.
parameter_type normal ivltests gold=parameter_type.gold parameter_type normal ivltests gold=parameter_type.gold
parameter_in_generate1 CE ivltests parameter_in_generate1 CE ivltests
parameter_omit1 CE ivltests
parameter_omit2 CE ivltests
parameter_omit3 CE ivltests
parameter_omit_invalid1 CE ivltests
parameter_omit_invalid2 CE ivltests
parameter_omit_invalid3 CE ivltests
patch1268 normal ivltests patch1268 normal ivltests
pca1 normal ivltests # Procedural Continuous Assignment in a mux pca1 normal ivltests # Procedural Continuous Assignment in a mux
pic normal contrib pictest gold=pic.gold pic normal contrib pictest gold=pic.gold

135
parse.y
View File

@ -309,9 +309,8 @@ static void current_task_set_statement(const YYLTYPE&loc, std::vector<Statement*
detected the case that there are no statements in the detected the case that there are no statements in the
task. If this is SystemVerilog, handle it as an task. If this is SystemVerilog, handle it as an
an empty block. */ an empty block. */
if (!gn_system_verilog()) { pform_requires_sv(loc, "Task body with no statements");
yyerror(loc, "error: Support for empty tasks requires SystemVerilog.");
}
PBlock*tmp = new PBlock(PBlock::BL_SEQ); PBlock*tmp = new PBlock(PBlock::BL_SEQ);
FILE_NAME(tmp, loc); FILE_NAME(tmp, loc);
current_task->set_statement(tmp); current_task->set_statement(tmp);
@ -330,9 +329,7 @@ static void current_task_set_statement(const YYLTYPE&loc, std::vector<Statement*
return; return;
} }
if (!gn_system_verilog()) { pform_requires_sv(loc, "Task body with multiple statements");
yyerror(loc, "error: Task body with multiple statements requires SystemVerilog.");
}
PBlock*tmp = new PBlock(PBlock::BL_SEQ); PBlock*tmp = new PBlock(PBlock::BL_SEQ);
FILE_NAME(tmp, loc); FILE_NAME(tmp, loc);
@ -347,9 +344,8 @@ static void current_function_set_statement(const YYLTYPE&loc, std::vector<Statem
detected the case that there are no statements in the detected the case that there are no statements in the
task. If this is SystemVerilog, handle it as an task. If this is SystemVerilog, handle it as an
an empty block. */ an empty block. */
if (!gn_system_verilog()) { pform_requires_sv(loc, "Function body with no statements");
yyerror(loc, "error: Support for empty functions requires SystemVerilog.");
}
PBlock*tmp = new PBlock(PBlock::BL_SEQ); PBlock*tmp = new PBlock(PBlock::BL_SEQ);
FILE_NAME(tmp, loc); FILE_NAME(tmp, loc);
current_function->set_statement(tmp); current_function->set_statement(tmp);
@ -368,9 +364,7 @@ static void current_function_set_statement(const YYLTYPE&loc, std::vector<Statem
return; return;
} }
if (!gn_system_verilog()) { pform_requires_sv(loc, "Function body with multiple statements");
yyerror(loc, "error: Function body with multiple statements requires SystemVerilog.");
}
PBlock*tmp = new PBlock(PBlock::BL_SEQ); PBlock*tmp = new PBlock(PBlock::BL_SEQ);
FILE_NAME(tmp, loc); FILE_NAME(tmp, loc);
@ -659,7 +653,7 @@ static void current_function_set_statement(const YYLTYPE&loc, std::vector<Statem
%type <decl_assignment> variable_decl_assignment %type <decl_assignment> variable_decl_assignment
%type <decl_assignments> list_of_variable_decl_assignments %type <decl_assignments> list_of_variable_decl_assignments
%type <data_type> data_type data_type_or_implicit data_type_or_implicit_or_void %type <data_type> data_type data_type_opt data_type_or_implicit data_type_or_implicit_or_void
%type <data_type> simple_type_or_string let_formal_type %type <data_type> simple_type_or_string let_formal_type
%type <data_type> packed_array_data_type %type <data_type> packed_array_data_type
%type <data_type> ps_type_identifier %type <data_type> ps_type_identifier
@ -1269,6 +1263,11 @@ data_type /* IEEE1800-2005: A.2.2.1 */
} }
; ;
/* Data type or nothing, but not implicit */
data_type_opt
: data_type { $$ = $1; }
| { $$ = 0; }
/* The data_type_or_implicit rule is a little more complex then the /* The data_type_or_implicit rule is a little more complex then the
rule documented in the IEEE format syntax in order to allow for rule documented in the IEEE format syntax in order to allow for
signaling the special case that the data_type is completely signaling the special case that the data_type is completely
@ -1285,7 +1284,7 @@ scalar_vector_opt /*IEEE1800-2005: optional support for packed array */
; ;
data_type_or_implicit /* IEEE1800-2005: A.2.2.1 */ data_type_or_implicit /* IEEE1800-2005: A.2.2.1 */
: data_type : data_type_opt
{ $$ = $1; } { $$ = $1; }
| signing dimensions_opt | signing dimensions_opt
{ vector_type_t*tmp = new vector_type_t(IVL_VT_LOGIC, $1, $2); { vector_type_t*tmp = new vector_type_t(IVL_VT_LOGIC, $1, $2);
@ -1299,8 +1298,6 @@ data_type_or_implicit /* IEEE1800-2005: A.2.2.1 */
FILE_NAME(tmp, @2); FILE_NAME(tmp, @2);
$$ = tmp; $$ = tmp;
} }
|
{ $$ = 0; }
; ;
@ -1489,8 +1486,8 @@ function_declaration /* IEEE1800-2005: A.2.6 */
pform_set_this_class(@4, current_function); pform_set_this_class(@4, current_function);
pform_pop_scope(); pform_pop_scope();
current_function = 0; current_function = 0;
if ($7==0 && !gn_system_verilog()) { if ($7 == 0) {
yyerror(@4, "error: Empty parenthesis syntax requires SystemVerilog."); pform_requires_sv(@4, "Empty parenthesis syntax");
} }
} }
label_opt label_opt
@ -2042,8 +2039,8 @@ port_direction /* IEEE1800-2005 A.1.3 */
| K_inout { $$ = NetNet::PINOUT; } | K_inout { $$ = NetNet::PINOUT; }
| K_ref | K_ref
{ $$ = NetNet::PREF; { $$ = NetNet::PREF;
if (!gn_system_verilog()) {
yyerror(@1, "error: Reference ports (ref) require SystemVerilog."); if (!pform_requires_sv(@1, "Reference port (ref)")) {
$$ = NetNet::PINPUT; $$ = NetNet::PINPUT;
} }
} }
@ -2265,11 +2262,10 @@ stream_operator
streaming_concatenation /* IEEE1800-2005: A.8.1 */ streaming_concatenation /* IEEE1800-2005: A.8.1 */
: '{' stream_operator '{' stream_expression_list '}' '}' : '{' stream_operator '{' stream_expression_list '}' '}'
{ /* streaming concatenation is a SystemVerilog thing. */ { /* streaming concatenation is a SystemVerilog thing. */
if (gn_system_verilog()) { if (pform_requires_sv(@2, "Streaming concatenation")) {
yyerror(@2, "sorry: Streaming concatenation not supported."); yyerror(@2, "sorry: Streaming concatenation not supported.");
$$ = 0; $$ = 0;
} else { } else {
yyerror(@2, "error: Streaming concatenation requires SystemVerilog");
$$ = 0; $$ = 0;
} }
} }
@ -2294,8 +2290,8 @@ task_declaration /* IEEE1800-2005: A.2.7 */
pform_set_this_class(@3, current_task); pform_set_this_class(@3, current_task);
pform_pop_scope(); pform_pop_scope();
current_task = 0; current_task = 0;
if ($7 && $7->size() > 1 && !gn_system_verilog()) { if ($7 && $7->size() > 1) {
yyerror(@7, "error: Task body with multiple statements requires SystemVerilog."); pform_requires_sv(@7, "Task body with multiple statements");
} }
delete $7; delete $7;
} }
@ -2452,10 +2448,8 @@ tf_port_item /* IEEE1800-2005: A.2.7 */
tmp = pform_make_task_ports(@3, use_port_type, $2, ilist); tmp = pform_make_task_ports(@3, use_port_type, $2, ilist);
} }
if ($4 != 0) { if ($4 != 0) {
if (gn_system_verilog()) { if (pform_requires_sv(@4, "Task/function port with unpacked dimensions")) {
pform_set_reg_idx(name, $4); pform_set_reg_idx(name, $4);
} else {
yyerror(@4, "error: Task/function port with unpacked dimensions requires SystemVerilog.");
} }
} }
@ -2479,10 +2473,7 @@ tf_port_item /* IEEE1800-2005: A.2.7 */
tf_port_item_expr_opt tf_port_item_expr_opt
: '=' expression : '=' expression
{ if (! gn_system_verilog()) { { pform_requires_sv(@$, "Task/function default argument");
yyerror(@1, "error: Task/function default arguments require "
"SystemVerilog.");
}
$$ = $2; $$ = $2;
} }
| { $$ = 0; } | { $$ = 0; }
@ -2582,9 +2573,7 @@ variable_dimension /* IEEE1800-2005: A.2.5 */
| '[' ']' | '[' ']'
{ std::list<pform_range_t> *tmp = new std::list<pform_range_t>; { std::list<pform_range_t> *tmp = new std::list<pform_range_t>;
pform_range_t index (0,0); pform_range_t index (0,0);
if (!gn_system_verilog()) { pform_requires_sv(@$, "Dynamic array declaration");
yyerror("error: Dynamic array declaration require SystemVerilog.");
}
tmp->push_back(index); tmp->push_back(index);
$$ = tmp; $$ = tmp;
} }
@ -2592,9 +2581,7 @@ variable_dimension /* IEEE1800-2005: A.2.5 */
{ // SystemVerilog queue { // SystemVerilog queue
list<pform_range_t> *tmp = new std::list<pform_range_t>; list<pform_range_t> *tmp = new std::list<pform_range_t>;
pform_range_t index (new PENull,0); pform_range_t index (new PENull,0);
if (!gn_system_verilog()) { pform_requires_sv(@$, "Queue declaration");
yyerror("error: Queue declaration require SystemVerilog.");
}
tmp->push_back(index); tmp->push_back(index);
$$ = tmp; $$ = tmp;
} }
@ -2602,9 +2589,7 @@ variable_dimension /* IEEE1800-2005: A.2.5 */
{ // SystemVerilog queue with a max size { // SystemVerilog queue with a max size
list<pform_range_t> *tmp = new std::list<pform_range_t>; list<pform_range_t> *tmp = new std::list<pform_range_t>;
pform_range_t index (new PENull,$4); pform_range_t index (new PENull,$4);
if (!gn_system_verilog()) { pform_requires_sv(@$, "Queue declaration");
yyerror("error: Queue declarations require SystemVerilog.");
}
tmp->push_back(index); tmp->push_back(index);
$$ = tmp; $$ = tmp;
} }
@ -2612,10 +2597,8 @@ variable_dimension /* IEEE1800-2005: A.2.5 */
variable_lifetime variable_lifetime
: lifetime : lifetime
{ if (!gn_system_verilog()) { { if (pform_requires_sv(@1, "Overriding default variable lifetime") &&
yyerror(@1, "error: overriding the default variable lifetime " $1 != pform_peek_scope()->default_lifetime) {
"requires SystemVerilog.");
} else if ($1 != pform_peek_scope()->default_lifetime) {
yyerror(@1, "sorry: overriding the default variable lifetime " yyerror(@1, "sorry: overriding the default variable lifetime "
"is not yet supported."); "is not yet supported.");
} }
@ -3913,9 +3896,7 @@ expr_primary
FILE_NAME(tmp, @1); FILE_NAME(tmp, @1);
delete[]$1; delete[]$1;
$$ = tmp; $$ = tmp;
if (!gn_system_verilog()) { pform_requires_sv(@1, "Empty function argument list");
yyerror(@1, "error: Empty function argument list requires SystemVerilog.");
}
} }
| implicit_class_handle | implicit_class_handle
@ -4158,24 +4139,22 @@ expr_primary
| expr_primary '\'' '(' expression ')' | expr_primary '\'' '(' expression ')'
{ PExpr*base = $4; { PExpr*base = $4;
if (gn_system_verilog()) { if (pform_requires_sv(@1, "Size cast")) {
PECastSize*tmp = new PECastSize($1, base); PECastSize*tmp = new PECastSize($1, base);
FILE_NAME(tmp, @1); FILE_NAME(tmp, @1);
$$ = tmp; $$ = tmp;
} else { } else {
yyerror(@1, "error: Size cast requires SystemVerilog.");
$$ = base; $$ = base;
} }
} }
| simple_type_or_string '\'' '(' expression ')' | simple_type_or_string '\'' '(' expression ')'
{ PExpr*base = $4; { PExpr*base = $4;
if (gn_system_verilog()) { if (pform_requires_sv(@1, "Type cast")) {
PECastType*tmp = new PECastType($1, base); PECastType*tmp = new PECastType($1, base);
FILE_NAME(tmp, @1); FILE_NAME(tmp, @1);
$$ = tmp; $$ = tmp;
} else { } else {
yyerror(@1, "error: Type cast requires SystemVerilog.");
$$ = base; $$ = base;
} }
} }
@ -4409,12 +4388,9 @@ hierarchy_identifier
$$ = tmp; $$ = tmp;
} }
| hierarchy_identifier '[' '$' ']' | hierarchy_identifier '[' '$' ']'
{ pform_name_t * tmp = $1; { pform_requires_sv(@3, "Last element expression ($)");
pform_name_t * tmp = $1;
name_component_t&tail = tmp->back(); name_component_t&tail = tmp->back();
if (! gn_system_verilog()) {
yyerror(@3, "error: Last element expression ($) "
"requires SystemVerilog. Try enabling SystemVerilog.");
}
index_component_t itmp; index_component_t itmp;
itmp.sel = index_component_t::SEL_BIT_LAST; itmp.sel = index_component_t::SEL_BIT_LAST;
itmp.msb = 0; itmp.msb = 0;
@ -4585,9 +4561,7 @@ port_declaration
$$ = ptmp; $$ = ptmp;
} }
| attribute_list_opt K_input net_type_opt data_type_or_implicit IDENTIFIER '=' expression | attribute_list_opt K_input net_type_opt data_type_or_implicit IDENTIFIER '=' expression
{ if (!gn_system_verilog()) { { pform_requires_sv(@6, "Default port value");
yyerror("error: Default port values require SystemVerilog.");
}
Module::port_t*ptmp; Module::port_t*ptmp;
perm_string name = lex_strings.make($5); perm_string name = lex_strings.make($5);
data_type_t*use_type = $4; data_type_t*use_type = $4;
@ -4935,17 +4909,29 @@ module_parameter_port_list_opt
module_parameter module_parameter
: parameter param_type parameter_assign : parameter param_type parameter_assign
| localparam param_type parameter_assign | localparam param_type parameter_assign
{ if (!gn_system_verilog()) { { pform_requires_sv(@1, "Local parameter in module parameter port list");
yyerror(@1, "error: Local parameters in module parameter " }
"port lists requires SystemVerilog.");
}
}
; ;
module_parameter_port_list module_parameter_port_list
: module_parameter : module_parameter
| data_type_opt
{ param_data_type = $1;
param_is_local = false;
}
parameter_assign
{ pform_requires_sv(@3, "Omitting initial `parameter` in parameter port "
"list");
}
| module_parameter_port_list ',' module_parameter | module_parameter_port_list ',' module_parameter
| module_parameter_port_list ',' parameter_assign | module_parameter_port_list ',' data_type_opt
{ if ($3) {
pform_requires_sv(@3, "Omitting `parameter`/`localparam` before "
"data type in parameter port list");
param_data_type = $3;
}
}
parameter_assign
; ;
module_item module_item
@ -5379,10 +5365,7 @@ module_item
| K_function error K_endfunction label_opt | K_function error K_endfunction label_opt
{ yyerror(@1, "error: I give up on this function definition."); { yyerror(@1, "error: I give up on this function definition.");
if ($4) { if ($4) {
if (!gn_system_verilog()) { pform_requires_sv(@4, "Function end label");
yyerror(@4, "error: Function end names require "
"SystemVerilog.");
}
delete[]$4; delete[]$4;
} }
yyerrok; yyerrok;
@ -6514,10 +6497,7 @@ statement_item /* This is roughly statement_item in the LRM */
block_item_decls_opt block_item_decls_opt
{ if (!$2) { { if (!$2) {
if ($4) { if ($4) {
if (! gn_system_verilog()) { pform_requires_sv(@4, "Variable declaration in unnamed block");
yyerror("error: Variable declaration in unnamed block "
"requires SystemVerilog.");
}
} else { } else {
/* If there are no declarations in the scope then just delete it. */ /* If there are no declarations in the scope then just delete it. */
pform_pop_scope(); pform_pop_scope();
@ -6560,10 +6540,7 @@ statement_item /* This is roughly statement_item in the LRM */
{ {
if (!$2) { if (!$2) {
if ($4) { if ($4) {
if (! gn_system_verilog()) { pform_requires_sv(@4, "Variable declaration in unnamed block");
yyerror("error: Variable declaration in unnamed block "
"requires SystemVerilog.");
}
} else { } else {
/* If there are no declarations in the scope then just delete it. */ /* If there are no declarations in the scope then just delete it. */
pform_pop_scope(); pform_pop_scope();
@ -6847,9 +6824,7 @@ statement_item /* This is roughly statement_item in the LRM */
| hierarchy_identifier K_with '{' constraint_block_item_list_opt '}' ';' | hierarchy_identifier K_with '{' constraint_block_item_list_opt '}' ';'
{ /* ....randomize with { <constraints> } */ { /* ....randomize with { <constraints> } */
if ($1 && peek_tail_name(*$1) == "randomize") { if ($1 && peek_tail_name(*$1) == "randomize") {
if (!gn_system_verilog()) if (pform_requires_sv(@2, "Randomize with constraint"))
yyerror(@2, "error: Randomize with constraint requires SystemVerilog.");
else
yyerror(@2, "sorry: Randomize with constraint not supported."); yyerror(@2, "sorry: Randomize with constraint not supported.");
} else { } else {
yyerror(@2, "error: Constraint block can only be applied to randomize method."); yyerror(@2, "error: Constraint block can only be applied to randomize method.");

View File

@ -57,6 +57,7 @@ extern YYLTYPE yylloc;
*/ */
extern int VLlex(); extern int VLlex();
extern void VLerror(const char*msg); extern void VLerror(const char*msg);
extern void VLerror(const YYLTYPE&loc, va_list ap);
extern void VLerror(const YYLTYPE&loc, const char*msg, ...) __attribute__((format(printf,2,3))); extern void VLerror(const YYLTYPE&loc, const char*msg, ...) __attribute__((format(printf,2,3)));
#define yywarn VLwarn #define yywarn VLwarn
extern void VLwarn(const char*msg); extern void VLwarn(const char*msg);

View File

@ -1334,10 +1334,9 @@ void pform_startmodule(const struct vlltype&loc, const char*name,
error_count += 1; error_count += 1;
} }
if (lifetime != LexicalScope::INHERITED && !gn_system_verilog()) {
cerr << loc << ": error: Default subroutine lifetimes " if (lifetime != LexicalScope::INHERITED) {
"require SystemVerilog." << endl; pform_requires_sv(loc, "Default subroutine lifetime");
error_count += 1;
} }
if (gn_system_verilog() && ! pform_cur_module.empty()) { if (gn_system_verilog() && ! pform_cur_module.empty()) {
@ -3138,11 +3137,7 @@ PAssign* pform_compressed_assign_from_inc_dec(const struct vlltype&loc, PExpr*ex
PExpr* pform_genvar_inc_dec(const struct vlltype&loc, const char*name, bool inc_flag) PExpr* pform_genvar_inc_dec(const struct vlltype&loc, const char*name, bool inc_flag)
{ {
if (!gn_system_verilog()) { pform_requires_sv(loc, "Increment/decrement operator");
cerr << loc << ": error: Increment/decrement operators "
"require SystemVerilog." << endl;
error_count += 1;
}
PExpr*lval = new PEIdent(lex_strings.make(name)); PExpr*lval = new PEIdent(lex_strings.make(name));
PExpr*rval = new PENumber(new verinum(1)); PExpr*rval = new PENumber(new verinum(1));
@ -3760,6 +3755,15 @@ void pform_add_modport_port(const struct vlltype&loc,
pform_cur_modport->simple_ports[name] = make_pair(port_type, expr); pform_cur_modport->simple_ports[name] = make_pair(port_type, expr);
} }
bool pform_requires_sv(const struct vlltype&loc, const char *feature)
{
if (gn_system_verilog())
return true;
VLerror(loc, "error: %s requires SystemVerilog.", feature);
return false;
}
FILE*vl_input = 0; FILE*vl_input = 0;
extern void reset_lexor(); extern void reset_lexor();

View File

@ -612,4 +612,6 @@ extern bool allow_timeprec_decl;
void pform_put_enum_type_in_scope(enum_type_t*enum_set); void pform_put_enum_type_in_scope(enum_type_t*enum_set);
bool pform_requires_sv(const struct vlltype&loc, const char *feature);
#endif /* IVL_pform_H */ #endif /* IVL_pform_H */