// Renaming Functions void V3NtkHandler::setAuxRenaming() { V3AuxHierSeparator = "_v3_hier_"; V3AuxNameInvPrefix = "v3_inv_"; V3AuxNameBitPrefix = "_v3_slice_"; V3AuxNameBitSuffix = ""; V3AuxExpansionName = "_v3_expand_at_"; V3AuxNetNamePrefix = "v3_" + v3Int2Str(time(NULL)) + "_"; }
// General Utilities for the Construction of Bit-Width Matching Ntk const V3NetId createNetExtensionGate(V3BvNtk* const ntk, const V3NetId& id, const uint32_t& width) { assert (ntk); assert (id.id < ntk->getNetSize()); assert (width > ntk->getNetWidth(id)); const uint32_t ext = width - ntk->getNetWidth(id); const V3NetId id1 = ntk->createNet(ext); assert (V3NetUD != id1); if (!createBvConstGate(ntk, id1, v3Int2Str(ext) + "'b" + string(ext, '0'))) return V3NetUD; const V3NetId id2 = ntk->createNet(width); assert (V3NetUD != id2); if (!createBvPairGate(ntk, BV_MERGE, id2, id1, id)) return V3NetUD; return id2; }
const string V3NtkHandler::getAuxPropertyName() const { const string pNamePrefix = "p"; string pName = ""; uint32_t i = 0; while (true) { pName = pNamePrefix + v3Int2Str(++i); if (!existProperty(pName)) break; } return pName; }
const string V3NtkHandler::getAuxFSMName() const { const string fsmNamePrefix = "fsm"; string fsmName = ""; uint32_t i = 0; while (true) { fsmName = fsmNamePrefix + v3Int2Str(++i); if (!existFSM(fsmName)) break; } assert (isLegalFSMName(fsmName)); return fsmName; }
void V3Handler::printRecurHierarchy(V3NtkHandler* const handler, const uint32_t& maxLevel, const uint32_t& level) const { assert (handler); assert (handler->getNtk()); uint32_t i = 0; for (; i < _ntkHandlerList.size(); ++i) if (handler == _ntkHandlerList[i]) break; const string curPath = "/" + v3Int2Str(i); assert (i < _ntkHandlerList.size()); Msg(MSG_IFO) << setw(5) << left << curPath; if ((!handler->getNtk()->getModuleSize()) || (maxLevel == level)) { Msg(MSG_IFO) << endl; return; } for (i = 0; i < handler->getNtk()->getModuleSize(); ++i) { if (i) for (i = 0; i <= level; ++i) Msg(MSG_IFO) << " "; // setw(5) printRecurHierarchy(handler->getNtk()->getModule(i)->getNtkRef(), maxLevel, 1 + level); } }
const bool createIOExtensionGate(V3BvNtk* const ntk, const V3NetId& id, const V3NetId& id1) { assert (ntk); assert (id.id < ntk->getNetSize()); assert (id1.id < ntk->getNetSize()); assert (ntk->getNetWidth(id) != ntk->getNetWidth(id1)); if (ntk->getNetWidth(id) > ntk->getNetWidth(id1)) { const uint32_t ext = ntk->getNetWidth(id) - ntk->getNetWidth(id1); const V3NetId id2 = ntk->createNet(ext); assert (V3NetUD != id2); if (!createBvConstGate(ntk, id2, v3Int2Str(ext) + "'b" + string(ext, '0'))) return false; return createBvPairGate(ntk, BV_MERGE, id, id2, id1); } assert (ntk->getNetWidth(id) < ntk->getNetWidth(id1)); return createBvSliceGate(ntk, id, id1, ntk->getNetWidth(id) - 1, 0); }
// Ntk for BV Gate Functions const V3BVXId V3BvNtk::hashV3ConstBitVec(const string& input_exp) { V3ConstHash::const_iterator it = _V3ConstHash.find(input_exp); if (it != _V3ConstHash.end()) return it->second; V3BitVecX* const value = new V3BitVecX(input_exp.c_str()); assert (value); const string exp = v3Int2Str(value->size()) + "'" + value->toExp(); if (input_exp != exp) { it = _V3ConstHash.find(exp); if (it != _V3ConstHash.end()) { delete value; return it->second; } } assert (_V3ConstHash.size() == _V3ValueVec.size()); _V3ConstHash.insert(make_pair(exp, _V3ValueVec.size())); _V3ValueVec.push_back(value); return _V3ValueVec.size() - 1; }
// Net Ancestry Functions void V3NtkExpand::getNetName(V3NetId& id, string& name) const { if (V3NetUD == id) return; // Current Network if (!id.cp) { V3NetStrHash::const_iterator it = _netHash.find(id.id); if (it != _netHash.end()) { name = it->second; return; } } // Parent Networks if (_handler) { const V3NetId netId = id; id = getParentNetId(id); _handler->getNetName(id, name); if (!name.size()) return; for (uint32_t i = 0; i < _cycle; ++i) if (netId.id == _p2cMap[i][id.id].id) { name += (V3AuxExpansionName + v3Int2Str(i)); break; } } }
const string V3NtkExpand::getInoutName(const uint32_t& index) const { // Current Network assert (_ntk); if (index >= _ntk->getInoutSize()) return ""; V3NetStrHash::const_iterator it = _netHash.find(_ntk->getInout(index).id); if (it != _netHash.end()) { assert (!_ntk->getInout(index).cp); return it->second; } // Parent Networks string name = ""; if (_handler) { const V3Ntk* const ntk = _handler->getNtk(); assert (ntk); name = _handler->getInoutName(index % ntk->getInoutSize()); if (name.size()) name += (V3AuxExpansionName + v3Int2Str(index / ntk->getInoutSize())); } return name.size() ? name : getNetNameOrFormedWithId(_ntk->getInout(index)); }
const string V3NtkExpand::getOutputName(const uint32_t& index) const { // Current Network assert (_ntk); if (index >= _ntk->getOutputSize()) return ""; V3IdxStrHash::const_iterator it = _outIndexHash.find(index); if (it != _outIndexHash.end()) return it->second; // Parent Networks string name = ""; if (_handler) { const V3Ntk* const ntk = _handler->getNtk(); assert (ntk); name = _handler->getOutputName(index % ntk->getOutputSize()); if (name.size()) name += (V3AuxExpansionName + v3Int2Str(index / ntk->getOutputSize())); } return name; }
void V3BvBlastBv::getNetName(V3NetId& id, string& name) const { if (V3NetUD == id) return; // Current Network if (!id.cp) { V3NetStrHash::const_iterator it = _netHash.find(id.id); if (it != _netHash.end()) { name = it->second; return; } } // Parent Networks if (_handler) { const V3NetId netId = id; id = getParentNetId(id); _handler->getNetName(id, name); if (_handler->getNtk()->getNetSize() <= netId.id && name.size()) name += (V3AuxNameBitPrefix + v3Int2Str(getParentIndex(netId)) + V3AuxNameBitSuffix); } }
// Net Ancestry Functions const string V3BvBlastBv::getInoutName(const uint32_t& index) const { // Current Network assert (_ntk); if (index >= _ntk->getInoutSize()) return ""; V3NetStrHash::const_iterator it = _netHash.find(_ntk->getInout(index).id); if (it != _netHash.end()) { assert (!_ntk->getInout(index).cp); return it->second; } // Parent Networks string name = ""; if (_handler) { const V3Ntk* const ntk = _handler->getNtk(); assert (ntk); uint32_t i = 0, pIndex = index; for (; i < ntk->getInoutSize(); ++i) if (pIndex < ntk->getNetWidth(ntk->getInout(i))) break; else pIndex -= ntk->getNetWidth(ntk->getInout(i)); name = _handler->getInoutName(i); assert (pIndex < ntk->getNetWidth(ntk->getInout(i))); if (name.size() && 1 < ntk->getNetWidth(ntk->getInout(i))) name += (V3AuxNameBitPrefix + v3Int2Str(pIndex) + V3AuxNameBitSuffix); } return name.size() ? name : getNetNameOrFormedWithId(_ntk->getInout(index)); }
void V3Handler::setCurHandlerFromPath(const string& path) { assert (path.size()); string curPath = path; uint32_t i; // Split Path by '/' V3Vec<string>::Vec idStr; idStr.clear(); while (curPath.size()) { for (i = 0; i < curPath.size(); ++i) if ('/' == curPath[i]) break; if (!i) idStr.push_back(""); else idStr.push_back(curPath.substr(0, i)); if ((i + 1) >= curPath.size()) break; else curPath = curPath.substr(i + 1); } // Copy Current Handler and RefId const uint32_t curHandlerId = _curHandlerId; assert (getHandler(curHandlerId)); V3UI32Vec curRefIdVec = _curRefIdVec; assert (curRefIdVec.size()); V3NtkHandler* handler = 0; bool isRoot = false; int temp; for (i = 0; i < idStr.size(); ++i) { if (handler) { // Expecting Sub-Module Index if (!idStr[i].size()) continue; if (v3Str2Int(idStr[i], temp)) { const uint32_t id = (uint32_t)temp; if (id < handler->getNtk()->getModuleSize()) { handler = handler->getNtk()->getModule(id)->getNtkRef(); uint32_t j = 0; for (; j < _ntkHandlerList.size(); ++j) if (handler == _ntkHandlerList[j]) break; _curHandlerId = j; _curRefIdVec.push_back(id); } else { string recoverPath = ""; for (uint32_t j = 0; j < _curRefIdVec.size(); ++j) recoverPath += ("/" + v3Int2Str(_curRefIdVec[j])); Msg(MSG_ERR) << "Sub-Module of " << recoverPath << " with Index = " << idStr[i] << " Does NOT Exist !!" << endl; return; } } } else { // Expecting NtkID or Location Symbols (/, ./, ~/, .) if (!idStr[i].size()) isRoot = true; else { // Lex if current token is a SubModule Index if (v3Str2Int(idStr[i], temp)) { const uint32_t id = (uint32_t)temp; if (isRoot) { if (id < getHandlerCount()) { handler = getHandler(id); _curHandlerId = id; _curRefIdVec.clear(); _curRefIdVec.push_back(id); } else { Msg(MSG_ERR) << "Ntk with ID = " << idStr[i] << " Does NOT Exist !!" << endl; return; } } else { if (id < getCurHandler()->getNtk()->getModuleSize()) { handler = getCurHandler()->getNtk()->getModule(id)->getNtkRef(); uint32_t j = 0; for (; j < _ntkHandlerList.size(); ++j) if (handler == _ntkHandlerList[j]) break; _curHandlerId = j; _curRefIdVec.push_back(id); } else { string recoverPath = ""; for (uint32_t j = 0; j < _curRefIdVec.size(); ++j) recoverPath += ("/" + v3Int2Str(_curRefIdVec[j])); Msg(MSG_ERR) << "Sub-Module of " << recoverPath << " with Index = " << idStr[i] << " Does NOT Exist !!" << endl; return; } } } else if (idStr[i].size() > 1) { Msg(MSG_ERR) << "Unexpected Symbol \"" << idStr[i] << "\" in the Path !!" << endl; return; } else if ('~' == idStr[i][0]) { const uint32_t baseId = _curHandlerId = _curRefIdVec[0]; handler = getHandler(baseId); _curRefIdVec.clear(); _curRefIdVec.push_back(baseId); } else if ('.' == idStr[i][0]) handler = getCurHandler(); assert (handler); } } } // Copy Data for Last if Valid, Or Resume Data for Current if (_curHandlerId < _ntkHandlerList.size()) { _lastHandlerId = curHandlerId; _lastRefIdVec = curRefIdVec; } else { _curHandlerId = curHandlerId; _curRefIdVec = curRefIdVec; Msg(MSG_ERR) << "Network " << path << " was Implicitly Created and it is Currently Untraceable !!" << endl; } }
// I/O Ancestry Functions const string V3NtkElaborate::getOutputName(const uint32_t& index) const { assert (_ntk); assert (index < _ntk->getOutputSize()); if (index >= _pOutput.size()) return "c_" + v3Int2Str((size_t)(this)) + "_" + v3Int2Str(index); else return "p_" + v3Int2Str((size_t)(_pOutput[index])) + "_" + _pOutput[index]->getName(); }
// Renaming Functions void V3NtkHandler::setAuxRenaming() { V3AuxNameInvPrefix = "v3_Inv_"; V3AuxExpansionName = "v3_expT_"; V3AuxNetNamePrefix = "v3_" + v3Int2Str(time(NULL)) + "_"; }
const string V3NtkHandler::getNetNameOrFormedWithId(const V3NetId& id) const { const string name = getNetName(id); if (name.size()) return name; return (id.cp ? V3AuxNameInvPrefix : "") + V3AuxNetNamePrefix + v3Int2Str(id.id); }
const bool V3QuteRTLFFHandler(V3NtkInput* const quteHandler, CktModule* const module, const bool& async2sync, V3NetVec& inputs) { assert (quteHandler); assert (module); CktCell* cell; CktOutPin* OutPin; uint32_t width; string name; V3NetId id, id1, id2, id3; // Build FF Nets (Renders the Same Order As Design Created by QuteRTL) V3BvNtk* const ntk = dynamic_cast<V3BvNtk*>(quteHandler->getNtk()); assert (ntk); V3NetVec quteFFVec; quteFFVec.clear(); V3Set<string>::Set quteFFClk; quteFFClk.clear(); for (uint32_t i = 0, j = quteGetDesignIoSize(module, QUTE_DFF_CELL); i < j; ++i) { // Get Cell Info from QuteRTL cell = quteGetDesignIoCell(module, QUTE_DFF_CELL, i); assert (cell); assert (quteGetCellOutputSize(cell) == 1); OutPin = quteGetCellOutputPin(cell, 0); assert (OutPin); name = quteGetOutPinName(OutPin); assert (name.size()); // Build DFF in V3 Ntk id = quteHandler->createNet(name, getOutPinWidthFromQuteRTL(name, OutPin)); if (V3NetUD == id) return false; quteFFVec.push_back(id); } // DFS Traverse On DFF Fanin Cone for (uint32_t i = 0, j = quteGetDesignIoSize(module, QUTE_DFF_CELL); i < j; ++i) { // Get Cell Info from QuteRTL cell = quteGetDesignIoCell(module, QUTE_DFF_CELL, i); assert (cell); const uint32_t inPinSize = quteGetCellInputSize(cell); assert (inPinSize >= 2); // Check Clock Signal OutPin = quteGetCellInputPin(cell, 1); assert (OutPin); name = quteGetOutPinExpr(OutPin); assert (name.size()); quteFFClk.insert(name); if (inPinSize > 2) { // Asynchronous Reset DFF : D, clk, reset, default OutPin = quteGetCellInputPin(cell, 0); assert (OutPin); id1 = dfsBuildNtkFromQuteRTL(quteHandler, OutPin, async2sync); if (V3NetUD == id1) return false; OutPin = quteGetCellInputPin(cell, 2); assert (OutPin); id2 = dfsBuildNtkFromQuteRTL(quteHandler, OutPin, async2sync); if (V3NetUD == id2) return false; OutPin = quteGetCellInputPin(cell, 3); assert (OutPin); id3 = dfsBuildNtkFromQuteRTL(quteHandler, OutPin, async2sync); if (V3NetUD == id3) return false; // Build DFF name = quteGetOutPinName(OutPin); assert (name.size()); width = quteHandler->getNtk()->getNetWidth(quteFFVec[i]); if (async2sync) { // Renders all Asynchronous DFF be Regarded as Synchronous DFF // Build MUX id = quteHandler->createNet(V3AsyncMuxName + name, width); if (V3NetUD == id) return false; if (!createBvMuxGate(ntk, id, id1, id3, id2)) return false; // Build DFF id2 = ntk->createNet(width); if (V3NetUD == id2) return false; if (!createBvConstGate(ntk, id2, v3Int2Str(width) + "'d0")) return false; if (!createV3FFGate(ntk, quteFFVec[i], id, id2)) return false; } else { // Retain Asynchronous Behavior in V3 Ntk // Build MUX id = quteHandler->createNet(V3AsyncDFFName + name, width); if (V3NetUD == id) return false; if (!createBvMuxGate(ntk, quteFFVec[i], id, id3, id2)) return false; // Build DFF id2 = ntk->createNet(width); if (V3NetUD == id2) return false; if (!createBvConstGate(ntk, id2, v3Int2Str(width) + "'d0")) return false; if (!createV3FFGate(ntk, id, id1, id2)) return false; } } else { // Synchronous Reset DFF : D, clk // Traverse DFF Input OutPin = quteGetCellInputPin(cell, 0); assert (OutPin); id1 = dfsBuildNtkFromQuteRTL(quteHandler, OutPin, async2sync); if (V3NetUD == id1) return false; // Build DFF width = quteHandler->getNtk()->getNetWidth(quteFFVec[i]); id2 = ntk->createNet(width); if (V3NetUD == id2) return false; if (!createBvConstGate(ntk, id2, v3Int2Str(width) + "'d0")) return false; if (!createV3FFGate(ntk, quteFFVec[i], id1, id2)) return false; } } // Report Multiple Clock Domain if Exists if (quteFFClk.size() > 1) { Msg(MSG_WAR) << "Multiple Clock Domains Found in RTL Design \"" << quteHandler->getNtkName() << "\" !!" << endl; Msg(MSG_IFO) << "Clock Domains (in terms of RTL signal names) are: "; for (V3Set<string>::Set::const_iterator it = quteFFClk.begin(); it != quteFFClk.end(); ++it) Msg(MSG_IFO) << (it == quteFFClk.begin() ? "" : ", ") << (*it); Msg(MSG_IFO) << endl; Msg(MSG_WAR) << "V3 Simply Treat All Clock Domains to be the Same One !!" << endl; } // Set Clock Signal and Remove Clock from Inputs if (V3NetUD == ntk->getClock()) { if (quteFFClk.size()) ntk->createClock(quteHandler->getNetId(*(quteFFClk.begin()))); } else { if (quteFFClk.size() && (ntk->getClock() != quteHandler->getNetId(*(quteFFClk.begin())))) Msg(MSG_WAR) << "Multiple Clock Domains Found in RTL Design \"" << quteHandler->getNtkName() << "\" !!" << endl; } return true; }
const V3NetId V3NtkElaborate::elaborateL2S(const V3NetId& id) { assert (_ntk); assert (_p2cMap.size()); assert (id.id < _ntk->getNetSize()); assert (isMutable()); assert (_shadow.size() == _handler->getNtk()->getLatchSize()); // Create L2S Data Members if NOT Exist V3BvNtk* const bvNtk = dynamic_cast<V3BvNtk*>(_ntk); V3InputVec inputs; inputs.clear(); inputs.reserve(4); if (V3NetUD == _saved || V3NetUD == _1stSave || V3NetUD == _inLoop) { assert (V3NetUD == _saved && V3NetUD == _1stSave && V3NetUD == _inLoop); _saved = _ntk->createNet(1); // Create Latch (_saved) for "In the Loop" const V3NetId oracle = _ntk->createNet(1), inSaved = _ntk->createNet(1); inputs.push_back(~_saved); inputs.push_back(~oracle); _ntk->setInput(inSaved, inputs); _ntk->createGate((bvNtk ? BV_AND : AIG_NODE), inSaved); inputs.clear(); inputs.push_back(~inSaved); inputs.push_back(0); _ntk->setInput(_saved, inputs); _ntk->createLatch(_saved); inputs.clear(); _ntk->createInput(oracle); _1stSave = _ntk->createNet(1); // Create Net (_1stSave) for "Loop Start" inputs.push_back(oracle); inputs.push_back(~_saved); _ntk->setInput(_1stSave, inputs); _ntk->createGate((bvNtk ? BV_AND : AIG_NODE), _1stSave); inputs.clear(); _inLoop = _ntk->createNet(1); // Create Net (_inLoop) for "_1stSave || _saved" inputs.push_back(~_1stSave); inputs.push_back(~_saved); _ntk->setInput(_inLoop, inputs); _ntk->createGate((bvNtk ? BV_AND : AIG_NODE), _inLoop); inputs.clear(); _inLoop = ~_inLoop; } // Create Equivalence Logic and Shadow FF if NOT Exist V3NetId ffId; V3GateType type; V3UI32Vec newShadow; newShadow.clear(); for (uint32_t i = 0; i < _shadow.size(); ++i) { ffId = _p2cMap[_handler->getNtk()->getLatch(i).id]; assert (V3_FF == _ntk->getGateType(ffId)); if (V3NetUD == ffId || V3NetUD != _shadow[i]) continue; newShadow.push_back(i); // Create Net for Shadow FF _shadow[i] = _ntk->createNet(_ntk->getNetWidth(ffId)); assert (V3NetUD != _shadow[i]); V3NetId shadowMux = V3NetUD; // Create Input MUX of Shadow FF if (bvNtk) { inputs.push_back(_shadow[i]); inputs.push_back(ffId); inputs.push_back(_1stSave); type = BV_MUX; shadowMux = elaborateBvGate(bvNtk, type, inputs, _netHash); } else { inputs.push_back(_1stSave); inputs.push_back(ffId); inputs.push_back(~_1stSave); inputs.push_back(_shadow[i]); type = AIG_NODE; shadowMux = elaborateAigAndOrAndGate(_ntk, inputs, _netHash); } // Create Shadow FF assert (V3NetUD != shadowMux); inputs.clear(); inputs.push_back(shadowMux); if (_ntk->getNetWidth(ffId) == 1) inputs.push_back(0); else { V3InputVec constInputs(1, bvNtk->hashV3ConstBitVec(v3Int2Str(_ntk->getNetWidth(ffId)) + "'d0")); type = BV_CONST; inputs.push_back(elaborateBvGate(bvNtk, type, constInputs, _netHash)); } _ntk->setInput(_shadow[i], inputs); _ntk->createLatch(_shadow[i]); inputs.clear(); // Create Equivalence Gate and Update _shadow if (bvNtk) { inputs.push_back(ffId); inputs.push_back(_shadow[i]); type = BV_EQUALITY; _shadow[i] = elaborateBvGate(bvNtk, type, inputs, _netHash); } else { inputs.push_back(ffId); inputs.push_back(_shadow[i]); inputs.push_back(~ffId); inputs.push_back(~_shadow[i]); _shadow[i] = elaborateAigAndOrAndGate(_ntk, inputs, _netHash); } assert (V3NetUD != _shadow[i]); assert (1 == _ntk->getNetWidth(_shadow[i])); inputs.clear(); } // Create or Update Net (_looped) for "Loop Found" if NOT Exist if (V3NetUD == _looped) _looped = _saved; for (uint32_t i = 0; i < newShadow.size(); ++i) { assert (V3NetUD != _p2cMap[_handler->getNtk()->getLatch(i).id]); assert (V3NetUD != _shadow[i]); inputs.push_back(_looped); inputs.push_back(_shadow[i]); if (bvNtk) { type = BV_AND; _looped = elaborateBvGate(bvNtk, type, inputs, _netHash); } else { type = AIG_NODE; _looped = elaborateAigGate(_ntk, type, inputs, _netHash); } assert (V3NetUD != _looped); inputs.clear(); } if (V3NetId::makeNetId(0) == ~id) return _looped; // Create Latch (pLatch) for Recording Existence of Violation to id const V3NetId pLatch = _ntk->createNet(1), in_pLatch = _ntk->createNet(1); inputs.push_back(~pLatch); inputs.push_back(id); _ntk->setInput(in_pLatch, inputs); _ntk->createGate((bvNtk ? BV_AND : AIG_NODE), in_pLatch); inputs.clear(); inputs.push_back(~in_pLatch); inputs.push_back(0); _ntk->setInput(pLatch, inputs); _ntk->createLatch(pLatch); inputs.clear(); // Create L2S Property Output (to Witness "_looped && in_pLatch") V3NetId pId = V3NetUD; inputs.push_back(_looped); inputs.push_back(in_pLatch); if (bvNtk) { type = BV_AND; pId = elaborateBvGate(bvNtk, type, inputs, _netHash); } else { type = AIG_NODE; pId = elaborateAigGate(_ntk, type, inputs, _netHash); } assert (V3NetUD != pId); inputs.clear(); return pId; }
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; }
const V3NetId V3NtkElaborate::elaborateL2S(const V3NetId& id) { assert (_ntk); assert (_p2cMap.size()); assert (id.id < _ntk->getNetSize()); assert (isMutable()); assert (_shadow.size() == _handler->getNtk()->getLatchSize()); // Create L2S Data Members if NOT Exists V3BvNtk* const bvNtk = dynamic_cast<V3BvNtk*>(_ntk); V3InputVec inputs; inputs.clear(); inputs.reserve(4); V3GateType type; if ((V3NetUD == _saved) || (V3NetUD == _1stSave)) { assert ((V3NetUD == _saved) && (V3NetUD == _1stSave)); _saved = _ntk->createNet(1); _1stSave = _ntk->createNet(1); const V3NetId oracle = _ntk->createNet(1), inSaved = _ntk->createNet(1); inputs.push_back(~_saved); inputs.push_back(~oracle); _ntk->setInput(inSaved, inputs); _ntk->createGate((bvNtk ? BV_AND : AIG_NODE), inSaved); inputs.clear(); inputs.push_back(~inSaved); inputs.push_back(0); _ntk->setInput(_saved, inputs); _ntk->createLatch(_saved); inputs.clear(); _ntk->createInput(oracle); // Set Inputs of _1stSave inputs.push_back(oracle); inputs.push_back(~_saved); _ntk->setInput(_1stSave, inputs); _ntk->createGate((bvNtk ? BV_AND : AIG_NODE), _1stSave); inputs.clear(); } // Create Equivalence Logic and Shadow FF if NOT Exists for (uint32_t i = 0; i < _shadow.size(); ++i) { if (V3NetUD == _shadow[i] && V3NetUD != _p2cMap[_handler->getNtk()->getLatch(i).id]) { assert (V3_FF == _ntk->getGateType(_p2cMap[_handler->getNtk()->getLatch(i).id])); _shadow[i] = _ntk->createNet(_ntk->getNetWidth(_p2cMap[_handler->getNtk()->getLatch(i).id])); // Create Input MUX of Shadow FF V3NetId shadowMux = V3NetUD; if (bvNtk) { inputs.push_back(_p2cMap[_handler->getNtk()->getLatch(i).id]); inputs.push_back(_shadow[i]); inputs.push_back(~_1stSave); type = BV_MUX; shadowMux = elaborateBvGate(bvNtk, type, inputs, _netHash); } else { inputs.push_back(_1stSave); inputs.push_back(_p2cMap[_handler->getNtk()->getLatch(i).id]); inputs.push_back(~_1stSave); inputs.push_back(_shadow[i]); type = AIG_NODE; shadowMux = elaborateAigAndOrAndGate(_ntk, inputs, _netHash); } assert (V3NetUD != shadowMux); inputs.clear(); // Create Shadow FF inputs.clear(); inputs.push_back(shadowMux); const uint32_t width = (bvNtk) ? _ntk->getNetWidth(_p2cMap[_handler->getNtk()->getLatch(i).id]) : 1; if (width > 1) { V3InputVec constInputs(1, bvNtk->hashV3ConstBitVec(v3Int2Str(width) + "'d0")); type = BV_CONST; inputs.push_back(elaborateBvGate(bvNtk, type, constInputs, _netHash)); } else inputs.push_back(0); _ntk->setInput(_shadow[i], inputs); _ntk->createLatch(_shadow[i]); inputs.clear(); // Create Equivalence Gate and Update _shadow if (bvNtk) { inputs.push_back(_p2cMap[_handler->getNtk()->getLatch(i).id]); inputs.push_back(_shadow[i]); type = BV_EQUALITY; _shadow[i] = elaborateBvGate(bvNtk, type, inputs, _netHash); } else { inputs.push_back(_p2cMap[_handler->getNtk()->getLatch(i).id]); inputs.push_back(_shadow[i]); inputs.push_back(~_shadow[i]); inputs.push_back(~_p2cMap[_handler->getNtk()->getLatch(i).id]); _shadow[i] = elaborateAigAndOrAndGate(_ntk, inputs, _netHash); } inputs.clear(); assert (V3NetUD != _shadow[i]); } } // Build LTL Formula Output Logic const V3NetId pLatch = _ntk->createNet(1), in_pLatch = _ntk->createNet(1); inputs.push_back(~pLatch); inputs.push_back(~id); _ntk->setInput(in_pLatch, inputs); _ntk->createGate((bvNtk ? BV_AND : AIG_NODE), in_pLatch); inputs.clear(); inputs.push_back(~in_pLatch); inputs.push_back(0); _ntk->setInput(pLatch, inputs); _ntk->createLatch(pLatch); inputs.clear(); // Build LTL Formula Output V3NetId pId = V3NetUD; inputs.push_back(_saved); inputs.push_back(~pLatch); if (bvNtk) { type = BV_AND; pId = elaborateBvGate(bvNtk, type, inputs, _netHash); } else { type = AIG_NODE; pId = elaborateAigGate(_ntk, type, inputs, _netHash); } assert (V3NetUD != pId); inputs.clear(); // Build LTL Formula Output with Related Latches Only _ntk->newMiscData(); dfsRecurMarkFaninCone(_ntk, id); for (uint32_t i = 0; i < _shadow.size(); ++i) { if (V3NetUD == _shadow[i]) continue; if (!_ntk->isLatestMiscData(_p2cMap[_handler->getNtk()->getLatch(i).id])) continue; inputs.push_back(pId); inputs.push_back(_shadow[i]); if (bvNtk) { type = BV_AND; pId = elaborateBvGate(bvNtk, type, inputs, _netHash); } else { type = AIG_NODE; pId = elaborateAigGate(_ntk, type, inputs, _netHash); } assert (V3NetUD != pId); inputs.clear(); } return pId; }