From 0fbd4313b22ab0c40efa3f434efb68b1f16ac292 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sun, 3 Mar 2024 11:10:46 -0500 Subject: [PATCH] Fix __Vlip undefined error in --freloop (#4824). --- Changes | 1 + src/V3Reloop.cpp | 24 ++++----- test_regress/t/t_reloop_local.pl | 22 ++++++++ test_regress/t/t_reloop_local.v | 88 ++++++++++++++++++++++++++++++++ 4 files changed, 120 insertions(+), 15 deletions(-) create mode 100755 test_regress/t/t_reloop_local.pl create mode 100644 test_regress/t/t_reloop_local.v diff --git a/Changes b/Changes index 98082a712..c1e4beccc 100644 --- a/Changes +++ b/Changes @@ -20,6 +20,7 @@ Verilator 5.023 devel **Minor:** * Fix invalid cast on string structure creation (#4921). [esynr3z] +* Fix __Vlip undefined error in --freloop (#4824). [Justin Yao Du] Verilator 5.022 2024-02-24 diff --git a/src/V3Reloop.cpp b/src/V3Reloop.cpp index c7329c8ad..15c4afbc7 100644 --- a/src/V3Reloop.cpp +++ b/src/V3Reloop.cpp @@ -41,7 +41,7 @@ VL_DEFINE_DEBUG_FUNCTIONS; class ReloopVisitor final : public VNVisitor { // NODE STATE - // AstCFunc::user1p -> Var* for temp var, 0=not set yet + // AstCFunc::user1p -> Var number temp var, 0=not set yet const VNUser1InUse m_inuser1; // STATE @@ -63,18 +63,11 @@ class ReloopVisitor final : public VNVisitor { // METHODS - static AstVar* findCreateVarTemp(FileLine* fl, AstCFunc* cfuncp) { - AstVar* varp = VN_AS(cfuncp->user1p(), Var); - if (!varp) { - const string newvarname{"__Vilp"}; - varp = new AstVar{fl, VVarType::STMTTEMP, newvarname, VFlagLogicPacked{}, 32}; - UASSERT_OBJ(cfuncp, fl, "Assignment not under a function"); - if (cfuncp->initsp()) - cfuncp->initsp()->addNextHere(varp); - else - cfuncp->addInitsp(varp); - cfuncp->user1p(varp); - } + static AstVar* createVarTemp(FileLine* fl, AstCFunc* cfuncp) { + UASSERT_OBJ(cfuncp, fl, "Assignment not under a function"); + const string newvarname{"__Vilp" + std::to_string(cfuncp->user1Inc() + 1)}; + AstVar* const varp + = new AstVar{fl, VVarType::STMTTEMP, newvarname, VFlagLogicPacked{}, 32}; return varp; } void mergeEnd() { @@ -93,7 +86,7 @@ class ReloopVisitor final : public VNVisitor { AstNodeAssign* const bodyp = m_mgAssignps.front(); UASSERT_OBJ(bodyp->lhsp() == m_mgSelLp, bodyp, "Corrupt queue/state"); FileLine* const fl = bodyp->fileline(); - AstVar* const itp = findCreateVarTemp(fl, m_mgCfuncp); + AstVar* const itp = createVarTemp(fl, m_mgCfuncp); if (m_mgOffset > 0) { UASSERT_OBJ(m_mgIndexLo >= m_mgOffset, bodyp, @@ -111,7 +104,8 @@ class ReloopVisitor final : public VNVisitor { new AstAdd{fl, new AstConst{fl, 1}, new AstVarRef{fl, itp, VAccess::READ}}}; AstWhile* const whilep = new AstWhile{fl, condp, nullptr, incp}; initp->addNext(whilep); - bodyp->replaceWith(initp); + itp->AstNode::addNext(initp); + bodyp->replaceWith(itp); whilep->addStmtsp(bodyp); // Replace constant index with new loop index diff --git a/test_regress/t/t_reloop_local.pl b/test_regress/t/t_reloop_local.pl new file mode 100755 index 000000000..8f8f11798 --- /dev/null +++ b/test_regress/t/t_reloop_local.pl @@ -0,0 +1,22 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(simulator => 1); + +compile( + verilator_flags2 => ['--assert'], + ); + +execute( + check_finished => 1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_reloop_local.v b/test_regress/t/t_reloop_local.v new file mode 100644 index 000000000..e66690090 --- /dev/null +++ b/test_regress/t/t_reloop_local.v @@ -0,0 +1,88 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2024 by Justin Yao Du. +// SPDX-License-Identifier: CC0-1.0 + +typedef logic [7:0] Word; +typedef logic [255:0] BigItem; + +module shuffler + ( + input logic clk, + input logic reset_l, + output logic odd, + output logic [255:0][7:0] shuffle + ); + + Word ctr; + assign odd = ctr[0]; + + always_ff @(posedge clk) begin + if (!reset_l) begin + ctr <= 0; + end + else begin + ctr <= ctr + 1; + end + end + + for (genvar i = 0; i < 256; i++) always_comb begin + shuffle[i] = Word'(i) - ctr; + end + + for (genvar i = 0; i < 256; i++) begin + assert property (@(posedge clk) shuffle[ctr + Word'(i)] == i); + end +endmodule + +interface big_port(); + BigItem big; + + function automatic BigItem get_big(); + return big; + endfunction + + modport reader(import get_big); +endinterface + +module foo ( + input clk, + input reset_l, + big_port.reader big); + + logic odd; + Word[255 : 0] shuffle; + shuffler fifo ( + .clk, + .reset_l, + .odd, + .shuffle + ); + + BigItem bigs[256]; + for (genvar i = 0; i < 256; i++) always_comb begin + bigs[i] = odd ? big.get_big() : 0; + end +endmodule + +module t (/*AUTOARG*/ + // Inputs + clk, reset_l + ); + + input clk; + input reset_l; + + big_port big(); + + foo foo ( + .clk, + .reset_l, + .big); + + initial begin + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule