const uint32_t dfsNtkForSimulationOrder(V3Ntk* const ntk, V3NetVec& orderMap, const V3NetVec& targetNets, const bool& allNets) { assert (ntk); V3BoolVec m(ntk->getNetSize(), false); orderMap.clear(); orderMap.reserve(ntk->getNetSize()); // Constants for (uint32_t i = 0; i < ntk->getConstSize(); ++i) orderMap.push_back(ntk->getConst(i)); // (Pseudo) Primary Inputs for (uint32_t i = 0; i < ntk->getInputSize(); ++i) orderMap.push_back(ntk->getInput(i)); for (uint32_t i = 0; i < ntk->getInoutSize(); ++i) orderMap.push_back(ntk->getInout(i)); for (uint32_t i = 0; i < ntk->getLatchSize(); ++i) orderMap.push_back(ntk->getLatch(i)); for (uint32_t i = 0; i < orderMap.size(); ++i) m[orderMap[i].id] = true; // Pseudo Primary Input Initial State Logics for (uint32_t i = 0; i < ntk->getLatchSize(); ++i) dfsSimulationOrder(ntk, ntk->getInputNetId(ntk->getLatch(i), 1), m, orderMap); // Record End of Initial Logic if Needed (e.g. simulator) const uint32_t initEndIndex = orderMap.size(); // (Pseudo) Primary Output Fanin Logics for (uint32_t i = 0; i < ntk->getLatchSize(); ++i) dfsSimulationOrder(ntk, ntk->getInputNetId(ntk->getLatch(i), 0), m, orderMap); for (uint32_t i = 0; i < ntk->getInoutSize(); ++i) dfsSimulationOrder(ntk, ntk->getInputNetId(ntk->getInout(i), 0), m, orderMap); if (targetNets.size()) for (uint32_t i = 0; i < targetNets.size(); ++i) dfsSimulationOrder(ntk, targetNets[i], m, orderMap); else for (uint32_t i = 0; i < ntk->getOutputSize(); ++i) dfsSimulationOrder(ntk, ntk->getOutput(i), m, orderMap); // Put Nets Not in COI into orderMap if (allNets) for (V3NetId id = V3NetId::makeNetId(0); id.id < ntk->getNetSize(); ++id.id) if (!m[id.id]) dfsSimulationOrder(ntk, id, m, orderMap); assert (orderMap.size() <= ntk->getNetSize()); return initEndIndex; }
const bool V3QuteRTLInputHandler(V3NtkInput* const quteHandler, CktModule* const module, V3NetVec& piList) { assert (quteHandler); assert (module); CktCell* cell; CktOutPin* OutPin; V3NetId id; string name; // Store Inputs for Clock Signal Pruning piList.clear(); piList.reserve(quteGetDesignIoSize(module, QUTE_PI_CELL)); // Build Input (Renders the Same Order As Design Created by QuteRTL) V3BvNtk* const ntk = dynamic_cast<V3BvNtk*>(quteHandler->getNtk()); assert (ntk); for (uint32_t i = 0, j = quteGetDesignIoSize(module, QUTE_PI_CELL); i < j; ++i) { // Get Cell Info from QuteRTL cell = quteGetDesignIoCell(module, QUTE_PI_CELL, i); assert (cell); assert (quteGetCellOutputSize(cell) == 1); OutPin = quteGetCellOutputPin(cell, 0); assert (OutPin); name = quteGetOutPinName(OutPin); assert (name.size()); // Build Input in V3 Ntk id = quteHandler->createNet(name, getOutPinWidthFromQuteRTL(name, OutPin)); if (V3NetUD == id) return false; piList.push_back(id); //if (!createInput(ntk, id)) return false; } for (uint32_t i = 0, j = quteGetDesignIoSize(module, QUTE_PIO_CELL); i < j; ++i) { // Get Cell Info from QuteRTL cell = quteGetDesignIoCell(module, QUTE_PIO_CELL, i); assert (cell); assert (quteGetCellOutputSize(cell) == 1); OutPin = quteGetCellOutputPin(cell, 0); assert (OutPin); name = quteGetOutPinName(OutPin); assert (name.size()); // Build Input in V3 Ntk id = quteHandler->createNet(name, getOutPinWidthFromQuteRTL(name, OutPin)); if (V3NetUD == id) return false; if (!createInout(ntk, id)) return false; } return true; }
// General Level Computation Functions for V3 Ntk void dfsComputeLevel(V3Ntk* const ntk, V3NetVec& orderMap, V3UI32Vec& levelData) { assert (ntk); assert (orderMap.size() <= ntk->getNetSize()); assert (levelData.size() == ntk->getNetSize()); // Set Net Levels According to the DFS Order V3NetId id, id1; V3GateType type; uint32_t inSize; for (uint32_t i = 0; i < orderMap.size(); ++i) { id = orderMap[i]; assert (id.id < levelData.size()); if (V3NtkUD != levelData[id.id]) continue; levelData[id.id] = 0; type = ntk->getGateType(id); assert (V3_XD > type); assert (V3_PI == type || V3_FF < type); if (V3_MODULE == type) { V3NtkModule* const moduleNtk = ntk->getModule(id); assert (moduleNtk); const V3NetVec& inputs = moduleNtk->getInputList(); inSize = inputs.size(); while (inSize--) { id1 = inputs[inSize]; assert (V3NtkUD != levelData[id1.id]); if (levelData[id.id] < levelData[id1.id]) levelData[id.id] = levelData[id1.id]; } } else { inSize = ntk->getInputNetSize(id); if (BV_SLICE == type || BV_CONST == type) --inSize; while (inSize--) { id1 = ntk->getInputNetId(id, inSize); assert (V3NtkUD != levelData[id1.id]); if (levelData[id.id] < levelData[id1.id]) levelData[id.id] = levelData[id1.id]; } } ++levelData[id.id]; } }
V3MPDRCube* const V3VrfMPDR::forwardModel(const V3MPDRCube* const curCube) { assert (curCube); if (!curCube->getNextCube()) return 0; // Set Pattern Values for Simulator if (_pdrSize) { const V3BitVecX& inputData = curCube->getInputData(); assert (inputData.size() == _pdrSize); uint32_t j = 0; for (uint32_t i = 0; i < _vrfNtk->getInputSize(); ++i, ++j) _pdrSim->setSource(_vrfNtk->getInput(i), inputData.bv_slice(j, j)); for (uint32_t i = 0; i < _vrfNtk->getInoutSize(); ++i, ++j) _pdrSim->setSource(_vrfNtk->getInout(i), inputData.bv_slice(j, j)); assert (j == inputData.size()); } // Set State Variable Values for Simulator const V3NetVec& state = curCube->getState(); _pdrSim->setSourceFree(V3_FF, false); V3BitVecX value0(1), value1(1); value0.set0(0); value1.set1(0); for (uint32_t i = 0; i < state.size(); ++i) _pdrSim->setSource(_vrfNtk->getLatch(state[i].id), (state[i].cp ? value0 : value1)); // Simulate for One Cycle _pdrSim->simulate(); _pdrSim->updateNextStateValue(); // Return the Cube that it Reached V3NetVec nextState; nextState.clear(); nextState.reserve(_vrfNtk->getLatchSize()); for (uint32_t i = 0; i < _vrfNtk->getLatchSize(); ++i) { switch (_pdrSim->getSimValue(_vrfNtk->getLatch(i))[0]) { case '0' : nextState.push_back(V3NetId::makeNetId(i, 1)); break; case '1' : nextState.push_back(V3NetId::makeNetId(i, 0)); break; } } if (existInitial(nextState)) return 0; V3MPDRCube* const cube = new V3MPDRCube(0); assert (cube); cube->setState(nextState); return cube; }
void V3NtkElaborate::elaborateFairnessL2S(V3Constraint* const constr, V3NetVec& constrList) { assert (V3NetUD != _saved); assert (V3NetUD != _1stSave); assert (V3NetUD != _inLoop); assert (V3NetUD != _looped); assert (constr); assert (!constr->isFSMConstr()); constrList.clear(); elaboratePOConstraints(constr->getStart(), constr->getEnd(), constrList); // Create Latches for Fairness Constraints (f) V3BvNtk* const bvNtk = dynamic_cast<V3BvNtk*>(_ntk); V3NetId id; V3GateType type; V3InputVec inputs(2); if (bvNtk) { for (uint32_t i = 0; i < constrList.size(); ++i) { // Create Input of Latch (F) : "F || (f && _inLoop)" inputs.clear(); inputs.push_back(_inLoop); inputs.push_back(constrList[i]); type = BV_AND; id = elaborateBvGate(bvNtk, type, inputs, _netHash); constrList[i] = _ntk->createNet(1); assert (V3NetUD != constrList[i]); inputs.clear(); inputs.push_back(~constrList[i]); inputs.push_back(~id); type = BV_AND; id = elaborateBvGate(bvNtk, type, inputs, _netHash); inputs.clear(); inputs.push_back(~id); inputs.push_back(0); _ntk->setInput(constrList[i], inputs); _ntk->createLatch(constrList[i]); } } else { for (uint32_t i = 0; i < constrList.size(); ++i) { // Create Input of Latch (F) : "F || (f && _inLoop)" inputs.clear(); inputs.push_back(_inLoop); inputs.push_back(constrList[i]); type = AIG_NODE; id = elaborateAigGate(_ntk, type, inputs, _netHash); constrList[i] = _ntk->createNet(1); assert (V3NetUD != constrList[i]); inputs.clear(); inputs.push_back(~constrList[i]); inputs.push_back(~id); type = AIG_NODE; id = elaborateAigGate(_ntk, type, inputs, _netHash); inputs.clear(); inputs.push_back(~id); inputs.push_back(0); _ntk->setInput(constrList[i], inputs); _ntk->createLatch(constrList[i]); } } }
const bool V3VrfMPDR::generalizeCex(V3MPDRTimedCube& timedCube) { // Try Turning the Reachability Check from SAT to UNSAT V3MPDRCube* cube = new V3MPDRCube(*(timedCube.second)); assert (cube); assert (!existInitial(cube->getState())); while (true) { // Get the SAT Model if (!checkReachability(timedCube.first, cube->getState())) break; V3MPDRCube* const prevCube = new V3MPDRCube(cube); // Create Cube generalizeSimulation(prevCube, cube, timedCube.first - 1); // Apply Simulation for the witness // Remove Variables of cube with Opposite Polarity in prevCube const V3NetVec cubeState = prevCube->getState(); delete prevCube; V3NetVec state; state.clear(); state.reserve(cube->getState().size()); uint32_t j = 0, k = 0, cubeSize = cube->getState().size(); while (j < cubeState.size() && k < cube->getState().size()) { assert (!j || (cubeState[j].id > cubeState[j - 1].id)); assert (!k || (cube->getState()[k].id > cube->getState()[k - 1].id)); if (cubeState[j].id > cube->getState()[k].id) { state.push_back(cube->getState()[k]); ++k; } else if (cubeState[j].id < cube->getState()[k].id) ++j; else { if (cubeState[j].cp == cube->getState()[k].cp) state.push_back(cube->getState()[k]); ++j; ++k; } } for (; k < cube->getState().size(); ++k) state.push_back(cube->getState()[k]); if (cubeSize == state.size() || existInitial(state)) { delete cube; return false; } // Update Cube for the Next Iteration assert (cubeSize > state.size()); cube->setState(state); } assert (cube); timedCube.second->setState(cube->getState()); delete cube; return true; }
void V3VrfMPDR::addCubeToSolver(const V3NetVec& state, const uint32_t& depth) { assert (state.size()); assert (depth < 2); assert (_pdrSvr); for (uint32_t i = 0; i < state.size(); ++i) { assert (state[i].id < _vrfNtk->getLatchSize()); _pdrSvr->addBoundedVerifyData(_vrfNtk->getLatch(state[i].id), depth); } }
const V3NetId V3NtkElaborate::elaborateInvariants(V3Constraint* const constr) { assert (constr); assert (constr->getHandler()); V3NetVec constrList; assert (_handler == constr->getHandler()); if (constr->isFSMConstr()) elaborateFSMInvariants(constr->getFSM(), constrList); else elaboratePOConstraints(constr->getStart(), constr->getEnd(), constrList); return constrList.size() ? combineConstraints(constrList) : V3NetId::makeNetId(0, 1); }
// Constraints Setting Functions void V3VrfBase::setConstraint(const V3NetVec& constrList, const uint32_t& p) { if (p >= _constr.size()) _constr.resize(1 + p); _constr[p].clear(); _constr[p].reserve(constrList.size()); for (uint32_t i = 0; i < constrList.size(); ++i) { assert (constrList[i].id < _vrfNtk->getNetSize()); _constr[p].push_back(constrList[i]); } }
void V3SVrfIPDR::addCubeToSolver2(const uint32_t& frame, const V3NetVec& state, const uint32_t& d) { assert (frame < _pdrSvr.size()); assert (_pdrSvr[frame]); assert (state.size()); assert (d < 2); for (uint32_t i = 0; i < state.size(); ++i) { assert (state[i].id < _vrfNtk->getLatchSize()); _pdrSvr[frame]->addBoundedVerifyData(_handler->_latchMap->at(_decompDepth)[state[i].id], d); } }
const bool V3SVrfIPDR::checkReachability2(const uint32_t& frame, const V3NetVec& cubeState, const bool& extend, const bool& notImportant) { if(heavy_debug && !notImportant){ cerr << "\n!!!!!!checkReachability2 frame : " << frame << " cube : "; printState(cubeState); cerr << endl; } assert (frame > 0); assert (frame < getPDRFrame()); const uint32_t& d = frame - 1; _pdrSvr[d]->assumeRelease(); // Assume cube' addCubeToSolver2(d, cubeState, 0); /*V3SSvrMiniSat * gg= (V3SSvrMiniSat *)_pdrSvr[d]; for (unsigned i = 0; i < 40; ++i){ cerr << i << " : " << gg->getVerifyData( i ,0 ) << endl; }*/ for (uint32_t i = 0; i < cubeState.size(); ++i) _pdrSvr[d]->assumeProperty(_pdrSvr[d]->getFormula(_handler->_latchMap->at(_decompDepth)[cubeState[i].id], 0), cubeState[i].cp); if (extend) { // Assume ~cube addCubeToSolver(d, cubeState, 0); V3SvrDataVec blockCube; blockCube.clear(); blockCube.reserve(cubeState.size()); size_t fId; for (uint32_t i = 0; i < cubeState.size(); ++i) { fId = _pdrSvr[d]->getFormula(_vrfNtk->getLatch(cubeState[i].id), 0); blockCube.push_back(cubeState[i].cp ? fId : _pdrSvr[d]->getNegFormula(fId)); } _pdrSvrData = _pdrSvr[d]->setImplyUnion(blockCube); assert (_pdrSvrData); _pdrSvr[d]->assumeProperty(_pdrSvrData); // Check Reachability by SAT Calling if (profileON()) _solveStat->start(); _pdrSvr[d]->simplify(); const bool result = _pdrSvr[d]->assump_solve(); if (profileON()) _solveStat->end(); _pdrSvr[d]->assertProperty(_pdrSvr[d]->getNegFormula(_pdrSvrData)); // Invalidate ~cube in future solving if(heavy_debug && !notImportant) cerr << "result: " << result << endl << endl; return result; } else { if (profileON()) _solveStat->start(); /*V3SSvrMiniSat * GG = (V3SSvrMiniSat *)_pdrSvr[d]; for (unsigned i = 0, s = GG->_assump.size(); i < s; ++i){ cout << var(GG->_assump[i]) << ":" << sign(GG->_assump[i]) << endl; }*/ _pdrSvr[d]->simplify(); const bool result = _pdrSvr[d]->assump_solve(); if (profileON()) _solveStat->end(); if(heavy_debug && !notImportant) cerr << "result: " << result << endl << endl; return result; } }
// General BFS Fanin Cone Indexing Functions for V3 Ntk void bfsIndexFaninConeFF(V3Ntk* const ntk, V3NetVec& ffList, const V3NetVec& sourceNets) { assert (ntk); V3BoolVec m(ntk->getNetSize(), false); ffList.clear(); V3NetVec source = sourceNets; uint32_t end = 0; while (true) { for (uint32_t i = 0; i < source.size(); ++i) bfsIndexFaninConeFF(ntk, ffList, source[i], m); if (end == ffList.size()) break; assert (end < ffList.size()); source.clear(); source.reserve(ffList.size() - end); while (end != ffList.size()) { source.push_back(ntk->getInputNetId(ffList[end], 0)); source.push_back(ntk->getInputNetId(ffList[end], 1)); ++end; } } }
V3NtkInput* const V3NtkFromVIA(const char* fileName, const bool& isFileList, const bool& toFlatten, const bool& async2sync) { // Set QuteRTL Log File setQuteLogFile(); // Parse Verilog by QuteRTL from API and Get a Pointer to CktModule in QuteRTL CktModule* const module = quteReadRTL2(fileName, isFileList, toFlatten); if (!module) { Msg(MSG_ERR) << "RTL Parse Failed !! " << "(See QuteRTL Log File \"" << quteRTL_MsgFile << "\" for Detailed Info)" << endl; return 0; } // Remove QuteRTL Log File v3DeleteDir(quteRTL_MsgFile.c_str()); // Traverse CktModule and Construct Ntk in V3 V3NetVec inputs; inputs.clear(); return V3QuteRTLHandler(module, async2sync, inputs); }
// General Hierarchical Ntk Construction Functions for V3 Ntk const bool createModule(V3Ntk* const ntk, const V3NetVec& inputs, const V3NetVec& outputs, V3NtkHandler* const moduleHandler, const bool& isBlackBoxed) { for (uint32_t i = 0; i < outputs.size(); ++i) if (ntk->reportMultipleDrivenNet(V3_MODULE, outputs[i])) return false; if (reportIncompatibleModule(ntk, inputs, outputs, moduleHandler)) return false; V3NtkModule* const module = new V3NtkModule(inputs, outputs); assert (module); module->updateNtkRef(moduleHandler, isBlackBoxed); ntk->createModule(module); const uint32_t index = ntk->getModuleSize() - 1; assert (module == ntk->getModule(index)); V3InputVec v3InputVec; v3InputVec.clear(); v3InputVec.push_back(V3NetType(index)); for (uint32_t i = 0; i < outputs.size(); ++i) { ntk->setInput(outputs[i], v3InputVec); ntk->createGate(V3_MODULE, outputs[i]); assert (module == ntk->getModule(outputs[i])); } moduleHandler->incInstRef(); return true; }
const V3NetId V3NtkElaborate::combineConstraints(const V3NetVec& constrList) { assert (constrList.size()); V3InputVec inputs(2, 0); V3BvNtk* const bvNtk = dynamic_cast<V3BvNtk*>(_ntk); // Combine All Constraints for (uint32_t i = 0; i < constrList.size(); ++i) { assert (constrList[i].id < _ntk->getNetSize()); assert (1 == _ntk->getNetWidth(constrList[i])); if (!i) inputs[0] = constrList[i]; else { inputs[1] = constrList[i]; inputs[0] = bvNtk ? elaborateBvGate(bvNtk, BV_AND, inputs, _netHash) : elaborateAigGate(_ntk, AIG_NODE, inputs, _netHash); } } return inputs[0].id; }
const bool V3SVrfIPDR::existInitial2(const V3NetVec& state) { for (uint32_t i = 0; i < state.size(); ++i) { assert (state[i].id < _pdrInitValue.size()); if (_pdrInitValue[state[i].id] ^ state[i].cp) return false; } return true; }
void V3VrfMPDR::resolveInitial(V3MPDRCube* const cube, const V3SvrDataSet& coreProofVars) { // Get Proof Related State Variables assert (cube); //if (coreProofVars.size() == cube->getState().size()) return; // Store Values of State Variable const V3NetVec& state = cube->getState(); // Remove Variables to Form New State assert (!existInitial(state)); bool conflictInitial = false; V3NetId conflictId = V3NetUD; uint32_t pos = 0; V3NetVec newState; newState.reserve(state.size()); for (uint32_t i = 0; i < state.size(); ++i) { if (coreProofVars.end() != coreProofVars.find(_pdrSvr->getFormula(_vrfNtk->getLatch(state[i].id), 1))) { newState.push_back(state[i]); if (!conflictInitial && (_pdrInitConst[state[i].id] && (_pdrInitValue[state[i].id] ^ state[i].cp))) { assert (!existInitial(newState)); conflictInitial = true; } } else if (!conflictInitial && V3NetUD == conflictId) { if (_pdrInitConst[state[i].id] && (_pdrInitValue[state[i].id] ^ state[i].cp)) { conflictId = state[i]; assert (V3NetUD != conflictId); pos = newState.size(); } } } // Resolve Intersection with Initial State if (!conflictInitial) { assert (V3NetUD != conflictId); newState.insert(newState.begin() + pos, conflictId); } if (newState.size() < state.size()) cube->setState(newState); }
// Constructor and Destructor V3NtkElaborate::V3NtkElaborate(V3NtkHandler* const handler, const V3NetVec& targetNets) : V3NtkHandler(handler) { assert (_handler); assert (!_ntk); _c2pMap.clear(); _p2cMap.clear(); _pOutput.clear(); const uint32_t shadowSize = _handler->getNtk()->getLatchSize(); _nextOpId = V3NetUD; _saved = _1stSave = _inLoop = _looped = V3NetUD; _mirror.clear(); _shadow.clear(); _shadow.reserve(shadowSize); for (uint32_t i = 0; i < shadowSize; ++i) _shadow.push_back(V3NetUD); // Duplicate from Parent Network if Necessary if (targetNets.size()) _ntk = elaborateNtk(_handler, targetNets, _p2cMap, _c2pMap, _netHash); }
void V3NtkElaborate::elaborateFSMInvariants(V3FSM* const fsm, V3NetVec& constrList) { // NOTE: We add constraints follow the reachability, and // For FSM with Milestones, we also add constraints follows the milestones. assert (fsm); assert (_handler == fsm->getNtkHandler()); constrList.clear(); if (!_ntk || !_p2cMap.size()) return; // Omit FSM Without Invariants: Every milestone is reachable from any states if (!fsm->getStateSize()) return; uint32_t comb = 0, seq = 0; // Extract Combinational Invariants : G (state != some forward unreachable state) V3NetId id1; V3NetVec stateNets; V3UI32Vec reachStates; V3InputVec inputs(2); V3BvNtk* const bvNtk = dynamic_cast<V3BvNtk*>(_ntk); for (uint32_t j = 0; j < fsm->getStateSize(); ++j) { if (V3NtkUD != fsm->getStepFwdFromInit(j)) continue; stateNets.clear(); fsm->getStateNetId(j, stateNets); assert (stateNets.size()); attachToNtk(_handler, _ntk, stateNets, _p2cMap, _c2pMap, _netHash); assert (_ntk); id1 = elaborateFSMState(stateNets, false); assert (id1.id < _ntk->getNetSize()); constrList.push_back(~id1); ++comb; } // Elaborate Sequential Invariants : nextOpState -> (j -> Prev(OR (reachStates))) const bool hasMileStone = fsm->getMileStoneSize(); if (hasMileStone) { for (uint32_t j = 0; j < fsm->getStateSize(); ++j) { if (!fsm->isMileStone(j)) continue; assert (V3NtkUD != fsm->getStepBwdFromTerm(j)); fsm->getStateBwdReachable(j, reachStates, true); if (fsm->getStateSize() == reachStates.size()) continue; if (fsm->getStateSize() < (reachStates.size() << 2)) continue; stateNets.clear(); fsm->getStateNetId(j, stateNets); assert (stateNets.size()); attachToNtk(_handler, _ntk, stateNets, _p2cMap, _c2pMap, _netHash); assert (_ntk); id1 = elaborateFSMState(stateNets, false); assert (id1.id < _ntk->getNetSize()); inputs[0] = ~id1; for (uint32_t k = 0; k < reachStates.size(); ++k) { stateNets.clear(); fsm->getStateNetId(reachStates[k], stateNets); assert (stateNets.size()); attachToNtk(_handler, _ntk, stateNets, _p2cMap, _c2pMap, _netHash); assert (_ntk); id1 = elaborateFSMState(stateNets, true); assert (id1.id < _ntk->getNetSize()); inputs[0] = ~(inputs[0].id); inputs[1] = ~id1; ++seq; inputs[0] = bvNtk ? ~elaborateBvGate(bvNtk, BV_AND, inputs, _netHash) : ~elaborateAigGate(_ntk, AIG_NODE, inputs, _netHash); } // Record Invariants inputs[0] = ~(inputs[0].id); inputs[1] = _nextOpId; assert (V3NetUD != _nextOpId); inputs[0] = bvNtk ? ~elaborateBvGate(bvNtk, BV_AND, inputs, _netHash) : ~elaborateAigGate(_ntk, AIG_NODE, inputs, _netHash); constrList.push_back(inputs[0].id); } } }
V3NtkInput* const V3QuteRTLHandler(CktModule* const& module, const bool& async2sync, V3NetVec& inputs, const string& instName) { // Create Network Handler V3NtkInput* quteHandler = new V3NtkInput(false, (instName.size() ? instName : quteGetModuleName(module))); if (!quteHandler) { Msg(MSG_ERR) << "Create RTL Design Failed !!" << endl; return 0; } if (!quteHandler->getNtk()) { Msg(MSG_ERR) << "Create BV Network Failed !!" << endl; return 0; } V3NetVec piList; piList.clear(); // 1. Create Input / Inout Nets if (!V3QuteRTLInputHandler(quteHandler, module, piList)) { delete quteHandler; return 0; } // 2. Create DFF and Traverse its Fanin Cones if (!V3QuteRTLFFHandler(quteHandler, module, async2sync, inputs)) { delete quteHandler; return 0; } // 3. Create Output if (!V3QuteRTLOutputHandler(quteHandler, module, async2sync)) { delete quteHandler; return 0; } // 4. Remove Clock Signal from Inputs if (!V3QuteRTLClockHandler(quteHandler, piList, inputs)) { delete quteHandler; return 0; } // 4. Remove Internal Names (Optional) quteHandler->removePrefixNetName(quteIsInternalName); return quteHandler; }
void computeFanout(V3Ntk* const ntk, V3NetTable& outputTable, const V3NetVec& targetNets) { assert (ntk); outputTable.clear(); outputTable.reserve(ntk->getNetSize()); for (uint32_t i = 0; i < ntk->getNetSize(); ++i) outputTable.push_back(V3NetVec()); V3BoolVec m(ntk->getNetSize(), false); // Set Latest Misc Data on (Pseudo) PI / PIO / Const for (uint32_t i = 0; i < ntk->getInputSize(); ++i) m[ntk->getInput(i).id] = true; for (uint32_t i = 0; i < ntk->getInoutSize(); ++i) m[ntk->getInout(i).id] = true; for (uint32_t i = 0; i < ntk->getLatchSize(); ++i) m[ntk->getLatch(i).id] = true; for (uint32_t i = 0; i < ntk->getConstSize(); ++i) m[ntk->getConst(i).id] = true; // DFS Compute Fanout List From (Pseudo) PO / PIO for (uint32_t i = 0; i < ntk->getLatchSize(); ++i) { dfsComputeFanout(ntk, ntk->getInputNetId(ntk->getLatch(i), 0), m, outputTable); dfsComputeFanout(ntk, ntk->getInputNetId(ntk->getLatch(i), 1), m, outputTable); } for (uint32_t i = 0; i < ntk->getInoutSize(); ++i) dfsComputeFanout(ntk, ntk->getInputNetId(ntk->getInout(i), 0), m, outputTable); if (targetNets.size()) for (uint32_t i = 0; i < targetNets.size(); ++i) dfsComputeFanout(ntk, targetNets[i], m, outputTable); else for (uint32_t i = 0; i < ntk->getOutputSize(); ++i) dfsComputeFanout(ntk, ntk->getOutput(i), m, outputTable); }
void V3NtkElaborate::combineInvariantToOutputs(const uint32_t& pIndex, const V3NetVec& invList) { assert (pIndex < _ntk->getOutputSize()); assert (invList.size()); // Combine All Invariants V3NetId id = combineConstraints(invList); V3InputVec inputs(2, 0); // Combine Invariants with the Property Output V3BvNtk* const bvNtk = dynamic_cast<V3BvNtk*>(_ntk); inputs[0] = id; inputs[1] = ~(_ntk->getOutput(pIndex)); id = bvNtk ? ~elaborateBvGate(bvNtk, BV_AND, inputs, _netHash) : ~elaborateAigGate(_ntk, AIG_NODE, inputs, _netHash); _ntk->replaceOutput(pIndex, id); }
// put fanins of a net (id) into a vector (nets) in topological order void V3Ntk::dfsOrder(const V3NetId& id, V3NetVec& nets) { if (isLatestMiscData(id)) return; // Set Latest Misc Data setLatestMiscData(id); // Traverse Fanin Logics const V3GateType type = getGateType(id); if(type == AIG_NODE) { dfsOrder(getInputNetId(id, 0), nets); dfsOrder(getInputNetId(id, 1), nets); } nets.push_back(id); // Record Order }
// General DFS Traversal Recursive Functions for V3 Ntk void dfsGeneralOrder(V3Ntk* const ntk, const V3NetId& pId, V3BoolVec& m, V3NetVec& orderMap) { assert (ntk); assert (m.size() == ntk->getNetSize()); V3Stack<V3NetId>::Stack s; s.push(pId); V3BoolVec t(ntk->getNetSize(), false); V3NetId id; V3GateType type; uint32_t inSize; // Traverse Fanin Logics while (s.size()) { id = s.top(); assert (id.id < m.size()); if (m[id.id]) { s.pop(); continue; } type = ntk->getGateType(id); assert (V3_XD > type); if (V3_MODULE == type) { assert (ntk->getInputNetSize(id) == 1); assert (ntk->getModule(id)); orderMap.push_back(id); m[id.id] = t[id.id] = true; s.pop(); const V3NetVec& inputs = ntk->getModule(id)->getInputList(); inSize = inputs.size(); while (inSize--) if (!t[inputs[inSize].id]) s.push(inputs[inSize]); } else { if (t[id.id]) { orderMap.push_back(id); m[id.id] = true; s.pop(); continue; } inSize = ntk->getInputNetSize(id); if (BV_SLICE == type || BV_CONST == type) --inSize; t[id.id] = true; while (inSize--) if (!t[ntk->getInputNetId(id, inSize).id]) s.push(ntk->getInputNetId(id, inSize)); } } }
// Private Member Functions void V3NtkElaborate::elaborate(V3LTLFormula* const ltlFormula) { // Collect Leaf Formula, and Retain Only New Ones V3UI32Set targetNetIdSet; targetNetIdSet.clear(); assert (isMutable()); assert (ltlFormula); ltlFormula->collectLeafFormula(targetNetIdSet); V3NetVec targetNets; targetNets.clear(); targetNets.reserve(targetNetIdSet.size()); if (_p2cMap.size()) for (V3UI32Set::const_iterator it = targetNetIdSet.begin(); it != targetNetIdSet.end(); ++it) { assert ((*it) < _p2cMap.size()); if (V3NetUD != _p2cMap[*it]) continue; targetNets.push_back(V3NetId::makeNetId(*it)); } else for (V3UI32Set::const_iterator it = targetNetIdSet.begin(); it != targetNetIdSet.end(); ++it) targetNets.push_back(V3NetId::makeNetId(*it)); // Create Ntk if NOT Exist, or Augment New Formula Logic to Existing Ntk if (!_ntk) { assert (!_p2cMap.size()); assert (!_c2pMap.size()); assert (!_pOutput.size()); _ntk = elaborateNtk(_handler, targetNets, _p2cMap, _c2pMap, _netHash); assert (_ntk); } else if (targetNets.size()) { attachToNtk(_handler, _ntk, targetNets, _p2cMap, _c2pMap, _netHash); assert (_ntk); } // Reserve Mapping Tables if Needed if (!V3NtkHandler::P2CMapON()) _p2cMap.clear(); if (!V3NtkHandler::C2PMapON()) _c2pMap.clear(); }
const bool V3QuteRTLClockHandler(V3NtkInput* const quteHandler, const V3NetVec& piList, V3NetVec& inputs) { assert (quteHandler); assert (!inputs.size() || (piList.size() == inputs.size())); V3BvNtk* const ntk = dynamic_cast<V3BvNtk*>(quteHandler->getNtk()); assert (ntk); if (V3NetUD != ntk->getClock()) { for (uint32_t i = 0; i < piList.size(); ++i) if (ntk->getClock().id == piList[i].id) { if (inputs.size()) inputs[i] = V3NetUD; continue; } else if (!createInput(ntk, piList[i])) return false; } else for (uint32_t i = 0; i < piList.size(); ++i) if (!createInput(ntk, piList[i])) return false; assert (ntk->getInputSize() == (piList.size() - ((V3NetUD != ntk->getClock()) ? 1 : 0))); return true; }
void dfsSimulationOrder(V3Ntk* const ntk, const V3NetId& pId, V3BoolVec& m, V3NetVec& orderMap) { assert (ntk); assert (m.size() == ntk->getNetSize()); V3Stack<V3NetId>::Stack s; s.push(pId); V3BoolVec t(ntk->getNetSize(), false); V3NetId id; V3GateType type; uint32_t inSize; // Traverse Fanin Logics while (s.size()) { id = s.top(); assert (id.id < m.size()); if (m[id.id]) { s.pop(); continue; } type = ntk->getGateType(id); assert (V3_XD > type); assert (V3_PI == type || (V3_MODULE < type && AIG_FALSE != type && BV_CONST != type)); if (t[id.id]) { orderMap.push_back(id); m[id.id] = true; s.pop(); continue; } inSize = ntk->getInputNetSize(id); if (BV_SLICE == type || BV_CONST == type) --inSize; t[id.id] = true; while (inSize--) if (!t[ntk->getInputNetId(id, inSize).id]) s.push(ntk->getInputNetId(id, inSize)); } }
const V3NetId V3NtkElaborate::elaborateFSMState(const V3NetVec& stateNets, const bool& nextState) { assert (stateNets.size()); V3InputVec inputs(2, V3NetUD); V3NetId id; V3BvNtk* const bvNtk = dynamic_cast<V3BvNtk*>(_ntk); if (!nextState) { for (uint32_t k = 0; k < stateNets.size(); ++k) { assert (1 == _handler->getNtk()->getNetWidth(stateNets[k])); id = getCurrentNetId(V3NetId::makeNetId(stateNets[k].id)); inputs[1] = (stateNets[k].cp) ? ~id : id; if (!k) { inputs[0] = inputs[1]; continue; } inputs[0] = bvNtk ? elaborateBvGate(bvNtk, BV_AND, inputs, _netHash) : elaborateAigGate(_ntk, AIG_NODE, inputs, _netHash); } } else { V3UI32Hash::const_iterator is; V3InputVec ffInputs(2, 0); if (V3NetUD == _nextOpId) { _nextOpId = _ntk->createNet(1); assert (V3NetUD != _nextOpId); ffInputs[0] = V3NetId::makeNetId(0, 1); ffInputs[1] = V3NetId::makeNetId(0); _ntk->setInput(_nextOpId, ffInputs); _ntk->createLatch(_nextOpId); } for (uint32_t k = 0; k < stateNets.size(); ++k) { assert (1 == _handler->getNtk()->getNetWidth(stateNets[k])); is = _mirror.find(_p2cMap[stateNets[k].id].id); if (_mirror.end() == is) { id = _ntk->createNet(1); _mirror.insert(make_pair((uint32_t)(_p2cMap[stateNets[k].id].id), id)); ffInputs[0] = V3NetId::makeNetId(_p2cMap[stateNets[k].id].id); ffInputs[1] = V3NetId::makeNetId(0); _ntk->setInput(id, ffInputs); _ntk->createLatch(id); } else id = is->second; inputs[1] = (_p2cMap[stateNets[k].id].cp ^ stateNets[k].cp) ? ~id : id; if (!k) { inputs[0] = inputs[1]; continue; } inputs[0] = bvNtk ? elaborateBvGate(bvNtk, BV_AND, inputs, _netHash) : elaborateAigGate(_ntk, AIG_NODE, inputs, _netHash); } } assert (V3NetUD != inputs[0].id); return inputs[0].id; }
const uint32_t computeLevel(V3Ntk* const ntk, V3UI32Vec& levelData, const V3NetVec& targetNets) { assert (ntk); levelData = V3UI32Vec(ntk->getNetSize(), V3NtkUD); // Set Level 0 on (Pseudo) PI / PIO / Const for (uint32_t i = 0; i < ntk->getInputSize(); ++i) levelData[ntk->getInput(i).id] = 0; for (uint32_t i = 0; i < ntk->getInoutSize(); ++i) levelData[ntk->getInout(i).id] = 0; for (uint32_t i = 0; i < ntk->getLatchSize(); ++i) levelData[ntk->getLatch(i).id] = 0; for (uint32_t i = 0; i < ntk->getConstSize(); ++i) levelData[ntk->getConst(i).id] = 0; // Compute General DFS Order V3NetId id; V3NetVec orderMap; uint32_t levelSize = 0; dfsNtkForGeneralOrder(ntk, orderMap, targetNets); // Compute Net Levels dfsComputeLevel(ntk, orderMap, levelData); // Update Global Level for (uint32_t i = 0; i < ntk->getLatchSize(); ++i) { id = ntk->getInputNetId(ntk->getLatch(i), 0); assert (V3NtkUD != levelData[id.id]); if (levelData[id.id] > levelSize) levelSize = levelData[id.id]; id = ntk->getInputNetId(ntk->getLatch(i), 1); assert (V3NtkUD != levelData[id.id]); if (levelData[id.id] > levelSize) levelSize = levelData[id.id]; } for (uint32_t i = 0; i < ntk->getInoutSize(); ++i) { id = ntk->getInputNetId(ntk->getInout(i), 0); assert (V3NtkUD != levelData[id.id]); if (levelData[id.id] > levelSize) levelSize = levelData[id.id]; } if (targetNets.size()) { for (uint32_t i = 0; i < targetNets.size(); ++i) { id = targetNets[i]; assert (V3NtkUD != levelData[id.id]); if (levelData[id.id] > levelSize) levelSize = levelData[id.id]; } } else { for (uint32_t i = 0; i < ntk->getOutputSize(); ++i) { id = ntk->getOutput(i); assert (V3NtkUD != levelData[id.id]); if (levelData[id.id] > levelSize) levelSize = levelData[id.id]; } } ++levelSize; return levelSize; }
void V3NtkElaborate::elaboratePOConstraints(const uint32_t& start, const uint32_t& end, V3NetVec& constrList) { V3Ntk* const ntk = _handler->getNtk(); assert (ntk); assert (start < ntk->getOutputSize() && end < ntk->getOutputSize()); constrList.clear(); if (!_ntk || !_p2cMap.size()) return; // Elaborate Constraint Logics if (start <= end) { // Fwd-Order Construction constrList.reserve(end - start); for (uint32_t i = start; i <= end; ++i) { assert (ntk->getOutput(i).id < _p2cMap.size()); assert (1 == ntk->getNetWidth(ntk->getOutput(i))); if (V3NetUD != _p2cMap[ntk->getOutput(i).id]) continue; constrList.push_back(V3NetId::makeNetId(ntk->getOutput(i).id)); } } else { // Rev-Order Construction uint32_t i = 1 + start; assert (i > start); constrList.reserve(start - end); while (i-- > end) { assert (ntk->getOutput(i).id < _p2cMap.size()); assert (1 == ntk->getNetWidth(ntk->getOutput(i))); if (V3NetUD != _p2cMap[ntk->getOutput(i).id]) continue; constrList.push_back(V3NetId::makeNetId(ntk->getOutput(i).id)); } } if (constrList.size()) attachToNtk(_handler, _ntk, constrList, _p2cMap, _c2pMap, _netHash); // Put Constraints into List constrList.clear(); if (start <= end) { // Fwd-Order Construction for (uint32_t i = start; i <= end; ++i) { const V3NetId id = ntk->getOutput(i); assert (V3NetUD != _p2cMap[id.id]); constrList.push_back(isV3NetInverted(id) ? getV3InvertNet(_p2cMap[id.id]) : _p2cMap[id.id]); } } else { // Rev-Order Construction uint32_t i = 1 + start; assert (i > start); while (i-- > end) { const V3NetId id = ntk->getOutput(i); assert (V3NetUD != _p2cMap[id.id]); constrList.push_back(isV3NetInverted(id) ? getV3InvertNet(_p2cMap[id.id]) : _p2cMap[id.id]); } } }