virtual void visit(AstArraySel* nodep, AstNUser*) { if (!m_assignp) return; if (nodep->user3()) return; // Prevent recursion on just created nodes unsigned dim = explicitDimensions(nodep); AstVarRef* refp = nodep->user1p()->castNode()->castVarRef(); pair<uint32_t,uint32_t> arrDim = refp->varp()->dtypep()->dimensions(false); uint32_t implicit = (arrDim.second) - dim; if (implicit > 0) { AstArraySel* newp = insertImplicit(nodep->cloneTree(false), dim+1, implicit); nodep->replaceWith(newp); nodep = newp; nodep->user3(true); } int clones = countClones(nodep); if (m_assignp->user2() > 0 && m_assignp->user2() != clones) { m_assignp->v3error("Slices of arrays in assignments must have the same unpacked dimensions"); } else if (!m_assignp->user2()) { if (m_extend && clones > 1 && !m_assignError) { m_assignp->v3error("Unsupported: Assignment between unpacked arrays of different dimensions"); m_assignError = true; } if (clones > 1 && !refp->lvalue() && refp->varp() == m_lhsVarRefp->varp() && !m_assignp->castAssignDly() && !m_assignError) { // LHS Var != RHS Var for a non-delayed assignment m_assignp->v3error("Unsupported: Slices in a non-delayed assignment with the same Var on both sides"); m_assignError = true; } m_assignp->user2(clones); } }
virtual void visit(AstConst* nodep, AstNUser*) { m_extend = true; if (m_assignp && m_assignp->user2() > 1 && !m_assignError) { m_assignp->v3error("Unsupported: Assignment between a constant and an array slice"); m_assignError = true; } }
virtual void visit(AstSel* nodep, AstNUser*) { m_extend = true; if (m_assignp && m_assignp->user2() > 1 && !m_assignError) { m_assignp->v3error("Unsupported: Assignment between unpacked arrays of different dimensions"); m_assignError = true; } nodep->iterateChildren(*this); }
virtual void visit(AstSenItem* nodep, AstNUser*) { // Remove bit selects, and bark if it's not a simple variable nodep->iterateChildren(*this); if (nodep->isClocked()) { // If it's not a simple variable wrap in a temporary // This is a bit unfortunate as we haven't done width resolution // and any width errors will look a bit odd, but it works. AstNode* sensp = nodep->sensp(); if (sensp && !sensp->castNodeVarRef() && !sensp->castConst()) { // Make a new temp wire string newvarname = "__Vsenitemexpr"+cvtToStr(++m_senitemCvtNum); AstVar* newvarp = new AstVar (sensp->fileline(), AstVarType::MODULETEMP, newvarname, VFlagLogicPacked(), 1); // We can't just add under the module, because we may be inside a generate, begin, etc. // We know a SenItem should be under a SenTree/Always etc, we we'll just hunt upwards AstNode* addwherep = nodep; // Add to this element's next while (addwherep->castSenItem() || addwherep->castSenTree()) { addwherep = addwherep->backp(); } if (!addwherep->castAlways()) { // Assertion perhaps? sensp->v3error("Unsupported: Non-single-bit pos/negedge clock statement under some complicated block"); addwherep = m_modp; } addwherep->addNext(newvarp); sensp->replaceWith(new AstVarRef (sensp->fileline(), newvarp, false)); AstAssignW* assignp = new AstAssignW (sensp->fileline(), new AstVarRef(sensp->fileline(), newvarp, true), sensp); addwherep->addNext(assignp); } } else { // Old V1995 sensitivity list; we'll probably mostly ignore bool did=1; while (did) { did=0; if (AstNodeSel* selp = nodep->sensp()->castNodeSel()) { AstNode* fromp = selp->fromp()->unlinkFrBack(); selp->replaceWith(fromp); selp->deleteTree(); selp=NULL; did=1; } // NodeSel doesn't include AstSel.... if (AstSel* selp = nodep->sensp()->castSel()) { AstNode* fromp = selp->fromp()->unlinkFrBack(); selp->replaceWith(fromp); selp->deleteTree(); selp=NULL; did=1; } if (AstNodePreSel* selp = nodep->sensp()->castNodePreSel()) { AstNode* fromp = selp->lhsp()->unlinkFrBack(); selp->replaceWith(fromp); selp->deleteTree(); selp=NULL; did=1; } } } if (!nodep->sensp()->castNodeVarRef() && !nodep->sensp()->castEnumItemRef()) { // V3Const will cleanup if (debug()) nodep->dumpTree(cout,"-tree: "); nodep->v3error("Unsupported: Complex statement in sensitivity list"); } }