From d2d38edf06ff9a0307f49a7bd19a617d27705ecb Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Tue, 6 May 2008 00:50:47 +0000 Subject: [PATCH] Fix preprocessor `else after series of `elsif. [Mark Nodine] git-svn-id: file://localhost/svn/verilator/trunk/verilator@1047 77ca24e4-aefa-0310-84f0-b9a241c72d87 --- Changes | 2 ++ src/V3PreProc.cpp | 43 +++++++++++++++++++++--------- test_regress/t/t_preproc_ifdef.pl | 18 +++++++++++++ test_regress/t/t_preproc_ifdef.v | 44 +++++++++++++++++++++++++++++++ 4 files changed, 94 insertions(+), 13 deletions(-) create mode 100755 test_regress/t/t_preproc_ifdef.pl create mode 100644 test_regress/t/t_preproc_ifdef.v diff --git a/Changes b/Changes index df3378fc0..ec2c747e6 100644 --- a/Changes +++ b/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 preprocessor `else after series of `elsif. [Mark Nodine] + * Verilator 3.662 2008/04/25 *** Add Verilog 2005 $clog2() function. diff --git a/src/V3PreProc.cpp b/src/V3PreProc.cpp index b7eb22fcb..810e27d59 100644 --- a/src/V3PreProc.cpp +++ b/src/V3PreProc.cpp @@ -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 m_defRefs; // Pending definine substitution - stack m_ifdefStack; // Stack of true/false emitting evaluations + stack 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 "<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 "<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")<v3error("`endif with no matching `if\n"); } else { - bool lastEnable = m_ifdefStack.top(); m_ifdefStack.pop(); - UINFO(4,"Endif "<1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_preproc_ifdef.v b/test_regress/t/t_preproc_ifdef.v new file mode 100644 index 000000000..61cfad07d --- /dev/null +++ b/test_regress/t/t_preproc_ifdef.v @@ -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