Support free-form `(no)unconnected_drive directives.

Also use VLerror for reporting errors.
This commit is contained in:
Martin Whitaker 2022-12-20 16:45:57 +00:00
parent 59d70cad45
commit 0dc64b99f3
3 changed files with 72 additions and 29 deletions

View File

@ -0,0 +1,45 @@
module top;
reg pass;
highz dutz();
pulllow dut0();
pullhigh dut1();
initial begin
pass = 1'b1;
#10;
if (pass) $display("PASSED");
end
endmodule
module highz(in);
input in;
initial #1 if (in !== 1'bz) begin
$display("FAILED: high-Z of floating input port (%b)", in);
top.pass = 1'b0;
end
endmodule
/* comment */ `unconnected_drive /* comment */ pull0 /* comment */ // comment
module pulllow(in);
input in;
initial #1 if (in !== 1'b0) begin
$display("FAILED: pull0 of floating input port (%b)", in);
top.pass = 1'b0;
end
endmodule
/* comment */ `nounconnected_drive /* comment */ // comment
/* comment */`unconnected_drive/*
comment */
/* comment */pull1/*
comment */
module pullhigh(in);
input in;
initial #1 if (in !== 1'b1) begin
$display("FAILED: pull1 of floating input port (%b)", in);
top.pass = 1'b0;
end
endmodule
/* comment */`nounconnected_drive/*
comment */

View File

@ -349,6 +349,7 @@ br_gh632b normal,-S ivltests
br_gh632c normal ivltests br_gh632c normal ivltests
br_gh674 normal ivltests br_gh674 normal ivltests
br_gh732 normal ivltests gold=br_gh732.gold br_gh732 normal ivltests gold=br_gh732.gold
br_gh782c normal ivltests
br_gh788 normal,-gno-io-range-error,-Wno-anachronisms ivltests gold=br_gh788.gold br_gh788 normal,-gno-io-range-error,-Wno-anachronisms ivltests gold=br_gh788.gold
br_gh793 normal ivltests br_gh793 normal ivltests
br_ml20150315 normal ivltests gold=br_ml_20150315.gold br_ml20150315 normal ivltests gold=br_ml_20150315.gold

View File

@ -150,6 +150,7 @@ void lex_in_package_scope(PPackage*pkg)
%x PPTIMESCALE_SLASH %x PPTIMESCALE_SLASH
%x PPTIMESCALE_ERROR %x PPTIMESCALE_ERROR
%x PPUCDRIVE %x PPUCDRIVE
%x PPUCDRIVE_ERROR
%x PPDEFAULT_NETTYPE %x PPDEFAULT_NETTYPE
%x PPBEGIN_KEYWORDS %x PPBEGIN_KEYWORDS
%s EDGES %s EDGES
@ -660,24 +661,32 @@ TU [munpf]
} } } }
/* Notice and handle the `unconnected_drive directive. */ /* Notice and handle the `unconnected_drive directive. */
^{W}?`unconnected_drive { BEGIN(PPUCDRIVE); }
<PPUCDRIVE>.* { process_ucdrive(yytext); } `unconnected_drive { BEGIN(PPUCDRIVE); }
<PPUCDRIVE>\n {
<PPUCDRIVE>[a-zA-Z0-9_]+ {
process_ucdrive(yytext);
if (in_module) { if (in_module) {
cerr << yylloc.text << ":" << yylloc.first_line << ": error: " VLerror(yylloc, "error: `unconnected_drive directive cannot be "
"`unconnected_drive directive can not be inside a " "inside a module definition.");
"module definition." << endl;
error_count += 1;
} }
yylloc.first_line += 1;
BEGIN(0); } BEGIN(0); }
^{W}?`nounconnected_drive{W}? { <PPUCDRIVE>"//" { comment_enter = PPUCDRIVE; BEGIN(LCOMMENT); }
<PPUCDRIVE>"/*" { comment_enter = PPUCDRIVE; BEGIN(CCOMMENT); }
<PPUCDRIVE>"\n" { yylloc.first_line += 1; }
<PPUCDRIVE>{W} { ; }
<PPUCDRIVE>. { BEGIN(PPUCDRIVE_ERROR); }
/* On error, try to recover by skipping to the end of the line. */
<PPUCDRIVE_ERROR>[^\n]+ {
VLerror(yylloc, "error: Invalid `unconnected_drive directive.");
BEGIN(0); }
`nounconnected_drive {
if (in_module) { if (in_module) {
cerr << yylloc.text << ":" << yylloc.first_line << ": error: " VLerror(yylloc, "error: `nounconnected_drive directive cannot be "
"`nounconnected_drive directive can not be inside a " "inside a module definition.");
"module definition." << endl;
error_count += 1;
} }
uc_drive = UCD_NONE; } uc_drive = UCD_NONE; }
@ -1397,21 +1406,13 @@ static int get_timescale_const(int scale, const char *units)
} }
/* /*
* process either a pull0 or a pull1. * Process either a pull0 or a pull1.
*/ */
static void process_ucdrive(const char*txt) static void process_ucdrive(const char*txt)
{ {
UCDriveType ucd = UCD_NONE; UCDriveType ucd = UCD_NONE;
const char*cp = txt + strspn(txt, " \t");
/* Skip the space after the `unconnected_drive directive. */ const char*cp = txt;
if (cp == txt) {
VLerror(yylloc, "Space required after `unconnected_drive "
"directive.");
return;
}
/* Check for the pull keyword. */
if (strncmp("pull", cp, 4) != 0) { if (strncmp("pull", cp, 4) != 0) {
VLerror(yylloc, "pull required for `unconnected_drive " VLerror(yylloc, "pull required for `unconnected_drive "
"directive."); "directive.");
@ -1428,13 +1429,9 @@ static void process_ucdrive(const char*txt)
return; return;
} }
cp += 1; cp += 1;
if (*cp != '\0') {
/* Verify that only space and/or a single line comment is left. */
cp += strspn(cp, " \t");
if (strncmp(cp, "//", 2) != 0 &&
(size_t)(cp-yytext) != strlen(yytext)) {
VLerror(yylloc, "Invalid `unconnected_drive directive (extra " VLerror(yylloc, "Invalid `unconnected_drive directive (extra "
"garbage after precision)."); "garbage after pull direction).");
return; return;
} }