// vector shell_cmd: command received from shell // vector reg_cmd: command registered in commands_lst[] int DesignMng::getCommandCode(vector<string> shell_cmd){ string cmd_tmp; vector<string> reg_cmd; bool same_cmd; if (shell_cmd[0]==commands_lst[COMMENT].name ) return COMMENT; // compare all the commands of the array for (int i=0; i<NR_COMMANDS; ++i){ same_cmd = true; reg_cmd.clear(); // separate the tokens istrstream cmd_stream(commands_lst[i].name.c_str()); while (cmd_stream>>cmd_tmp) reg_cmd.push_back(cmd_tmp); if (reg_cmd.size() == shell_cmd.size()){ int j; // compare all the tokens between the two commands for (j=0; j<reg_cmd.size(); ++j) if ((reg_cmd[j][0] != '<') && (reg_cmd[j] != upcase(shell_cmd[j]))) same_cmd = false; if(same_cmd){ // compare the parameters if they are numbers when expected for (j=0; j<reg_cmd.size(); ++j) if (((reg_cmd[j].substr(0,4) == "<int") || (reg_cmd[j].substr(0,6) == "<float")) && (!isNumber(shell_cmd[j]))) throw AstranError("Parameters invalid"); return (i); // OK - command found and valid parameters, return its code } } } throw AstranError("Command invalid or wrong number of parameters"); }
void Spice::saveFile(string filename, Circuit& netList){ ofstream file; file.open(filename.c_str()); // Write if (!file) throw AstranError("Could not save file: " + filename); printHeader (file, "* ", ""); map<string, CellNetlst>::iterator cells_it; for ( cells_it = netList.getCellNetlsts()->begin(); cells_it != netList.getCellNetlsts()->end(); cells_it++ ){ file << ".SUBCKT " << cells_it->first; for ( vector<int>::iterator inouts_it=cells_it->second.getInouts().begin(); inouts_it != cells_it->second.getInouts().end(); inouts_it++ ) file << " " << cells_it->second.getNetName(*inouts_it); file << endl; for(map<string,Inst>::iterator tmp=cells_it->second.getInstances().begin(); tmp!=cells_it->second.getInstances().end(); ++tmp){ file << tmp->first << " "; for(vector<int>::iterator tmp2=tmp->second.ports.begin(); tmp2!=tmp->second.ports.end(); ++tmp2) file << cells_it->second.getNetName(*tmp2) << " "; file << tmp->second.subCircuit << endl; } for(int x=0; x<cells_it->second.size(); x++){ file << cells_it->second.getTrans(x).name << " " << cells_it->second.getNetName(cells_it->second.getTrans(x).drain) << " " << cells_it->second.getNetName(cells_it->second.getTrans(x).gate) << " " << cells_it->second.getNetName(cells_it->second.getTrans(x).source) << " "; if(cells_it->second.getTrans(x).type==PMOS) file << netList.getVddNet() << " PMOS"; else file << netList.getGndNet() << " NMOS"; file << " L=" << cells_it->second.getTrans(x).length << "U W=" << cells_it->second.getTrans(x).width << "U"<< endl; } file << ".ENDS " << cells_it->first << endl << endl; } }
void Circuit::writeCellSizesFile(string filename){ ofstream file; file.open(filename.c_str()); // Write if ((!file)) throw AstranError("Could not save file: " + filename); map<string,CellNetlst>::iterator cells_it; for(cells_it=cellNetlsts.begin(); cells_it!=cellNetlsts.end(); cells_it++){ CLayout* l=getLayout(cells_it->first); if(!l) throw AstranError("Cell Layout " + cells_it->first + " not found"); file << cells_it->first << endl; file << l->getWidth()/currentRules->getIntValue(getHPitch()) << endl; file << l->getHeight()/currentRules->getIntValue(getVPitch()) << endl; } }
void DesignMng::saveProjectConfig(string filename, string project_name){ ofstream file_out; file_out.open(filename.c_str()); if (!file_out) throw AstranError("Could not save project to file: " + filename);; file_out << "new design " << name << "\n"; file_out << "set hgrid " << circuit->getHPitch() << "\n"; file_out << "set vgrid " << circuit->getVPitch() << "\n"; file_out << "set vddnet " << circuit->getVddNet() << "\n"; file_out << "set gndnet " << circuit->getGndNet() << "\n"; file_out << "set rowheight " << circuit->getRowHeight() << "\n"; file_out << "set supplysize " << circuit->getSupplyVSize() << "\n"; file_out << "set viewer \"" << viewerProgram << "\"\n"; file_out << "set rotdl \"" << rotdlFile << "\"\n"; file_out << "set placer \"" << placerFile << "\"\n"; file_out << "set lpsolve \"" << lpSolverFile << "\"\n"; file_out << "set log \"" << historyFile << "\"\n"; file_out << "load technology \"" << project_name << ".rul\"\n"; file_out << "load netlist \"" << project_name << ".sp\"\n"; file_out << "load layouts \"" << project_name << ".lay\"\n"; //file_out << "load placement \"" << project_name << ".pl\"\n"; //file_out << "load placement \"" << project_name << ".place\"\n"; //file_out << "load routing \"" << project_name << ".rot\"\n"; string file_to_save; //save technology file_to_save = project_name + ".rul"; rules->saveRules(file_to_save); //save netlist file_to_save = project_name + ".sp"; Spice spice; spice.saveFile(file_to_save, *circuit); //save cell library file_to_save = project_name + ".lay"; Lef lef; lef.saveFile(file_to_save, *circuit); //save placement /* ret &= placer->writeBookshelfFiles(project_name, true); file_to_save = project_name + ".place"; ret &= placer->writeCadende(file_to_save); //save routing Router router; file_to_save = project_name + ".rot"; ret &= router.saveRoutingRotdl(file_to_save); */ file_out.close(); }
void DesignMng::addToHistoryLog(string cmd){ if(historyFile!=""){ ofstream file; file.open(historyFile.c_str(),ios_base::app); // Write if (!file) throw AstranError("Could not save history to file: " + historyFile); else if(cmd.size()) file << cmd << endl; file.close(); } }
void DesignMng::run(string filename) { cout << "-> Reading file: " << filename << endl; ifstream file(filename.c_str()); // Read if (!file) throw AstranError("File not found"); int line=1; string str_tmp; while(getline(file, str_tmp)){ if((str_tmp[0] != '*') && !readCommand(str_tmp)) cout << "-> WARNING: Could not execute line " << intToStr(line) << " of: " << filename << endl; line++; } }
void DesignMng::saveHistory(string filename){ ofstream file_out; file_out.open(filename.c_str()); if (!file_out) throw AstranError("Could not save history to file: " + filename); if (commandlog.size() > 1) { for (int i=0; i < commandlog.size()-1; ++i) file_out << commandlog[i] << endl; } else cout << "-> Command log is empty\n"; file_out.close(); }
void Circuit::printInstance(CLayout* l, string instance){ Instance *currentInstance = l->getInstance(instance); if(!currentInstance) throw AstranError("Instance " + instance + " not found"); cout << "-> Instance: " << instance << " => " << currentInstance->getTargetCell() << endl; currentInstance->print(); cout << "-> Pins Assignment (Global Net->Pin): "; /* map<string, list<Net> >::iterator netList_it; for(netList_it=netList.begin(); netList_it!=netList.end(); netList_it++) for(tmp_it=netList_it->second.begin(); tmp_it!=netList_it->second.end(); tmp_it++) if(tmp_it->targetCellInst==instance) cout << " (" << netList_it->first << "->" << tmp_it->targetPin << ") "; cout << endl; */ }
void Circuit::printInterface(string net){ map<string, Interface>::iterator interface_it=interfaces.find(net); if(interface_it==interfaces.end()) throw AstranError("Could not find interface: " + net); cout << "-> Interface: " << net << " => Orientation: "; switch(interface_it->second.orient){ case N: cout << "N"; break; case S: cout << "S"; break; case W: cout << "W"; break; case E: cout << "E"; break; } cout << "; Type: "; switch(interface_it->second.ioType){ case IOTYPE_INPUT: cout << "INPUT"; break; case IOTYPE_OUTPUT: cout << "OUTPUT"; break; case IOTYPE_INOUT: cout << "INOUT"; break; } cout << "; Position: (" << interface_it->second.pos.getX() << "," << interface_it->second.pos.getY() << ")"; cout << endl; }
CellNetlst* Circuit::getCellNetlst(string n){ CellNetlst* tmp=findCellNetlst(n); if(!tmp) throw AstranError("Could not find cell netlist: " + n); return tmp; }
bool DesignMng::readCommand(string cmd){ try { if(verboseMode){ cout << "[" << name << "]$ " << cmd << endl; addToHistoryLog(cmd); if (cmd.size()){ commandlog.push_back(cmd); poscmdlog = commandlog.size(); } } vector<string> words; // Parser, analyzing tokens int inicio=0, fim=0; bool insideaspas=false, ok=false; for (int c=0; c < cmd.size(); ++c){ if (cmd[c] != ' ') fim = c; if (insideaspas) fim = fim-1; if ((c == cmd.size()-1 && cmd[cmd.size()-1] != ' ') || (cmd[c] == ' ' && !insideaspas && fim-inicio >= 0)) ok = true; if (ok){ string tmp = cmd.substr(inicio,fim-inicio+1); words.push_back(tmp); ok = false; inicio = c+1; } switch (cmd[c]){ case '"': if (!insideaspas) inicio = c+1; insideaspas = !insideaspas; break; case ' ': if (!insideaspas) inicio = c+1; break; } } // tokens are separated and inserted in vector 'words' int tmp; if (words.size() != 0){ switch (getCommandCode(words)){ case NEW_DESIGN:{ delete circuit; delete placer; delete rules; delete autocell; delete router; circuit = new Circuit(); placer = new Placer(); rules = new Rules(); autocell = new AutoCell(); router = new Router(); circuit->setRules(rules); placer->setCircuit(circuit); router->setCircuit(circuit); setName(words[2].c_str()); } break; case NEW_CELL:{ CellNetlst tmp; tmp.setName(words[2]); circuit->insertCell(tmp); } break; /**** LOAD - 6 ****/ case LOAD_PROJECT: cout << "-> Loading project from file: " << words[2] << endl; verboseMode=0; run(words[2]); verboseMode=1; break; case LOAD_TECHNOLOGY: cout << "-> Loading technology from file: " << words[2] << endl; rules->readRules(words[2]); break; case LOAD_NETLIST:{ string tipo=upcase(getExt(words[2])); cout << "-> Loading cells netlist from file: " << words[2] << endl; if(tipo=="V"){ Verilog vlog; if(!vlog.readFile(words[2], *circuit)) throw AstranError("Could not read verilog file: " + words[2]); }else {//if(tipo=="SP" || tipo="LIB"){ Spice spice; spice.readFile(words[2], *circuit, false); } } break; case LOAD_LAYOUTS: { cout << "-> Loading LEF library: " << words[2] << endl; Lef lef; lef.readFile(words[2], *circuit, false); } break; case LOAD_PLACEMENT:{ string tipo=upcase(getExt(words[2])); cout << "-> Loading placement from file: " << words[2] << endl; if(tipo=="PL"){ placer->readBookshelfPlacement(words[2]); }else if(tipo=="MPP") placer->readMangoParrotPlacement(words[2]); else throw AstranError("File extension not supported" + getExt(words[2])); } break; case LOAD_ROUTING: cout << "-> Loading routing from file: " << words[2] << endl; router->readRoutingRotdl(words[2]); break; /**** SAVE - 7 ****/ case SAVE_PROJECT: cout << "-> Saving project to file: " << words[2] << endl; saveProjectConfig(words[2], removeExt(words[2])); break; case SAVE_TECHNOLOGY: rules->saveRules(words[2]); break; case SAVE_NETLIST:{ cout << "-> Saving spice netlist to file: " << words[2] << endl; Spice spice; spice.saveFile(words[2], *circuit); } break; case SAVE_LAYOUTS:{ cout << "-> Saving layouts to file: " << words[2] << endl; Lef lef; lef.saveFile(words[2], *circuit); } break; case SAVE_PLACEMENT: cout << "-> Saving placement to file: " << words[2] << endl; placer->writeBookshelfFiles(removeExt(getFileName(words[2])), true); break; case SAVE_ROUTING: cout << "-> Saving routing to file: " << words[2] << endl; router->saveRoutingRotdl(words[2]); break; case SAVE_HISTORY: cout << "-> Saving script to file: " << words[2] << endl; saveHistory(words[2]); break; /**** IMPORT - 2 ****/ case IMPORT_NETLIST:{ cout << "-> Importing netlist from file: " << words[2] << endl; Spice spice; spice.readFile(words[2], *circuit, true); } break; case IMPORT_LEF:{ cout << "-> Importing LEF library: " << words[2] << endl; Lef lef; lef.readFile(words[2], *circuit, true); } break; /**** EXPORT - 3 ****/ case EXPORT_LAYOUT:{ string tipo=upcase(getExt(words[3])); string filename=words[3]; if(circuit->getLayout(upcase(words[2]))){ if(tipo=="GDS"){ rules->saveGDSIILayerTable(getPath(filename)+"GDSIILTable.txt"); cout << "-> Saving layout " << words[2] << " to file: " << filename << endl; Gds g(filename); char tmp[20] = " "; strcpy(tmp, words[2].substr(0,19).c_str()); g.open(); g.generateHeader(1); g.generateLibrary(); g.generateLibname(tmp); g.generateUnits(); g.generateStruct(); g.generateStructname(tmp); //Insert Boxes list <Box>::iterator layer_it; map <layer_name , list<Box> >::iterator layers_it; // iterador das camadas for (layers_it = circuit->getLayout(words[2])->layers.begin(); layers_it != circuit->getLayout(words[2])->layers.end(); layers_it++) { if ( !layers_it->second.empty() ) { int layer = strToInt(rules->getGDSIIVal(layers_it->first)); for ( layer_it = layers_it->second.begin(); layer_it != layers_it->second.end(); layer_it++ ){ long int x1 = 2*layer_it->getX1(); long int y1 = 2*layer_it->getY1(); long int x2 = 2*layer_it->getX2(); long int y2 = 2*layer_it->getY2(); if(x2-x1!=0 & y2-y1!=0){ g.generateBox(layer, x1, y1, x2, y2); // cout << layer << "-"<< x1 << "-" << y1 << "-" << x2 << "-" << y2 << endl; g.generateEndelement(); } } } } list<Label>::iterator labels_it; for (labels_it = circuit->getLayout(words[2])->labels.begin(); labels_it != circuit->getLayout(words[2])->labels.end(); labels_it++){ strcpy(tmp, labels_it->text.c_str()); g.generateLabel(strToInt(rules->getGDSIIVal(MET1)), 2*labels_it->pt.getX(), 2*labels_it->pt.getY(), tmp); g.generateEndelement(); } g.generateEndStruct(); g.generateEndLibrary(); }else if(tipo=="C2C"){ Cif cifOut(removeExt(filename)+".cif", *rules); cifOut.cellCif(*(circuit->getLayouts()), words[2]); cifOut.cif2Cadence(name, words[2]); }else if(tipo=="CIF"){ Cif cifOut(filename, *rules); cifOut.cellCif(*(circuit->getLayouts()), words[2]); }else throw AstranError("Unknown file type: " + tipo); }else throw AstranError("Cell not found: " + words[2]); } break; case EXPORT_CELLSIZES: cout << "-> Writing Cell Sizes to file: " << words[2] << endl; circuit->writeCellSizesFile(words[2]); break; case EXPORT_PLACEMENT: cout << "-> Saving placement to file: " << words[2] << endl; placer->writeCadende(words[2]); break; case READ: run(words[1]); break; /**** PLACE - 7 ****/ case PLACE_TERMINALS: placer->placeInterfaceTerminals(); break; case PLACE_FPLACE:{ cout << "-> Writing bookshelf files for placement..." << endl; placer->writeBookshelfFiles("test", false); string cmd = "\"" + placerFile + "\"" + " test > temp.log"; cout << "-> Calling placement tool: " << cmd << endl; FILE *x = _popen(cmd.c_str(), "r"); if ( x == NULL ) throw AstranError("Could not execute: " + cmd); _pclose(x); cout << "-> Placing Cells..." << endl; placer->readBookshelfPlacement("test_mp.pl"); } break; case PLACE_GETWL: placer->checkWL(); break; case PLACE_INSTANCE:{ CLayout *tmp=circuit->getLayout(upcase(words[2])); if(!tmp) throw AstranError("Could not find Layout: " + upcase(words[2])); tmp->placeCell(upcase(words[3]), atoi(words[4].c_str()), atoi(words[5].c_str()), atoi(words[6].c_str()), atoi(words[7].c_str())); break; } case PLACE_AUTOFLIP: placer->autoFlip(); break; case PLACE_INCREMENTAL: placer->incrementalPlacement(router, lpSolverFile); break; case PLACE_CHECK: placer->checkPlacement(); break; /**** ROUTE - 6 ****/ case ROUTE_ROTDL: router->setup(placer->getHSize(), placer->getVSize(), 3); router->rotdl(rotdlFile); break; case ROUTE_PFINDER: router->setup(placer->getHSize(), placer->getVSize(), 3); router->route(atoi(words[2].c_str())); break; case ROUTE_OPTIMIZE: router->optimize(); break; case ROUTE_COMPACT: router->compactLayout(lpSolverFile); break; case ROUTE_TEST: router->test(rotdlFile); break; case ROUTE_CLEAR: router->getPathfinderRt()->clear(); break; /**** PRINT - 4 ****/ case PRINT_INSTANCE: circuit->printInstance(circuit->getLayout(upcase(words[2])), upcase(words[3])); break; case PRINT_CELL: circuit->getCellNetlst(upcase(words[2]))->print(); break; case PRINT_NET: circuit->printNet(upcase(words[2])); break; case PRINT_INTERFACE: circuit->printInterface(upcase(words[2])); break; /**** PREFERENCES - 6 ****/ case SET_PLACER: if (!fileExist(words[2])) throw AstranError("Could not find file: " + words[2]); placerFile=words[2]; cout << "-> Setting placer executable to: " << placerFile << endl; break; case SET_ROTDL: if (!fileExist(words[2])) throw AstranError("Could not find file: " + words[2]); rotdlFile=words[2]; cout << "-> Setting rotdl executable path to: " << rotdlFile << endl; break; case SET_VIEWER: if (!fileExist(words[2])) throw AstranError("Could not find file: " + words[2]); viewerProgram=words[2]; cout << "-> Setting viewer executable path to: " << viewerProgram << endl; break; case SET_LPSOLVE: if (!fileExist(words[2])) throw AstranError("Could not find file: " + words[2]); lpSolverFile=words[2]; cout << "-> Setting lpsolve executable to: " << lpSolverFile << endl; break; case SET_LOG: historyFile = words[2]; remove(historyFile.c_str()); cout << "-> Saving history log to file: " << historyFile << endl; break; case SET_VERBOSEMODE: cout << "-> Setting verbose mode = " << words[2] << endl; verboseMode=atoi(words[2].c_str()); break; /**** TECHNOLOGY - 8 ****/ case SET_TECH_NAME: rules->setTechName(words[3].c_str()); break; case SET_TECH_MLAYERS: rules->setMLayers(words[3].c_str()); break; case SET_TECH_SOI: rules->setSOI(words[3].c_str()); break; case SET_TECH_RESOLUTION: rules->setResolution(atoi(words[3].c_str())); break; case SET_TECH_RULE: tmp=rules->findRule(words[3].c_str()); if (tmp==-1) throw AstranError("Rule not Found: " + words[3]); rules->setRule((rule_name)tmp, atof(words[4].c_str())); break; case SET_TECH_CIF: tmp=rules->findLayerName(words[3].c_str()); if (tmp==-1) throw AstranError("Layer not Found: " + words[3]); rules->setCIFVal((layer_name)tmp, words[4].c_str()); break; case SET_TECH_GDSII: tmp=rules->findLayerName(words[3].c_str()); if (tmp==-1) throw AstranError("Layer not Found: " + words[3]); rules->setGDSIIVal((layer_name)tmp, words[4].c_str()); break; case SET_TECH_VALTECH: tmp=rules->findLayerName(words[3].c_str()); if (tmp==-1) throw AstranError("Layer not Found: " + words[3]); rules->setTechVal((layer_name)tmp, words[4].c_str()); break; /**** CIRCUIT - 8 ****/ case SET_DESIGNNAME: setName(words[2].c_str()); break; case SET_GRID: circuit->setHPitch(atof(words[2].c_str())); circuit->setVPitch(atof(words[3].c_str())); break; case SET_HGRID: circuit->setHPitch(atof(words[2].c_str())); break; case SET_VGRID: circuit->setVPitch(atof(words[2].c_str())); break; case SET_HGRID_OFFSET: circuit->setHGridOffset(upcase(words[2].c_str())=="YES"?true:false); break; case SET_VGRID_OFFSET: circuit->setVGridOffset(upcase(words[2].c_str())=="YES"?true:false); break; case SET_VDDNET: circuit->setVddNet(upcase(words[2].c_str())); break; case SET_GNDNET: circuit->setGndNet(upcase(words[2].c_str())); break; case SET_ROWHEIGHT: circuit->setRowHeight(atoi(words[2].c_str())); break; case SET_SUPPLYSIZE: circuit->setSupplyVSize(atof(words[2].c_str())); break; case SET_NWELLPOS: circuit->setnWellPos(atof(words[2].c_str())); break; case SET_NWELLBORDER: circuit->setnWellBorder(atof(words[2].c_str())); break; case SET_PNSELBORDER: circuit->setpnSelBorder(atof(words[2].c_str())); break; case SET_CELLTEMPLATE: circuit->setCellTemplate(words[2].c_str()); break; /**** FLOORPLAN - 3 ****/ case SET_TOPCELL: circuit->setTopCell(upcase(words[2])); break; case SET_AREA: placer->setArea(atoi(words[2].c_str()), atof(words[3].c_str())); break; case SET_MARGINS: circuit->setMargins(atof(words[2].c_str()), atof(words[3].c_str()), atof(words[4].c_str()), atof(words[5].c_str())); break; case CALCPINSPOS: circuit->calculateCellsPins(); break; /**** CELLGEN - 9 ****/ case CELLGEN_SELECT: autocell->selectCell(circuit,upcase(words[2])); break; case CELLGEN_AUTOFLOW: autocell->autoFlow(lpSolverFile); break; case CELLGEN_FOLD: autocell->calcArea(atoi(words[2].c_str()), atoi(words[3].c_str())); autocell->foldTrans(); break; case CELLGEN_PLACE: autocell->placeTrans(true, atoi(words[2].c_str()), atoi(words[3].c_str()), atoi(words[4].c_str()), atoi(words[5].c_str()), atoi(words[6].c_str()), atoi(words[7].c_str()), atoi(words[8].c_str())); break; case CELLGEN_GETARCCOST: cout << autocell->getRouting()->getArcCost(atoi(words[2].c_str()), atoi(words[3].c_str())); break; case CELLGEN_SETARCCOST: cout << autocell->getRouting()->setArcCost(atoi(words[2].c_str()), atoi(words[3].c_str()), atoi(words[4].c_str())); break; case CELLGEN_ROUTE: autocell->route(atoi(words[2].c_str()), atoi(words[3].c_str()), atoi(words[4].c_str()), atoi(words[5].c_str())); break; case CELLGEN_COMPACT: if(!autocell->compact(lpSolverFile, atoi(words[2].c_str()), atoi(words[3].c_str()), atoi(words[4].c_str()), atoi(words[5].c_str()), atoi(words[6].c_str()), atoi(words[7].c_str()), atoi(words[8].c_str()), atoi(words[9].c_str()), atoi(words[10].c_str()), atoi(words[11].c_str()))) throw AstranError("Could not solve the ILP model. Try to adjust the constraints!"); break; /**** HELP - 2 ****/ case HELP: for (int i=0; i<NR_COMMANDS; ++i) cout << commands_lst[i].name << endl; cout << "-> Note: For detailed instructions, use command \"HELP <str_Command>\"\n\n"; break; case HELP_PARAM: for (int i=0; i<NR_COMMANDS; ++i) if (commands_lst[i].name.find(upcase(words[1])) != string::npos) cout << commands_lst[i].name << " - " << commands_lst[i].desc << endl; break; case COMMENT: break; case EXIT: exit(EXIT_SUCCESS); break; } } } catch (AstranError& e){ cout << "** ERROR: " << e.what() << endl; return false; } return true; }
void Pathfinder::routeNets(int nrAttempts){ list<int> targetNodes; map<int,t_nets>::iterator nets_it; list<int>::iterator netTree_it; vector<int>::iterator netTree_it2; vector<int>::iterator nodes_it; //Initializations clock_t start=clock(); actualAttempt=0; trace_id=0; conflicts=0; visited=0; netlist.erase(blockageNet); for(nets_it=netlist.begin(); nets_it!=netlist.end(); ++nets_it){ //cout << (nets_it->second).nodes[0] << endl; if(rand()%2==0) getCenter((nets_it->second).nodes); //cout << (nets_it->second).nodes[0] << endl; } //Pathfinder Routing cout << "-> Routing graph..." << endl; do{ // Loop over all nets for(nets_it=netlist.begin(); nets_it!=netlist.end(); ++nets_it){ if(nets_it->second.conflict){ //If conflict exists, check it out and do rip-upand re-route. Otherwise jump net. --conflicts; nets_it->second.conflict=false; for(netTree_it=nets_it->second.netTree.begin();netTree_it!=nets_it->second.netTree.end(); ++netTree_it){ if(graph[*netTree_it].nrNets>1){ nets_it->second.conflict=true; break; } } } if(nets_it->second.conflict | !actualAttempt){ //Rip-up net for(netTree_it=(nets_it->second).netTree.begin(); netTree_it!=(nets_it->second).netTree.end(); ++netTree_it){ if(!isSource(*netTree_it)){ --graph[*netTree_it].nrNets; if(getNet(*netTree_it)==nets_it->first) graph[*netTree_it].net=0; } } //Clear netTree of the net (nets_it->second).netTree.clear(); (nets_it->second).routeResult.clear(); //Create list of target nodes targetNodes.clear(); for(nodes_it=(nets_it->second).nodes.begin();nodes_it!=(nets_it->second).nodes.end(); ++nodes_it){ targetNodes.push_back(*nodes_it); //cout << *nodes_it << endl; } //Insert the first node to the tree (nets_it->second).netTree.push_back(*targetNodes.begin()); targetNodes.erase(targetNodes.begin()); //Loop until all sinks have been found while(!targetNodes.empty() && aStar(nets_it, targetNodes)){} //Route the tree to the closest node in the graph if(!targetNodes.empty()) break; if(nets_it->second.conflict) ++conflicts; } } //update H cost ++trace_id; for(nets_it=netlist.begin(); nets_it!=netlist.end(); ++nets_it){ if(nets_it->second.conflict){ for(netTree_it=nets_it->second.netTree.begin();netTree_it!=nets_it->second.netTree.end(); ++netTree_it){ if(graph[*netTree_it].nrNets>1 && graph[*netTree_it].idNr!=trace_id){ ++graph[*netTree_it].history; graph[*netTree_it].idNr=trace_id; } } } } if(!(++actualAttempt%15)) cerr << "." << conflicts << "."; // cout << conflicts << endl; }while(targetNodes.empty() && conflicts && actualAttempt<nrAttempts); // cout << visited << endl; cout << endl << "-> Runtime = " << float((clock()-start)/(CLOCKS_PER_SEC/1000))/1000 << "s" << endl; if(!targetNodes.empty()) cout << "-> Impossible to route net: " << nets_it->first << endl; if(conflicts || !targetNodes.empty()){ cout <<"-> Unable to route the circuit after "; cout << actualAttempt << " attempts."<< endl; }else{ cout <<"-> Routing finished in "; cout << actualAttempt << " attempts."<< endl; showResult(); } if(!targetNodes.empty() || conflicts) throw AstranError("Could not finish routing"); }
void Spice::readFile(string nome, Circuit& netlist, bool reading_cadence) { ifstream arq (nome.c_str()); string linha; if (!arq.is_open()) throw AstranError("Could not open Spice file: " + nome ); vector<string> palavras; string palavra; CellNetlst subcktCell,topCell; CellNetlst *currentCell=&topCell; topCell.setName(upcase(removeExt(getFileName(nome)))); string cellName; unsigned int lineNr=0; while (!arq.eof()){ lineNr++; getline(arq,linha); palavras.clear(); istrstream clin(linha.c_str()); while (clin>>palavra) palavras.push_back(upcase(palavra)); if (palavras.size() == 0 || palavras[0] == ".GLOBAL") continue; if (palavras[0] == "*INTERFACE"){ if(palavras.size() == 4 || palavras.size() == 6){ IOType type; direction orient; switch(palavras[2][palavras[2].size()-1]){ case 'N': orient=N; break; case 'S': orient=S; break; case 'E': orient=E; break; case 'W': orient=W; break; default: throw AstranError("Line" + intToStr(lineNr) + ": Interface orientation unknown."); } switch(palavras[3][0]){ case 'I': type=IOTYPE_INPUT; break; case 'O': type=IOTYPE_OUTPUT; break; default: throw AstranError("Line" + intToStr(lineNr) + ": Interface type unknown. Use INPUT or OUTPUT"); } topCell.insertInOut(palavras[1]); netlist.insertInterface(palavras[1], orient, type, 0, 0); } else throw AstranError("Line" + intToStr(lineNr) + ": Number of parameters for *interface is not correct"); continue; } if (reading_cadence && palavras[0] == "*" && palavras.size() == 5 && palavras[1] == "SUBCIRCUIT"){ currentCell->clear(); topCell.setName(palavras[4].substr(0,palavras[4].size()-1)); } if (palavras[0][0] == '*' || palavras[0][0] == 'C' || palavras[0][0] == '+' || palavras[0][0] == 'D' || (palavras[0][0]=='X' && reading_cadence)) // corrigir aqui para ler o '+' e ignorar os parâmetros desnecessários continue; if (palavras[0] == ".MODEL" || palavras[0] == ".END") break; if (palavras[0] == ".SUBCKT" && currentCell==&topCell && !reading_cadence){ // It's a new cell definition. . . subcktCell.clear(); currentCell=&subcktCell; cellName=palavras[1]; // compare if subcircuit name is the same as the top cell name if(cellName == topCell.getName()){ string topname = topCell.getName() + "-TOP"; topCell.setName(topname); } for (int p=2; p<palavras.size(); p++) currentCell->insertInOut(palavras[p]); } else if (palavras[0] == string(".INCLUDE")){ readFile(getPath(nome)+palavras[1],netlist,reading_cadence); // throw AstranError("Could not read included file in line: " + intToStr(lineNr)); } // declaring transistor in subcircuit read from Cadence else if (palavras[0][0] == 'M' && palavras.size()>=5){ // insert in and out pins if (reading_cadence){ for (int p=1; p<5; ++p){ if (!isNumber(palavras[p]) || palavras[p] == "0") currentCell->insertInOut(palavras[p]); } } // identify transistor type transType type; if(palavras[5]=="PMOS" || palavras[5]=="CMOSP" || palavras[5]=="MODP" || palavras[5]=="PMOS_VTL") type=PMOS; else if(palavras[5]=="NMOS" || palavras[5]=="CMOSN" || palavras[5]=="MODN" || palavras[5]=="NMOS_VTL") type=NMOS; else throw AstranError("Line" + intToStr(lineNr) + ": Parameter " + palavras[5] + " is incorrect. Use NMOS or PMOS"); // get parameters' values float length=0, width=0; for (int p=6; p<palavras.size(); p++){ int pos=palavras[p].find("="); string parm=palavras[p].substr(0,pos++); float tam=atof((palavras[p].substr(pos)).c_str())*getFactor(palavras[p][palavras[p].size()-1])*getFactor(palavras[p][palavras[p].size()-2]); if(parm=="L") length=tam; else if(parm=="W") width=tam; else if(parm!="AD" && parm!="PD" && parm!="AS" && parm!="PS" && parm!="NRD" && parm!="NRS" && parm!="M") throw AstranError("Line" + intToStr(lineNr) + ": Parameter " + parm + " not supported"); } // insert transistor in cell currentCell->insertTrans(palavras[0], palavras[1], palavras[2], palavras[3], type, length, width); } else if (palavras[0][0] == 'X' && !reading_cadence){ string instName=palavras[0]; vector<string> net_ids; int p; for (p=1; p<palavras.size()-1; p++) net_ids.push_back(palavras[p]); currentCell->insertInstance(instName, palavras[p], net_ids); } else if (currentCell==&subcktCell && palavras[0] == ".ENDS"){ currentCell->setName(cellName); netlist.insertCell(*currentCell); currentCell=&topCell; } else throw AstranError("Line" + intToStr(lineNr)); } if(topCell.getNets().size() != 0) netlist.insertCell(topCell); }