Result bvConcatBothWays(vector<FixedBits*>& children, FixedBits& output) { Result r = NO_CHANGE; const size_t numberOfChildren = children.size(); unsigned current = 0; for (int i = (int)numberOfChildren - 1; i >= 0; i--) // least significant is last. { FixedBits& child = *children[i]; for (unsigned j = 0; j < child.getWidth(); j++) { // values are different. Bad. if (output.isFixed(current) && child.isFixed(j) && (output.getValue(current) != child.getValue(j))) return CONFLICT; if (output.isFixed(current) && !child.isFixed(j)) { // only output is fixed. child.setFixed(j, true); child.setValue(j, output.getValue(current)); r = CHANGED; } else if (!output.isFixed(current) && child.isFixed(j)) { // only input is fixed. output.setFixed(current, true); output.setValue(current, child.getValue(j)); r = CHANGED; } current++; } } return r; }
Result bvNotBothWays(FixedBits& a, FixedBits& output) { assert(a.getWidth() == output.getWidth()); const int bitWidth = a.getWidth(); Result result = NO_CHANGE; for (int i = 0; i < bitWidth; i++) { // error if they are the same. if (a.isFixed(i) && output.isFixed(i) && (a.getValue(i) == output.getValue(i))) { return CONFLICT; } if (a.isFixed(i) && !output.isFixed(i)) { output.setFixed(i, true); output.setValue(i, !a.getValue(i)); result = CHANGED; } if (output.isFixed(i) && !a.isFixed(i)) { a.setFixed(i, true); a.setValue(i, !output.getValue(i)); result = CHANGED; } } return result; }
Result makeEqual(FixedBits& a, FixedBits& b, unsigned from, unsigned to) { assert(to >= from); assert(from <= a.getWidth()); assert(from <= b.getWidth()); Result result = NO_CHANGE; for (unsigned i = from; i < to; i++) { if (a.isFixed(i) && !b.isFixed(i)) { b.setFixed(i, true); b.setValue(i, a.getValue(i)); result = CHANGED; } else if (b.isFixed(i) && !a.isFixed(i)) { a.setFixed(i, true); a.setValue(i, b.getValue(i)); result = CHANGED; } else if (b.isFixed(i) && a.isFixed(i)) { if (a.getValue(i) != b.getValue(i)) return CONFLICT; } } return result; }
// if output bit is true. Fix all the operands. // if all the operands are fixed. Fix the output. // given 1,1,1,- == 0, fix - to 0. Result bvAndBothWays(vector<FixedBits*>& operands, FixedBits& output) { Result result = NO_CHANGE; const int bitWidth = output.getWidth(); for (int i = 0; i < bitWidth; i++) { const stats status = getStats(operands, i); // output is fixed to one. But an input value is false! if (output.isFixed(i) && output.getValue(i) && status.fixedToZero > 0) return CONFLICT; // output is fixed to one. But an input value is false! if (output.isFixed(i) && !output.getValue(i) && status.fixedToZero == 0 && status.unfixed == 0) return CONFLICT; // output is fixed to one. So all should be one. if (output.isFixed(i) && output.getValue(i) && status.unfixed > 0) { fixUnfixedTo(operands, i, true); result = CHANGED; } // The output is unfixed. At least one input is false. if (!output.isFixed(i) && status.fixedToZero > 0) { output.setFixed(i, true); output.setValue(i, false); result = CHANGED; } // Everything is fixed to one! if (!output.isFixed(i) && status.fixedToZero == 0 && status.unfixed == 0) { output.setFixed(i, true); output.setValue(i, true); result = CHANGED; } // If the output is false, and there is a single unfixed value with // everything else true.. if (output.isFixed(i) && !output.getValue(i) && status.fixedToZero == 0 && status.unfixed == 1) { fixUnfixedTo(operands, i, false); result = CHANGED; } } return result; }
Result bvExtractBothWays(vector<FixedBits*>& children, FixedBits& output) { const size_t numberOfChildren = children.size(); const unsigned outputBitWidth = output.getWidth(); Result result = NO_CHANGE; assert(3 == numberOfChildren); unsigned top = children[1]->getUnsignedValue(); unsigned bottom = children[2]->getUnsignedValue(); FixedBits& input = *(children[0]); assert(top >= bottom); assert(top - bottom + 1 == outputBitWidth); assert(top < input.getWidth()); for (unsigned outputPosition = 0; outputPosition < outputBitWidth; outputPosition++) { unsigned inputPosition = outputPosition + bottom; if (input.isFixed(inputPosition) && output.isFixed(outputPosition)) if (input.getValue(inputPosition) ^ output.getValue(outputPosition)) return CONFLICT; if (input.isFixed(inputPosition) ^ output.isFixed(outputPosition)) { if (input.isFixed(inputPosition)) { output.setFixed(outputPosition, true); output.setValue(outputPosition, input.getValue(inputPosition)); result = CHANGED; } else { input.setFixed(inputPosition, true); input.setValue(inputPosition, output.getValue(outputPosition)); result = CHANGED; } } } // cerr << "extract[" << top << ":" << bottom << "]" << input << "=" << // output<< endl; return result; }
Result bvSignExtendBothWays(vector<FixedBits*>& children, FixedBits& output) { assert(children.size() == 2); // The second argument is a junk size arugment. FixedBits& input = *children[0]; const int inputBitWidth = input.getWidth(); const int outputBitWidth = output.getWidth(); assert(inputBitWidth <= outputBitWidth); Result result = makeEqual(input, output, 0, inputBitWidth); if (CONFLICT == result) return CONFLICT; // If any of the topmost bits of the output are fixed. Then they all should // be. // They should all be fixed to the same value. bool found = false; bool setTo; for (int i = inputBitWidth - /**/ 1 /**/; i < outputBitWidth; i++) { if (output.isFixed(i)) { setTo = output.getValue(i); found = true; break; } } if (found) { for (int i = inputBitWidth - 1; i < outputBitWidth; i++) { if (output.isFixed(i) && (output.getValue(i) != setTo)) return CONFLICT; // if any are set to the wrong value! bad. else if (!output.isFixed(i)) { output.setFixed(i, true); output.setValue(i, setTo); result = CHANGED; } } Result result2 = makeEqual(input, output, 0, inputBitWidth); if (CONFLICT == result2) return CONFLICT; } return result; }
Result bvZeroExtendBothWays(vector<FixedBits*>& children, FixedBits& output) { assert(children.size() == 2); // The second argument is a junk size arugment. FixedBits& input = *children[0]; const int inputBitWidth = input.getWidth(); const int outputBitWidth = output.getWidth(); Result result = makeEqual(input, output, 0, inputBitWidth); if (CONFLICT == result) return CONFLICT; // Fix all the topmost bits of the output to zero. for (int i = inputBitWidth; i < outputBitWidth; i++) { if (output.isFixed(i) && output.getValue(i)) return CONFLICT; // set to one. Never right. else if (!output.isFixed(i)) { output.setFixed(i, true); output.setValue(i, false); result = CHANGED; } } return result; }
void setUnsignedMinMax(const FixedBits& v, CBV min, CBV max) { CONSTANTBV::BitVector_Fill(max); CONSTANTBV::BitVector_Empty(min); for (unsigned i = 0; i < v.getWidth(); i++) { if (v.isFixed(i)) { if (v.getValue(i)) // if it's on. It's on. { // CONSTANTBV::BitVector_Bit_On(max, i); CONSTANTBV::BitVector_Bit_On(min, i); } else { CONSTANTBV::BitVector_Bit_Off(max, i); // CONSTANTBV::BitVector_Bit_Off(min, i); } } // else // not fixed. Just set the max. //{ // CONSTANTBV::BitVector_Bit_On(max, i); // CONSTANTBV::BitVector_Bit_Off(min, i); //} } assert(CONSTANTBV::BitVector_Lexicompare(min, max) <= 0); }
// If the bits are totally fixed, then return a new matching ASTNode. ASTNode bitsToNode(const ASTNode& node, const FixedBits& bits) { ASTNode result; STPMgr & beev = *node.GetSTPMgr(); assert (bits.isTotallyFixed()); assert (!node.isConstant()); // Peformance. Shouldn't waste time calling it on constants. if (node.GetType() == BOOLEAN_TYPE) { if (bits.getValue(0)) { result = beev.CreateNode(TRUE); } else { result = beev.CreateNode(FALSE); } } else if (node.GetType() == BITVECTOR_TYPE) { result = beev.CreateBVConst(bits.GetBVConst(), node.GetValueWidth()); } else FatalError("sadf234s"); assert(result.isConstant()); return result; }
Result bvXorBothWays(vector<FixedBits*>& operands, FixedBits& output) { Result result = NO_CHANGE; const int bitWidth = output.getWidth(); for (int i = 0; i < bitWidth; i++) { const stats status = getStats(operands, i); if (status.unfixed == 0) // if they are all fixed. We know the answer. { bool answer = (status.fixedToOne % 2) != 0; if (!output.isFixed(i)) { output.setFixed(i, true); output.setValue(i, answer); result = CHANGED; } else if (output.getValue(i) != answer) return CONFLICT; } else if (status.unfixed == 1 && output.isFixed(i)) { // If there is just one unfixed, and we have the answer --> We know the // value. bool soFar = ((status.fixedToOne % 2) != 0); if (soFar != output.getValue(i)) { // result needs to be flipped. fixUnfixedTo(operands, i, true); } else fixUnfixedTo(operands, i, false); result = CHANGED; } } return result; }
void setSignedMinMax(FixedBits& v, CBV min, CBV max) { const unsigned int msb = v.getWidth() - 1; for (unsigned i = 0; i < (unsigned)v.getWidth(); i++) { if (v.isFixed(i)) { if (v.getValue(i)) // if it's on. It's on. { CONSTANTBV::BitVector_Bit_On(max, i); CONSTANTBV::BitVector_Bit_On(min, i); } else { CONSTANTBV::BitVector_Bit_Off(max, i); CONSTANTBV::BitVector_Bit_Off(min, i); } } else { if (i != msb) { // not fixed. Make the maximum Maximum. CONSTANTBV::BitVector_Bit_On(max, i); CONSTANTBV::BitVector_Bit_Off(min, i); } else { // except for the msb. Where we reduce the min. CONSTANTBV::BitVector_Bit_On(min, i); CONSTANTBV::BitVector_Bit_Off(max, i); } } } assert(CONSTANTBV::BitVector_Compare(min, max) <= 0); }
Result bvAddBothWays(vector<FixedBits*>& children, FixedBits& output) { const size_t numberOfChildren = children.size(); if (numberOfChildren==2) { return bvAddBothWays(*children[0],*children[1],output); } const unsigned bitWidth = output.getWidth(); for (size_t i = 0; i < numberOfChildren; i++) { assert(children[i]->getWidth() == bitWidth ); } int columnL[bitWidth]; // minimum "" "" int columnH[bitWidth]; // maximum number of true partial products. initialiseColumnCounts(columnL, columnH, bitWidth, numberOfChildren, children); int sumH[bitWidth]; int sumL[bitWidth]; sumL[0] = columnL[0]; sumH[0] = columnH[0]; for (unsigned i = /**/1 /**/; i < (unsigned) bitWidth; i++) { assert((columnH[i] >= columnL[i]) && (columnL[i] >= 0)); sumH[i] = columnH[i] + (sumH[i - 1] / 2); sumL[i] = columnL[i] + (sumL[i - 1] / 2); } // Now the sums counts are all updated. And consistent with each other. bool changed = true; while (changed) { changed = false; // Make sure each column's sum is consistent with the output. for (unsigned i = 0; i < bitWidth; i++) { if (output.isFixed(i)) { int expected = output.getValue(i) ? 1 : 0; // output is true. So the maximum and minimum can only be even. if (sumH[i] % 2 != expected) { sumH[i]--; changed = true; } if (sumL[i] % 2 != expected) { sumL[i]++; changed = true; } if (changed && ((sumH[i] < sumL[i]) || (sumL[i] < 0))) return CONFLICT; } } // update the column counts to make them consistent to the totals. for (unsigned i = /**/0 /**/; i < bitWidth; i++) { if (sumH[i] < columnH[i]) { columnH[i]--; changed = true; if (columnH[i] < columnL[i]) return CONFLICT; } } // Go from low to high making each of the sums consistent. for (unsigned i = /**/1 /**/; i < bitWidth; i++) { assert((columnH[i] >= columnL[i]) && (columnL[i] >= 0)); if (sumH[i] > columnH[i] + (sumH[i - 1] / 2)) { sumH[i] = columnH[i] + (sumH[i - 1] / 2); changed = true; } if (sumL[i] < columnL[i] + (sumL[i - 1] / 2)) { sumL[i] = columnL[i] + (sumL[i - 1] / 2); changed = true; } if (changed && (sumH[i] < sumL[i] || sumL[i] < 0)) return CONFLICT; } // go from high to low, making each of the sums consistent. for (int i = /**/(int)bitWidth - 1 /**/; i >= 1; i--) { if ((sumH[i] == sumL[i])) { stats s = getStats(children, i); if (0 == s.unfixed) { // amount that the prior column needs to contribute. int toContribute = (sumH[i] - s.fixedToOne) * 2; if (sumH[i - 1] > (toContribute + 1)) { changed = true; sumH[i - 1] = toContribute + 1; // plus one because of rounding down. } if (sumL[i - 1] < toContribute) { changed = true; sumL[i - 1] = toContribute; } if (sumH[i - 1] < sumL[i - 1]) { return CONFLICT; } } } } if (add_debug_messages) { std::cerr << "bottom" << std::endl; cerr << "columnL:"; printArray(columnL, bitWidth); cerr << "columnH:"; printArray(columnH, bitWidth); cerr << "sumL:"; printArray(sumL, bitWidth); cerr << "sumH:"; printArray(sumH, bitWidth); } for (unsigned column = 0; column < bitWidth; column++) { if (sumH[column] == sumL[column]) { // (1) If the low and high sum is equal. Then the output is know. bool newResult = (sumH[column] % 2 == 0) ? false : true; if (!output.isFixed(column)) { output.setFixed(column, true); output.setValue(column, newResult); changed = true; } else if (output.isFixed(column) && (output.getValue(column) != newResult)) return CONFLICT; // (2) If this column has some unfixed values. Then we may be able to determine them. Result tempResult; if (0 == column) tempResult = fixIfCanForAddition(children, column, sumH[column], 0, 0); else tempResult = fixIfCanForAddition(children, column, sumH[column], sumL[column - 1] / 2, sumH[column - 1] / 2); if (CONFLICT == tempResult) return CONFLICT; if (CHANGED == tempResult) changed = true; } } } return NOT_IMPLEMENTED; }
// if a==b then fix the result to true. // if a!=b then fix the result to false. Result bvEqualsBothWays(FixedBits& a, FixedBits& b, FixedBits& output) { assert(a.getWidth() == b.getWidth()); assert(1 == output.getWidth()); const int childWidth = a.getWidth(); Result r = NO_CHANGE; bool allSame = true; bool definatelyFalse = false; for (int i = 0; i < childWidth; i++) { // if both fixed if (a.isFixed(i) && b.isFixed(i)) { // And have different values. if (a.getValue(i) != b.getValue(i)) { definatelyFalse = true; break; } else { allSame &= true; continue; } } allSame &= false; } if (definatelyFalse) { if (output.isFixed(0) && output.getValue(0)) { return CONFLICT; } else if (!output.isFixed(0)) { output.setFixed(0, true); output.setValue(0, false); r = CHANGED; } } else if (allSame) { if (output.isFixed(0) && !output.getValue(0)) { return CONFLICT; } else if (!output.isFixed(0)) { output.setFixed(0, true); output.setValue(0, true); r = CHANGED; } } if (output.isFixed(0) && output.getValue(0)) // all should be the same. { for (int i = 0; i < childWidth; i++) { if (a.isFixed(i) && b.isFixed(i)) { if (a.getValue(i) != b.getValue(i)) { return CONFLICT; } } else if (a.isFixed(i) != b.isFixed(i)) // both same but only one is fixed. { if (a.isFixed(i)) { b.setFixed(i, true); b.setValue(i, a.getValue(i)); r = CHANGED; } else { a.setFixed(i, true); a.setValue(i, b.getValue(i)); r = CHANGED; } } } } // if the result is fixed to false, there is a single unspecied value, and all // the rest are the same. Fix it to the opposite. if (output.isFixed(0) && !output.getValue(0)) { int unknown = 0; for (int i = 0; i < childWidth && unknown < 2; i++) { if (!a.isFixed(i)) unknown++; if (!b.isFixed(i)) unknown++; else if (a.isFixed(i) && b.isFixed(i) && a.getValue(i) != b.getValue(i)) { unknown = 10; // hack, don't do the next loop. break; } } if (1 == unknown) { for (int i = 0; i < childWidth; i++) { if (!a.isFixed(i)) { a.setFixed(i, true); a.setValue(i, !b.getValue(i)); r = CHANGED; } if (!b.isFixed(i)) { b.setFixed(i, true); b.setValue(i, !a.getValue(i)); r = CHANGED; } } } } return r; }
// If the guard is fixed, make equal the appropriate input and output. // If one input can not possibly be the output. Then set the guard to make it // the other one. // If both values are the same. Set the output to that value. Result bvITEBothWays(vector<FixedBits*>& children, FixedBits& output) { Result result = NO_CHANGE; assert(3 == children.size()); const int bitWidth = output.getWidth(); FixedBits& guard = *children[0]; FixedBits& c1 = *children[1]; FixedBits& c2 = *children[2]; assert(c1.getWidth() == c2.getWidth()); assert(output.getWidth() == c2.getWidth()); if (guard.isFixed(0) && guard.getValue(0)) { // guard fixed to true. So make (first arg == output) result = makeEqual(output, c1, 0, bitWidth); if (CONFLICT == result) return CONFLICT; } else if (guard.isFixed(0) && !guard.getValue(0)) { result = makeEqual(output, c2, 0, bitWidth); if (CONFLICT == result) return CONFLICT; } else { for (int i = 0; i < bitWidth; i++) { if (c1.isFixed(i) && c2.isFixed(i) && (c1.getValue(i) == c2.getValue(i))) { if (output.isFixed(i) && (output.getValue(i) != c1.getValue(i))) return CONFLICT; if (!output.isFixed(i)) { output.setFixed(i, true); output.setValue(i, c1.getValue(i)); result = CHANGED; } } } } bool changed = false; if (CHANGED == result) changed = true; for (int i = 0; i < bitWidth; i++) { if (output.isFixed(i)) { if (c1.isFixed(i) && (c1.getValue(i) != output.getValue(i))) { // c1 is fixed to a value that's not the same as the output. if (!guard.isFixed(0)) { guard.setFixed(0, true); guard.setValue(0, false); result = bvITEBothWays(children, output); if (CONFLICT == result) return CONFLICT; changed = true; } else if (guard.getValue(0)) return CONFLICT; } if (c2.isFixed(i) && (c2.getValue(i) != output.getValue(i))) { // c2 is fixed to a value that's not the same as the output. if (!guard.isFixed(0)) { guard.setFixed(0, true); guard.setValue(0, true); result = bvITEBothWays(children, output); if (CONFLICT == result) return CONFLICT; changed = true; } else if (!guard.getValue(0)) return CONFLICT; } } } if (result == CONFLICT) return CONFLICT; if (changed) return CHANGED; return result; }
Result bvOrBothWays(vector<FixedBits*>& children, FixedBits& output) { Result r = NO_CHANGE; const int numberOfChildren = children.size(); const int bitWidth = output.getWidth(); for (int i = 0; i < bitWidth; i++) { bool answerKnown = output.isFixed(i); bool answer = false; if (answerKnown) answer = output.getValue(i); int unks = 0; int ones = 0; int zeroes = 0; for (int j = 0; j < numberOfChildren; j++) { assert(output.getWidth() == children[j]->getWidth()); if (!children[j]->isFixed(i)) unks++; else if (children[j]->getValue(i)) ones++; else zeroes++; } if (ones > 0) // Atleast a single one found! { if (answerKnown && !answer) return CONFLICT; if (!answerKnown) { output.setFixed(i, true); output.setValue(i, true); r = CHANGED; } } if (zeroes == numberOfChildren) // all zeroes. { if (answerKnown && answer) return CONFLICT; if (!answerKnown) { r = CHANGED; output.setFixed(i, true); output.setValue(i, false); } } if (answerKnown && !answer) // known false { if (ones > 0) return CONFLICT; // set all the column to false. for (int j = 0; j < numberOfChildren; j++) { if (!children[j]->isFixed(i)) { r = CHANGED; children[j]->setFixed(i, true); children[j]->setValue(i, false); } } } if (unks == 1 && answerKnown && answer && (zeroes == (numberOfChildren - 1))) { // A single unknown, everything else is false. The answer is true. So the // unknown is true. for (int j = 0; j < numberOfChildren; j++) { if (!children[j]->isFixed(i)) { r = CHANGED; children[j]->setFixed(i, true); children[j]->setValue(i, true); } } } } return r; }