const bool createBvPairGate(V3BvNtk* const ntk, const V3GateType& type, const V3NetId& id, const V3NetId& id1, const V3NetId& id2) { assert (isV3PairType(type) || isV3ExtendType(type)); if (ntk->reportMultipleDrivenNet(type, id)) return false; // Extended Gate Type if (isV3ExtendType(type)) { V3NetId ext1 = id1, ext2 = id2; if (isV3ExtendSwapIn(type)) { V3NetId t = ext2; ext2 = ext1; ext1 = t; } if (isV3ExtendInvIn(type)) { ext1.cp ^= 1; ext2.cp ^= 1; } V3NetId id_new = isV3ExtendInvOut(type) ? ntk->createNet(ntk->getNetWidth(id)) : id; assert (V3NetUD != id_new); assert (isV3ExtendInvOut(type) ^ (id == id_new)); if (!createBvPairGate(ntk, getV3ExtendNormal(type), id_new, ext1, ext2)) return false; if (id != id_new) { id_new.cp ^= 1; return createV3BufGate(ntk, id, id_new); } return true; } else { if (type != BV_SHL && type != BV_SHR && type != BV_MERGE) if (ntk->reportNetWidthInconsistency(id1, id2, V3GateTypeStr[type] + " I/O")) return false; if (type == BV_EQUALITY || type == BV_GEQ) { if (ntk->reportUnexpectedNetWidth(id, 1, V3GateTypeStr[type] + " Output")) return false; } else if (type != BV_MERGE) { if (ntk->reportNetWidthInconsistency(id, id1, V3GateTypeStr[type] + " I/O")) return false; if (type != BV_SHL && type != BV_SHR) if (ntk->reportNetWidthInconsistency(id, id2, V3GateTypeStr[type] + " I/O")) return false; } else if (ntk->reportUnexpectedNetWidth(id, ntk->getNetWidth(id1) + ntk->getNetWidth(id2), "BV_MERGE Output")) return false; V3InputVec v3InputVec; v3InputVec.clear(); v3InputVec.push_back(V3NetType(id1)); v3InputVec.push_back(V3NetType(id2)); ntk->setInput(id, v3InputVec); ntk->createGate(type, id); return true; } }
void V3NtkHandler::printNetlist() const { assert (_ntk); V3NetId id = V3NetId::makeNetId(1); V3GateType type; for (uint32_t i = 1; i < _ntk->getNetSize(); ++i, ++id.id) { assert (i == id.id); Msg(MSG_IFO) << "[" << getNetNameOrFormedWithId(id) << "]"; type = _ntk->getGateType(id); Msg(MSG_IFO) << " = " << V3GateTypeStr[type]; if (V3_FF == type || AIG_NODE == type || isV3PairType(type)) Msg(MSG_IFO) << "(.A(" << getNetNameOrFormedWithId(_ntk->getInputNetId(id, 0)) << ")," << " .B(" << getNetNameOrFormedWithId(_ntk->getInputNetId(id, 1)) << "))" << endl; else if (V3_PIO == type || isV3ReducedType(type)) Msg(MSG_IFO) << "(.A(" << getNetNameOrFormedWithId(_ntk->getInputNetId(id, 0)) << "))" << endl; else if (BV_MUX == type) Msg(MSG_IFO) << "(.F(" << getNetNameOrFormedWithId(_ntk->getInputNetId(id, 0)) << ")," << " .T(" << getNetNameOrFormedWithId(_ntk->getInputNetId(id, 1)) << ")," << " .S(" << getNetNameOrFormedWithId(_ntk->getInputNetId(id, 2)) << "))" << endl; else if (BV_SLICE == type) Msg(MSG_IFO) << "(.A(" << getNetNameOrFormedWithId(_ntk->getInputNetId(id, 0)) << "[" << dynamic_cast<V3BvNtk*>(_ntk)->getInputSliceBit(id, true) << " : " << dynamic_cast<V3BvNtk*>(_ntk)->getInputSliceBit(id, false) << "))" << endl; else if (BV_CONST == type) Msg(MSG_IFO) << "(.A(" << (dynamic_cast<V3BvNtk*>(_ntk)->getInputConstValue(id)) << "))" << endl; else if (V3_MODULE == type) Msg(MSG_IFO) << "(" << _ntk->getModule(id)->getNtkRef()->getNtkName() << ")" << endl; else Msg(MSG_IFO) << endl; } }
// Ntk Reconstruction Functions void V3Ntk::replaceFanin(const V3RepIdHash& repIdHash) { //cerr << "called replaceFanin" << endl; assert (repIdHash.size()); uint32_t i, inSize; V3GateType type; V3RepIdHash::const_iterator it; for (V3NetId id = V3NetId::makeNetId(1); id.id < _inputData.size(); ++id.id) { type = getGateType(id); if (V3_MODULE == type) { V3NtkModule* const module = getModule(_inputData[id.id][0].value); assert (module); for (i = 0; i < module->getInputList().size(); ++i) { it = repIdHash.find(module->getInputList()[i].id); if (repIdHash.end() == it) continue; module->updateInput(i, module->getInputList()[i].cp ? ~(it->second) : it->second); } } else { inSize = (AIG_NODE == type || isV3PairType(type)) ? 2 : (BV_MUX == type) ? 3 : (V3_FF == type || BV_SLICE == type || isV3ReducedType(type)) ? 1 : 0; for (i = 0; i < inSize; ++i) { it = repIdHash.find(_inputData[id.id][i].id.id); if (repIdHash.end() == it) continue; //cout << "replacing : " << id.id << "'s input\n"; _inputData[id.id][i] = V3NetType(_inputData[id.id][i].id.cp ? ~(it->second) : it->second); } } } }
const bool V3Ntk::reportUnexpectedFaninSize(const V3GateType& type, const V3NetId& id) const { assert (type < V3_XD); assert (validNetId(id)); if (((isV3ReducedType(type) || BV_CONST == type || V3_PIO == type) && (getInputNetSize(id) != 1)) || ((isV3PairType(type) || AIG_NODE == type || V3_FF == type || BV_SLICE == type) && (getInputNetSize(id) != 2)) || ((BV_MUX == type) && (getInputNetSize(id) != 3)) || ((V3_MODULE == type) && (getInputNetSize(id) != 1))) Msg(MSG_ERR) << "Expecting Fanin Size is One while " << getInputNetSize(id) << " is Found @ " << id.id << " for Gate Type = " << V3GateTypeStr[type] << endl; else return false; return true; }
const uint32_t reportCombinationalLoops(V3Ntk* const ntk) { assert (ntk); V3UI32Vec levelData; computeLevel(ntk, levelData); V3Vec<V3PairType>::Vec netLoop; netLoop.clear(); V3GateType type; uint32_t j = 0; for (V3NetId id = V3NetId::makeNetId(0); id.id < ntk->getNetSize(); ++id.id) { type = ntk->getGateType(id); assert (V3_XD > type); if (V3NtkUD == levelData[id.id]) continue; // Unreachable net else if (V3_MODULE >= type || BV_CONST == type || AIG_FALSE == type) continue; const uint32_t inSize = (type == AIG_NODE || isV3PairType(type)) ? 2 : (BV_MUX == type) ? 3 : (isV3ReducedType(type) || BV_SLICE == type) ? 1 : 0; for (uint32_t i = 0; i < inSize; ++i) { if (levelData[id.id] > levelData[ntk->getInputNetId(id, i).id]) continue; // Report Combinational Loops netLoop.clear(); netLoop.push_back(V3PairType(id.id, i)); ++j; if (reportCombinationalLoops(ntk, ntk->getInputNetId(id, i), levelData, netLoop)) { Msg(MSG_IFO) << "Combinational Loop " << j << " : " << endl; uint32_t k = netLoop.size(); while (k--) { Msg(MSG_IFO) << netLoop[k].bus[0] << "[" << netLoop[k].bus[1] << "] --> "; } Msg(MSG_IFO) << netLoop.back().bus[0] << endl; } else Msg(MSG_ERR) << "Unknown Combinational Loop Starting from " << id.id << "[" << i << "] ..." << endl; } } return j; }
// General Ntk Topology Validation Functions for V3 Ntk const bool reportCombinationalLoops(V3Ntk* const ntk, const V3NetId& id, const V3UI32Vec levelData, V3Vec<V3PairType>::Vec& netLoop) { assert (ntk); assert (1 == netLoop.size()); assert (id.id < ntk->getNetSize()); if (id.id == netLoop[0].bus[0]) return true; assert (V3NtkUD != levelData[id.id]); const V3GateType type = ntk->getGateType(id); assert (V3_XD > type); if (V3_MODULE > type || BV_CONST == type || AIG_FALSE == type) return false; else if (V3_MODULE == type) { V3NtkModule* const moduleNtk = ntk->getModule(id); assert (moduleNtk); const V3NetVec& inputs = moduleNtk->getInputList(); for (uint32_t i = 0; i < inputs.size(); ++i) { if (!reportCombinationalLoops(ntk, inputs[i], levelData, netLoop)) continue; netLoop.push_back(V3PairType(id.id, i)); return true; } } else { const uint32_t inSize = (type == AIG_NODE || isV3PairType(type)) ? 2 : (BV_MUX == type) ? 3 : (isV3ReducedType(type) || BV_SLICE == type) ? 1 : 0; for (uint32_t i = 0; i < inSize; ++i) { if (levelData[id.id] <= levelData[ntk->getInputNetId(id, i).id]) continue; if (!reportCombinationalLoops(ntk, ntk->getInputNetId(id, i), levelData, netLoop)) continue; netLoop.push_back(V3PairType(id.id, i)); return true; } } return false; }
const V3NetId dfsBuildNtkFromQuteRTL(V3NtkInput* const quteHandler, CktOutPin* const OutPin, const bool& a2s) { assert (quteHandler); assert (OutPin); // Check if OutPin Already Exists const string name = quteGetOutPinName(OutPin); assert (name.size()); V3NetId id = quteHandler->getNetId(name); if (V3NetUD != id) return id; // Get OutPin Info CktCell* const cell = quteGetCellFromPin(OutPin); assert (cell); const QuteRTL_API_CellType type = quteGetCellType(cell); assert (type < QUTE_TOTAL_CELL); assert (type != QUTE_PI_CELL && type != QUTE_PO_CELL && type != QUTE_PIO_CELL && type != QUTE_DFF_CELL); // Create V3NetId for OutPin if (QUTE_MODULE_CELL != type) { id = quteHandler->createNet(name, getOutPinWidthFromQuteRTL(name, OutPin)); if (V3NetUD == id) return id; } // Compute V3 Gate Type According to QuteRTL Cell Type V3BvNtk* const ntk = dynamic_cast<V3BvNtk*>(quteHandler->getNtk()); assert (ntk); bool invert = false, exactTwo = false; V3GateType v3Type; switch (type) { // Single Input : Reduced case QUTE_RED_AND_CELL : v3Type = BV_RED_AND; break; case QUTE_RED_OR_CELL : v3Type = BV_RED_OR; break; case QUTE_RED_NAND_CELL : v3Type = BV_RED_AND; invert = true; break; case QUTE_RED_NOR_CELL : v3Type = BV_RED_OR; invert = true; break; case QUTE_RED_XOR_CELL : v3Type = BV_RED_XOR; break; case QUTE_RED_XNOR_CELL : v3Type = BV_RED_XOR; invert = true; break; // Single Input : Logic case QUTE_BUF_CELL : v3Type = BV_BUF; break; case QUTE_INV_CELL : v3Type = BV_BUF; invert = true; break; // One+ Input : Logic case QUTE_AND_CELL : v3Type = BV_AND; break; case QUTE_OR_CELL : v3Type = BV_OR; break; case QUTE_NAND_CELL : v3Type = BV_AND; invert = true; break; case QUTE_NOR_CELL : v3Type = BV_OR; invert = true; break; case QUTE_XOR_CELL : v3Type = BV_XOR; break; case QUTE_XNOR_CELL : v3Type = BV_XOR; invert = true; break; // One+ Input : Arithmetic case QUTE_ADD_CELL : v3Type = BV_ADD; break; case QUTE_SUB_CELL : v3Type = BV_SUB; break; case QUTE_MULT_CELL : v3Type = BV_MULT; break; case QUTE_DIV_CELL : v3Type = BV_DIV; break; case QUTE_MODULO_CELL : v3Type = BV_MODULO; break; // One+ Input : Model case QUTE_MERGE_CELL : v3Type = BV_MERGE; break; // Two Inputs : Arithmetic case QUTE_SHL_CELL : v3Type = BV_SHL; break; case QUTE_SHR_CELL : v3Type = BV_SHR; break; // Two Inputs : Comparator case QUTE_EQUALITY_CELL : v3Type = BV_EQUALITY; exactTwo = true; break; case QUTE_GEQ_CELL : v3Type = BV_GEQ; exactTwo = true; break; case QUTE_GREATER_CELL : v3Type = BV_GREATER; exactTwo = true; break; case QUTE_LEQ_CELL : v3Type = BV_LEQ; exactTwo = true; break; case QUTE_LESS_CELL : v3Type = BV_LESS; exactTwo = true; break; // Multiplexer case QUTE_MUX_CELL : v3Type = BV_MUX; break; // Model case QUTE_CONST_CELL : v3Type = BV_CONST; break; case QUTE_SPLIT_CELL : v3Type = BV_SLICE; break; // Unsupported : Model case QUTE_MEMORY_CELL : Msg(MSG_ERR) << "Memory Exists in RTL Design !!" << endl; return V3NetUD; // Unsupported : Module Instance case QUTE_MODULE_CELL : v3Type = V3_MODULE; break; // Unsupported : Latch case QUTE_DLAT_CELL : Msg(MSG_ERR) << "Latch Exists in RTL Design !!" << endl; return V3NetUD; default : Msg(MSG_ERR) << "Unexpected QuteRTL Cell Type : " << type << endl; return V3NetUD; } // Build V3 Gate V3NetId id1, id2, id3, id4; if (isV3ReducedType(v3Type)) { // REDUCED assert (quteGetCellInputSize(cell) == 1); assert (V3NetUD != id); id1 = dfsBuildNtkFromQuteRTL(quteHandler, quteGetCellInputPin(cell, 0), a2s); if (V3NetUD == id1) return id1; id2 = ntk->createNet(1); if (V3NetUD == id2) return id2; if (!createBvReducedGate(ntk, v3Type, id2, id1)) return V3NetUD; // Matching Output and Input Bit-widths if (ntk->getNetWidth(id) == ntk->getNetWidth(id2)) { if (!createV3BufGate(ntk, id, (invert ? getV3InvertNet(id2) : id2))) return V3NetUD; } else { id3 = ntk->createNet(1); if (V3NetUD == id3) return id3; if (!createV3BufGate(ntk, id3, (invert ? getV3InvertNet(id2) : id2))) return V3NetUD; if (!createIOExtensionGate(ntk, id, id3)) return V3NetUD; } } else if (exactTwo) { // TWO INPUTS assert (quteGetCellInputSize(cell) == 2); assert (V3NetUD != id); assert (!invert); id1 = dfsBuildNtkFromQuteRTL(quteHandler, quteGetCellInputPin(cell, 0), a2s); if (V3NetUD == id1) return id1; id2 = dfsBuildNtkFromQuteRTL(quteHandler, quteGetCellInputPin(cell, 1), a2s); if (V3NetUD == id2) return id2; // Matching Input Bit-widths if (ntk->getNetWidth(id1) > ntk->getNetWidth(id2)) { id2 = createNetExtensionGate(ntk, id2, ntk->getNetWidth(id1)); if (V3NetUD == id2) return id2; } else if (ntk->getNetWidth(id1) < ntk->getNetWidth(id2)) { id1 = createNetExtensionGate(ntk, id1, ntk->getNetWidth(id2)); if (V3NetUD == id1) return id1; } // Matching Output and Input Bit-widths if (1 == ntk->getNetWidth(id)) { if (!createBvPairGate(ntk, v3Type, id, id1, id2)) return V3NetUD; } else { id3 = ntk->createNet(1); if (V3NetUD == id3) return id3; if (!createBvPairGate(ntk, v3Type, id3, id1, id2)) return V3NetUD; if (!createIOExtensionGate(ntk, id, id3)) return V3NetUD; } } else if (BV_MUX == v3Type) { // MULTIPLEXER assert (quteGetCellInputSize(cell) == 3); assert (V3NetUD != id); assert (!invert); id1 = dfsBuildNtkFromQuteRTL(quteHandler, quteGetCellInputPin(cell, 0), a2s); if (V3NetUD == id1) return id1; id2 = dfsBuildNtkFromQuteRTL(quteHandler, quteGetCellInputPin(cell, 1), a2s); if (V3NetUD == id2) return id2; // Matching Input Bit-widths if (ntk->getNetWidth(id1) > ntk->getNetWidth(id2)) { id2 = createNetExtensionGate(ntk, id2, ntk->getNetWidth(id1)); if (V3NetUD == id2) return id2; } else if (ntk->getNetWidth(id1) < ntk->getNetWidth(id2)) { id1 = createNetExtensionGate(ntk, id1, ntk->getNetWidth(id2)); if (V3NetUD == id1) return id1; } id3 = dfsBuildNtkFromQuteRTL(quteHandler, quteGetCellInputPin(cell, 2), a2s); if (V3NetUD == id3) return id3; // Matching Output and Input Bit-widths if (ntk->getNetWidth(id) == ntk->getNetWidth(id1)) { if (!createBvMuxGate(ntk, id, id1, id2, id3)) return V3NetUD; } else { id4 = ntk->createNet(ntk->getNetWidth(id1)); if (V3NetUD == id4) return id4; if (!createBvMuxGate(ntk, id4, id1, id2, id3)) return V3NetUD; if (!createIOExtensionGate(ntk, id, id4)) return V3NetUD; } } else if (BV_SLICE == v3Type) { // SLICE assert (quteGetCellInputSize(cell) == 1); assert (V3NetUD != id); assert (!invert); CktOutPin* inOutPin = quteGetCellInputPin(cell, 0); assert (inOutPin); id1 = dfsBuildNtkFromQuteRTL(quteHandler, inOutPin, a2s); if (V3NetUD == id1) return id1; const uint32_t sliceEnd = quteGetSplitOutPinEnd(OutPin), sliceBegin = quteGetSplitOutPinBegin(OutPin); const uint32_t end = quteGetPinEnd(inOutPin), begin = quteGetPinBegin(inOutPin); if (end >= begin) { assert (sliceEnd <= end); assert (sliceBegin >= begin); // Matching Output and Input Bit-widths if (ntk->getNetWidth(id) == (1 + sliceEnd - sliceBegin)) { if (!createBvSliceGate(ntk, id, id1, sliceEnd - begin, sliceBegin - begin)) return V3NetUD; } else { id2 = ntk->createNet(1 + sliceEnd - sliceBegin); if (V3NetUD == id2) return id2; if (!createBvSliceGate(ntk, id2, id1, sliceEnd - begin, sliceBegin - begin)) return V3NetUD; if (!createIOExtensionGate(ntk, id, id2)) return V3NetUD; } } else { assert (sliceEnd >= end); assert (sliceBegin <= begin); // Matching Output and Input Bit-widths if (ntk->getNetWidth(id) == (1 + sliceBegin - sliceEnd)) { if (!createBvSliceGate(ntk, id, id1, begin - sliceEnd, begin - sliceBegin)) return V3NetUD; } else { id2 = ntk->createNet(1 + sliceBegin - sliceEnd); if (V3NetUD == id2) return id2; if (!createBvSliceGate(ntk, id2, id1, begin - sliceEnd, begin - sliceBegin)) return V3NetUD; if (!createIOExtensionGate(ntk, id, id2)) return V3NetUD; } } } else if (BV_CONST == v3Type) { // CONST assert (quteGetCellInputSize(cell) == 0); assert (V3NetUD != id); assert (!invert); const string value = quteGetConstCellValue(cell); assert (value.size()); // Matching Output and Input Bit-widths V3BitVec bvValue(value.c_str()); if (ntk->getNetWidth(id) == bvValue.size()) { if (!createBvConstGate(ntk, id, value)) return V3NetUD; } else { id2 = ntk->createNet(bvValue.size()); if (V3NetUD == id2) return id2; if (!createBvConstGate(ntk, id2, value)) return V3NetUD; if (!createIOExtensionGate(ntk, id, id2)) return V3NetUD; } } else if (BV_BUF == v3Type) { // BUF / INV assert (quteGetCellInputSize(cell) == 1); assert (V3NetUD != id); id1 = dfsBuildNtkFromQuteRTL(quteHandler, quteGetCellInputPin(cell, 0), a2s); if (V3NetUD == id1) return id1; // Matching Output and Input Bit-widths if (ntk->getNetWidth(id) == ntk->getNetWidth(id1)) { if (!createV3BufGate(ntk, id, (invert ? getV3InvertNet(id1) : id1))) return V3NetUD; } else { id2 = ntk->createNet(ntk->getNetWidth(id1)); if (V3NetUD == id2) return id2; if (!createV3BufGate(ntk, id2, (invert ? getV3InvertNet(id1) : id1))) return V3NetUD; if (!createIOExtensionGate(ntk, id, id2)) return V3NetUD; } } else if (BV_MERGE == v3Type) { // MERGE assert (quteGetCellInputSize(cell) >= 1); assert (V3NetUD != id); id1 = V3NetUD; uint32_t merge_width = 0; for (uint32_t i = 0, j = quteGetCellInputSize(cell); i < j; ++i) { id2 = dfsBuildNtkFromQuteRTL(quteHandler, quteGetCellInputPin(cell, i), a2s); if (V3NetUD == id2) return id2; merge_width += ntk->getNetWidth(id2); assert (merge_width); if (V3NetUD == id1) { id1 = id2; continue; } id3 = ntk->createNet(merge_width); if (V3NetUD == id3) return id3; if (!createBvPairGate(ntk, v3Type, id3, id1, id2)) return V3NetUD; id1 = id3; } // Matching Output and Input Bit-widths if (ntk->getNetWidth(id) == ntk->getNetWidth(id1)) { if (!createV3BufGate(ntk, id, id1)) return V3NetUD; } else { id2 = ntk->createNet(ntk->getNetWidth(id1)); if (V3NetUD == id2) return id2; if (!createV3BufGate(ntk, id2, id1)) return V3NetUD; if (!createIOExtensionGate(ntk, id, id2)) return V3NetUD; } } else if (V3_MODULE == v3Type) { // MODULE // Get Module Instance CktModule* const module = quteGetModuleInstance(cell); assert (module); // Create Output Nets for Module Instance V3NetVec outputs(quteGetCellOutputSize(cell), V3NetUD); assert (V3NetUD == id); assert (outputs.size() == quteGetDesignIoSize(module, QUTE_PO_CELL)); for (uint32_t i = 0; i < outputs.size(); ++i) { CktOutPin* const outputPin = quteGetCellOutputPin(cell, i); if (outputPin) { // Non-Floating Output const string outputName = quteGetOutPinName(outputPin); assert (outputName.size()); assert (V3NetUD == quteHandler->getNetId(outputName)); outputs[i] = quteHandler->createNet(outputName, getOutPinWidthFromQuteRTL(outputName, outputPin)); if (V3NetUD == outputs[i]) return outputs[i]; if (OutPin == outputPin) id = outputs[i]; // Matching Module Output Bit-widths CktCell* const outputCell = quteGetDesignIoCell(module, QUTE_PO_CELL, i); assert (outputCell); assert (1 == quteGetCellOutputSize(outputCell)); assert (quteGetCellOutputPin(outputCell, 0)); if (quteGetPinWidth(quteGetCellOutputPin(outputCell, 0)) != ntk->getNetWidth(outputs[i])) { id1 = ntk->createNet(quteGetPinWidth(quteGetCellOutputPin(outputCell, 0))); if (V3NetUD == id1) return id1; if (!createIOExtensionGate(ntk, outputs[i], id1)) return V3NetUD; outputs[i] = id1; } } else { // Floating Output CktCell* const outputCell = quteGetDesignIoCell(module, QUTE_PO_CELL, i); assert (outputCell); assert (1 == quteGetCellOutputSize(outputCell)); assert (quteGetCellOutputPin(outputCell, 0)); outputs[i] = quteHandler->createNet("", quteGetPinWidth(quteGetCellOutputPin(outputCell, 0))); if (V3NetUD == outputs[i]) return outputs[i]; } } // Collect Input Nets for Module Instance V3NetVec inputs(quteGetCellInputSize(cell), V3NetUD); assert (inputs.size() == quteGetDesignIoSize(module, QUTE_PI_CELL)); for (uint32_t i = 0; i < inputs.size(); ++i) { inputs[i] = dfsBuildNtkFromQuteRTL(quteHandler, quteGetCellInputPin(cell, i), a2s); if (V3NetUD == inputs[i]) return inputs[i]; // Matching Module Input Bit-widths CktCell* const inputCell = quteGetDesignIoCell(module, QUTE_PI_CELL, i); assert (inputCell); assert (1 == quteGetCellOutputSize(inputCell)); assert (quteGetCellOutputPin(inputCell, 0)); if (quteGetPinWidth(quteGetCellOutputPin(inputCell, 0)) != ntk->getNetWidth(inputs[i])) { id1 = ntk->createNet(quteGetPinWidth(quteGetCellOutputPin(inputCell, 0))); if (V3NetUD == id1) return id1; if (!createIOExtensionGate(ntk, id1, inputs[i])) return V3NetUD; inputs[i] = id1; } } // Create Module Instance const V3NetVec oInputs = inputs; // Backup for Clock Signal Identification V3NtkHandler* const moduleHandler = V3QuteRTLHandler(module, a2s, inputs, quteGetModuleInstanceName(cell)); if (!moduleHandler) return V3NetUD; assert (moduleHandler->getNtk()); // Set Clock From Module Instance for (uint32_t i = 0; i < inputs.size(); ++i) { if (V3NetUD != inputs[i]) continue; inputs.erase(inputs.begin() + i); // Remove Clock Signal if (V3NetUD == ntk->getClock()) ntk->createClock(oInputs[i]); else if (oInputs[i] != ntk->getClock()) Msg(MSG_WAR) << "Multiple Clock Domains Found in RTL Design \"" << quteHandler->getNtkName() << "\" !!" << endl; break; } createModule(ntk, inputs, outputs, moduleHandler, false); } else { // ONE+ INPUT assert (quteGetCellInputSize(cell) >= 1); assert (V3NetUD != id); assert (isV3PairType(v3Type) || (BV_OR == v3Type)); id1 = V3NetUD; for (uint32_t i = 0, j = quteGetCellInputSize(cell); i < j; ++i) { id2 = dfsBuildNtkFromQuteRTL(quteHandler, quteGetCellInputPin(cell, i), a2s); if (V3NetUD == id2) return id2; //if (BV_ADD == v3Type || BV_SUB == v3Type) { // id2 = createNetExtensionGate(ntk, id2, 1 + ntk->getNetWidth(id2)); if (V3NetUD == id2) return id2; } //else if (BV_MULT == v3Type) { // id2 = createNetExtensionGate(ntk, id2, ntk->getNetWidth(id2) << 1); if (V3NetUD == id2) return id2; } if (V3NetUD == id1) { id1 = id2; continue; } // Matching Input Bit-widths if (ntk->getNetWidth(id1) > ntk->getNetWidth(id2)) { id2 = createNetExtensionGate(ntk, id2, ntk->getNetWidth(id1)); if (V3NetUD == id2) return id2; } else if (ntk->getNetWidth(id1) < ntk->getNetWidth(id2)) { id1 = createNetExtensionGate(ntk, id1, ntk->getNetWidth(id2)); if (V3NetUD == id1) return id1; } //if (BV_SHL == v3Type) { // id1 = createNetExtensionGate(ntk, id1, ntk->getNetWidth(id1) + ntk->getNetWidth(id2)); // if (V3NetUD == id1) return id1; // id2 = createNetExtensionGate(ntk, id2, ntk->getNetWidth(id1)); // if (V3NetUD == id2) return id2; //} id3 = ntk->createNet(ntk->getNetWidth(id1)); if (V3NetUD == id3) return id3; if (!createBvPairGate(ntk, v3Type, id3, id1, id2)) return V3NetUD; id1 = id3; } if (invert) { id3 = ntk->createNet(1); if (V3NetUD == id3) return id3; if (!createV3BufGate(ntk, id3, ~id1)) return V3NetUD; id1 = id3; } // Reset Bit-Width for Internal Output Signal if (quteIsInternalName(name)) ntk->resetNetWidth(id, ntk->getNetWidth(id1)); // Matching Output and Input Bit-widths if (ntk->getNetWidth(id) == ntk->getNetWidth(id1)) { if (!createV3BufGate(ntk, id, id1)) return V3NetUD; } else { id2 = ntk->createNet(ntk->getNetWidth(id1)); if (V3NetUD == id2) return id2; if (!createV3BufGate(ntk, id2, id1)) return V3NetUD; if (!createIOExtensionGate(ntk, id, id2)) return V3NetUD; } } // Return V3NetId for OutPin return id; }
const string V3NtkHandler::getNetRecurExpression(const V3NetId& id) const { assert (_ntk); assert (id.id < _ntk->getNetSize()); string name = ""; const V3GateType& type = _ntk->getGateType(id); assert (V3_XD > type); if (V3_FF >= type) return (id.cp ? V3AuxNameInvPrefix : "") + v3Int2Str(id.id); else if (V3_MODULE == type) { Msg(MSG_WAR) << "Currently Expression Over Module Instances has NOT Been Implemented !!" << endl; } else { if (dynamic_cast<V3BvNtk*>(_ntk)) { assert (AIG_FALSE < type); if (isV3PairType(type)) { const string name1 = getNetExpression(_ntk->getInputNetId(id, 0)); assert (name1.size()); const string name2 = getNetExpression(_ntk->getInputNetId(id, 1)); assert (name2.size()); if (BV_MERGE == type) name = "{" + name1 + ", " + name2 + "}"; else { switch (type) { case BV_AND : name = "(" + name1 + " & " + name2 + ")"; break; case BV_XOR : name = "(" + name1 + " ^ " + name2 + ")"; break; case BV_ADD : name = "(" + name1 + " + " + name2 + ")"; break; case BV_SUB : name = "(" + name1 + " - " + name2 + ")"; break; case BV_MULT : name = "(" + name1 + " * " + name2 + ")"; break; case BV_SHL : name = "(" + name1 + " << " + name2 + ")"; break; case BV_SHR : name = "(" + name1 + " >> " + name2 + ")"; break; case BV_DIV : name = "(" + name1 + " / " + name2 + ")"; break; case BV_MODULO : name = "(" + name1 + " % " + name2 + ")"; break; case BV_EQUALITY : return "(" + name1 + (id.cp ? " != " : " == ") + name2 + ")"; case BV_GEQ : return "(" + name1 + (id.cp ? " < " : " >= ") + name2 + ")"; default : assert (0); } } } else if (isV3ReducedType(type)) { const string name1 = getNetExpression(_ntk->getInputNetId(id, 0)); assert (name1.size()); switch (type) { case BV_RED_AND : name = "(&(" + name1 + "))"; break; case BV_RED_OR : name = "(|(" + name1 + "))"; break; case BV_RED_XOR : name = "(^(" + name1 + "))"; break; default : assert (0); } } else if (BV_MUX == type) { const string fName = getNetExpression(_ntk->getInputNetId(id, 0)); assert (fName.size()); const string tName = getNetExpression(_ntk->getInputNetId(id, 1)); assert (tName.size()); const string sName = getNetExpression(_ntk->getInputNetId(id, 2)); assert (sName.size()); name = "(" + sName + " ? " + tName + " : " + fName + ")"; } else if (BV_SLICE == type) { const string name1 = getNetExpression(_ntk->getInputNetId(id, 0)); assert (name1.size()); const uint32_t msb = dynamic_cast<V3BvNtk*>(_ntk)->getInputSliceBit(id, true); const uint32_t lsb = dynamic_cast<V3BvNtk*>(_ntk)->getInputSliceBit(id, false); const uint32_t width = _ntk->getNetWidth(_ntk->getInputNetId(id, 0)); assert (width); name = ((msb >= lsb) && (width == (1 + msb - lsb))) ? name1 : (msb == lsb) ? ("(" + name1 + ")[" + v3Int2Str(msb) + "]") : ("(" + name1 + ")[" + v3Int2Str(msb) + ":" + v3Int2Str(lsb) + "]"); } else { assert (BV_CONST == type); const V3BitVecX value = dynamic_cast<V3BvNtk*>(_ntk)->getInputConstValue(id); return v3Int2Str(value.size()) + "'b" + value.regEx(); } } else { assert (AIG_FALSE >= type); if (AIG_NODE == type) { const string name1 = getNetExpression(_ntk->getInputNetId(id, 0)); assert (name1.size()); const string name2 = getNetExpression(_ntk->getInputNetId(id, 1)); assert (name2.size()); name = "(" + name1 + " && " + name2 + ")"; } else { assert (AIG_FALSE == type); return (id.cp ? "AIGER_TRUE" : "AIGER_FALSE"); } } } return (id.cp ? V3AuxNameInvPrefix : "") + name; }