148 lines
4.6 KiB
C++
148 lines
4.6 KiB
C++
#include "circuit.h"
|
|
|
|
#include <iostream>
|
|
#include <fstream>
|
|
#include <string>
|
|
#include <regex>
|
|
#include <set>
|
|
|
|
void line2tokens(const std::string &line, std::vector<std::string> &tokens) {
|
|
std::string token;
|
|
for(char c : line) {
|
|
if(c == ' ' || c == '\t' || c == '\r' || c == '\n') continue;
|
|
if(c == '=' || c == ',' || c == '(' || c == ')') {
|
|
if(!token.size()) continue;
|
|
tokens.push_back(token);
|
|
token.clear(); token += c;
|
|
tokens.push_back(token);
|
|
token.clear();
|
|
} else {
|
|
token += c;
|
|
}
|
|
}
|
|
if(token.size()) {
|
|
tokens.push_back(token);
|
|
}
|
|
}
|
|
|
|
void Circuit::parse_from_file(const char *filename) {
|
|
|
|
std::ifstream file(filename);
|
|
if(!file.is_open()) {
|
|
printf("Error while reading %s\n", filename);
|
|
exit(1);
|
|
}
|
|
|
|
// buf 10MB
|
|
file.rdbuf()->pubsetbuf(0, 10 * 1024 * 1024);
|
|
|
|
std::vector<std::string> bufPO;
|
|
|
|
std::string line;
|
|
while(std::getline(file, line)) {
|
|
if(line[0] == '#') continue;
|
|
if(line == "\r" || line == "") continue;
|
|
|
|
std::vector<std::string> tokens;
|
|
|
|
line2tokens(line, tokens);
|
|
// std::cout << line << std::endl;
|
|
// std::cout << "tokens: ";
|
|
// for(auto &token : tokens) {
|
|
// std::cout << "$" << token << "$ ";
|
|
// }
|
|
// std::cout << std::endl;
|
|
|
|
// gate
|
|
if(tokens.size() >= 6 && tokens[1] == "=" && tokens[3] == "(" && tokens.back() == ")") {
|
|
std::vector<std::string> ins;
|
|
|
|
for(int i=4; i<tokens.size()-1; i+=2) {
|
|
if(tokens[i] == ",") {
|
|
printf("Error while reading line: %s\n", line.c_str());
|
|
exit(1);
|
|
}
|
|
ins.push_back(tokens[i]);
|
|
}
|
|
for(int i=5; i<tokens.size()-1; i+=2) {
|
|
if(tokens[i] != ",") {
|
|
printf("Error while reading line: %s\n", line.c_str());
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
Gate* gate = new Gate();
|
|
gate->name = tokens[0];
|
|
gate->propagate = false;
|
|
gate->stem = false;
|
|
gate->pi = false;
|
|
gate->po = false;
|
|
|
|
|
|
for(auto &in : ins) {
|
|
if(!name2gate.count(in)) {
|
|
printf("Error while reading file: gate %s used before defination.\n", in.c_str());
|
|
exit(1);
|
|
}
|
|
|
|
auto in_gate = name2gate[in];
|
|
|
|
gate->inputs.push_back(in_gate);
|
|
in_gate->outputs.push_back(gate);
|
|
}
|
|
|
|
if(tokens[2] == "AND") { gate->type = Gate::AND; }
|
|
else if(tokens[2] == "NAND") { gate->type = Gate::NAND; }
|
|
else if(tokens[2] == "OR") { gate->type = Gate::OR; }
|
|
else if(tokens[2] == "NOR") { gate->type = Gate::NOR; }
|
|
else if(tokens[2] == "XOR") { gate->type = Gate::XOR; }
|
|
else if(tokens[2] == "XNOR") { gate->type = Gate::XNOR; }
|
|
else if(tokens[2] == "NOT") { gate->type = Gate::NOT; }
|
|
else if(tokens[2] == "BUFF") { gate->type = Gate::BUF; }
|
|
else if(tokens[2] == "BUF") { gate->type = Gate::BUF; }
|
|
else {
|
|
printf("Error while reading file: %s is not a valid gate.\n", tokens[2].c_str());
|
|
exit(1);
|
|
}
|
|
|
|
name2gate.insert(std::make_pair(gate->name, gate));
|
|
gates.push_back(gate);
|
|
}
|
|
// input
|
|
else if(tokens.size() == 4 && tokens[0] == "INPUT" && tokens[1] == "(" && tokens[3] == ")") {
|
|
Gate* gate = new Gate();
|
|
gate->name = tokens[2];
|
|
gate->type = Gate::INPUT;
|
|
gate->propagate = false;
|
|
gate->stem = true;
|
|
gate->pi = true;
|
|
gate->po = false;
|
|
|
|
name2gate.insert(std::make_pair(gate->name, gate));
|
|
gates.push_back(gate);
|
|
PIs.push_back(gate);
|
|
}
|
|
// gate
|
|
else if(tokens.size() == 4 && tokens[0] == "OUTPUT" && tokens[1] == "(" && tokens[3] == ")") {
|
|
bufPO.push_back(tokens[2]);
|
|
}
|
|
// invalid line
|
|
else {
|
|
printf("Error while reading line: %s\n", line.c_str());
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
// handle PO
|
|
for(auto& po_name : bufPO) {
|
|
if(!name2gate.count(po_name)) {
|
|
printf("Error while reading file: po %s is not a exist gate.\n", po_name.c_str());
|
|
exit(1);
|
|
}
|
|
|
|
Gate* po = name2gate[po_name];
|
|
po->po = true;
|
|
po->stem = true;
|
|
POs.push_back(po);
|
|
}
|
|
} |