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 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; }
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 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; }
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); }
void setValue(FixedBits& a, const int i, bool v) { if (a.isFixed(i)) return; a.setFixed(i,true); a.setValue(i,v); }
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; }
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; }
// 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; }
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; }
// Specialisation for two operands. Result bvAddBothWays(FixedBits& x, FixedBits& y, FixedBits& output) { const int bitWidth = output.getWidth(); FixedBits carry(bitWidth + 1, false); carry.setFixed(0, true); carry.setValue(0, false); //cerr << "input" << x << y << output << endl; for (int i = 0; i < bitWidth; i++) { //cerr << i << ":"<< x[i] << y[i] << carry[i] << "=" << output[i]<< endl; int lb = (x[i] == '1' ? 1 : 0) + (y[i] == '1' ? 1 : 0) + (carry[i] == '1' ? 1 : 0); int ub = (x[i] == '0' ? 0 : 1) + (y[i] == '0' ? 0 : 1) + (carry[i] == '0' ? 0 : 1); const int lb_initial = lb; const int ub_initial = ub; if (carry[i+1] == '1') // carry out is true. lb = std::max(2, lb); if (carry[i+1] == '0') // carry out is false. ub = std::min(1, ub); const char output_i = output[i]; if (output_i == '1' && (lb % 2 == 0)) lb++; if (output_i == '0' && (lb % 2 == 1)) lb++; if (output_i == '1' && (ub % 2 == 0)) ub--; if (output_i == '0' && (ub % 2 == 1)) ub--; if (lb >= 2) setValue(carry, i+1, true); if (ub <= 1) setValue(carry, i+1, false); if (ub < lb) return CONFLICT; if (lb == ub) { setValue(output, i, ((lb % 2) == 1)); if (lb_initial ==lb) { if (!x.isFixed(i)) setValue(x, i, false); if (!y.isFixed(i)) setValue(y, i, false); if (!carry.isFixed(i)) { setValue(carry, i, false); i = std::max(i-2,-1); // go back to the prior column. continue; } } if (ub_initial ==lb) { if (!x.isFixed(i)) setValue(x, i, true); if (!y.isFixed(i)) setValue(y, i, true); if (!carry.isFixed(i)) { setValue(carry, i, true); i = std::max(i-2,-1); // go back to the prior column. continue; } } } //cerr << i << "[" << ub << ":" << lb << "]" << endl; } return NOT_IMPLEMENTED; }
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; }
// 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 bvImpliesBothWays(vector<FixedBits*>& children, FixedBits& result) { FixedBits& a = (*children[0]); FixedBits& b = (*children[1]); assert(a.getWidth() == result.getWidth()); const int bitWidth = a.getWidth(); assert(bitWidth == 1); Result r = NO_CHANGE; int i = 0; // (false -> something) is always true. // (something -> true ) is always true. if (a.isFixedToZero(i) || b.isFixedToOne(i)) { if (!result.isFixed(i)) { result.setFixed(i, true); result.setValue(i, true); r = CHANGED; } else if (result.isFixedToZero(i)) return CONFLICT; } // If the result is false. it must be (true -> false) if (result.isFixedToZero(i)) { if (a.isFixedToZero(i) || b.isFixedToOne(i)) return CONFLICT; if (!a.isFixed(i)) { a.setFixed(i, true); a.setValue(i, true); r = CHANGED; } if (!b.isFixed(i)) { b.setFixed(i, true); b.setValue(i, false); r = CHANGED; } } if (result.isFixedToOne(i)) { if (a.isFixedToOne(i)) { if (!b.isFixed(i)) { b.setFixed(i, true); b.setValue(i, true); r = CHANGED; } else if (b.isFixedToZero(i)) return CONFLICT; } if (b.isFixedToZero(i)) { if (!a.isFixed(i)) { a.setFixed(i, true); a.setValue(i, false); r = CHANGED; } } } if (a.isFixedToOne(i) && b.isFixedToZero(i)) { if (result.isFixedToOne(i)) return CONFLICT; if (!result.isFixed(i)) { result.setFixed(i, true); result.setValue(i, false); r = CHANGED; } } return r; }