diff --git a/src/V3DfgAstToDfg.cpp b/src/V3DfgAstToDfg.cpp index 5c5e326d4..73ddd848a 100644 --- a/src/V3DfgAstToDfg.cpp +++ b/src/V3DfgAstToDfg.cpp @@ -439,11 +439,14 @@ class AstToDfgVisitor final : public VNVisitor { if (nodep->isSc()) return; // No need to (and in fact cannot) handle variables with unsupported dtypes if (!DfgVertex::isSupportedDType(nodep->dtypep())) return; - // Mark ports as having external references - if (nodep->isIO()) getNet(nodep)->setHasExtRefs(); - // Mark variables that are the target of a hierarchical reference - // (these flags were set up in DataflowPrepVisitor) - if (nodep->user2()) getNet(nodep)->setHasExtRefs(); + + // Mark variables with external references + if (nodep->isIO() // Ports + || nodep->user2() // Target of a hierarchical reference + || nodep->isForceable() // Forceable + ) { + getNet(nodep)->setHasExtRefs(); + } } void visit(AstAssignW* nodep) override { diff --git a/src/V3DfgPasses.cpp b/src/V3DfgPasses.cpp index 819c00f59..d2d96bb7a 100644 --- a/src/V3DfgPasses.cpp +++ b/src/V3DfgPasses.cpp @@ -167,9 +167,14 @@ void V3DfgPasses::inlineVars(const DfgGraph& dfg) { if (varp->hasSinks() && varp->isDrivenFullyByDfg() && !varp->varp()->isSc()) { DfgVertex* const driverp = varp->source(0); - // If driven from a SystemC variable, don't inline this variable + // We must keep the original driver in certain cases, when swapping them would + // not be functionally or technically (implementation reasons) equivalent if (DfgVertexVar* const driverVarp = driverp->cast()) { - if (driverVarp->varp()->isSc()) continue; + const AstVar* const varp = driverVarp->varp(); + // If driven from a SystemC variable + if (varp->isSc()) continue; + // If the variable is forceable + if (varp->isForceable()) continue; } varp->forEachSinkEdge([=](DfgEdge& edge) { diff --git a/src/V3DfgVertices.h b/src/V3DfgVertices.h index 9f892d46a..f65a3f283 100644 --- a/src/V3DfgVertices.h +++ b/src/V3DfgVertices.h @@ -248,7 +248,9 @@ public: : DfgVertexVar{dfg, dfgType(), varp, 1u} {} ASTGEN_MEMBERS_DfgVarPacked; - bool isDrivenFullyByDfg() const { return arity() == 1 && source(0)->dtypep() == dtypep(); } + bool isDrivenFullyByDfg() const { + return arity() == 1 && source(0)->dtypep() == dtypep() && !varp()->isForceable(); + } void addDriver(FileLine* flp, uint32_t lsb, DfgVertex* vtxp) { m_driverData.emplace_back(flp, lsb); diff --git a/test_regress/t/t_forceable_net.v b/test_regress/t/t_forceable_net.v index c84645a38..ba18adc2c 100644 --- a/test_regress/t/t_forceable_net.v +++ b/test_regress/t/t_forceable_net.v @@ -32,41 +32,44 @@ module t ( assign net_1 = ~cyc[0]; assign net_8 = ~cyc[1 +: 8]; + wire obs_1 = net_1; + wire [7:0] obs_8 = net_8; + always @ (posedge clk) begin - $display("%d: %x %x", cyc, net_8, net_1); + $display("%d: %x %x", cyc, obs_8, obs_1); if (!rst) begin case (cyc) 3: begin - `checkh (net_1, 0); - `checkh (net_8, ~cyc[1 +: 8]); + `checkh (obs_1, 0); + `checkh (obs_8, ~cyc[1 +: 8]); end 4: begin - `checkh (net_1, 0); - `checkh (net_8, 8'h5f); + `checkh (obs_1, 0); + `checkh (obs_8, 8'h5f); end 5: begin - `checkh (net_1, 1); - `checkh (net_8, 8'h5f); + `checkh (obs_1, 1); + `checkh (obs_8, 8'h5f); end 6, 7: begin - `checkh (net_1, 1); - `checkh (net_8, 8'hf5); + `checkh (obs_1, 1); + `checkh (obs_8, 8'hf5); end 8: begin - `checkh (net_1, ~cyc[0]); - `checkh (net_8, 8'hf5); + `checkh (obs_1, ~cyc[0]); + `checkh (obs_8, 8'hf5); end 10, 11: begin - `checkh (net_1, 1); - `checkh (net_8, 8'h5a); + `checkh (obs_1, 1); + `checkh (obs_8, 8'h5a); end 12, 13: begin - `checkh (net_1, 0); - `checkh (net_8, 8'ha5); + `checkh (obs_1, 0); + `checkh (obs_8, 8'ha5); end default: begin - `checkh ({net_8, net_1}, ~cyc[0 +: 9]); + `checkh ({obs_8, obs_1}, ~cyc[0 +: 9]); end endcase end diff --git a/test_regress/t/t_forceable_net_trace.vcd b/test_regress/t/t_forceable_net_trace.vcd index 23a870d1e..fde04185b 100644 --- a/test_regress/t/t_forceable_net_trace.vcd +++ b/test_regress/t/t_forceable_net_trace.vcd @@ -1,6 +1,5 @@ $version Generated by VerilatedVcd $end $timescale 1ps $end - $scope module top $end $var wire 1 # clk $end $var wire 1 $ rst $end @@ -11,6 +10,8 @@ $timescale 1ps $end $var wire 32 % cyc [31:0] $end $var wire 1 & net_1 $end $var wire 8 ' net_8 [7:0] $end + $var wire 1 & obs_1 $end + $var wire 8 ' obs_8 [7:0] $end $upscope $end $upscope $end $enddefinitions $end diff --git a/test_regress/t/t_forceable_var.v b/test_regress/t/t_forceable_var.v index fbd7164c6..4079780e8 100644 --- a/test_regress/t/t_forceable_var.v +++ b/test_regress/t/t_forceable_var.v @@ -21,6 +21,19 @@ module t ( end end + reg tmp_1; + reg [7:0] tmp_8; + + always @(posedge clk) begin + if (rst) begin + tmp_1 <= 0; + tmp_8 <= 0; + end else begin + tmp_1 <= cyc[0]; + tmp_8 <= cyc[1 +: 8]; + end + end + `ifdef CMT reg var_1 /* verilator forceable */; reg [7:0] var_8 /* verilator forceable */; @@ -29,55 +42,54 @@ module t ( reg [7:0] var_8; `endif - always @(posedge clk) begin - if (rst) begin - var_1 <= 0; - var_8 <= 0; - end else begin - var_1 <= cyc[0]; - var_8 <= cyc[1 +: 8]; - end - end + always @* var_1 = tmp_1; + always @* var_8 = tmp_8; + + reg obs_1; + reg [7:0] obs_8; + + always @* obs_1 = var_1; + always @* obs_8 = var_8; always @ (posedge clk) begin - $display("%d: %x %x", cyc, var_8, var_1); + $display("%d: %x %x", cyc, obs_8, obs_1); if (!rst) begin case (cyc) 0: begin // Reset values - `checkh (var_1, 0); - `checkh (var_8, 0); + `checkh (obs_1, 0); + `checkh (obs_8, 0); end 13: begin - `checkh (var_1, 1); - `checkh ({1'b0, var_8}, (cyc[0 +: 9] - 1) >> 1); + `checkh (obs_1, 1); + `checkh ({1'b0, obs_8}, (cyc[0 +: 9] - 1) >> 1); end 14: begin - `checkh (var_1, 1); - `checkh (var_8, 8'hf5); + `checkh (obs_1, 1); + `checkh (obs_8, 8'hf5); end 15: begin - `checkh (var_1, 0); - `checkh (var_8, 8'hf5); + `checkh (obs_1, 0); + `checkh (obs_8, 8'hf5); end 16, 17: begin - `checkh (var_1, 0); - `checkh (var_8, 8'h5f); + `checkh (obs_1, 0); + `checkh (obs_8, 8'h5f); end 18: begin - `checkh (var_1, ~cyc[0]); - `checkh (var_8, 8'h5f); + `checkh (obs_1, ~cyc[0]); + `checkh (obs_8, 8'h5f); end 20, 21: begin - `checkh (var_1, 1); - `checkh (var_8, 8'h5a); + `checkh (obs_1, 1); + `checkh (obs_8, 8'h5a); end 22, 23: begin - `checkh (var_1, 0); - `checkh (var_8, 8'ha5); + `checkh (obs_1, 0); + `checkh (obs_8, 8'ha5); end default: begin - `checkh ({var_8, var_1}, cyc[0 +: 9] - 1); + `checkh ({obs_8, obs_1}, cyc[0 +: 9] - 1); end endcase end diff --git a/test_regress/t/t_forceable_var_trace.vcd b/test_regress/t/t_forceable_var_trace.vcd index 1e5824fa2..1079c8e3e 100644 --- a/test_regress/t/t_forceable_var_trace.vcd +++ b/test_regress/t/t_forceable_var_trace.vcd @@ -1,6 +1,5 @@ $version Generated by VerilatedVcd $end $timescale 1ps $end - $scope module top $end $var wire 1 # clk $end $var wire 1 $ rst $end @@ -9,8 +8,12 @@ $timescale 1ps $end $var wire 1 # clk $end $var wire 1 $ rst $end $var wire 32 % cyc [31:0] $end - $var wire 1 & var_1 $end - $var wire 8 ' var_8 [7:0] $end + $var wire 1 & tmp_1 $end + $var wire 8 ' tmp_8 [7:0] $end + $var wire 1 ( var_1 $end + $var wire 8 ) var_8 [7:0] $end + $var wire 1 ( obs_1 $end + $var wire 8 ) obs_8 [7:0] $end $upscope $end $upscope $end $enddefinitions $end @@ -22,6 +25,8 @@ $enddefinitions $end b00000000000000000000000000000000 % 0& b00000000 ' +0( +b00000000 ) #5 1# 0$ @@ -36,6 +41,7 @@ b00000000000000000000000000000001 % 1# b00000000000000000000000000000010 % 1& +1( #30 0# #35 @@ -43,12 +49,15 @@ b00000000000000000000000000000010 % b00000000000000000000000000000011 % 0& b00000001 ' +0( +b00000001 ) #40 0# #45 1# b00000000000000000000000000000100 % 1& +1( #50 0# #55 @@ -56,12 +65,15 @@ b00000000000000000000000000000100 % b00000000000000000000000000000101 % 0& b00000010 ' +0( +b00000010 ) #60 0# #65 1# b00000000000000000000000000000110 % 1& +1( #70 0# #75 @@ -69,12 +81,15 @@ b00000000000000000000000000000110 % b00000000000000000000000000000111 % 0& b00000011 ' +0( +b00000011 ) #80 0# #85 1# b00000000000000000000000000001000 % 1& +1( #90 0# #95 @@ -82,12 +97,15 @@ b00000000000000000000000000001000 % b00000000000000000000000000001001 % 0& b00000100 ' +0( +b00000100 ) #100 0# #105 1# b00000000000000000000000000001010 % 1& +1( #110 0# #115 @@ -95,47 +113,59 @@ b00000000000000000000000000001010 % b00000000000000000000000000001011 % 0& b00000101 ' +0( +b00000101 ) #120 0# #125 1# b00000000000000000000000000001100 % 1& +1( #130 0# #135 1# b00000000000000000000000000001101 % +0& b00000110 ' +b00000110 ) #140 0# #145 1# b00000000000000000000000000001110 % -b11110101 ' +1& +b11110101 ) #150 0# #155 1# b00000000000000000000000000001111 % 0& +b00000111 ' +0( #160 0# #165 1# b00000000000000000000000000010000 % -b01011111 ' +1& +b01011111 ) #170 0# #175 1# b00000000000000000000000000010001 % +0& +b00001000 ' #180 0# #185 1# b00000000000000000000000000010010 % 1& +1( #190 0# #195 @@ -143,37 +173,46 @@ b00000000000000000000000000010010 % b00000000000000000000000000010011 % 0& b00001001 ' +0( +b00001001 ) #200 0# #205 1# b00000000000000000000000000010100 % 1& -b01011010 ' +1( +b01011010 ) #210 0# #215 1# b00000000000000000000000000010101 % +0& +b00001010 ' #220 0# #225 1# b00000000000000000000000000010110 % -0& -b10100101 ' +1& +0( +b10100101 ) #230 0# #235 1# b00000000000000000000000000010111 % +0& +b00001011 ' #240 0# #245 1# b00000000000000000000000000011000 % 1& -b00001011 ' +1( +b00001011 ) #250 0# #255 @@ -181,12 +220,15 @@ b00001011 ' b00000000000000000000000000011001 % 0& b00001100 ' +0( +b00001100 ) #260 0# #265 1# b00000000000000000000000000011010 % 1& +1( #270 0# #275 @@ -194,12 +236,15 @@ b00000000000000000000000000011010 % b00000000000000000000000000011011 % 0& b00001101 ' +0( +b00001101 ) #280 0# #285 1# b00000000000000000000000000011100 % 1& +1( #290 0# #295 @@ -207,12 +252,15 @@ b00000000000000000000000000011100 % b00000000000000000000000000011101 % 0& b00001110 ' +0( +b00001110 ) #300 0# #305 1# b00000000000000000000000000011110 % 1& +1( #310 0# #315 @@ -220,3 +268,5 @@ b00000000000000000000000000011110 % b00000000000000000000000000011111 % 0& b00001111 ' +0( +b00001111 )