Exemple #1
0
    AstArraySel* insertImplicit(AstNode* nodep, unsigned start, unsigned count) {
	// Insert any implicit slices as explicit slices (ArraySel nodes).
	// Return a new pointer to replace nodep() in the ArraySel.
	UINFO(9,"  insertImplicit (start="<<start<<",c="<<count<<") "<<nodep<<endl);
	AstVarRef* refp = nodep->user1p()->castNode()->castVarRef();
	if (!refp) nodep->v3fatalSrc("No VarRef in user1 of node "<<nodep);
	AstVar* varp = refp->varp();
	AstNode* topp = nodep;
	for (unsigned i = start; i < start + count; ++i) {
	    AstNodeDType* dtypep = varp->dtypep()->dtypeDimensionp(i-1);
	    AstUnpackArrayDType* adtypep = dtypep->castUnpackArrayDType();
	    if (!adtypep) nodep->v3fatalSrc("insertImplicit tried to expand an array without an ArrayDType");
	    vlsint32_t msb = adtypep->msb();
	    vlsint32_t lsb = adtypep->lsb();
	    if (lsb > msb) {
		// Below code assumes big bit endian; just works out if we swap
		int x = msb; msb = lsb; lsb = x;
	    }
	    UINFO(9,"    ArraySel-child: "<<topp<<endl);
	    AstArraySel* newp = new AstArraySel(nodep->fileline(), topp,
						// "lsb-lsb": Arrays are zero-based so index 0 is always lsb
						new AstConst(nodep->fileline(), lsb-lsb));
	    if (!newp->dtypep()) {
		newp->v3fatalSrc("ArraySel dtyping failed when resolving slice");  // see ArraySel constructor
	    }
	    newp->user1p(refp);
	    newp->start(lsb);
	    newp->length(msb - lsb + 1);
	    topp = newp;
	}
	return topp->castArraySel();
    }
Exemple #2
0
    virtual void visit(AstSelExtract* nodep, AstNUser*) {
	// Select of a range specified part of an array, i.e. "array[2:3]"
	// SELEXTRACT(from,msb,lsb) -> SEL(from, lsb, 1+msb-lsb)
	// This select style has a (msb or lsb) and width
	UINFO(6,"SELEXTRACT "<<nodep<<endl);
	//if (debug()>=9) nodep->dumpTree(cout,"--SELEX0: ");
	// Below 2 lines may change nodep->widthp()
	V3Const::constifyParamsEdit(nodep->lsbp()); // May relink pointed to node
	V3Const::constifyParamsEdit(nodep->msbp()); // May relink pointed to node
	//if (debug()>=9) nodep->dumpTree(cout,"--SELEX3: ");
	checkConstantOrReplace(nodep->lsbp(), "First value of [a:b] isn't a constant, maybe you want +: or -:");
	checkConstantOrReplace(nodep->msbp(), "Second value of [a:b] isn't a constant, maybe you want +: or -:");
	AstNode* fromp = nodep->lhsp()->unlinkFrBack();
	AstNode* msbp = nodep->rhsp()->unlinkFrBack();
	AstNode* lsbp = nodep->thsp()->unlinkFrBack();
	vlsint32_t msb = msbp->castConst()->toSInt();
	vlsint32_t lsb = lsbp->castConst()->toSInt();
	FromData fromdata = fromDataForArray(nodep, fromp, false);
	AstNodeDType* ddtypep = fromdata.m_dtypep;
	VNumRange fromRange = fromdata.m_fromRange;
	if (ddtypep->castUnpackArrayDType()) {
	    // Slice extraction
	    if (fromRange.elements() == (msb-lsb+1)
		&& fromRange.lo() == lsb) { // Extracting whole of original array
		nodep->replaceWith(fromp); pushDeletep(nodep); VL_DANGLING(nodep);
	    } else {
		// TODO when unpacked arrays fully supported probably need new data type here
		AstArraySel* newp = new AstArraySel (nodep->fileline(), fromp, lsbp);
		newp->start(lsb);
		newp->length((msb - lsb) + 1);
		nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep);
	    }
	}
	else if (AstPackArrayDType* adtypep = ddtypep->castPackArrayDType()) {
	    // SELEXTRACT(array, msb, lsb) -> SEL(array, lsb*width-of-subindex, width-of-subindex*(msb-lsb))
	    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 AstConst(nodep->fileline(),AstConst::Unsized32(),lsb*elwidth),
				       new AstConst(nodep->fileline(),AstConst::Unsized32(),(msb-lsb+1)*elwidth));
	    newp->declRange(fromRange);
	    newp->declElWidth(elwidth);
	    newp->dtypeFrom(sliceDType(adtypep, msb, lsb));
	    //if (debug()>=9) newp->dumpTree(cout,"--EXTBTn: ");
	    if (newp->widthMin()!=(int)newp->widthConst()) nodep->v3fatalSrc("Width mismatch");
	    nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep);
	}
	else if (ddtypep->castBasicDType()) {
	    if (fromRange.littleEndian()) {
		// Below code assumes big bit endian; just works out if we swap
		int x = msb; msb = lsb; lsb = x;
	    }
	    if (lsb > msb) {
		nodep->v3error("["<<msb<<":"<<lsb<<"] Range extract has backward bit ordering, perhaps you wanted ["<<lsb<<":"<<msb<<"]");
		int x = msb; msb = lsb; lsb = x;
	    }
	    AstNode* widthp = new AstConst (msbp->fileline(), AstConst::Unsized32(), // Unsized so width from user
					    msb +1-lsb);
	    AstSel* newp = new AstSel (nodep->fileline(),
				       fromp,
				       newSubLsbOf(lsbp, fromRange),
				       widthp);
	    newp->declRange(fromRange);
	    UINFO(6,"   new "<<newp<<endl);
	    //if (debug()>=9) newp->dumpTree(cout,"--SELEXnew: ");
	    nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep);
	}
	else if (ddtypep->castNodeClassDType()) {
	    // Classes aren't little endian
	    if (lsb > msb) {
		nodep->v3error("["<<msb<<":"<<lsb<<"] Range extract has backward bit ordering, perhaps you wanted ["<<lsb<<":"<<msb<<"]");
		int x = msb; msb = lsb; lsb = x;
	    }
	    AstNode* widthp = new AstConst (msbp->fileline(), AstConst::Unsized32(), // Unsized so width from user
					    msb +1-lsb);
	    AstSel* newp = new AstSel (nodep->fileline(),
				       fromp,
				       newSubLsbOf(lsbp, fromRange),
				       widthp);
	    newp->declRange(fromRange);
	    UINFO(6,"   new "<<newp<<endl);
	    //if (debug()>=9) newp->dumpTree(cout,"--SELEXnew: ");
	    nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep);
	}
	else {  // NULL=bad extract, or unknown node type
	    nodep->v3error("Illegal range select; type already selected, or bad dimension: type is "
			   <<fromdata.m_errp->prettyName());
	    UINFO(1,"    Related ddtype: "<<ddtypep<<endl);
	    // 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 (!msbp->backp()) { pushDeletep(msbp); VL_DANGLING(msbp); }
	if (!lsbp->backp()) { pushDeletep(lsbp); VL_DANGLING(lsbp); }
    }