@@ -95,15 +95,61 @@ class ForceState final {
9595
9696 AstVarRef* const enRefp = new AstVarRef{flp, m_enVscp, VAccess::WRITE};
9797
98+ AstNodeStmt* toInsertp = nullptr ;
99+ AstNodeStmt* outerStmtp = nullptr ;
100+ std::vector<AstNodeExpr*> loopVarRefs;
101+ if (VN_IS (enRefp->dtypep ()->skipRefp (), UnpackArrayDType)) {
102+ // Create a loop to set all elements of __VforceEn array to 0.
103+ // That loop node is then copied and used for updating elements of __VforceRd array
104+ if (AstUnpackArrayDType* const unpackedp
105+ = VN_CAST (m_rdVscp->varp ()->dtypep (), UnpackArrayDType)) {
106+ std::vector<AstUnpackArrayDType*> dims = unpackedp->unpackDimensions ();
107+ loopVarRefs.reserve (dims.size ());
108+ for (size_t i = 0 ; i < dims.size (); i++) {
109+ AstVar* const loopVarp = new AstVar{
110+ flp, VVarType::MODULETEMP,
111+ m_rdVscp->varp ()->name () + " __VwhileIter" + std::to_string (i),
112+ VFlagBitPacked{}, 32 };
113+ m_rdVscp->varp ()->addNext (loopVarp);
114+ AstVarScope* const loopVarScopep
115+ = new AstVarScope{flp, m_rdVscp->scopep (), loopVarp};
116+ m_rdVscp->addNext (loopVarScopep);
117+ AstVarRef* const readRefp
118+ = new AstVarRef{flp, loopVarScopep, VAccess::READ};
119+ loopVarRefs.push_back (readRefp);
120+ AstNodeStmt* const currInitp
121+ = new AstAssign{flp, new AstVarRef{flp, loopVarScopep, VAccess::WRITE},
122+ new AstConst{flp, 0 }};
123+ if (toInsertp) {
124+ toInsertp->addNextHere (currInitp);
125+ } else {
126+ outerStmtp = currInitp;
127+ }
128+ AstLoop* const currWhilep = new AstLoop{flp};
129+ currInitp->addNextHere (currWhilep);
130+ AstLoopTest* const loopTestp = new AstLoopTest{
131+ flp, currWhilep,
132+ new AstNeq{flp, readRefp,
133+ new AstConst{
134+ flp, static_cast <uint32_t >(dims[i]->elementsConst ())}}};
135+ currWhilep->addStmtsp (loopTestp);
136+ toInsertp = loopTestp;
137+ AstAssign* const currIncrp = new AstAssign{
138+ flp, new AstVarRef{flp, loopVarScopep, VAccess::WRITE},
139+ new AstAdd{flp, readRefp->cloneTree (false ), new AstConst{flp, 1 }}};
140+ currWhilep->addStmtsp (currIncrp);
141+ }
142+ }
143+ }
98144 V3Number zero{m_enVscp, m_enVscp->width ()};
99- AstNodeExpr* const zeroConstp = new AstConst{flp, zero};
100- AstNodeExpr* enRhsp ;
101- if ( VN_IS (m_enVscp-> dtypep ()-> skipRefp (), UnpackArrayDType)) {
102- enRhsp = new AstInitArray{flp, enRefp-> dtypep (), zeroConstp};
103- } else {
104- enRhsp = zeroConstp ;
145+ AstNodeExpr* const enRhsp = new AstConst{flp, zero};
146+ AstNodeExpr* enLhsp = applySelects (enRefp, loopVarRefs) ;
147+ AstNodeStmt* stmtp = new AstAssign{flp, enLhsp, enRhsp};
148+ if (toInsertp) {
149+ toInsertp-> addNextHere (stmtp);
150+ stmtp = outerStmtp ;
105151 }
106- activeInitp->addStmtsp (new AstInitial{flp, new AstAssign{flp, enRefp, enRhsp} });
152+ activeInitp->addStmtsp (new AstInitial{flp, stmtp-> cloneTree ( true ) });
107153 { // Add the combinational override
108154 // Explicitly list dependencies for update.
109155 // Note: rdVscp is also needed to retrigger assignment for the first time.
@@ -120,59 +166,15 @@ class ForceState final {
120166 = new AstActive{flp, " force-update" , new AstSenTree{flp, itemsp}};
121167 activep->senTreeStorep (activep->sentreep ());
122168
123- AstNodeStmt* toInsertp = nullptr ;
124- AstNodeStmt* outerStmtp = nullptr ;
125- std::vector<AstNodeExpr*> loopVarRefs;
126- if (VN_IS (enRefp->dtypep ()->skipRefp (), UnpackArrayDType)) {
127- // Create a loop to update all elements of __VforceRd array
128- if (AstUnpackArrayDType* const unpackedp
129- = VN_CAST (m_rdVscp->varp ()->dtypep (), UnpackArrayDType)) {
130- std::vector<AstUnpackArrayDType*> dims = unpackedp->unpackDimensions ();
131- loopVarRefs.reserve (dims.size ());
132- for (size_t i = 0 ; i < dims.size (); i++) {
133- AstVar* const loopVarp = new AstVar{
134- flp, VVarType::MODULETEMP,
135- m_rdVscp->varp ()->name () + " __VwhileIter" + std::to_string (i),
136- VFlagBitPacked{}, 32 };
137- m_rdVscp->varp ()->addNext (loopVarp);
138- AstVarScope* const loopVarScopep
139- = new AstVarScope{flp, m_rdVscp->scopep (), loopVarp};
140- m_rdVscp->addNext (loopVarScopep);
141- AstVarRef* const readRefp
142- = new AstVarRef{flp, loopVarScopep, VAccess::READ};
143- loopVarRefs.push_back (readRefp);
144- AstNodeStmt* const currInitp = new AstAssign{
145- flp, new AstVarRef{flp, loopVarScopep, VAccess::WRITE},
146- new AstConst{flp, 0 }};
147- if (toInsertp) {
148- toInsertp->addNextHere (currInitp);
149- } else {
150- outerStmtp = currInitp;
151- }
152- AstLoop* const currWhilep = new AstLoop{flp};
153- currInitp->addNextHere (currWhilep);
154- AstLoopTest* const loopTestp = new AstLoopTest{
155- flp, currWhilep,
156- new AstNeq{flp, readRefp,
157- new AstConst{flp, static_cast <uint32_t >(
158- dims[i]->elementsConst ())}}};
159- currWhilep->addStmtsp (loopTestp);
160- toInsertp = loopTestp;
161- AstAssign* const currIncrp = new AstAssign{
162- flp, new AstVarRef{flp, loopVarScopep, VAccess::WRITE},
163- new AstAdd{flp, readRefp->cloneTree (false ), new AstConst{flp, 1 }}};
164- currWhilep->addStmtsp (currIncrp);
165- }
166- }
167- }
169+ // Reuse the statements created for __VforceEn initialization
170+ // and replace var ref on the LHS and the RHS
168171 AstVarRef* const rdRefp = new AstVarRef{flp, m_rdVscp, VAccess::WRITE};
169172 AstNodeExpr* const rdRhsp = forcedUpdate (vscp, loopVarRefs);
170- AstNodeExpr* rdLhsp = applySelects (rdRefp, loopVarRefs);
171- AstNodeStmt* stmtp = new AstAssign{flp, rdLhsp, rdRhsp};
172- if (toInsertp) {
173- toInsertp->addNextHere (stmtp);
174- stmtp = outerStmtp;
175- }
173+ enRefp->replaceWith (rdRefp);
174+ VL_DO_DANGLING (enRefp->deleteTree (), enRefp);
175+ enRhsp->replaceWith (rdRhsp);
176+ VL_DO_DANGLING (enRhsp->deleteTree (), enRhsp);
177+
176178 activep->addStmtsp (new AstAlways{flp, VAlwaysKwd::ALWAYS, nullptr , stmtp});
177179 vscp->scopep ()->addBlocksp (activep);
178180 }
0 commit comments