From 27686d8c2fe5249e3ccac4ca956047ff00266a65 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Mon, 30 Sep 2013 16:52:43 -0400 Subject: [PATCH] Add --no-order-clock-delay to work around bug613. --- Changes | 2 + bin/verilator | 7 ++ src/V3Options.cpp | 2 + src/V3Options.h | 2 + src/V3Order.cpp | 6 +- test_regress/t/t_clk_condflop_nord.pl | 19 ++++ test_regress/t/t_clk_condflop_nord.v | 131 ++++++++++++++++++++++++++ 7 files changed, 168 insertions(+), 1 deletion(-) create mode 100755 test_regress/t/t_clk_condflop_nord.pl create mode 100644 test_regress/t/t_clk_condflop_nord.v diff --git a/Changes b/Changes index 7b2fe56cf..ed73f5f27 100644 --- a/Changes +++ b/Changes @@ -6,6 +6,8 @@ indicates the contributor was also the author of the fix; Thanks! * Verilator 3.853 devel +**** Add --no-order-clock-delay to work around bug613. [Charlie Brej] + * Verilator 3.852 2013-09-29 diff --git a/bin/verilator b/bin/verilator index 11f1c1da5..5b49ad5ad 100755 --- a/bin/verilator +++ b/bin/verilator @@ -299,6 +299,7 @@ descriptions in the next sections for more information. -O3 High performance optimizations -O Selectable optimizations -o Name of final executable + --no-order-clock-delay Disable ordering clock enable assignments --output-split Split .cpp files into pieces --output-split-cfuncs Split .cpp functions --output-split-ctrace Split tracing functions @@ -789,6 +790,12 @@ mappings of optimizations to -O letters. Specify the name for the final executable built if using --exe. Defaults to the --prefix if not specified. +=item --no-order-clock-delay + +Rarely needed. Disables a bug fix for ordering of clock enables with +delayed assignments. This flag should only be used when suggested by the +developers. + =item --output-split I Enables splitting the output .cpp/.sp files into multiple outputs. When a diff --git a/src/V3Options.cpp b/src/V3Options.cpp index caecbb4e6..0acf37047 100644 --- a/src/V3Options.cpp +++ b/src/V3Options.cpp @@ -738,6 +738,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char else if ( onoff (sw, "-l2name", flag/*ref*/) ) { m_l2Name = flag; } else if ( onoff (sw, "-lint-only", flag/*ref*/) ) { m_lintOnly = flag; } else if ( !strcmp (sw, "-no-pins64") ) { m_pinsBv = 33; } + else if ( onoff (sw, "-order-clock-delay", flag/*ref*/) ) { m_orderClockDly = flag; } else if ( !strcmp (sw, "-pins64") ) { m_pinsBv = 65; } else if ( onoff (sw, "-pins-sc-uint", flag/*ref*/) ){ m_pinsScUint = flag; if (!m_pinsScBigUint) m_pinsBv = 65; } else if ( onoff (sw, "-pins-sc-biguint", flag/*ref*/) ){ m_pinsScBigUint = flag; m_pinsBv = 513; } @@ -1203,6 +1204,7 @@ V3Options::V3Options() { m_lintOnly = false; m_makeDepend = true; m_makePhony = false; + m_orderClockDly = true; m_outFormatOk = false; m_warnFatal = true; m_pinsBv = 65; diff --git a/src/V3Options.h b/src/V3Options.h index 84feac46d..695d552e8 100644 --- a/src/V3Options.h +++ b/src/V3Options.h @@ -74,6 +74,7 @@ class V3Options { bool m_inhibitSim; // main switch: --inhibit-sim bool m_l2Name; // main switch: --l2name bool m_lintOnly; // main switch: --lint-only + bool m_orderClockDly;// main switch: --order-clock-delay bool m_outFormatOk; // main switch: --cc, --sc or --sp was specified bool m_warnFatal; // main switch: --warnFatal bool m_pinsScUint; // main switch: --pins-sc-uint @@ -214,6 +215,7 @@ class V3Options { bool trace() const { return m_trace; } bool traceDups() const { return m_traceDups; } bool traceUnderscore() const { return m_traceUnderscore; } + bool orderClockDly() const { return m_orderClockDly; } bool outFormatOk() const { return m_outFormatOk; } bool keepTempFiles() const { return (V3Error::debugDefault()!=0); } bool warnFatal() const { return m_warnFatal; } diff --git a/src/V3Order.cpp b/src/V3Order.cpp index 313dcb6a6..5cdc0f321 100644 --- a/src/V3Order.cpp +++ b/src/V3Order.cpp @@ -1161,7 +1161,11 @@ void OrderVisitor::processCircular() { // it is generated by delayed assignment, we need the loop. If // it is combinatorial, we do not (and indeed it will break // other tests such as t_gated_clk_1. - if (vvertexp->isDelayed()) { + if (!v3Global.opt.orderClockDly()) { + UINFO(5,"Circular Clock, no-order-clock-delay "<isDelayed()) { UINFO(5,"Circular Clock, delayed "<["-no-order-clock-delay"], + ); + +execute ( + check_finished => 1 + ); + +ok(1); +1; diff --git a/test_regress/t/t_clk_condflop_nord.v b/test_regress/t/t_clk_condflop_nord.v new file mode 100644 index 000000000..e6a18e0db --- /dev/null +++ b/test_regress/t/t_clk_condflop_nord.v @@ -0,0 +1,131 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2005 by Wilson Snyder. + +module t (clk); + input clk; + + reg [0:0] d1; + reg [2:0] d3; + reg [7:0] d8; + + wire [0:0] q1; + wire [2:0] q3; + wire [7:0] q8; + + // verilator lint_off UNOPTFLAT + reg ena; + // verilator lint_on UNOPTFLAT + + condff #(12) condff + (.clk(clk), .sen(1'b0), .ena(ena), + .d({d8,d3,d1}), + .q({q8,q3,q1})); + + integer cyc; initial cyc=1; + always @ (posedge clk) begin + if (cyc!=0) begin + //$write("%x %x %x %x\n", cyc, q8, q3, q1); + cyc <= cyc + 1; + if (cyc==1) begin + d1 <= 1'b1; d3<=3'h1; d8<=8'h11; + ena <= 1'b1; + end + if (cyc==2) begin + d1 <= 1'b0; d3<=3'h2; d8<=8'h33; + ena <= 1'b0; + end + if (cyc==3) begin + d1 <= 1'b1; d3<=3'h3; d8<=8'h44; + ena <= 1'b1; + // PROPER ANSWER is 8'h11, but we are negative-testing + //if (q8 != 8'h11) $stop; + if (q8 != 8'h33) $stop; + end + if (cyc==4) begin + d1 <= 1'b1; d3<=3'h4; d8<=8'h77; + ena <= 1'b1; + // PROPER ANSWER is 8'h11, but we are negative-testing + //if (q8 != 8'h11) $stop; + if (q8 != 8'h33) $stop; + end + if (cyc==5) begin + d1 <= 1'b1; d3<=3'h0; d8<=8'h88; + ena <= 1'b1; + // PROPER ANSWER is 8'h44, but we are negative-testing + //if (q8 != 8'h44) $stop; + end + if (cyc==6) begin + // PROPER ANSWER is 8'h77, but we are negative-testing + //if (q8 != 8'h77) $stop; + end + if (cyc==7) begin + // PROPER ANSWER is 8'h88, but we are negative-testing + //if (q8 != 8'h88) $stop; + end + // + if (cyc==20) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end + end +endmodule + +module condff (clk, sen, ena, d, q); + parameter WIDTH = 1; + input clk; + + input sen; + input ena; + input [WIDTH-1:0] d; + output [WIDTH-1:0] q; + + condffimp #(.WIDTH(WIDTH)) + imp (.clk(clk), .sen(sen), .ena(ena), .d(d), .q(q)); +endmodule + +module condffimp (clk, sen, ena, d, q); + parameter WIDTH = 1; + input clk; + input sen; + input ena; + input [WIDTH-1:0] d; + output reg [WIDTH-1:0] q; + wire gatedclk; + + clockgate clockgate (.clk(clk), .sen(sen), .ena(ena), .gatedclk(gatedclk)); + + always @(posedge gatedclk) begin + if (gatedclk === 1'bX) begin + q <= {WIDTH{1'bX}}; + end + else begin + q <= d; + end + end + +endmodule + +module clockgate (clk, sen, ena, gatedclk); + input clk; + input sen; + input ena; + output gatedclk; + + reg ena_b; + wire gatedclk = clk & ena_b; + + // verilator lint_off COMBDLY + always @(clk or ena or sen) begin + if (~clk) begin + ena_b <= ena | sen; + end + else begin + if ((clk^sen)===1'bX) ena_b <= 1'bX; + end + end + // verilator lint_on COMBDLY + +endmodule