2012-04-13 03:08:20 +02:00
|
|
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
2006-12-21 15:35:19 +01:00
|
|
|
//*************************************************************************
|
|
|
|
|
// DESCRIPTION: Verilator: LValue module/signal name references
|
|
|
|
|
//
|
2019-11-08 04:33:59 +01:00
|
|
|
// Code available from: https://verilator.org
|
2006-12-21 15:35:19 +01:00
|
|
|
//
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
//
|
2024-01-01 09:19:59 +01:00
|
|
|
// Copyright 2003-2024 by Wilson Snyder. This program is free software; you
|
2020-03-21 16:24:24 +01:00
|
|
|
// can redistribute it and/or modify it under the terms of either the GNU
|
2009-05-04 23:07:57 +02:00
|
|
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
|
|
|
|
// Version 2.0.
|
2020-03-21 16:24:24 +01:00
|
|
|
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
2006-12-21 15:35:19 +01:00
|
|
|
//
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
// LinkLValue TRANSFORMATIONS:
|
2019-05-19 22:13:13 +02:00
|
|
|
// Top-down traversal
|
|
|
|
|
// Set lvalue() attributes on appropriate VARREFs.
|
2006-12-21 15:35:19 +01:00
|
|
|
//*************************************************************************
|
2019-10-05 02:17:11 +02:00
|
|
|
|
2023-10-18 04:50:27 +02:00
|
|
|
#include "V3PchAstNoMT.h" // VL_MT_DISABLED_CODE_UNIT
|
|
|
|
|
|
2023-10-18 12:37:46 +02:00
|
|
|
#include "V3LinkLValue.h"
|
|
|
|
|
|
2024-04-27 01:26:21 +02:00
|
|
|
#include "V3Task.h"
|
|
|
|
|
|
2022-09-18 21:53:42 +02:00
|
|
|
VL_DEFINE_DEBUG_FUNCTIONS;
|
|
|
|
|
|
2006-12-21 15:35:19 +01:00
|
|
|
//######################################################################
|
|
|
|
|
// Link state, as a visitor of each AstNode
|
|
|
|
|
|
2022-01-02 19:56:40 +01:00
|
|
|
class LinkLValueVisitor final : public VNVisitor {
|
2006-12-21 15:35:19 +01:00
|
|
|
// NODE STATE
|
|
|
|
|
|
2024-11-05 05:55:39 +01:00
|
|
|
// STATE - for current visit position (use VL_RESTORER)
|
2022-01-01 18:24:19 +01:00
|
|
|
bool m_setContinuously = false; // Set that var has some continuous assignment
|
2024-05-10 19:19:51 +02:00
|
|
|
bool m_setForcedByCode = false; // Set that var is the target of an AstAssignForce/AstRelease
|
2024-08-02 17:45:17 +02:00
|
|
|
bool m_setIfRand = false; // Update VarRefs if var declared as rand
|
2024-08-05 09:39:43 +02:00
|
|
|
bool m_inInitialStatic = false; // Set if inside AstInitialStatic
|
|
|
|
|
bool m_inFunc = false; // Set if inside AstNodeFTask
|
2024-11-05 05:55:39 +01:00
|
|
|
|
|
|
|
|
// STATE - TODO
|
|
|
|
|
bool m_setStrengthSpecified = false; // Set that var has assignment with strength specified.
|
2020-11-07 16:37:55 +01:00
|
|
|
VAccess m_setRefLvalue; // Set VarRefs to lvalues for pin assignments
|
2006-12-21 15:35:19 +01:00
|
|
|
|
|
|
|
|
// VISITs
|
|
|
|
|
// Result handing
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstNodeVarRef* nodep) override {
|
2019-05-19 22:13:13 +02:00
|
|
|
// VarRef: LValue its reference
|
2024-08-02 17:45:17 +02:00
|
|
|
if (m_setIfRand && !(nodep->varp() && nodep->varp()->isRand())) return;
|
2020-11-07 16:37:55 +01:00
|
|
|
if (m_setRefLvalue != VAccess::NOCHANGE) nodep->access(m_setRefLvalue);
|
2024-05-10 19:19:51 +02:00
|
|
|
if (nodep->varp() && nodep->access().isWriteOrRW()) {
|
|
|
|
|
if (m_setContinuously) {
|
2022-01-01 18:24:19 +01:00
|
|
|
nodep->varp()->isContinuously(true);
|
2022-09-14 13:39:27 +02:00
|
|
|
// Strength may only be specified in continuous assignment,
|
|
|
|
|
// so it is needed to check only if m_setContinuously is true
|
|
|
|
|
if (m_setStrengthSpecified) nodep->varp()->hasStrengthAssignment(true);
|
2022-01-01 18:24:19 +01:00
|
|
|
}
|
2024-07-10 00:31:58 +02:00
|
|
|
if (const AstClockingItem* const itemp
|
|
|
|
|
= VN_CAST(nodep->varp()->backp(), ClockingItem)) {
|
2024-06-07 14:30:58 +02:00
|
|
|
UINFO(5, "ClkOut " << nodep << endl);
|
|
|
|
|
if (itemp->outputp()) nodep->varp(itemp->outputp()->varp());
|
|
|
|
|
}
|
2024-05-10 19:19:51 +02:00
|
|
|
if (m_setForcedByCode) {
|
|
|
|
|
nodep->varp()->setForcedByCode();
|
|
|
|
|
} else if (!nodep->varp()->isFuncLocal() && nodep->varp()->isReadOnly()) {
|
2024-08-15 16:04:07 +02:00
|
|
|
// This is allowed with IEEE 1800-2009 module input with default value.
|
|
|
|
|
// the checking now happens in V3Width::visit(AstNodeVarRef*)
|
|
|
|
|
// If you were to check here, it would fail on module inputs with default value,
|
|
|
|
|
// because Inputs are isReadOnly()=true, and we don't yet have visibility into
|
|
|
|
|
// it being an Initial style procedure.
|
2018-10-27 23:29:00 +02:00
|
|
|
}
|
|
|
|
|
}
|
2018-05-11 02:55:37 +02:00
|
|
|
iterateChildren(nodep);
|
2006-12-21 15:35:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Nodes that start propagating down lvalues
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstPin* nodep) override {
|
2018-10-27 23:29:00 +02:00
|
|
|
if (nodep->modVarp() && nodep->modVarp()->isWritable()) {
|
|
|
|
|
// When the varref's were created, we didn't know the I/O state
|
|
|
|
|
// Now that we do, and it's from a output, we know it's a lvalue
|
2020-09-07 23:09:25 +02:00
|
|
|
m_setRefLvalue = VAccess::WRITE;
|
2018-05-11 02:55:37 +02:00
|
|
|
iterateChildren(nodep);
|
2020-11-07 16:37:55 +01:00
|
|
|
m_setRefLvalue = VAccess::NOCHANGE;
|
2019-05-19 22:13:13 +02:00
|
|
|
} else {
|
2018-05-11 02:55:37 +02:00
|
|
|
iterateChildren(nodep);
|
2019-05-19 22:13:13 +02:00
|
|
|
}
|
2006-12-21 15:35:19 +01:00
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstNodeAssign* nodep) override {
|
2020-08-25 03:10:43 +02:00
|
|
|
VL_RESTORER(m_setRefLvalue);
|
2022-01-01 18:24:19 +01:00
|
|
|
VL_RESTORER(m_setContinuously);
|
2019-05-19 22:13:13 +02:00
|
|
|
{
|
2020-09-07 23:09:25 +02:00
|
|
|
m_setRefLvalue = VAccess::WRITE;
|
2022-01-01 18:24:19 +01:00
|
|
|
m_setContinuously = VN_IS(nodep, AssignW) || VN_IS(nodep, AssignAlias);
|
2022-09-14 13:39:27 +02:00
|
|
|
if (AstAssignW* assignwp = VN_CAST(nodep, AssignW)) {
|
|
|
|
|
if (assignwp->strengthSpecp()) m_setStrengthSpecified = true;
|
|
|
|
|
}
|
2024-05-10 19:19:51 +02:00
|
|
|
{
|
|
|
|
|
VL_RESTORER(m_setForcedByCode);
|
|
|
|
|
m_setForcedByCode = VN_IS(nodep, AssignForce);
|
|
|
|
|
iterateAndNextNull(nodep->lhsp());
|
|
|
|
|
}
|
2020-11-07 16:37:55 +01:00
|
|
|
m_setRefLvalue = VAccess::NOCHANGE;
|
2022-01-01 18:24:19 +01:00
|
|
|
m_setContinuously = false;
|
2022-09-14 13:39:27 +02:00
|
|
|
m_setStrengthSpecified = false;
|
2018-05-11 02:55:37 +02:00
|
|
|
iterateAndNextNull(nodep->rhsp());
|
2019-05-19 22:13:13 +02:00
|
|
|
}
|
2024-08-05 09:39:43 +02:00
|
|
|
|
|
|
|
|
if (m_inInitialStatic && m_inFunc) {
|
|
|
|
|
const bool rhsHasIO = nodep->rhsp()->exists([](const AstNodeVarRef* const refp) {
|
|
|
|
|
// Exclude module I/O referenced from a function/task.
|
|
|
|
|
return refp->varp() && refp->varp()->isIO()
|
|
|
|
|
&& refp->varp()->lifetime() != VLifetime::NONE;
|
|
|
|
|
});
|
|
|
|
|
if (rhsHasIO) {
|
|
|
|
|
nodep->rhsp()->v3warn(E_UNSUPPORTED,
|
|
|
|
|
"Static variable initializer\n"
|
|
|
|
|
<< nodep->rhsp()->warnMore()
|
|
|
|
|
<< "is dependent on function/task I/O variable");
|
|
|
|
|
} else {
|
|
|
|
|
const bool rhsHasAutomatic
|
|
|
|
|
= nodep->rhsp()->exists([](const AstNodeVarRef* const refp) {
|
|
|
|
|
return refp->varp() && refp->varp()->lifetime() == VLifetime::AUTOMATIC;
|
|
|
|
|
});
|
|
|
|
|
if (rhsHasAutomatic) {
|
|
|
|
|
nodep->rhsp()->v3error("Static variable initializer\n"
|
|
|
|
|
<< nodep->rhsp()->warnMore()
|
|
|
|
|
<< "is dependent on automatic variable");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
void visit(AstInitialStatic* nodep) override {
|
|
|
|
|
VL_RESTORER(m_inInitialStatic);
|
|
|
|
|
m_inInitialStatic = true;
|
|
|
|
|
iterateChildren(nodep);
|
2006-12-21 15:35:19 +01:00
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstRelease* nodep) override {
|
2021-12-17 18:56:33 +01:00
|
|
|
VL_RESTORER(m_setRefLvalue);
|
|
|
|
|
VL_RESTORER(m_setContinuously);
|
2024-05-10 19:19:51 +02:00
|
|
|
VL_RESTORER(m_setForcedByCode);
|
2024-11-05 05:55:39 +01:00
|
|
|
m_setRefLvalue = VAccess::WRITE;
|
|
|
|
|
m_setContinuously = false;
|
|
|
|
|
m_setForcedByCode = true;
|
|
|
|
|
iterateAndNextNull(nodep->lhsp());
|
2021-12-17 18:56:33 +01:00
|
|
|
}
|
2022-09-16 17:15:10 +02:00
|
|
|
void visit(AstFireEvent* nodep) override {
|
2022-05-15 17:03:32 +02:00
|
|
|
VL_RESTORER(m_setRefLvalue);
|
2024-11-05 05:55:39 +01:00
|
|
|
m_setRefLvalue = VAccess::WRITE;
|
|
|
|
|
iterateAndNextNull(nodep->operandp());
|
2022-05-15 17:03:32 +02:00
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstCastDynamic* nodep) override {
|
2020-10-25 02:30:52 +02:00
|
|
|
VL_RESTORER(m_setRefLvalue);
|
2024-11-05 05:55:39 +01:00
|
|
|
m_setRefLvalue = VAccess::NOCHANGE;
|
|
|
|
|
iterateAndNextNull(nodep->fromp());
|
|
|
|
|
m_setRefLvalue = VAccess::WRITE;
|
|
|
|
|
iterateAndNextNull(nodep->top());
|
2020-10-25 02:30:52 +02:00
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstFError* nodep) override {
|
2020-08-25 03:10:43 +02:00
|
|
|
VL_RESTORER(m_setRefLvalue);
|
2024-11-05 05:55:39 +01:00
|
|
|
iterateAndNextNull(nodep->filep());
|
|
|
|
|
m_setRefLvalue = VAccess::WRITE;
|
|
|
|
|
iterateAndNextNull(nodep->strp());
|
2008-06-28 02:04:20 +02:00
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstFGetS* nodep) override {
|
2020-08-25 03:10:43 +02:00
|
|
|
VL_RESTORER(m_setRefLvalue);
|
2024-11-05 05:55:39 +01:00
|
|
|
iterateAndNextNull(nodep->filep());
|
|
|
|
|
m_setRefLvalue = VAccess::WRITE;
|
|
|
|
|
iterateAndNextNull(nodep->strgp());
|
2008-06-28 02:04:20 +02:00
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstFRead* nodep) override {
|
2020-08-25 03:10:43 +02:00
|
|
|
VL_RESTORER(m_setRefLvalue);
|
2024-11-05 05:55:39 +01:00
|
|
|
iterateAndNextNull(nodep->filep());
|
|
|
|
|
m_setRefLvalue = VAccess::WRITE;
|
|
|
|
|
iterateAndNextNull(nodep->memp());
|
2019-03-08 02:56:53 +01:00
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstFScanF* nodep) override {
|
2020-08-25 03:10:43 +02:00
|
|
|
VL_RESTORER(m_setRefLvalue);
|
2024-11-05 05:55:39 +01:00
|
|
|
iterateAndNextNull(nodep->filep());
|
|
|
|
|
m_setRefLvalue = VAccess::WRITE;
|
|
|
|
|
iterateAndNextNull(nodep->exprsp());
|
2008-07-01 20:15:10 +02:00
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstFUngetC* nodep) override {
|
2020-08-25 03:10:43 +02:00
|
|
|
VL_RESTORER(m_setRefLvalue);
|
2024-11-05 05:55:39 +01:00
|
|
|
iterateAndNextNull(nodep->filep());
|
|
|
|
|
m_setRefLvalue = VAccess::WRITE;
|
|
|
|
|
iterateAndNextNull(nodep->rhsp());
|
2019-11-16 18:55:10 +01:00
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstSScanF* nodep) override {
|
2020-08-25 03:10:43 +02:00
|
|
|
VL_RESTORER(m_setRefLvalue);
|
2024-11-05 05:55:39 +01:00
|
|
|
m_setRefLvalue = VAccess::WRITE;
|
|
|
|
|
iterateAndNextNull(nodep->exprsp());
|
2008-07-01 20:15:10 +02:00
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstSysIgnore* nodep) override {
|
2022-12-23 19:00:34 +01:00
|
|
|
// Can't know if lvalue or not; presume not
|
2018-05-11 02:55:37 +02:00
|
|
|
iterateChildren(nodep);
|
2010-12-30 13:55:31 +01:00
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstRand* nodep) override {
|
2022-01-01 22:43:06 +01:00
|
|
|
VL_RESTORER(m_setRefLvalue);
|
2024-11-05 05:55:39 +01:00
|
|
|
if (!nodep->urandom()) m_setRefLvalue = VAccess::WRITE;
|
|
|
|
|
iterateAndNextNull(nodep->seedp());
|
2022-01-01 22:43:06 +01:00
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstReadMem* nodep) override {
|
2020-08-25 03:10:43 +02:00
|
|
|
VL_RESTORER(m_setRefLvalue);
|
2024-11-05 05:55:39 +01:00
|
|
|
m_setRefLvalue = VAccess::WRITE;
|
|
|
|
|
iterateAndNextNull(nodep->memp());
|
|
|
|
|
m_setRefLvalue = VAccess::NOCHANGE;
|
|
|
|
|
iterateAndNextNull(nodep->filenamep());
|
|
|
|
|
iterateAndNextNull(nodep->lsbp());
|
|
|
|
|
iterateAndNextNull(nodep->msbp());
|
2006-12-21 15:35:19 +01:00
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstTestPlusArgs* nodep) override {
|
2022-07-11 12:21:35 +02:00
|
|
|
VL_RESTORER(m_setRefLvalue);
|
2024-11-05 05:55:39 +01:00
|
|
|
m_setRefLvalue = VAccess::NOCHANGE;
|
|
|
|
|
iterateAndNextNull(nodep->searchp());
|
2022-07-11 12:21:35 +02:00
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstValuePlusArgs* nodep) override {
|
2020-08-25 03:10:43 +02:00
|
|
|
VL_RESTORER(m_setRefLvalue);
|
2024-11-05 05:55:39 +01:00
|
|
|
m_setRefLvalue = VAccess::NOCHANGE;
|
|
|
|
|
iterateAndNextNull(nodep->searchp());
|
|
|
|
|
m_setRefLvalue = VAccess::WRITE;
|
|
|
|
|
iterateAndNextNull(nodep->outp());
|
2009-11-19 23:04:21 +01:00
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstSFormat* nodep) override {
|
2020-08-25 03:10:43 +02:00
|
|
|
VL_RESTORER(m_setRefLvalue);
|
2024-11-05 05:55:39 +01:00
|
|
|
m_setRefLvalue = VAccess::WRITE;
|
|
|
|
|
iterateAndNextNull(nodep->lhsp());
|
|
|
|
|
m_setRefLvalue = VAccess::NOCHANGE;
|
|
|
|
|
iterateAndNextNull(nodep->fmtp());
|
2009-11-24 03:24:55 +01:00
|
|
|
}
|
2022-12-04 23:30:51 +01:00
|
|
|
void visit(AstNodeDistBiop* nodep) override {
|
|
|
|
|
VL_RESTORER(m_setRefLvalue);
|
|
|
|
|
m_setRefLvalue = VAccess::WRITE;
|
|
|
|
|
iterateAndNextNull(nodep->lhsp());
|
|
|
|
|
m_setRefLvalue = VAccess::NOCHANGE;
|
|
|
|
|
iterateAndNextNull(nodep->rhsp());
|
|
|
|
|
}
|
|
|
|
|
void visit(AstNodeDistTriop* nodep) override {
|
|
|
|
|
VL_RESTORER(m_setRefLvalue);
|
|
|
|
|
m_setRefLvalue = VAccess::WRITE;
|
|
|
|
|
iterateAndNextNull(nodep->lhsp());
|
|
|
|
|
m_setRefLvalue = VAccess::NOCHANGE;
|
|
|
|
|
iterateAndNextNull(nodep->rhsp());
|
|
|
|
|
iterateAndNextNull(nodep->thsp());
|
|
|
|
|
}
|
2020-05-29 00:08:15 +02:00
|
|
|
void prepost_visit(AstNodeTriop* nodep) {
|
2020-08-25 03:10:43 +02:00
|
|
|
VL_RESTORER(m_setRefLvalue);
|
2024-11-05 05:55:39 +01:00
|
|
|
m_setRefLvalue = VAccess::NOCHANGE;
|
|
|
|
|
iterateAndNextNull(nodep->lhsp());
|
|
|
|
|
iterateAndNextNull(nodep->rhsp());
|
|
|
|
|
m_setRefLvalue = VAccess::WRITE;
|
|
|
|
|
iterateAndNextNull(nodep->thsp());
|
2020-05-29 00:08:15 +02:00
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstPreAdd* nodep) override { prepost_visit(nodep); }
|
|
|
|
|
void visit(AstPostAdd* nodep) override { prepost_visit(nodep); }
|
|
|
|
|
void visit(AstPreSub* nodep) override { prepost_visit(nodep); }
|
|
|
|
|
void visit(AstPostSub* nodep) override { prepost_visit(nodep); }
|
2006-12-21 15:35:19 +01:00
|
|
|
|
|
|
|
|
// Nodes that change LValue state
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstSel* nodep) override {
|
2020-08-25 03:10:43 +02:00
|
|
|
VL_RESTORER(m_setRefLvalue);
|
2024-11-05 05:55:39 +01:00
|
|
|
iterateAndNextNull(nodep->fromp());
|
|
|
|
|
// Only set lvalues on the from
|
|
|
|
|
m_setRefLvalue = VAccess::NOCHANGE;
|
|
|
|
|
iterateAndNextNull(nodep->lsbp());
|
|
|
|
|
iterateAndNextNull(nodep->widthp());
|
2006-12-21 15:35:19 +01:00
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstNodeSel* nodep) override {
|
2020-08-25 03:10:43 +02:00
|
|
|
VL_RESTORER(m_setRefLvalue);
|
2024-11-05 05:55:39 +01:00
|
|
|
// Only set lvalues on the from
|
|
|
|
|
iterateAndNextNull(nodep->fromp());
|
|
|
|
|
m_setRefLvalue = VAccess::NOCHANGE;
|
|
|
|
|
iterateAndNextNull(nodep->bitp());
|
2006-12-21 15:35:19 +01:00
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstCellArrayRef* nodep) override {
|
2020-08-25 03:10:43 +02:00
|
|
|
VL_RESTORER(m_setRefLvalue);
|
2024-11-05 05:55:39 +01:00
|
|
|
// selp is not an lvalue
|
|
|
|
|
m_setRefLvalue = VAccess::NOCHANGE;
|
|
|
|
|
iterateAndNextNull(nodep->selp());
|
2015-10-23 02:13:49 +02:00
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstNodePreSel* nodep) override {
|
2024-10-24 15:40:54 +02:00
|
|
|
if (AstSelBit* const selbitp = VN_CAST(nodep, SelBit)) selbitp->access(m_setRefLvalue);
|
2020-08-25 03:10:43 +02:00
|
|
|
VL_RESTORER(m_setRefLvalue);
|
2024-11-05 05:55:39 +01:00
|
|
|
// Only set lvalues on the from
|
|
|
|
|
iterateAndNextNull(nodep->fromp());
|
|
|
|
|
m_setRefLvalue = VAccess::NOCHANGE;
|
|
|
|
|
iterateAndNextNull(nodep->rhsp());
|
|
|
|
|
iterateAndNextNull(nodep->thsp());
|
2006-12-21 15:35:19 +01:00
|
|
|
}
|
2023-06-30 09:12:22 +02:00
|
|
|
void visit(AstMemberSel* nodep) override {
|
|
|
|
|
if (m_setRefLvalue != VAccess::NOCHANGE) {
|
|
|
|
|
nodep->access(m_setRefLvalue);
|
2024-07-10 00:31:58 +02:00
|
|
|
if (nodep->varp() && nodep->access().isWriteOrRW()) {
|
|
|
|
|
if (const AstClockingItem* const itemp
|
|
|
|
|
= VN_CAST(nodep->varp()->backp(), ClockingItem)) {
|
|
|
|
|
UINFO(5, "ClkOut " << nodep << endl);
|
|
|
|
|
if (itemp->outputp()) nodep->varp(itemp->outputp()->varp());
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-06-30 09:12:22 +02:00
|
|
|
} else {
|
|
|
|
|
// It is the only place where the access is set to member select nodes.
|
|
|
|
|
// If it doesn't have to be set to WRITE, it means that it is READ.
|
|
|
|
|
nodep->access(VAccess::READ);
|
|
|
|
|
}
|
|
|
|
|
iterateChildren(nodep);
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstNodeFTaskRef* nodep) override {
|
2021-11-13 19:50:44 +01:00
|
|
|
const AstNodeFTask* const taskp = nodep->taskp();
|
2019-05-19 22:13:13 +02:00
|
|
|
// We'll deal with mismatching pins later
|
|
|
|
|
if (!taskp) return;
|
2024-04-27 01:26:21 +02:00
|
|
|
const V3TaskConnects tconnects
|
|
|
|
|
= V3Task::taskConnects(nodep, taskp->stmtsp(), nullptr, false);
|
|
|
|
|
for (const auto& tconnect : tconnects) {
|
|
|
|
|
const AstVar* const portp = tconnect.first;
|
|
|
|
|
const AstArg* const argp = tconnect.second;
|
|
|
|
|
if (!argp) continue;
|
|
|
|
|
AstNodeExpr* const pinp = argp->exprp();
|
|
|
|
|
if (!pinp) continue;
|
|
|
|
|
if (portp->isWritable()) {
|
|
|
|
|
m_setRefLvalue = VAccess::WRITE;
|
|
|
|
|
iterate(pinp);
|
|
|
|
|
m_setRefLvalue = VAccess::NOCHANGE;
|
|
|
|
|
} else {
|
|
|
|
|
iterate(pinp);
|
2019-05-19 22:13:13 +02:00
|
|
|
}
|
|
|
|
|
}
|
2008-07-22 17:15:28 +02:00
|
|
|
}
|
2024-08-02 17:45:17 +02:00
|
|
|
void visit(AstConstraint* nodep) override {
|
|
|
|
|
VL_RESTORER(m_setIfRand);
|
|
|
|
|
m_setIfRand = true;
|
|
|
|
|
iterateChildren(nodep);
|
|
|
|
|
}
|
2024-08-05 09:39:43 +02:00
|
|
|
void visit(AstNodeFTask* nodep) override {
|
|
|
|
|
VL_RESTORER(m_inFunc);
|
|
|
|
|
m_inFunc = true;
|
|
|
|
|
iterateChildren(nodep);
|
|
|
|
|
}
|
2006-12-21 15:35:19 +01:00
|
|
|
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
2006-12-21 15:35:19 +01:00
|
|
|
|
|
|
|
|
public:
|
2019-09-12 13:22:22 +02:00
|
|
|
// CONSTRUCTORS
|
2020-11-07 16:37:55 +01:00
|
|
|
LinkLValueVisitor(AstNode* nodep, VAccess start)
|
2020-08-16 15:55:36 +02:00
|
|
|
: m_setRefLvalue{start} {
|
2018-05-11 02:55:37 +02:00
|
|
|
iterate(nodep);
|
2006-12-21 15:35:19 +01:00
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
~LinkLValueVisitor() override = default;
|
2006-12-21 15:35:19 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
// Link class functions
|
|
|
|
|
|
2018-10-15 00:39:33 +02:00
|
|
|
void V3LinkLValue::linkLValue(AstNetlist* nodep) {
|
2020-04-14 04:51:35 +02:00
|
|
|
UINFO(4, __FUNCTION__ << ": " << endl);
|
2021-11-26 16:52:36 +01:00
|
|
|
{ LinkLValueVisitor{nodep, VAccess::NOCHANGE}; } // Destruct before checking
|
2024-01-09 16:35:13 +01:00
|
|
|
V3Global::dumpCheckGlobalTree("linklvalue", 0, dumpTreeEitherLevel() >= 6);
|
2008-03-28 22:55:23 +01:00
|
|
|
}
|
|
|
|
|
void V3LinkLValue::linkLValueSet(AstNode* nodep) {
|
|
|
|
|
// Called by later link functions when it is known a node needs
|
|
|
|
|
// to be converted to a lvalue.
|
2020-04-14 04:51:35 +02:00
|
|
|
UINFO(9, __FUNCTION__ << ": " << endl);
|
2021-11-26 16:52:36 +01:00
|
|
|
{ LinkLValueVisitor{nodep, VAccess::WRITE}; }
|
2006-12-21 15:35:19 +01:00
|
|
|
}
|