mirror of
https://github.com/verilator/verilator.git
synced 2026-10-06 10:03:44 +02:00
Rename AstAssignAlias to AstAlias and make it derive from AstNode instead of AstNodeStmt. Replace AstAlias with AstAssignW in V3LinkDot::linkDotScope, which is the last place we need to be aware of the alias construct. Using AstAssignW dowstream enables further optimization while preserving the same functionality.
This commit is contained in:
@@ -505,7 +505,6 @@ class ActiveVisitor final : public VNVisitor {
|
||||
const ActiveDlyVisitor dlyvisitor{nodep, ActiveDlyVisitor::CT_INITIAL};
|
||||
moveUnderSpecial<AstSenItem::Final>(nodep);
|
||||
}
|
||||
void visit(AstAssignAlias* nodep) override { moveUnderSpecial<AstSenItem::Combo>(nodep); }
|
||||
void visit(AstCoverToggle* nodep) override { moveUnderSpecial<AstSenItem::Combo>(nodep); }
|
||||
void visit(AstAssignW* nodep) override { moveUnderSpecial<AstSenItem::Combo>(nodep); }
|
||||
void visit(AstAlways* nodep) override {
|
||||
|
||||
@@ -131,9 +131,6 @@ class ActiveTopVisitor final : public VNVisitor {
|
||||
void visit(AstNodeProcedure* nodep) override { // LCOV_EXCL_LINE
|
||||
nodep->v3fatalSrc("Node should have been under ACTIVE");
|
||||
}
|
||||
void visit(AstAssignAlias* nodep) override { // LCOV_EXCL_LINE
|
||||
nodep->v3fatalSrc("Node should have been under ACTIVE");
|
||||
}
|
||||
void visit(AstAssignW* nodep) override { // LCOV_EXCL_LINE
|
||||
nodep->v3fatalSrc("Node should have been under ACTIVE");
|
||||
}
|
||||
|
||||
@@ -456,6 +456,21 @@ public:
|
||||
inline bool hasClocked() const;
|
||||
inline bool hasCombo() const;
|
||||
};
|
||||
class AstAlias final : public AstNode {
|
||||
// Alias (currently only used internally, not as the SV 'alias' construct).
|
||||
// All references to the LHS are treated as references to the RHS
|
||||
// If both sides are wires, there's no LHS vs RHS,
|
||||
// @astgen op1 := rhsp : AstVarRef
|
||||
// @astgen op2 := lhsp : AstVarRef
|
||||
|
||||
public:
|
||||
AstAlias(FileLine* fl, AstVarRef* lhsp, AstVarRef* rhsp)
|
||||
: ASTGEN_SUPER_Alias(fl) {
|
||||
this->lhsp(lhsp);
|
||||
this->rhsp(rhsp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstAlias;
|
||||
};
|
||||
class AstBind final : public AstNode {
|
||||
// Parents: MODULE
|
||||
// Children: CELL
|
||||
|
||||
@@ -1070,19 +1070,6 @@ public:
|
||||
}
|
||||
bool brokeLhsMustBeLvalue() const override { return true; }
|
||||
};
|
||||
class AstAssignAlias final : public AstNodeAssign {
|
||||
// Like AstAssignW, but a true bidirect interconnection alias
|
||||
// If both sides are wires, there's no LHS vs RHS,
|
||||
public:
|
||||
AstAssignAlias(FileLine* fl, AstVarRef* lhsp, AstVarRef* rhsp)
|
||||
: ASTGEN_SUPER_AssignAlias(fl, reinterpret_cast<AstNodeExpr*>(lhsp),
|
||||
reinterpret_cast<AstNodeExpr*>(rhsp)) {}
|
||||
ASTGEN_MEMBERS_AstAssignAlias;
|
||||
AstNodeAssign* cloneType(AstNodeExpr* lhsp, AstNodeExpr* rhsp) override {
|
||||
V3ERROR_NA_RETURN(nullptr);
|
||||
}
|
||||
bool brokeLhsMustBeLvalue() const override { return false; }
|
||||
};
|
||||
class AstAssignDly final : public AstNodeAssign {
|
||||
public:
|
||||
AstAssignDly(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp,
|
||||
|
||||
+1
-1
@@ -3145,7 +3145,7 @@ class ConstVisitor final : public VNVisitor {
|
||||
if (nodep->timingControlp()) m_hasJumpDelay = true;
|
||||
if (m_doNConst && replaceNodeAssign(nodep)) return;
|
||||
}
|
||||
void visit(AstAssignAlias* nodep) override {
|
||||
void visit(AstAlias* nodep) override {
|
||||
// Don't perform any optimizations, keep the alias around
|
||||
}
|
||||
void visit(AstAssignVarScope* nodep) override {
|
||||
|
||||
+1
-1
@@ -155,7 +155,7 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public VNVisitorConst {
|
||||
iterateAndNextConstNull(nodep->rhsp());
|
||||
puts(";\n");
|
||||
}
|
||||
void visit(AstAssignAlias* nodep) override {
|
||||
void visit(AstAlias* nodep) override {
|
||||
putbs("alias ");
|
||||
iterateAndNextConstNull(nodep->lhsp());
|
||||
putfs(nodep, " = ");
|
||||
|
||||
@@ -257,9 +257,6 @@ class GateBuildVisitor final : public VNVisitorConst {
|
||||
const bool slow = VN_IS(nodep, Initial) || VN_IS(nodep, Final);
|
||||
iterateLogic(nodep, slow, nodep->isJustOneBodyStmt() ? nullptr : "Multiple Stmts");
|
||||
}
|
||||
void visit(AstAssignAlias* nodep) override { //
|
||||
iterateLogic(nodep);
|
||||
}
|
||||
void visit(AstAssignW* nodep) override { //
|
||||
iterateLogic(nodep);
|
||||
}
|
||||
|
||||
+2
-3
@@ -317,7 +317,7 @@ class InlineRelinkVisitor final : public VNVisitor {
|
||||
nodep->name(m_cellp->name() + "__DOT__" + nodep->name());
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
void visit(AstAssignAlias* nodep) override {
|
||||
void visit(AstAlias* nodep) override {
|
||||
// Don't replace port variable in the alias
|
||||
}
|
||||
void visit(AstVarRef* nodep) override {
|
||||
@@ -501,8 +501,7 @@ void connectPort(AstNodeModule* modp, AstVar* nodep, AstNodeExpr* pinExprp) {
|
||||
modp->addStmtsp(
|
||||
new AstAssignVarScope{flp, portRef(VAccess::WRITE), pinRef(VAccess::READ)});
|
||||
} else {
|
||||
modp->addStmtsp(
|
||||
new AstAssignAlias{flp, portRef(VAccess::WRITE), pinRef(VAccess::READ)});
|
||||
modp->addStmtsp(new AstAlias{flp, portRef(VAccess::WRITE), pinRef(VAccess::READ)});
|
||||
}
|
||||
// They will become the same variable, so propagate file-line and variable attributes
|
||||
pinRefp->varp()->fileline()->modifyStateInherit(flp);
|
||||
|
||||
+15
-16
@@ -2102,18 +2102,7 @@ class LinkDotParamVisitor final : public VNVisitor {
|
||||
pinImplicitExprRecurse(nodep->lhsp());
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
void visit(AstAssignAlias* nodep) override { // ParamVisitor::
|
||||
// tran gates need implicit creation
|
||||
// As VarRefs don't exist in forPrimary, sanity check
|
||||
UASSERT_OBJ(!m_statep->forPrimary(), nodep, "Assign aliases unexpected pre-dot");
|
||||
if (AstVarRef* const forrefp = VN_CAST(nodep->lhsp(), VarRef)) {
|
||||
pinImplicitExprRecurse(forrefp);
|
||||
}
|
||||
if (AstVarRef* const forrefp = VN_CAST(nodep->rhsp(), VarRef)) {
|
||||
pinImplicitExprRecurse(forrefp);
|
||||
}
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
|
||||
void visit(AstImplicit* nodep) override { // ParamVisitor::
|
||||
// Unsupported gates need implicit creation
|
||||
pinImplicitExprRecurse(nodep->exprsp());
|
||||
@@ -2265,15 +2254,25 @@ class LinkDotScopeVisitor final : public VNVisitor {
|
||||
symp->fallbackp(m_modSymp);
|
||||
// No recursion, we don't want to pick up variables
|
||||
}
|
||||
void visit(AstAssignAlias* nodep) override { // ScopeVisitor::
|
||||
void visit(AstAlias* nodep) override { // ScopeVisitor::
|
||||
// Track aliases created by V3Inline; if we get a VARXREF(aliased_from)
|
||||
// we'll need to replace it with a VARXREF(aliased_to)
|
||||
UINFOTREE(9, nodep, "", "alias");
|
||||
AstVarScope* const fromVscp = VN_AS(nodep->lhsp(), VarRef)->varScopep();
|
||||
AstVarScope* const toVscp = VN_AS(nodep->rhsp(), VarRef)->varScopep();
|
||||
AstVarRef* const lhsp = nodep->lhsp();
|
||||
AstVarRef* const rhsp = nodep->rhsp();
|
||||
AstVarScope* const fromVscp = lhsp->varScopep();
|
||||
AstVarScope* const toVscp = rhsp->varScopep();
|
||||
UASSERT_OBJ(fromVscp && toVscp, nodep, "Bad alias scopes");
|
||||
fromVscp->user2p(toVscp);
|
||||
iterateChildren(nodep);
|
||||
|
||||
// Replace alias with an assignment. The LHS might still be references from otuside,
|
||||
// eg throught the VPI, and is traced, so we need the value to propagate.
|
||||
// TODO: this means external writes to the LHS (e.g.: through the VPI) don't work
|
||||
AstAssignW* const newp
|
||||
= new AstAssignW{nodep->fileline(), lhsp->unlinkFrBack(), rhsp->unlinkFrBack()};
|
||||
nodep->replaceWith(newp);
|
||||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||
iterateChildren(newp);
|
||||
}
|
||||
void visit(AstAssignVarScope* nodep) override { // ScopeVisitor::
|
||||
UINFO(5, "ASSIGNVARSCOPE " << nodep);
|
||||
|
||||
@@ -98,7 +98,7 @@ class LinkLValueVisitor final : public VNVisitor {
|
||||
VL_RESTORER(m_setStrengthSpecified);
|
||||
{
|
||||
m_setRefLvalue = VAccess::WRITE;
|
||||
m_setContinuously = VN_IS(nodep, AssignW) || VN_IS(nodep, AssignAlias);
|
||||
m_setContinuously = VN_IS(nodep, AssignW);
|
||||
if (const AstAssignW* const assignwp = VN_CAST(nodep, AssignW)) {
|
||||
if (assignwp->strengthSpecp()) m_setStrengthSpecified = true;
|
||||
}
|
||||
|
||||
@@ -327,10 +327,7 @@ class OrderGraphBuilder final : public VNVisitor {
|
||||
nodep->v3fatalSrc("AstFinal should not need ordering");
|
||||
} // LCOV_EXCL_STOP
|
||||
|
||||
//--- Logic akin go SystemVerilog continuous assignments
|
||||
void visit(AstAssignAlias* nodep) override { //
|
||||
iterateLogic(nodep);
|
||||
}
|
||||
//--- SystemVerilog continuous assignments
|
||||
void visit(AstAssignW* nodep) override { iterateLogic(nodep); }
|
||||
|
||||
//--- Verilator concoctions
|
||||
|
||||
+2
-2
@@ -208,7 +208,7 @@ class ScopeVisitor final : public VNVisitor {
|
||||
m_scopep->addBlocksp(clonep);
|
||||
iterateChildren(clonep); // We iterate under the *clone*
|
||||
}
|
||||
void visit(AstAssignAlias* nodep) override {
|
||||
void visit(AstAlias* nodep) override {
|
||||
// Add to list of blocks under this scope
|
||||
UINFO(4, " Move " << nodep);
|
||||
AstNode* const clonep = nodep->cloneTree(false);
|
||||
@@ -353,7 +353,7 @@ class ScopeCleanupVisitor final : public VNVisitor {
|
||||
}
|
||||
|
||||
void visit(AstNodeProcedure* nodep) override { movedDeleteOrIterate(nodep); }
|
||||
void visit(AstAssignAlias* nodep) override { movedDeleteOrIterate(nodep); }
|
||||
void visit(AstAlias* nodep) override { movedDeleteOrIterate(nodep); }
|
||||
void visit(AstAssignVarScope* nodep) override { movedDeleteOrIterate(nodep); }
|
||||
void visit(AstAssignW* nodep) override { movedDeleteOrIterate(nodep); }
|
||||
void visit(AstCoverToggle* nodep) override { movedDeleteOrIterate(nodep); }
|
||||
|
||||
@@ -286,7 +286,6 @@ class SliceVisitor final : public VNVisitor {
|
||||
void visit(AstNodeAssign* nodep) override {
|
||||
// Called recursively on newly created assignments
|
||||
if (nodep->user1SetOnce()) return; // Process once
|
||||
if (VN_IS(nodep, AssignAlias)) return;
|
||||
UINFOTREE(9, nodep, "", "Deslice-In");
|
||||
VL_RESTORER(m_assignError);
|
||||
VL_RESTORER(m_assignp);
|
||||
|
||||
@@ -337,6 +337,7 @@ static void process() {
|
||||
V3Const::constifyAll(v3Global.rootp());
|
||||
|
||||
// Flatten hierarchy, creating a SCOPE for each module's usage as a cell
|
||||
// No more AstAlias after linkDotScope
|
||||
V3Scope::scopeAll(v3Global.rootp());
|
||||
V3LinkDot::linkDotScope(v3Global.rootp());
|
||||
|
||||
|
||||
Reference in New Issue
Block a user