Fix unpacked array concatenation function arguments (#6900)
This commit is contained in:
parent
4563501192
commit
3072907ea4
|
|
@ -32,6 +32,7 @@
|
|||
#include "V3EmitCBase.h"
|
||||
#include "V3Graph.h"
|
||||
#include "V3Stats.h"
|
||||
#include "V3UniqueNames.h"
|
||||
|
||||
#include <tuple>
|
||||
|
||||
|
|
@ -393,6 +394,8 @@ class TaskVisitor final : public VNVisitor {
|
|||
|
||||
// STATE
|
||||
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
|
||||
AstTopScope* const m_topScopep = v3Global.rootp()->topScopep(); // The AstTopScope
|
||||
AstScope* m_scopep = nullptr; // Current scope
|
||||
|
|
@ -1441,6 +1444,29 @@ class TaskVisitor final : public VNVisitor {
|
|||
UINFOTREE(9, newp, "", "newfunc");
|
||||
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
|
||||
void visit(AstNodeModule* nodep) override {
|
||||
|
|
@ -1497,6 +1523,7 @@ class TaskVisitor final : public VNVisitor {
|
|||
AstNode* beginp;
|
||||
AstCNew* cnewp = nullptr;
|
||||
if (m_statep->ftaskNoInline(nodep->taskp())) {
|
||||
processPins(nodep);
|
||||
// This may share VarScope's with a public task, if any. Yuk.
|
||||
beginp = createNonInlinedFTask(nodep, namePrefix, outvscp, cnewp /*ref*/);
|
||||
} else {
|
||||
|
|
@ -1672,7 +1699,8 @@ class TaskVisitor final : public VNVisitor {
|
|||
public:
|
||||
// CONSTRUCTORS
|
||||
TaskVisitor(AstNetlist* nodep, TaskStateVisitor* statep)
|
||||
: m_statep{statep} {
|
||||
: m_statep{statep}
|
||||
, m_initArrayTmpNames{"__VInitArrayTemp"} {
|
||||
iterate(nodep);
|
||||
}
|
||||
~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