void replaceSelPlusMinus(AstNodePreSel* nodep) { // Select of a range specified with +: or -:, i.e. "array[2+:3], [2-:3]" // This select style has a lsb and width UINFO(6,"SELPLUS/MINUS "<<nodep<<endl); // Below 2 lines may change nodep->widthp() if (debug()>=9) nodep->dumpTree(cout,"--SELPM0: "); V3Const::constifyParamsEdit(nodep->thsp()); // May relink pointed to node checkConstantOrReplace(nodep->thsp(), "Width of :+ or :- bit extract isn't a constant"); if (debug()>=9) nodep->dumpTree(cout,"--SELPM3: "); // Now replace it with an AstSel AstNode* fromp = nodep->lhsp()->unlinkFrBack(); AstNode* rhsp = nodep->rhsp()->unlinkFrBack(); AstNode* widthp = nodep->thsp()->unlinkFrBack(); int width = widthp->castConst()->toSInt(); if (width > (1<<28)) nodep->v3error("Width of :+ or :- is huge; vector of over 1billion bits: "<<widthp->prettyName()); if (width<0) nodep->v3error("Width of :+ or :- is < 0: "<<widthp->prettyName()); FromData fromdata = fromDataForArray(nodep, fromp, width!=1); AstNodeDType* ddtypep = fromdata.m_dtypep; VNumRange fromRange = fromdata.m_fromRange; if (ddtypep->castBasicDType() || ddtypep->castPackArrayDType() || (ddtypep->castNodeClassDType() && ddtypep->castNodeClassDType()->packedUnsup())) { int elwidth = 1; AstNode* newwidthp = widthp; if (AstPackArrayDType* adtypep = ddtypep->castPackArrayDType()) { elwidth = adtypep->width() / fromRange.elements(); newwidthp = new AstConst (nodep->fileline(),AstConst::Unsized32(), width * elwidth); } AstNode* newlsbp = NULL; if (nodep->castSelPlus()) { if (fromRange.littleEndian()) { // SELPLUS(from,lsb,width) -> SEL(from, (vector_msb-width+1)-sel, width) newlsbp = newSubNeg((fromRange.hi()-width+1), rhsp); } else { // SELPLUS(from,lsb,width) -> SEL(from, lsb-vector_lsb, width) newlsbp = newSubNeg(rhsp, fromRange.lo()); } } else if (nodep->castSelMinus()) { if (fromRange.littleEndian()) { // SELMINUS(from,msb,width) -> SEL(from, msb-[bit]) newlsbp = newSubNeg(fromRange.hi(), rhsp); } else { // SELMINUS(from,msb,width) -> SEL(from, msb-(width-1)-lsb#) newlsbp = newSubNeg(rhsp, fromRange.lo()+(width-1)); } } else { nodep->v3fatalSrc("Bad Case"); } if (elwidth != 1) newlsbp = new AstMul (nodep->fileline(), newlsbp, new AstConst (nodep->fileline(), elwidth)); AstSel* newp = new AstSel (nodep->fileline(), fromp, newlsbp, newwidthp); newp->declRange(fromRange); newp->declElWidth(elwidth); UINFO(6," new "<<newp<<endl); if (debug()>=9) newp->dumpTree(cout,"--SELNEW: "); nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep); } else { // NULL=bad extract, or unknown node type nodep->v3error("Illegal +: or -: select; type already selected, or bad dimension: type is " <<fromdata.m_errp->prettyTypeName()); // How to recover? We'll strip a dimension. nodep->replaceWith(fromp); pushDeletep(nodep); VL_DANGLING(nodep); } // delete whataver we didn't use in reconstruction if (!fromp->backp()) { pushDeletep(fromp); VL_DANGLING(fromp); } if (!rhsp->backp()) { pushDeletep(rhsp); VL_DANGLING(rhsp); } if (!widthp->backp()) { pushDeletep(widthp); VL_DANGLING(widthp); } }
virtual void visit(AstSelBit* nodep, AstNUser*) { // Select of a non-width specified part of an array, i.e. "array[2]" // This select style has a lsb and msb (no user specified width) UINFO(6,"SELBIT "<<nodep<<endl); if (debug()>=9) nodep->backp()->dumpTree(cout,"--SELBT0: "); // lhsp/rhsp do not need to be constant AstNode* fromp = nodep->lhsp()->unlinkFrBack(); AstNode* rhsp = nodep->rhsp()->unlinkFrBack(); // bit we're extracting if (debug()>=9) nodep->dumpTree(cout,"--SELBT2: "); FromData fromdata = fromDataForArray(nodep, fromp, false); AstNodeDType* ddtypep = fromdata.m_dtypep; VNumRange fromRange = fromdata.m_fromRange; UINFO(6," ddtypep "<<ddtypep<<endl); if (AstUnpackArrayDType* adtypep = ddtypep->castUnpackArrayDType()) { // SELBIT(array, index) -> ARRAYSEL(array, index) AstNode* subp = rhsp; if (fromRange.lo()!=0 || fromRange.hi()<0) { subp = newSubNeg (subp, fromRange.lo()); } AstArraySel* newp = new AstArraySel (nodep->fileline(), fromp, subp); newp->dtypeFrom(adtypep->subDTypep()); // Need to strip off array reference if (debug()>=9) newp->dumpTree(cout,"--SELBTn: "); nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep); } else if (AstPackArrayDType* adtypep = ddtypep->castPackArrayDType()) { // SELBIT(array, index) -> SEL(array, index*width-of-subindex, width-of-subindex) AstNode* subp = rhsp; if (fromRange.lo()!=0 || fromRange.hi()<0) { subp = newSubNeg (subp, fromRange.lo()); } if (!fromRange.elements() || (adtypep->width() % fromRange.elements())!=0) adtypep->v3fatalSrc("Array extraction with width miscomputed " <<adtypep->width()<<"/"<<fromRange.elements()); int elwidth = adtypep->width() / fromRange.elements(); AstSel* newp = new AstSel (nodep->fileline(), fromp, new AstMul(nodep->fileline(), new AstConst(nodep->fileline(),AstConst::Unsized32(),elwidth), subp), new AstConst (nodep->fileline(),AstConst::Unsized32(),elwidth)); newp->declRange(fromRange); newp->declElWidth(elwidth); newp->dtypeFrom(adtypep->subDTypep()); // Need to strip off array reference if (debug()>=9) newp->dumpTree(cout,"--SELBTn: "); nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep); } else if (ddtypep->castBasicDType()) { // SELBIT(range, index) -> SEL(array, index, 1) AstSel* newp = new AstSel (nodep->fileline(), fromp, newSubLsbOf(rhsp, fromRange), // Unsized so width from user new AstConst (nodep->fileline(),AstConst::Unsized32(),1)); newp->declRange(fromRange); UINFO(6," new "<<newp<<endl); if (debug()>=9) newp->dumpTree(cout,"--SELBTn: "); nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep); } else if (ddtypep->castNodeClassDType()) { // It's packed, so a bit from the packed struct // SELBIT(range, index) -> SEL(array, index, 1) AstSel* newp = new AstSel (nodep->fileline(), fromp, newSubLsbOf(rhsp, fromRange), // Unsized so width from user new AstConst (nodep->fileline(),AstConst::Unsized32(),1)); newp->declRange(fromRange); UINFO(6," new "<<newp<<endl); if (debug()>=9) newp->dumpTree(cout,"--SELBTn: "); nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep); } else { // NULL=bad extract, or unknown node type nodep->v3error("Illegal bit or array select; type already selected, or bad dimension: type is" <<fromdata.m_errp->prettyName()); // How to recover? We'll strip a dimension. nodep->replaceWith(fromp); pushDeletep(nodep); VL_DANGLING(nodep); } if (!rhsp->backp()) { pushDeletep(rhsp); VL_DANGLING(rhsp); } }