00001
00026 #ifndef NETLISTPARSER_H_
00027 #define NETLISTPARSER_H_
00028
00029 #include <vector>
00030 #include <string>
00031 #include <map>
00032 #include <set>
00033 #include <iostream>
00034 #include <fstream>
00035 #include <algorithm>
00036 #include <utility>
00037 #include <boost/utility.hpp>
00038
00039 #include <cstring>
00040 #include <cassert>
00041 #include <cstdio>
00042
00043 #include "logicDefs.h"
00044 #include "comDefs.h"
00045
00051 class NetlistTokenizer: public boost::noncopyable {
00083 private:
00085 std::ifstream ifs;
00086
00088 const char* delim;
00089
00091 const char* comments;
00092
00093
00095 char* linePtr;
00096
00098 char* nextTokPtr;
00099
00101 char* currTokPtr;
00102
00103 private:
00104
00108 bool isCommentBegin () const {
00109 std::string tok(nextTokPtr);
00110 if (tok.find (comments) == 0) {
00111 return true;
00112 } else {
00113 return false;
00114 }
00115 }
00116
00121 char* getNextLine () {
00122
00123 std::string currLine;
00124
00125 if (ifs.eof () || ifs.bad ()) {
00126 linePtr = NULL;
00127 }
00128 else {
00129
00130 std::getline (ifs, currLine);
00131
00132 delete[] linePtr;
00133 linePtr = new char[currLine.size () + 1];
00134 strcpy (linePtr, currLine.c_str ());
00135 }
00136
00137 return linePtr;
00138 }
00139
00143 char* readNextToken () {
00144 nextTokPtr = strtok (NULL, delim);
00145
00146 while (nextTokPtr == NULL || isCommentBegin ()) {
00147 linePtr = getNextLine ();
00148 if (linePtr == NULL) {
00149 nextTokPtr = NULL;
00150 break;
00151 }
00152 nextTokPtr = strtok (linePtr, delim);
00153 }
00154 return nextTokPtr;
00155 }
00156
00157 public:
00165 NetlistTokenizer (const char* fileName, const char* delim, const char* comments)
00166 : ifs(fileName), delim (delim), comments(comments), linePtr (NULL), currTokPtr (NULL) {
00167
00168 if (!ifs.good ()) {
00169 std::cerr << "Failed to open this file for reading: " << fileName << std::endl;
00170 abort ();
00171 }
00172 nextTokPtr = readNextToken();
00173
00174 }
00175
00179 const std::string nextToken () {
00180 assert (nextTokPtr != NULL);
00181
00182 std::string retval(nextTokPtr);
00183 nextTokPtr = readNextToken ();
00184
00185 return retval;
00186 }
00187
00188 bool hasMoreTokens () const {
00189 return !ifs.eof() || nextTokPtr != NULL;
00190 }
00191 };
00192
00197 struct GateRec {
00198
00200 std::string name;
00201
00203 std::vector<std::string> outputs;
00204
00206 std::vector<std::string> inputs;
00207
00209 SimTime delay;
00210
00216 void addOutput(const std::string& net) {
00217 outputs.push_back(net);
00218 }
00219
00225 void addInput(const std::string& net) {
00226 inputs.push_back(net);
00227 }
00228
00234 void setDelay(const SimTime& delay) {
00235 this->delay = delay;
00236 }
00237
00243 void setName(const std::string& name) {
00244 this->name = name;
00245 }
00246
00252 const std::string& getName() const {
00253 return name;
00254 }
00255 };
00256
00260 class NetlistParser {
00261 public:
00262
00264 static const char* DELIM;
00265
00267 static const char* COMMENTS;
00268
00269 public:
00270 typedef std::map<std::string, std::vector<std::pair<SimTime, LogicVal> > > StimulusMapType;
00271
00272 private:
00274 const char* netlistFile;
00275
00277 std::vector<std::string> inputNames;
00278
00280 std::vector<std::string> outputNames;
00281
00283 std::map<std::string, LogicVal> outValues;
00284
00286 StimulusMapType inputStimulusMap;
00287
00289 std::vector<GateRec> gates;
00290
00292 SimTime finishTime;
00293
00294
00295
00296 private:
00297
00301 static const std::set<std::string> oneInputGates () {
00302 std::set<std::string> oneInSet;
00303 oneInSet.insert (toLowerCase (std::string("INV")));
00304 return oneInSet;
00305 }
00306
00310 static const std::set<std::string> twoInputGates () {
00311 std::set<std::string> twoInSet;
00312 twoInSet.insert (toLowerCase (std::string ("AND2")));
00313 twoInSet.insert (toLowerCase (std::string ("OR2")));
00314 twoInSet.insert (toLowerCase (std::string ("NAND2")));
00315 twoInSet.insert (toLowerCase (std::string ("NOR2")));
00316 twoInSet.insert (toLowerCase (std::string ("XOR2")));
00317 twoInSet.insert (toLowerCase (std::string ("XNOR2")));
00318 return twoInSet;
00319 }
00320
00321
00328 static void parsePortList(NetlistTokenizer& tokenizer, std::vector<std::string>& portNames) {
00329 std::string token = toLowerCase (tokenizer.nextToken ());
00330 while (token != ("end")) {
00331 portNames.push_back(token);
00332 token = toLowerCase (tokenizer.nextToken ());
00333 }
00334 }
00335
00343 static void parseOutValues(NetlistTokenizer& tokenizer, std::map<std::string, LogicVal>& outValues) {
00344 std::string token = toLowerCase (tokenizer.nextToken ());
00345 while (token != ("end")) {
00346 std::string outName = token;
00347 token = toLowerCase (tokenizer.nextToken ());
00348 LogicVal value = token[0];
00349 token = toLowerCase (tokenizer.nextToken ());
00350
00351 outValues.insert (std::make_pair(outName, value));
00352 }
00353 }
00354
00361 static void parseInitList(NetlistTokenizer& tokenizer, StimulusMapType& inputStimulusMap) {
00362
00363 std::string input = toLowerCase (tokenizer.nextToken ());
00364
00365 std::string token = toLowerCase (tokenizer.nextToken ());
00366
00367 std::vector<std::pair<SimTime, LogicVal> > timeValList;
00368 while (token != ("end")) {
00369
00370 SimTime t = static_cast<SimTime> (atol (token.c_str ()));
00371
00372 token = toLowerCase (tokenizer.nextToken ());
00373 LogicVal v = token[0];
00374
00375 timeValList.push_back (std::make_pair(t, v));
00376
00377 token = toLowerCase (tokenizer.nextToken ());
00378 }
00379
00380 inputStimulusMap.insert (std::make_pair(input, timeValList));
00381 }
00382
00389 static void parseNetlist(NetlistTokenizer& tokenizer, std::vector<GateRec>& gates) {
00390
00391 std::string token = toLowerCase (tokenizer.nextToken ());
00392
00393 while (token != ("end")) {
00394
00395 if (oneInputGates().count (token) > 0) {
00396
00397 GateRec g;
00398 g.setName(token);
00399
00400 token = toLowerCase (tokenizer.nextToken ());
00401 g.addOutput(token);
00402
00403 token = toLowerCase (tokenizer.nextToken ());
00404 g.addInput(token);
00405
00406
00407 token = toLowerCase (tokenizer.nextToken ());
00408 if (token[0] == '#') {
00409 token = token.substr(1);
00410 SimTime d = static_cast<SimTime> (atol (token.c_str ()));
00411 g.setDelay(d);
00412 gates.push_back (g);
00413 } else {
00414 gates.push_back (g);
00415 continue;
00416 }
00417 } else if (twoInputGates().count (token) > 0) {
00418 GateRec g;
00419 g.setName(token);
00420
00421 token = toLowerCase (tokenizer.nextToken ());
00422 g.addOutput(token);
00423
00424 token = toLowerCase (tokenizer.nextToken ());
00425 g.addInput(token);
00426
00427 token = toLowerCase (tokenizer.nextToken ());
00428 g.addInput(token);
00429
00430
00431 token = toLowerCase (tokenizer.nextToken ());
00432 if (token[0] == '#') {
00433 token = token.substr(1);
00434 SimTime d = static_cast<SimTime> (atol (token.c_str ()));
00435 g.setDelay(d);
00436 gates.push_back (g);
00437 } else {
00438 gates.push_back (g);
00439 continue;
00440 }
00441 } else {
00442 std::cerr << "Unknown type of gate " << token << std::endl;
00443 abort ();
00444 }
00445
00446
00447 token = toLowerCase (tokenizer.nextToken ());
00448 }
00449 }
00450
00451 public:
00457 NetlistParser(const char* netlistFile): netlistFile(netlistFile) {
00458 parse(netlistFile);
00459 }
00460
00474 void parse(const char* fileName) {
00475 std::cout << "input: reading circuit from file: " << fileName << std::endl;
00476
00477
00478 NetlistTokenizer tokenizer (fileName, DELIM, COMMENTS);
00479
00480 std::string token;
00481
00482 while (tokenizer.hasMoreTokens()) {
00483
00484 token = toLowerCase (tokenizer.nextToken ());
00485
00486 if (token == ("inputs")) {
00487 parsePortList(tokenizer, inputNames);
00488 } else if (token == ("outputs")) {
00489 parsePortList(tokenizer, outputNames);
00490 } else if (token == ("outvalues")) {
00491 parseOutValues(tokenizer, outValues);
00492 } else if (token == ("finish")) {
00493 token = toLowerCase (tokenizer.nextToken ());
00494 finishTime = static_cast<SimTime> (atol (token.c_str ()));
00495 } else if (token == ("initlist")) {
00496 parseInitList(tokenizer, inputStimulusMap);
00497 } else if (token == ("netlist")) {
00498 parseNetlist(tokenizer, gates);
00499 }
00500 }
00501
00502 }
00503
00504
00510 const SimTime& getFinishTime() const {
00511 return finishTime;
00512 }
00513
00519 const char* getNetlistFile() const {
00520 return netlistFile;
00521 }
00522
00528 const std::vector<std::string>& getInputNames() const {
00529 return inputNames;
00530 }
00531
00537 const std::vector<std::string>& getOutputNames() const {
00538 return outputNames;
00539 }
00540
00546 const std::map<std::string, LogicVal>& getOutValues() const {
00547 return outValues;
00548 }
00549
00555 const StimulusMapType& getInputStimulusMap() const {
00556 return inputStimulusMap;
00557 }
00558
00564 const std::vector<GateRec>& getGates() const {
00565 return gates;
00566 }
00567
00568 };
00569
00570
00571 #endif