//------------------------------------------------------------------------------ std::string changeExt(const std::string& fileName, const std::string& newext) { return removeExt(fileName)+ "." + newext; }
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 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); }