void dfsMarkFaninCone(V3Ntk* const ntk, const V3NetTable& idGroup, V3BoolTable& v) { assert (ntk); assert (idGroup.size()); v.clear(); v.reserve(ntk->getNetSize()); for (uint32_t i = 0; i < ntk->getNetSize(); ++i) v.push_back(V3BoolVec(idGroup.size(), false)); // Record Latch Markers V3BoolTable ff(ntk->getLatchSize(), V3BoolVec(idGroup.size(), false)); // Set Marker for Each idGroup for (uint32_t i = 0; i < idGroup.size(); ++i) for (uint32_t j = 0; j < idGroup[i].size(); ++j) v[idGroup[i][j].id][i] = true; // Propagate the Marker to Primary Inputs and Latches V3NetVec orderMap, targetNets; targetNets.clear(); for (uint32_t i = 0; i < idGroup.size(); ++i) targetNets.insert(targetNets.end(), idGroup[i].begin(), idGroup[i].end()); while (targetNets.size()) { // Make a DFS Order of Nets dfsNtkForGeneralOrder(ntk, orderMap, targetNets, false); V3NetTable outputTable; computeFanout(ntk, outputTable, targetNets); // Update Markers In Reversed DFS Order uint32_t i = orderMap.size(); while (i--) { for (uint32_t j = 0; j < outputTable[orderMap[i].id].size(); ++j) { for (uint32_t k = 0; k < idGroup.size(); ++k) if (v[outputTable[orderMap[i].id][j].id][k]) v[orderMap[i].id][k] = true; } } // Check if Any Latches Are Updated targetNets.clear(); for (i = 0; i < ff.size(); ++i) { if (ff[i] == v[ntk->getLatch(i).id]) continue; ff[i] = v[ntk->getLatch(i).id]; targetNets.push_back(ntk->getInputNetId(ntk->getLatch(i), 0)); targetNets.push_back(ntk->getInputNetId(ntk->getLatch(i), 1)); } } }
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; }
// Transformation Functions void V3NtkExpand2::performNtkTransformation(const bool& init) { V3Ntk* const ntk = _handler->getNtk(); assert (ntk); const uint32_t parentNets = ntk->getNetSize(); assert (parentNets); // Initialize Mappers From Parent Ntk (Index) to Current Ntk (V3NetId) _p2cMap = V3NetTable(_cycle, V3NetVec(parentNets, V3NetUD)); _latchMap = V3NetTable(_cycle, V3NetVec(parentNets, V3NetUD)); for (uint32_t cycle = 0; cycle < _cycle; ++cycle) _p2cMap[cycle][0] = V3NetId::makeNetId(0); // Compute DFS Order for Transformation V3NetVec orderMap; orderMap.clear(); dfsNtkForGeneralOrder(ntk, orderMap); assert (orderMap.size() <= parentNets); assert (!orderMap[0].id); V3NetId id; V3InputVec inputs; inputs.reserve(3); inputs.clear(); // Expand Network for (uint32_t cycle = 0; cycle < _cycle; ++cycle) { V3NetVec& p2cMap = _p2cMap[cycle]; assert (parentNets == p2cMap.size()); // Construct PI / PIO in Consistent Order uint32_t i = 1; for (uint32_t j = i + ntk->getInputSize(); i < j; ++i) { assert (parentNets > orderMap[i].id); assert (V3NetUD == p2cMap[orderMap[i].id]); p2cMap[orderMap[i].id] = _ntk->createNet(ntk->getNetWidth(orderMap[i])); assert (V3_PI == ntk->getGateType(orderMap[i])); _ntk->createInput(p2cMap[orderMap[i].id]); //cout << "PI " << orderMap[i].id << endl; //cout << "PI " << p2cMap[orderMap[i].id].id << endl; } for (uint32_t j = i + ntk->getInoutSize(); i < j; ++i) { assert (parentNets > orderMap[i].id); assert (V3NetUD == p2cMap[orderMap[i].id]); p2cMap[orderMap[i].id] = _ntk->createNet(ntk->getNetWidth(orderMap[i])); assert (V3_PIO == ntk->getGateType(orderMap[i])); _ntk->createInout(p2cMap[orderMap[i].id]); } // Construct Latches in Consistent Order for (uint32_t j = i + ntk->getLatchSize(); i < j; ++i) { assert (parentNets > orderMap[i].id); assert (V3NetUD == p2cMap[orderMap[i].id]); assert (V3_FF == ntk->getGateType(orderMap[i])); if (cycle) { // Connect FF with the Last Frame id = ntk->getInputNetId(orderMap[i], 0); assert (V3NetUD != _p2cMap[cycle - 1][id.id]); p2cMap[orderMap[i].id] = V3NetId::makeNetId(_p2cMap[cycle - 1][id.id].id, _p2cMap[cycle - 1][id.id].cp ^ id.cp); _latchMap[cycle][i-1-(ntk->getInputSize())] = p2cMap[orderMap[i].id]; //cout << "FF " << orderMap[i].id << endl; //cout << "FF " << p2cMap[orderMap[i].id].id << endl; } else { // Set Latches as Free Inputs (which will be appended after PI / PIO) p2cMap[orderMap[i].id] = _ntk->createNet(1); _ntk->createLatch(p2cMap[orderMap[i].id]); _latchMap[cycle][i-1-(ntk->getInputSize())] = p2cMap[orderMap[i].id]; } } // Construct Nets and Connections for (; i < orderMap.size(); ++i) { assert (parentNets > orderMap[i].id); assert (V3NetUD == p2cMap[orderMap[i].id]); const V3GateType& type = ntk->getGateType(orderMap[i]); assert (V3_XD > type); p2cMap[orderMap[i].id] = _ntk->createNet(ntk->getNetWidth(orderMap[i])); //cout << "AIG " << orderMap[i].id << endl; //cout << "AIG " << p2cMap[orderMap[i].id].id << endl; if (AIG_NODE == type) { id = ntk->getInputNetId(orderMap[i], 0); assert (V3NetUD != p2cMap[id.id]); inputs.push_back(V3NetId::makeNetId(p2cMap[id.id].id, p2cMap[id.id].cp ^ id.cp)); id = ntk->getInputNetId(orderMap[i], 1); assert (V3NetUD != p2cMap[id.id]); inputs.push_back(V3NetId::makeNetId(p2cMap[id.id].id, p2cMap[id.id].cp ^ id.cp)); } else { _ntk->createConst(p2cMap[orderMap[i].id]); continue; } _ntk->setInput(p2cMap[orderMap[i].id], inputs); inputs.clear(); _ntk->createGate(ntk->getGateType(orderMap[i]), p2cMap[orderMap[i].id]); } // Construct PO in Consistent Order for (i = 0; i < ntk->getOutputSize(); ++i) { id = ntk->getOutput(i); assert (V3NetUD != p2cMap[id.id]); _ntk->createOutput(V3NetId::makeNetId(p2cMap[id.id].id, p2cMap[id.id].cp ^ id.cp)); } } // Set Latches in Consistent Order as Primary Inputs uint32_t i = 1; for (uint32_t j = i + ntk->getInputSize(); i < j; ++i) {} for (uint32_t j = i + ntk->getLatchSize(); i < j; ++i) { id = ntk->getInputNetId( orderMap[i], 0 ); inputs.push_back(V3NetId::makeNetId(_p2cMap[0][id.id].id, _p2cMap[0][id.id].cp ^ id.cp)); id = ntk->getInputNetId( orderMap[i], 1 ); inputs.push_back(V3NetId::makeNetId(id.id, id.cp)); //cerr << "id.id:" << id.id << "id.cp:" << id.cp << endl; _ntk->setInput(_p2cMap[0][orderMap[i].id], inputs); inputs.clear(); //cout << "FF " << orderMap[i].id << endl; //cout << "FF " << p2cMap[orderMap[i].id].id << endl; } // Complete Mapping Table from Current Ntk to Parent Ntk _c2pMap = V3NetVec(_ntk->getNetSize(), V3NetUD); _c2pMap[0] = V3NetId::makeNetId(0); for (uint32_t cycle = 0; cycle < _cycle; ++cycle) { V3NetVec& p2cMap = _p2cMap[cycle]; assert (_c2pMap[0] == p2cMap[0]); for (uint32_t i = 0; i < p2cMap.size(); ++i) { if (V3NetUD == p2cMap[i] || V3NetUD != _c2pMap[p2cMap[i].id]) continue; else _c2pMap[p2cMap[i].id] = V3NetId::makeNetId(i, p2cMap[i].cp); } } }
// Transformation Functions void V3NtkExpand::performNtkTransformation(const bool& init) { V3Ntk* const ntk = _handler->getNtk(); assert (ntk); const uint32_t parentNets = ntk->getNetSize(); assert (parentNets); const bool isBvNtk = dynamic_cast<V3BvNtk*>(ntk); // Initialize Mappers From Parent Ntk (Index) to Current Ntk (V3NetId) _p2cMap = V3NetTable(_cycle, V3NetVec(parentNets, V3NetUD)); for (uint32_t cycle = 0; cycle < _cycle; ++cycle) _p2cMap[cycle][0] = V3NetId::makeNetId(0); // Compute DFS Order for Transformation V3NetVec orderMap; orderMap.clear(); dfsNtkForGeneralOrder(ntk, orderMap); assert (orderMap.size() <= parentNets); assert (!orderMap[0].id); V3NetId id; V3InputVec inputs; inputs.reserve(3); inputs.clear(); // Expand Network for (uint32_t cycle = 0; cycle < _cycle; ++cycle) { V3NetVec& p2cMap = _p2cMap[cycle]; assert (parentNets == p2cMap.size()); // Construct PI / PIO in Consistent Order uint32_t i = 1; for (uint32_t j = i + ntk->getInputSize(); i < j; ++i) { assert (parentNets > orderMap[i].id); assert (V3NetUD == p2cMap[orderMap[i].id]); p2cMap[orderMap[i].id] = _ntk->createNet(ntk->getNetWidth(orderMap[i])); assert (V3_PI == ntk->getGateType(orderMap[i])); _ntk->createInput(p2cMap[orderMap[i].id]); //cout << "PI " << orderMap[i].id << endl; //cout << "PI " << p2cMap[orderMap[i].id].id << endl; } for (uint32_t j = i + ntk->getInoutSize(); i < j; ++i) { assert (parentNets > orderMap[i].id); assert (V3NetUD == p2cMap[orderMap[i].id]); p2cMap[orderMap[i].id] = _ntk->createNet(ntk->getNetWidth(orderMap[i])); assert (V3_PIO == ntk->getGateType(orderMap[i])); _ntk->createInout(p2cMap[orderMap[i].id]); } // Construct Latches in Consistent Order for (uint32_t j = i + ntk->getLatchSize(); i < j; ++i) { assert (parentNets > orderMap[i].id); assert (V3NetUD == p2cMap[orderMap[i].id]); assert (V3_FF == ntk->getGateType(orderMap[i])); if (cycle) { // Connect FF with the Last Frame id = ntk->getInputNetId(orderMap[i], 0); assert (V3NetUD != _p2cMap[cycle - 1][id.id]); p2cMap[orderMap[i].id] = V3NetId::makeNetId(_p2cMap[cycle - 1][id.id].id, _p2cMap[cycle - 1][id.id].cp ^ id.cp); //cout << "FF0 " << orderMap[i].id << endl; //cout << "FF0 " << p2cMap[orderMap[i].id].id << endl; } else { // Set Latches as Free Inputs (which will be appended after PI / PIO) if (!init) p2cMap[orderMap[i].id] = _ntk->createNet(ntk->getNetWidth(orderMap[i])); else { const V3NetId id1 = ntk->getInputNetId(orderMap[i], 1); assert (id1.id < ntk->getNetSize()); if (!id1.id) p2cMap[orderMap[i].id] = id1; else if (id1 == orderMap[i]) p2cMap[orderMap[i].id] = _ntk->createNet(ntk->getNetWidth(orderMap[i])); else p2cMap[orderMap[i].id] = V3NetId::makeNetId(p2cMap[id1.id].id, p2cMap[id1.id].cp ^ id1.cp); //cout << "FF " << orderMap[i].id << endl; //cout << "FF " << p2cMap[orderMap[i].id].id << endl; } } } // Construct Nets and Connections for (; i < orderMap.size(); ++i) { assert (parentNets > orderMap[i].id); assert (V3NetUD == p2cMap[orderMap[i].id]); const V3GateType& type = ntk->getGateType(orderMap[i]); assert (V3_XD > type); p2cMap[orderMap[i].id] = _ntk->createNet(ntk->getNetWidth(orderMap[i])); //cout << "AIG " << orderMap[i].id << endl; //cout << "AIG " << p2cMap[orderMap[i].id].id << endl; if (isBvNtk) { assert (AIG_FALSE < type); if (BV_CONST == type) { inputs.push_back(ntk->getInputNetId(orderMap[i], 0)); _ntk->setInput(p2cMap[orderMap[i].id], inputs); inputs.clear(); _ntk->createConst(p2cMap[orderMap[i].id]); continue; } else if (BV_SLICE == type) { id = ntk->getInputNetId(orderMap[i], 0); assert (V3NetUD != p2cMap[id.id]); inputs.push_back(V3NetId::makeNetId(p2cMap[id.id].id, p2cMap[id.id].cp ^ id.cp)); inputs.push_back(ntk->getInputNetId(orderMap[i], 1)); } else { for (uint32_t j = 0; j < ntk->getInputNetSize(orderMap[i]); ++j) { id = ntk->getInputNetId(orderMap[i], j); assert (V3NetUD != p2cMap[id.id]); inputs.push_back(V3NetId::makeNetId(p2cMap[id.id].id, p2cMap[id.id].cp ^ id.cp)); } } } else { if (AIG_NODE == type) { id = ntk->getInputNetId(orderMap[i], 0); assert (V3NetUD != p2cMap[id.id]); inputs.push_back(V3NetId::makeNetId(p2cMap[id.id].id, p2cMap[id.id].cp ^ id.cp)); id = ntk->getInputNetId(orderMap[i], 1); assert (V3NetUD != p2cMap[id.id]); inputs.push_back(V3NetId::makeNetId(p2cMap[id.id].id, p2cMap[id.id].cp ^ id.cp)); } else { _ntk->createConst(p2cMap[orderMap[i].id]); continue; } } /*for (unsigned ii = 0, s = inputs.size(); ii < s; ++ii){ cout << inputs[ii].id.id << " "; } cout << endl;*/ //cout << "?? " << (_ntk->getGateType(p2cMap[orderMap[i].id]) == V3_PI) << endl; _ntk->setInput(p2cMap[orderMap[i].id], inputs); inputs.clear(); _ntk->createGate(ntk->getGateType(orderMap[i]), p2cMap[orderMap[i].id]); } // Construct PO in Consistent Order for (i = 0; i < ntk->getOutputSize(); ++i) { id = ntk->getOutput(i); assert (V3NetUD != p2cMap[id.id]); _ntk->createOutput(V3NetId::makeNetId(p2cMap[id.id].id, p2cMap[id.id].cp ^ id.cp)); } } // Set Latches in Consistent Order as Primary Inputs for (uint32_t i = 0; i < ntk->getLatchSize(); ++i) { id = ntk->getLatch(i); assert (V3NetUD != _p2cMap[0][id.id]); //cout << id.id << endl; //cout << V3GateTypeStr[_ntk->getGateType(id)] << endl; //cout << V3GateTypeStr[_ntk->getGateType(_p2cMap[0][id.id])] << endl; if (V3_PI == _ntk->getGateType(_p2cMap[0][id.id]))_ntk->createInput(_p2cMap[0][id.id]); } // Complete Mapping Table from Current Ntk to Parent Ntk _c2pMap = V3NetVec(_ntk->getNetSize(), V3NetUD); _c2pMap[0] = V3NetId::makeNetId(0); for (uint32_t cycle = 0; cycle < _cycle; ++cycle) { V3NetVec& p2cMap = _p2cMap[cycle]; assert (_c2pMap[0] == p2cMap[0]); for (uint32_t i = 0; i < p2cMap.size(); ++i) { if (V3NetUD == p2cMap[i] || V3NetUD != _c2pMap[p2cMap[i].id]) continue; else _c2pMap[p2cMap[i].id] = V3NetId::makeNetId(i, p2cMap[i].cp); } } }