fix(interface): allow forward interface port types
This commit is contained in:
parent
377881b723
commit
56afcb6e75
|
|
@ -1,3 +1,3 @@
|
|||
ivltests/sv_interface_port_forwarding_restrict_fail.v:30: error: Interface member `hidden' is not listed in modport `consumer'.
|
||||
ivltests/sv_interface_port_forwarding_restrict_fail.v:30: error: Unable to elaborate r-value: bus.hidden
|
||||
ivltests/sv_interface_port_forwarding_restrict_fail.v:23: error: Interface member `hidden' is not listed in modport `consumer'.
|
||||
ivltests/sv_interface_port_forwarding_restrict_fail.v:23: error: Unable to elaborate r-value: bus.hidden
|
||||
2 error(s) during elaboration.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
ivltests/sv_interface_port_missing_type_fail.v:7: error: Interface port bus uses unknown interface type `missing_if'.
|
||||
1 error(s) during elaboration.
|
||||
|
|
@ -1,2 +1,2 @@
|
|||
ivltests/sv_interface_port_positional_unconnected_fail.v:13: error: Interface port `bus' of module bus_user is not connected.
|
||||
ivltests/sv_interface_port_positional_unconnected_fail.v:7: error: Interface port `bus' of module bus_user is not connected.
|
||||
Elaboration failed
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
ivltests/sv_interface_port_unmodported_missing_type_fail.v:7: error: Interface port bus uses unknown interface type `missing_if'.
|
||||
1 error(s) during elaboration.
|
||||
|
|
@ -4,14 +4,6 @@
|
|||
// This file is placed into the Public Domain, for any use, without
|
||||
// warranty.
|
||||
|
||||
interface bus_if ();
|
||||
logic value;
|
||||
logic mirror;
|
||||
logic hidden;
|
||||
|
||||
modport consumer(input value, output mirror);
|
||||
endinterface
|
||||
|
||||
module test;
|
||||
bus_if bus();
|
||||
|
||||
|
|
@ -39,3 +31,11 @@ module child(
|
|||
);
|
||||
assign bus.mirror = bus.value;
|
||||
endmodule
|
||||
|
||||
interface bus_if ();
|
||||
logic value;
|
||||
logic mirror;
|
||||
logic hidden;
|
||||
|
||||
modport consumer(input value, output mirror);
|
||||
endinterface
|
||||
|
|
|
|||
|
|
@ -4,13 +4,6 @@
|
|||
// This file is placed into the Public Domain, for any use, without
|
||||
// warranty.
|
||||
|
||||
interface bus_if ();
|
||||
logic value;
|
||||
logic hidden;
|
||||
|
||||
modport consumer(input value);
|
||||
endinterface
|
||||
|
||||
module test;
|
||||
bus_if bus();
|
||||
parent dut(.bus(bus));
|
||||
|
|
@ -29,3 +22,10 @@ module child(
|
|||
|
||||
assign sample = bus.hidden;
|
||||
endmodule
|
||||
|
||||
interface bus_if ();
|
||||
logic value;
|
||||
logic hidden;
|
||||
|
||||
modport consumer(input value);
|
||||
endinterface
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
// This tests the diagnostic path for an interface-typed module port
|
||||
// whose interface type name is not declared.
|
||||
//
|
||||
// This file is placed into the Public Domain, for any use, without
|
||||
// warranty.
|
||||
|
||||
module bus_user(
|
||||
missing_if.consumer bus
|
||||
);
|
||||
initial $display("FAILED");
|
||||
endmodule
|
||||
|
|
@ -3,13 +3,6 @@
|
|||
// This file is placed into the Public Domain, for any use, without
|
||||
// warranty.
|
||||
|
||||
interface bus_if ();
|
||||
logic value;
|
||||
logic sample;
|
||||
|
||||
modport consumer(input value, output sample);
|
||||
endinterface
|
||||
|
||||
module test;
|
||||
bus_if bus();
|
||||
|
||||
|
|
@ -31,3 +24,10 @@ module bus_user(
|
|||
);
|
||||
assign bus.sample = bus.value;
|
||||
endmodule
|
||||
|
||||
interface bus_if ();
|
||||
logic value;
|
||||
logic sample;
|
||||
|
||||
modport consumer(input value, output sample);
|
||||
endinterface
|
||||
|
|
|
|||
|
|
@ -3,12 +3,6 @@
|
|||
// This file is placed into the Public Domain, for any use, without
|
||||
// warranty.
|
||||
|
||||
interface bus_if ();
|
||||
logic value;
|
||||
|
||||
modport consumer(input value);
|
||||
endinterface
|
||||
|
||||
module test;
|
||||
bus_user dut();
|
||||
endmodule
|
||||
|
|
@ -17,3 +11,9 @@ module bus_user(
|
|||
bus_if.consumer bus
|
||||
);
|
||||
endmodule
|
||||
|
||||
interface bus_if ();
|
||||
logic value;
|
||||
|
||||
modport consumer(input value);
|
||||
endinterface
|
||||
|
|
|
|||
|
|
@ -4,12 +4,6 @@
|
|||
// This file is placed into the Public Domain, for any use, without
|
||||
// warranty.
|
||||
|
||||
interface bus_if ();
|
||||
logic [7:0] lhs;
|
||||
logic [7:0] rhs;
|
||||
logic [8:0] sum;
|
||||
endinterface
|
||||
|
||||
module test;
|
||||
logic [7:0] lhs;
|
||||
logic [7:0] rhs;
|
||||
|
|
@ -38,3 +32,9 @@ module add_if(
|
|||
);
|
||||
assign bus.sum = bus.lhs + bus.rhs;
|
||||
endmodule
|
||||
|
||||
interface bus_if ();
|
||||
logic [7:0] lhs;
|
||||
logic [7:0] rhs;
|
||||
logic [8:0] sum;
|
||||
endinterface
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
// This tests the diagnostic path for an unmodported interface-typed
|
||||
// module port whose interface type name is not declared.
|
||||
//
|
||||
// This file is placed into the Public Domain, for any use, without
|
||||
// warranty.
|
||||
|
||||
module bus_user(
|
||||
missing_if bus
|
||||
);
|
||||
initial $display("FAILED");
|
||||
endmodule
|
||||
|
|
@ -3,13 +3,6 @@
|
|||
// This file is placed into the Public Domain, for any use, without
|
||||
// warranty.
|
||||
|
||||
interface bus_if ();
|
||||
logic value;
|
||||
logic sample;
|
||||
|
||||
modport consumer(input value, output sample);
|
||||
endinterface
|
||||
|
||||
module test;
|
||||
bus_if bus();
|
||||
|
||||
|
|
@ -31,3 +24,10 @@ module bus_user(
|
|||
);
|
||||
assign bus.sample = bus.value;
|
||||
endmodule
|
||||
|
||||
interface bus_if ();
|
||||
logic value;
|
||||
logic sample;
|
||||
|
||||
modport consumer(input value, output sample);
|
||||
endinterface
|
||||
|
|
|
|||
|
|
@ -270,12 +270,14 @@ sv_foreach9 vvp_tests/sv_foreach9.json
|
|||
sv_foreach10 vvp_tests/sv_foreach10.json
|
||||
sv_interface vvp_tests/sv_interface.json
|
||||
sv_interface_port_basic vvp_tests/sv_interface_port_basic.json
|
||||
sv_interface_port_missing_type_fail vvp_tests/sv_interface_port_missing_type_fail.json
|
||||
sv_interface_port_missing_modport_fail vvp_tests/sv_interface_port_missing_modport_fail.json
|
||||
sv_interface_port_non_interface_actual_fail vvp_tests/sv_interface_port_non_interface_actual_fail.json
|
||||
sv_interface_port_wrong_type_fail vvp_tests/sv_interface_port_wrong_type_fail.json
|
||||
sv_interface_port_modport_input_write_fail vvp_tests/sv_interface_port_modport_input_write_fail.json
|
||||
sv_interface_port_unlisted_member_fail vvp_tests/sv_interface_port_unlisted_member_fail.json
|
||||
sv_interface_port_unmodported_basic vvp_tests/sv_interface_port_unmodported_basic.json
|
||||
sv_interface_port_unmodported_missing_type_fail vvp_tests/sv_interface_port_unmodported_missing_type_fail.json
|
||||
sv_interface_port_forwarding vvp_tests/sv_interface_port_forwarding.json
|
||||
sv_interface_port_forwarding_restrict_fail vvp_tests/sv_interface_port_forwarding_restrict_fail.json
|
||||
sv_interface_port_positional vvp_tests/sv_interface_port_positional.json
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"type" : "CE",
|
||||
"source" : "sv_interface_port_missing_type_fail.v",
|
||||
"gold" : "sv_interface_port_missing_type_fail",
|
||||
"iverilog-args" : [ "-g2005-sv" ]
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"type" : "CE",
|
||||
"source" : "sv_interface_port_unmodported_missing_type_fail.v",
|
||||
"gold" : "sv_interface_port_unmodported_missing_type_fail",
|
||||
"iverilog-args" : [ "-g2005-sv" ]
|
||||
}
|
||||
38
lexor.lex
38
lexor.lex
|
|
@ -120,6 +120,8 @@ static list<int> keyword_mask_stack;
|
|||
static int comment_enter;
|
||||
static bool in_module = false;
|
||||
static bool in_UDP = false;
|
||||
static bool in_module_port_list = false;
|
||||
static bool module_port_list_start = false;
|
||||
bool in_celldefine = false;
|
||||
UCDriveType uc_drive = UCD_NONE;
|
||||
static int ts_state = 0;
|
||||
|
|
@ -139,6 +141,12 @@ void lex_in_package_scope(PPackage*pkg)
|
|||
in_package_scope = pkg;
|
||||
}
|
||||
|
||||
void lex_in_module_port_list(bool flag)
|
||||
{
|
||||
in_module_port_list = flag;
|
||||
module_port_list_start = flag;
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
%x CCOMMENT
|
||||
|
|
@ -160,6 +168,7 @@ void lex_in_package_scope(PPackage*pkg)
|
|||
%x REAL_SCALE
|
||||
|
||||
W [ \t\b\f\r]+
|
||||
ID [a-zA-Z_][a-zA-Z0-9$_]*
|
||||
|
||||
S [afpnumkKMGT]
|
||||
|
||||
|
|
@ -335,7 +344,7 @@ TU [munpf]
|
|||
<EDGES>"z0" { return K_edge_descriptor; }
|
||||
<EDGES>"z1" { return K_edge_descriptor; }
|
||||
|
||||
[a-zA-Z_][a-zA-Z0-9$_]* {
|
||||
{ID} {
|
||||
int rc = lexor_keyword_code(yytext, yyleng);
|
||||
switch (rc) {
|
||||
case IDENTIFIER:
|
||||
|
|
@ -434,6 +443,22 @@ TU [munpf]
|
|||
}
|
||||
}
|
||||
|
||||
if (rc == IDENTIFIER && gn_system_verilog() &&
|
||||
in_module_port_list && module_port_list_start) {
|
||||
char save_ch = *yy_c_buf_p;
|
||||
*yy_c_buf_p = yy_hold_char;
|
||||
const char*cp = yy_c_buf_p;
|
||||
while (*cp == ' ' || *cp == '\t' || *cp == '\b' ||
|
||||
*cp == '\f' || *cp == '\r' || *cp == '\n')
|
||||
cp += 1;
|
||||
if (*cp == '.' || isalpha(static_cast<unsigned char>(*cp)) ||
|
||||
*cp == '_' || *cp == '\\')
|
||||
rc = INTERFACE_IDENTIFIER;
|
||||
*yy_c_buf_p = save_ch;
|
||||
}
|
||||
|
||||
if (in_module_port_list)
|
||||
module_port_list_start = false;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
@ -906,7 +931,16 @@ TU [munpf]
|
|||
`{W} { VLerror(yylloc, "error: Stray tic (`) here. Perhaps you put white "
|
||||
"space between the tic and preprocessor directive?"); }
|
||||
|
||||
. { return yytext[0]; }
|
||||
. {
|
||||
if (in_module_port_list) {
|
||||
if (yytext[0] == '(' || yytext[0] == ',')
|
||||
module_port_list_start = true;
|
||||
else if (yytext[0] != ')' && yytext[0] != '[' &&
|
||||
yytext[0] != ']' && yytext[0] != ':')
|
||||
module_port_list_start = false;
|
||||
}
|
||||
return yytext[0];
|
||||
}
|
||||
|
||||
/* Final catchall. something got lost or mishandled. */
|
||||
/* XXX Should we tell the user something about the lexical state? */
|
||||
|
|
|
|||
18
parse.y
18
parse.y
|
|
@ -4781,9 +4781,11 @@ module
|
|||
port_declaration_context_init(); }
|
||||
module_package_import_list_opt
|
||||
module_parameter_port_list_opt
|
||||
{ lex_in_module_port_list(true); }
|
||||
module_port_list_opt
|
||||
{ lex_in_module_port_list(false); }
|
||||
module_attribute_foreign ';'
|
||||
{ pform_module_set_ports($8); }
|
||||
{ pform_module_set_ports($9); }
|
||||
timeunits_declaration_opt
|
||||
{ pform_set_scope_timescale(@2); }
|
||||
module_item_list_opt
|
||||
|
|
@ -4806,16 +4808,16 @@ module
|
|||
}
|
||||
// Check that program/endprogram and module/endmodule
|
||||
// keywords match.
|
||||
if ($2 != $15) {
|
||||
if ($2 != $17) {
|
||||
switch ($2) {
|
||||
case K_module:
|
||||
yyerror(@15, "error: module not closed by endmodule.");
|
||||
yyerror(@17, "error: module not closed by endmodule.");
|
||||
break;
|
||||
case K_program:
|
||||
yyerror(@15, "error: program not closed by endprogram.");
|
||||
yyerror(@17, "error: program not closed by endprogram.");
|
||||
break;
|
||||
case K_interface:
|
||||
yyerror(@15, "error: interface not closed by endinterface.");
|
||||
yyerror(@17, "error: interface not closed by endinterface.");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
@ -4831,13 +4833,13 @@ module
|
|||
// module.
|
||||
switch ($2) {
|
||||
case K_module:
|
||||
check_end_label(@17, "module", $4, $17);
|
||||
check_end_label(@19, "module", $4, $19);
|
||||
break;
|
||||
case K_program:
|
||||
check_end_label(@17, "program", $4, $17);
|
||||
check_end_label(@19, "program", $4, $19);
|
||||
break;
|
||||
case K_interface:
|
||||
check_end_label(@17, "interface", $4, $17);
|
||||
check_end_label(@19, "interface", $4, $19);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -83,6 +83,13 @@ extern UCDriveType uc_drive;
|
|||
*/
|
||||
extern void lex_in_package_scope(PPackage*pkg);
|
||||
|
||||
/*
|
||||
* The parser signals when the lexor is scanning a module/interface/program
|
||||
* port list so that ambiguous SystemVerilog interface formals can be
|
||||
* tokenized without depending on declaration order.
|
||||
*/
|
||||
extern void lex_in_module_port_list(bool flag);
|
||||
|
||||
/*
|
||||
* Test if this identifier is a type identifier in the current
|
||||
* context. The pform code needs to help the lexor here because the
|
||||
|
|
|
|||
Loading…
Reference in New Issue