// UMINUS, is NEG followed by +1 Result bvUnaryMinusBothWays(vector<FixedBits*>& children, FixedBits& output) { assert(children.size() == 1); const int bitWidth = children[0]->getWidth(); // If it's only one bit. This will be negative one. FixedBits one(bitWidth, false); one.fixToZero(); one.setFixed(0, true); one.setValue(0, true); FixedBits notted(bitWidth, false); vector<FixedBits*> args; args.push_back(¬ted); args.push_back(&one); Result result = NO_CHANGE; while (true) // until it fixed points { FixedBits initialNot(notted); FixedBits initialIn(*children[0]); FixedBits initialOut(output); result = bvNotBothWays(*children[0], notted); if (CONFLICT == result) return CONFLICT; result = bvAddBothWays(args, output); if (CONFLICT == result) return CONFLICT; if (FixedBits::equals(initialNot, notted) && FixedBits::equals(initialIn, *children[0]) && FixedBits::equals(initialOut, output)) break; } return NOT_IMPLEMENTED; // don't set the status properly yet.. }
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; }