Fix unpacked array concatenation function arguments (#6900)
This commit is contained in:
parent
4563501192
commit
3072907ea4
|
|
@ -32,6 +32,7 @@
|
||||||
#include "V3EmitCBase.h"
|
#include "V3EmitCBase.h"
|
||||||
#include "V3Graph.h"
|
#include "V3Graph.h"
|
||||||
#include "V3Stats.h"
|
#include "V3Stats.h"
|
||||||
|
#include "V3UniqueNames.h"
|
||||||
|
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
|
||||||
|
|
@ -393,6 +394,8 @@ class TaskVisitor final : public VNVisitor {
|
||||||
|
|
||||||
// STATE
|
// STATE
|
||||||
TaskStateVisitor* const m_statep; // Common state between visitors
|
TaskStateVisitor* const m_statep; // Common state between visitors
|
||||||
|
V3UniqueNames m_initArrayTmpNames; // For generating unique temporary variable names for
|
||||||
|
// arguments being AstInitArray
|
||||||
AstNodeModule* m_modp = nullptr; // Current module
|
AstNodeModule* m_modp = nullptr; // Current module
|
||||||
AstTopScope* const m_topScopep = v3Global.rootp()->topScopep(); // The AstTopScope
|
AstTopScope* const m_topScopep = v3Global.rootp()->topScopep(); // The AstTopScope
|
||||||
AstScope* m_scopep = nullptr; // Current scope
|
AstScope* m_scopep = nullptr; // Current scope
|
||||||
|
|
@ -1441,6 +1444,29 @@ class TaskVisitor final : public VNVisitor {
|
||||||
UINFOTREE(9, newp, "", "newfunc");
|
UINFOTREE(9, newp, "", "newfunc");
|
||||||
m_insStmtp->addHereThisAsNext(newp);
|
m_insStmtp->addHereThisAsNext(newp);
|
||||||
}
|
}
|
||||||
|
void processPins(AstNodeFTaskRef* nodep) {
|
||||||
|
// Create a fresh variable for each concat array present in pins list
|
||||||
|
for (AstNode* pinp = nodep->pinsp(); pinp; pinp = pinp->nextp()) {
|
||||||
|
AstArg* const argp = VN_AS(pinp, Arg);
|
||||||
|
AstInitArray* const arrayp = VN_CAST(argp->exprp(), InitArray);
|
||||||
|
if (!arrayp) continue;
|
||||||
|
|
||||||
|
FileLine* const flp = arrayp->fileline();
|
||||||
|
const std::string tempName = m_initArrayTmpNames.get(argp);
|
||||||
|
AstVar* const substp = new AstVar{flp, VVarType::VAR, tempName, arrayp->dtypep()};
|
||||||
|
substp->funcLocal(true);
|
||||||
|
AstVarScope* const substvscp = createVarScope(substp, tempName);
|
||||||
|
|
||||||
|
AstAssign* const assignp
|
||||||
|
= new AstAssign{flp, new AstVarRef{arrayp->fileline(), substvscp, VAccess::WRITE},
|
||||||
|
arrayp->unlinkFrBack()};
|
||||||
|
|
||||||
|
AstExprStmt* const exprstmtp = new AstExprStmt{
|
||||||
|
flp, substp, new AstVarRef{arrayp->fileline(), substvscp, VAccess::READ}};
|
||||||
|
exprstmtp->stmtsp()->addNext(assignp);
|
||||||
|
argp->exprp(exprstmtp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
void visit(AstNodeModule* nodep) override {
|
void visit(AstNodeModule* nodep) override {
|
||||||
|
|
@ -1497,6 +1523,7 @@ class TaskVisitor final : public VNVisitor {
|
||||||
AstNode* beginp;
|
AstNode* beginp;
|
||||||
AstCNew* cnewp = nullptr;
|
AstCNew* cnewp = nullptr;
|
||||||
if (m_statep->ftaskNoInline(nodep->taskp())) {
|
if (m_statep->ftaskNoInline(nodep->taskp())) {
|
||||||
|
processPins(nodep);
|
||||||
// This may share VarScope's with a public task, if any. Yuk.
|
// This may share VarScope's with a public task, if any. Yuk.
|
||||||
beginp = createNonInlinedFTask(nodep, namePrefix, outvscp, cnewp /*ref*/);
|
beginp = createNonInlinedFTask(nodep, namePrefix, outvscp, cnewp /*ref*/);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1672,7 +1699,8 @@ class TaskVisitor final : public VNVisitor {
|
||||||
public:
|
public:
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
TaskVisitor(AstNetlist* nodep, TaskStateVisitor* statep)
|
TaskVisitor(AstNetlist* nodep, TaskStateVisitor* statep)
|
||||||
: m_statep{statep} {
|
: m_statep{statep}
|
||||||
|
, m_initArrayTmpNames{"__VInitArrayTemp"} {
|
||||||
iterate(nodep);
|
iterate(nodep);
|
||||||
}
|
}
|
||||||
~TaskVisitor() {
|
~TaskVisitor() {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# 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
|
||||||
|
|
||||||
|
import vltest_bootstrap
|
||||||
|
|
||||||
|
test.scenarios('simulator')
|
||||||
|
|
||||||
|
test.compile()
|
||||||
|
|
||||||
|
test.execute()
|
||||||
|
|
||||||
|
test.passes()
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// Simple test for unpacked concatenation arrays used as function arguments.
|
||||||
|
//
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
|
// any use, without warranty, 2026 by Antmicro.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
//
|
||||||
|
|
||||||
|
class A;
|
||||||
|
int r1[2];
|
||||||
|
int r2;
|
||||||
|
endclass
|
||||||
|
|
||||||
|
class B;
|
||||||
|
virtual function int B_virt_func(int r[3], p[4]);
|
||||||
|
return r[0] + r[1] + r[2] + p[0] + p[1] + p[2] + p[3];
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
|
|
||||||
|
function int func_1_concat(int r[4]);
|
||||||
|
// verilator no_inline_task
|
||||||
|
return r[0] + r[1] + r[2] + r[3];
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function int func_2_concat(int r[3], int p[4]);
|
||||||
|
// verilator no_inline_task
|
||||||
|
return r[0] + r[1] + r[2] + p[0] + p[1] + p[2] + p[3];
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
module t;
|
||||||
|
int s;
|
||||||
|
A a = new;
|
||||||
|
B b = new;
|
||||||
|
initial begin
|
||||||
|
a.r1 = {1,2};
|
||||||
|
a.r2 = 5;
|
||||||
|
s = func_1_concat({a.r1, a.r1});
|
||||||
|
if (s != 6) $stop;
|
||||||
|
|
||||||
|
s = func_2_concat({a.r1, a.r2}, {a.r1, a.r1});
|
||||||
|
if (s != 14) $stop;
|
||||||
|
|
||||||
|
s = b.B_virt_func({a.r1, a.r2}, {a.r1, a.r1});
|
||||||
|
if (s != 14) $stop;
|
||||||
|
|
||||||
|
$write("*-* All finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
Loading…
Reference in New Issue