void test(string lhss, string op, string rhss, string exps) {
    char* l1 = strdup(lhss.c_str());
    char* r1 = strdup(rhss.c_str());
    char* e1 = strdup(exps.c_str());

    V3Number lhnum (new FileLine ("ck",__LINE__), l1);
    V3Number rhnum (new FileLine ("ck",__LINE__), r1);
    V3Number expnum (new FileLine("ck",__LINE__), e1);

    V3Number gotnum (new FileLine("ck",__LINE__), expnum.width());

    if (op=="redOr")	 	gotnum.opRedOr		(lhnum);
    else if (op=="redAnd")	gotnum.opRedAnd		(lhnum);
    else if (op=="redXor")	gotnum.opRedXor		(lhnum);
    else if (op=="redXnor")	gotnum.opRedXnor	(lhnum);
    else if (op=="concat")	gotnum.opConcat		(lhnum,rhnum);
    else if (op=="repl")	gotnum.opRepl		(lhnum,rhnum);
    else if (op=="~")	 	gotnum.opNot		(lhnum);
    else if (op=="!")	 	gotnum.opLogNot		(lhnum);
    else if (op=="negate") 	gotnum.opNegate		(lhnum);
    else if (op=="+")	 	gotnum.opAdd		(lhnum,rhnum);
    else if (op=="-")	 	gotnum.opSub		(lhnum,rhnum);
    else if (op=="*")	 	gotnum.opMul		(lhnum,rhnum);
    else if (op=="/")	 	gotnum.opDiv		(lhnum,rhnum);
    else if (op=="%")	 	gotnum.opModDiv		(lhnum,rhnum);
    else if (op=="&")	 	gotnum.opAnd		(lhnum,rhnum);
    else if (op=="|")	 	gotnum.opOr		(lhnum,rhnum);
    else if (op=="<")	 	gotnum.opLt		(lhnum,rhnum);
    else if (op==">")	 	gotnum.opGt		(lhnum,rhnum);
    else if (op==">>")	 	gotnum.opShiftR		(lhnum,rhnum);
    else if (op=="<<")	 	gotnum.opShiftL		(lhnum,rhnum);
    else if (op=="==")	 	gotnum.opEq		(lhnum,rhnum);
    else if (op=="===")	 	gotnum.opCaseEq		(lhnum,rhnum);
    else if (op=="==?")	 	gotnum.opWildEq		(lhnum,rhnum);
    else if (op=="!=")	 	gotnum.opNeq		(lhnum,rhnum);
    else if (op=="!==")	 	gotnum.opCaseNeq	(lhnum,rhnum);
    else if (op=="!=?")	 	gotnum.opWildNeq	(lhnum,rhnum);
    else if (op=="<=")	 	gotnum.opLte		(lhnum,rhnum);
    else if (op==">=")	 	gotnum.opGte		(lhnum,rhnum);
    else if (op=="&&")	 	gotnum.opLogAnd		(lhnum,rhnum);
    else if (op=="||")	 	gotnum.opLogOr		(lhnum,rhnum);
    else v3fatalSrc("Bad opcode: "<<op);

    UINFO(0,"------- Test:\n"
	  <<"       "<<lhnum<<" "<<op<<endl
	  <<"       "<<rhnum<<endl
	  <<"     = "<<expnum<<endl
	  <<"    =? "<<gotnum<<endl);

    V3Number ok (new FileLine("ck",__LINE__), 1);
    ok.opCaseEq(expnum,gotnum);
    if (ok.toUInt()!=1) {
	v3fatalSrc("%Error:Test FAILED\n");
    }
}
Esempio n. 2
0
    bool isCaseTreeFast(AstCase* nodep) {
	int width = 0;
	bool opaque = false;
	m_caseItems = 0;
	m_caseNoOverlapsAllCovered = true;
	for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
	    for (AstNode* icondp = itemp->condsp(); icondp!=NULL; icondp=icondp->nextp()) {
		if (icondp->width() > width) width = icondp->width();
		if (icondp->isDouble()) opaque = true;
		if (!icondp->castConst()) width = CASE_BARF;  // Can't parse; not a constant
		m_caseItems++;
	    }
	}
	m_caseWidth = width;
	if (width==0 || width > CASE_OVERLAP_WIDTH || opaque) {
	    m_caseNoOverlapsAllCovered = false;
	    return false;	// Too wide for analysis
	}
	UINFO(8,"Simple case statement: "<<nodep<<endl);
	// Zero list of items for each value
	for (uint32_t i=0; i<(1UL<<m_caseWidth); i++) m_valueItem[i] = NULL;
	// Now pick up the values for each assignment
	// We can cheat and use uint32_t's because we only support narrow case's
	bool bitched = false;
	for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
	    for (AstNode* icondp = itemp->condsp(); icondp!=NULL; icondp=icondp->nextp()) {
		//if (debug()>=9) icondp->dumpTree(cout," caseitem: ");
		AstConst* iconstp = icondp->castConst();
		if (!iconstp) nodep->v3fatalSrc("above 'can't parse' should have caught this\n");
		if (neverItem(nodep, iconstp)) {
		    // X in casez can't ever be executed
		} else {
		    V3Number nummask (itemp->fileline(), iconstp->width());
		    nummask.opBitsNonX(iconstp->num());
		    uint32_t mask = nummask.toUInt();
		    V3Number numval  (itemp->fileline(), iconstp->width());
		    numval.opBitsOne(iconstp->num());
		    uint32_t val  = numval.toUInt();
		    for (uint32_t i=0; i<(1UL<<m_caseWidth); i++) {
			if ((i & mask) == val) {
			    if (!m_valueItem[i]) {
				m_valueItem[i] = itemp;
			    } else if (!itemp->ignoreOverlap() && !bitched) {
				itemp->v3warn(CASEOVERLAP,"Case values overlap (example pattern 0x"<<hex<<i<<")");
				bitched = true;
				m_caseNoOverlapsAllCovered = false;
			    }
			}
		    }
		}
	    }
	    // Defaults were moved to last in the caseitem list by V3LinkDot
	    if (itemp->isDefault()) {  // Case statement's default... Fill the table
		for (uint32_t i=0; i<(1UL<<m_caseWidth); i++) {
		    if (!m_valueItem[i]) m_valueItem[i] = itemp;
		}
	    }
	}
	for (uint32_t i=0; i<(1UL<<m_caseWidth); i++) {
	    if (!m_valueItem[i]) {
		nodep->v3warn(CASEINCOMPLETE,"Case values incompletely covered (example pattern 0x"<<hex<<i<<")");
		m_caseNoOverlapsAllCovered = false;
		return false;
	    }
	}
	if (m_caseItems <= 3) return false;	// Not worth simplifing
	// Convert valueItem from AstCaseItem* to the expression
	// Not done earlier, as we may now have a NULL because it's just a ";" NOP branch
	for (uint32_t i=0; i<(1UL<<m_caseWidth); i++) {
	    m_valueItem[i] = m_valueItem[i]->castCaseItem()->bodysp();
	}
	return true;  // All is fine
    }