Fix preprocessor else after series of elsif. [Mark Nodine]

git-svn-id: file://localhost/svn/verilator/trunk/verilator@1047 77ca24e4-aefa-0310-84f0-b9a241c72d87
This commit is contained in:
Wilson Snyder 2008-05-06 00:50:47 +00:00
parent e0abd238e3
commit d2d38edf06
4 changed files with 94 additions and 13 deletions

View File

@ -7,6 +7,8 @@ indicates the contributor was also the author of the fix; Thanks!
**** Fix compiler warnings under GCC 4.2.1.
**** Fix preprocessor `else after series of `elsif. [Mark Nodine]
* Verilator 3.662 2008/04/25
*** Add Verilog 2005 $clog2() function.

View File

@ -83,6 +83,21 @@ public:
~V3DefineRef() {}
};
//*************************************************************************
/// Data for parsing on/off
class VPreIfEntry {
// One for each pending ifdef/ifndef
bool m_on; // Current parse for this ifdef level is "on"
bool m_everOn; // Some if term in elsif tree has been on
public:
bool on() const { return m_on; }
bool everOn() const { return m_everOn; }
VPreIfEntry(bool on, bool everOn)
: m_on(on), m_everOn(everOn || on) {} // Note everOn includes new state
~VPreIfEntry() {}
};
//*************************************************************************
// Data for a preprocessor instantiation.
@ -111,7 +126,7 @@ struct V3PreProcImp : public V3PreProc {
// For defines
stack<V3DefineRef> m_defRefs; // Pending definine substitution
stack<bool> m_ifdefStack; // Stack of true/false emitting evaluations
stack<VPreIfEntry> m_ifdefStack; ///< Stack of true/false emitting evaluations
unsigned m_defDepth; // How many `defines deep
// Defines list
@ -655,7 +670,7 @@ int V3PreProcImp::getToken() {
bool enable = defExists(m_lastSym);
UINFO(4,"Ifdef "<<m_lastSym<<(enable?" ON":" OFF")<<endl);
if (m_stateFor==VP_IFNDEF) enable = !enable;
m_ifdefStack.push(enable);
m_ifdefStack.push(VPreIfEntry(enable,false));
if (!enable) parsingOff();
}
else if (m_stateFor==VP_ELSIF) {
@ -663,12 +678,12 @@ int V3PreProcImp::getToken() {
fileline()->v3error("`elsif with no matching `if\n");
} else {
// Handle `else portion
bool lastEnable = m_ifdefStack.top(); m_ifdefStack.pop();
if (!lastEnable) parsingOn();
VPreIfEntry lastIf = m_ifdefStack.top(); m_ifdefStack.pop();
if (!lastIf.on()) parsingOn();
// Handle `if portion
bool enable = !lastEnable && defExists(m_lastSym);
bool enable = !lastIf.everOn() && defExists(m_lastSym);
UINFO(4,"Elsif "<<m_lastSym<<(enable?" ON":" OFF")<<endl);
m_ifdefStack.push(enable);
m_ifdefStack.push(VPreIfEntry(enable, lastIf.everOn()));
if (!enable) parsingOff();
}
}
@ -856,21 +871,23 @@ int V3PreProcImp::getToken() {
if (m_ifdefStack.empty()) {
fileline()->v3error("`else with no matching `if\n");
} else {
bool lastEnable = m_ifdefStack.top(); m_ifdefStack.pop();
bool enable = !lastEnable;
VPreIfEntry lastIf = m_ifdefStack.top(); m_ifdefStack.pop();
bool enable = !lastIf.everOn();
UINFO(4,"Else "<<(enable?" ON":" OFF")<<endl);
m_ifdefStack.push(enable);
if (!lastEnable) parsingOn();
m_ifdefStack.push(VPreIfEntry(enable, lastIf.everOn()));
if (!lastIf.on()) parsingOn();
if (!enable) parsingOff();
}
goto next_tok;
case VP_ENDIF:
UINFO(4,"Endif "<<endl);
if (m_ifdefStack.empty()) {
fileline()->v3error("`endif with no matching `if\n");
} else {
bool lastEnable = m_ifdefStack.top(); m_ifdefStack.pop();
UINFO(4,"Endif "<<endl);
if (!lastEnable) parsingOn();
VPreIfEntry lastIf = m_ifdefStack.top(); m_ifdefStack.pop();
if (!lastIf.on()) parsingOn();
// parsingOn() really only enables parsing if
// all ifdef's above this want it on
}
goto next_tok;

View File

@ -0,0 +1,18 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
# $Id$
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# General Public License or the Perl Artistic License.
compile (
);
execute (
check_finished=>1,
);
ok(1);
1;

View File

@ -0,0 +1,44 @@
// $Id$
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2007 by Wilson Snyder.
module t (/*AUTOARG*/);
integer num;
initial begin
num = 0;
`define EMPTY_TRUE
`ifndef EMPTY_TRUE
`error "Empty is still true"
`endif
`define A
`ifdef A $display("1A"); num = num + 1;
`ifdef C $stop;
`elsif A $display("2A"); num = num + 1;
`ifdef C $stop;
`elsif B $stop;
`else $display("3A"); num = num + 1;
`endif
`else $stop;
`endif
`elsif B $stop;
`ifdef A $stop;
`elsif A $stop;
`else
`endif
`elsif C $stop;
`else $stop;
`endif
if (num == 3) begin
$write("*-* All Finished *-*\n");
$finish;
end
else begin
$write("%%Error: Bad count: %d\n", num);
$stop;
end
end
endmodule