diff --git a/src/V3AstNodeOther.h b/src/V3AstNodeOther.h index 3ee3b6911..ed3f46ee1 100644 --- a/src/V3AstNodeOther.h +++ b/src/V3AstNodeOther.h @@ -450,7 +450,7 @@ public: inline bool hasCombo() const; }; class AstAlias final : public AstNode { - // Alias statement + // Alias construct - Used for source level net alias, and also for variable aliases internally // @astgen op1 := itemsp : List[AstNodeExpr] // Alias operands public: AstAlias(FileLine* fl, AstNodeExpr* itemsp) @@ -459,6 +459,18 @@ public: } ASTGEN_MEMBERS_AstAlias; }; +class AstAliasScope final : public AstNode { + // Like AstAlias, but aliases two scopes instead of nets/variables + // @astgen op1 := rhsp : AstNodeExpr + // @astgen op2 := lhsp : AstNodeExpr +public: + AstAliasScope(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp) + : ASTGEN_SUPER_AliasScope(fl) { + this->lhsp(lhsp); + this->rhsp(rhsp); + } + ASTGEN_MEMBERS_AstAliasScope; +}; class AstBind final : public AstNode { // Parents: MODULE // Children: CELL diff --git a/src/V3AstNodeStmt.h b/src/V3AstNodeStmt.h index e93506005..38fd4adba 100644 --- a/src/V3AstNodeStmt.h +++ b/src/V3AstNodeStmt.h @@ -68,7 +68,6 @@ public: bool sameNode(const AstNode*) const override { return true; } string verilogKwd() const override { return "="; } bool isTimingControl() const override { return timingControlp(); } - virtual bool brokeLhsMustBeLvalue() const = 0; }; class AstNodeBlock VL_NOT_FINAL : public AstNodeStmt { // A Begin/fork block @@ -1119,7 +1118,6 @@ public: AstNode* const controlp = timingControlp() ? timingControlp()->cloneTree(false) : nullptr; return new AstAssign{fileline(), lhsp, rhsp, controlp}; } - bool brokeLhsMustBeLvalue() const override { return true; } }; class AstAssignDly final : public AstNodeAssign { public: @@ -1133,7 +1131,6 @@ public: } bool isGateOptimizable() const override { return false; } string verilogKwd() const override { return "<="; } - bool brokeLhsMustBeLvalue() const override { return true; } }; class AstAssignForce final : public AstNodeAssign { // Procedural 'force' statement @@ -1144,20 +1141,6 @@ public: AstNodeAssign* cloneType(AstNodeExpr* lhsp, AstNodeExpr* rhsp) override { return new AstAssignForce{fileline(), lhsp, rhsp}; } - bool brokeLhsMustBeLvalue() const override { return true; } -}; -class AstAssignVarScope final : public AstNodeAssign { - // Assign two VarScopes to each other -public: - AstAssignVarScope(FileLine* fl, AstNodeExpr* lhsp, AstNodeExpr* rhsp) - : ASTGEN_SUPER_AssignVarScope(fl, lhsp, rhsp) { - dtypeFrom(rhsp); - } - ASTGEN_MEMBERS_AstAssignVarScope; - AstNodeAssign* cloneType(AstNodeExpr* lhsp, AstNodeExpr* rhsp) override { - return new AstAssignVarScope{fileline(), lhsp, rhsp}; - } - bool brokeLhsMustBeLvalue() const override { return false; } }; class AstAssignW final : public AstNodeAssign { // Like assign, but wire/assign's in verilog, the only setting of the specified variable @@ -1176,7 +1159,6 @@ public: return refp->access().isWriteOrRW() && refp->varp()->delayp(); }); } - bool brokeLhsMustBeLvalue() const override { return true; } AstDelay* getLhsNetDelay() const; AstAlways* convertToAlways(); }; diff --git a/src/V3Broken.cpp b/src/V3Broken.cpp index 8c7f4584e..e88fe4f90 100644 --- a/src/V3Broken.cpp +++ b/src/V3Broken.cpp @@ -225,8 +225,7 @@ private: // VISITORS void visit(AstNodeAssign* nodep) override { processAndIterate(nodep); - UASSERT_OBJ(!(v3Global.assertDTypesResolved() && nodep->brokeLhsMustBeLvalue() - && VN_IS(nodep->lhsp(), NodeVarRef) + UASSERT_OBJ(!(v3Global.assertDTypesResolved() && VN_IS(nodep->lhsp(), NodeVarRef) && !VN_AS(nodep->lhsp(), NodeVarRef)->access().isWriteOrRW()), nodep, "Assignment LHS is not an lvalue"); } diff --git a/src/V3Const.cpp b/src/V3Const.cpp index 4eb72ee55..7655282f6 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -3244,8 +3244,8 @@ class ConstVisitor final : public VNVisitor { void visit(AstAlias* nodep) override { // Don't perform any optimizations, keep the alias around } - void visit(AstAssignVarScope* nodep) override { - // Don't perform any optimizations, the node won't be linked yet + void visit(AstAliasScope* nodep) override { + // Don't perform any optimizations, keep the alias around } void visit(AstAssignW* nodep) override { iterateChildren(nodep); diff --git a/src/V3Inline.cpp b/src/V3Inline.cpp index bac96e085..b269d5885 100644 --- a/src/V3Inline.cpp +++ b/src/V3Inline.cpp @@ -499,7 +499,7 @@ void connectPort(AstNodeModule* modp, AstVar* nodep, AstNodeExpr* pinExprp) { UINFO(6, "Inlning port variable: " << nodep); if (nodep->isIfaceRef()) { modp->addStmtsp( - new AstAssignVarScope{flp, portRef(VAccess::WRITE), pinRef(VAccess::READ)}); + new AstAliasScope{flp, portRef(VAccess::WRITE), pinRef(VAccess::READ)}); } else { AstVarRef* const aliasArgsp = portRef(VAccess::WRITE); aliasArgsp->addNext(pinRef(VAccess::READ)); @@ -633,7 +633,7 @@ void process(AstNetlist* netlistp, ModuleStateUser1Allocator& moduleStates) { // Clean up AstIfaceRefDType references // If the cell has been removed let's make sure we don't leave a // reference to it. This dtype may still be in use by the - // AstAssignVarScope created earlier but that'll get cleared up later + // AstAliasScope created earlier but that'll get cleared up later netlistp->typeTablep()->foreach([](AstIfaceRefDType* nodep) { if (nodep->user1()) nodep->cellp(nullptr); }); diff --git a/src/V3Inst.cpp b/src/V3Inst.cpp index 8a2dcec51..7be798e91 100644 --- a/src/V3Inst.cpp +++ b/src/V3Inst.cpp @@ -90,7 +90,7 @@ class InstVisitor final : public VNVisitor { ->subDTypep() ->skipRefp(), IfaceRefDType))) { - // Create an AstAssignVarScope for Vars to Cells so we can + // Create an AstAliasScope for Vars to Cells so we can // link with their scope later AstNodeExpr* const lhsp = new AstVarXRef{exprp->fileline(), nodep->modVarp(), m_cellp->name(), VAccess::READ}; @@ -98,9 +98,7 @@ class InstVisitor final : public VNVisitor { const AstVarXRef* const xrefp = VN_CAST(exprp, VarXRef); UASSERT_OBJ(refp || xrefp, exprp, "Interfaces: Pin is not connected to a VarRef or VarXRef"); - AstAssignVarScope* const assp - = new AstAssignVarScope{exprp->fileline(), lhsp, exprp}; - m_cellp->addNextHere(assp); + m_cellp->addNextHere(new AstAliasScope{exprp->fileline(), lhsp, exprp}); } else { nodep->v3error("Assigned pin is neither input nor output"); } diff --git a/src/V3Interface.cpp b/src/V3Interface.cpp index 4537fab18..9fb995579 100644 --- a/src/V3Interface.cpp +++ b/src/V3Interface.cpp @@ -70,7 +70,7 @@ class InlineIntfRefVisitor final : public VNVisitor { iterateChildren(modp); } - void visit(AstAssignVarScope* nodep) override { + void visit(AstAliasScope* nodep) override { // Reference const AstVarRef* const reflp = VN_CAST(nodep->lhsp(), VarRef); // What the reference refers to diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index 93cccc7dc..90808479e 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -2326,8 +2326,8 @@ private: iterateChildren(nodep); pushDeletep(nodep->unlinkFrBack()); } - void visit(AstAssignVarScope* nodep) override { // ScopeVisitor:: - UINFO(5, "ASSIGNVARSCOPE " << nodep); + void visit(AstAliasScope* nodep) override { // ScopeVisitor:: + UINFO(5, "ALIASSCOPE " << nodep); UINFOTREE(9, nodep, "", "avs"); VSymEnt* rhsSymp; { diff --git a/src/V3Scope.cpp b/src/V3Scope.cpp index 6ddffd5a7..bc825cda0 100644 --- a/src/V3Scope.cpp +++ b/src/V3Scope.cpp @@ -216,7 +216,7 @@ class ScopeVisitor final : public VNVisitor { m_scopep->addBlocksp(clonep); iterateChildren(clonep); // We iterate under the *clone* } - void visit(AstAssignVarScope* nodep) override { + void visit(AstAliasScope* nodep) override { // Copy under the scope but don't recurse UINFO(4, " Move " << nodep); AstNode* const clonep = nodep->cloneTree(false); @@ -354,7 +354,7 @@ class ScopeCleanupVisitor final : public VNVisitor { void visit(AstNodeProcedure* nodep) override { movedDeleteOrIterate(nodep); } void visit(AstAlias* nodep) override { movedDeleteOrIterate(nodep); } - void visit(AstAssignVarScope* nodep) override { movedDeleteOrIterate(nodep); } + void visit(AstAliasScope* nodep) override { movedDeleteOrIterate(nodep); } void visit(AstAssignW* nodep) override { movedDeleteOrIterate(nodep); } void visit(AstCoverToggle* nodep) override { movedDeleteOrIterate(nodep); } void visit(AstNodeFTask* nodep) override { movedDeleteOrIterate(nodep); }