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:
parent
e0abd238e3
commit
d2d38edf06
2
Changes
2
Changes
|
|
@ -7,6 +7,8 @@ indicates the contributor was also the author of the fix; Thanks!
|
||||||
|
|
||||||
**** Fix compiler warnings under GCC 4.2.1.
|
**** Fix compiler warnings under GCC 4.2.1.
|
||||||
|
|
||||||
|
**** Fix preprocessor `else after series of `elsif. [Mark Nodine]
|
||||||
|
|
||||||
* Verilator 3.662 2008/04/25
|
* Verilator 3.662 2008/04/25
|
||||||
|
|
||||||
*** Add Verilog 2005 $clog2() function.
|
*** Add Verilog 2005 $clog2() function.
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,21 @@ public:
|
||||||
~V3DefineRef() {}
|
~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.
|
// Data for a preprocessor instantiation.
|
||||||
|
|
||||||
|
|
@ -111,7 +126,7 @@ struct V3PreProcImp : public V3PreProc {
|
||||||
|
|
||||||
// For defines
|
// For defines
|
||||||
stack<V3DefineRef> m_defRefs; // Pending definine substitution
|
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
|
unsigned m_defDepth; // How many `defines deep
|
||||||
|
|
||||||
// Defines list
|
// Defines list
|
||||||
|
|
@ -655,7 +670,7 @@ int V3PreProcImp::getToken() {
|
||||||
bool enable = defExists(m_lastSym);
|
bool enable = defExists(m_lastSym);
|
||||||
UINFO(4,"Ifdef "<<m_lastSym<<(enable?" ON":" OFF")<<endl);
|
UINFO(4,"Ifdef "<<m_lastSym<<(enable?" ON":" OFF")<<endl);
|
||||||
if (m_stateFor==VP_IFNDEF) enable = !enable;
|
if (m_stateFor==VP_IFNDEF) enable = !enable;
|
||||||
m_ifdefStack.push(enable);
|
m_ifdefStack.push(VPreIfEntry(enable,false));
|
||||||
if (!enable) parsingOff();
|
if (!enable) parsingOff();
|
||||||
}
|
}
|
||||||
else if (m_stateFor==VP_ELSIF) {
|
else if (m_stateFor==VP_ELSIF) {
|
||||||
|
|
@ -663,12 +678,12 @@ int V3PreProcImp::getToken() {
|
||||||
fileline()->v3error("`elsif with no matching `if\n");
|
fileline()->v3error("`elsif with no matching `if\n");
|
||||||
} else {
|
} else {
|
||||||
// Handle `else portion
|
// Handle `else portion
|
||||||
bool lastEnable = m_ifdefStack.top(); m_ifdefStack.pop();
|
VPreIfEntry lastIf = m_ifdefStack.top(); m_ifdefStack.pop();
|
||||||
if (!lastEnable) parsingOn();
|
if (!lastIf.on()) parsingOn();
|
||||||
// Handle `if portion
|
// 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);
|
UINFO(4,"Elsif "<<m_lastSym<<(enable?" ON":" OFF")<<endl);
|
||||||
m_ifdefStack.push(enable);
|
m_ifdefStack.push(VPreIfEntry(enable, lastIf.everOn()));
|
||||||
if (!enable) parsingOff();
|
if (!enable) parsingOff();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -856,21 +871,23 @@ int V3PreProcImp::getToken() {
|
||||||
if (m_ifdefStack.empty()) {
|
if (m_ifdefStack.empty()) {
|
||||||
fileline()->v3error("`else with no matching `if\n");
|
fileline()->v3error("`else with no matching `if\n");
|
||||||
} else {
|
} else {
|
||||||
bool lastEnable = m_ifdefStack.top(); m_ifdefStack.pop();
|
VPreIfEntry lastIf = m_ifdefStack.top(); m_ifdefStack.pop();
|
||||||
bool enable = !lastEnable;
|
bool enable = !lastIf.everOn();
|
||||||
UINFO(4,"Else "<<(enable?" ON":" OFF")<<endl);
|
UINFO(4,"Else "<<(enable?" ON":" OFF")<<endl);
|
||||||
m_ifdefStack.push(enable);
|
m_ifdefStack.push(VPreIfEntry(enable, lastIf.everOn()));
|
||||||
if (!lastEnable) parsingOn();
|
if (!lastIf.on()) parsingOn();
|
||||||
if (!enable) parsingOff();
|
if (!enable) parsingOff();
|
||||||
}
|
}
|
||||||
goto next_tok;
|
goto next_tok;
|
||||||
case VP_ENDIF:
|
case VP_ENDIF:
|
||||||
|
UINFO(4,"Endif "<<endl);
|
||||||
if (m_ifdefStack.empty()) {
|
if (m_ifdefStack.empty()) {
|
||||||
fileline()->v3error("`endif with no matching `if\n");
|
fileline()->v3error("`endif with no matching `if\n");
|
||||||
} else {
|
} else {
|
||||||
bool lastEnable = m_ifdefStack.top(); m_ifdefStack.pop();
|
VPreIfEntry lastIf = m_ifdefStack.top(); m_ifdefStack.pop();
|
||||||
UINFO(4,"Endif "<<endl);
|
if (!lastIf.on()) parsingOn();
|
||||||
if (!lastEnable) parsingOn();
|
// parsingOn() really only enables parsing if
|
||||||
|
// all ifdef's above this want it on
|
||||||
}
|
}
|
||||||
goto next_tok;
|
goto next_tok;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
@ -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
|
||||||
Loading…
Reference in New Issue