101 lines
3.5 KiB
C++
101 lines
3.5 KiB
C++
#include "circuit.h"
|
|
|
|
#include <iostream>
|
|
#include <fstream>
|
|
#include <string>
|
|
#include <regex>
|
|
#include <set>
|
|
|
|
std::string trim(const std::string& s) {
|
|
auto wsfront = std::find_if_not(s.begin(), s.end(), [](int c){ return std::isspace(c); });
|
|
auto wsback = std::find_if_not(s.rbegin(), s.rend(), [](int c){ return std::isspace(c); }).base();
|
|
return (wsback <= wsfront ? std::string() : std::string(wsfront, wsback));
|
|
}
|
|
|
|
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::string line;
|
|
while(std::getline(file, line)) {
|
|
if(line[0] == '#') continue;
|
|
if(line == "\r" || line == "") continue;
|
|
|
|
std::cmatch m;
|
|
if(std::regex_match(line.c_str(), m, std::regex("INPUT\\s*\\(\\s*(.*)\\s*\\)\\s*"))) {
|
|
|
|
Gate *input = new Gate();
|
|
input->name = m.str(1);
|
|
input->type = Gate::INPUT;
|
|
input->value = Gate::VAL_X;
|
|
name2gate.insert(std::make_pair(input->name, input));
|
|
|
|
|
|
std::cout << "input -> $" << input->name << "$" << std::endl;
|
|
|
|
PIs.push_back(input);
|
|
} else if(std::regex_match(line.c_str(), m, std::regex("OUTPUT\\s*\\(\\s*(.*)\\s*\\)\\s*"))) {
|
|
|
|
Gate *output = new Gate();
|
|
output->name = m.str(1);
|
|
output->type = Gate::OUTPUT;
|
|
output->value = Gate::VAL_X;
|
|
name2gate.insert(std::make_pair(output->name, output));
|
|
|
|
POs.push_back(output);
|
|
} else if(std::regex_match(line.c_str(), m, std::regex("\\s*(\\S+)\\s*=\\s*(\\w+)\\s*\\(\\s*(.*)\\s*\\)\\s*"))) {
|
|
|
|
std::string output_name = m.str(1);
|
|
std::string gate_name = m.str(2);
|
|
std::string list = m.str(3);
|
|
|
|
Gate *gate = new Gate();
|
|
|
|
gate->name = output_name;
|
|
gate->value = Gate::VAL_X;
|
|
|
|
name2gate.insert(std::make_pair(gate->name, gate));
|
|
|
|
// split by ","
|
|
std::regex pattern(R"(\s*,\s*)");
|
|
std::sregex_token_iterator it(list.begin(), list.end(), pattern, -1);
|
|
std::sregex_token_iterator end;
|
|
|
|
while (it != end) {
|
|
std::string in = trim(*it++);
|
|
if(!name2gate.count(in)) {
|
|
printf("Error while reading file: $%s$ is not defined before used.\n", in.c_str());
|
|
exit(1);
|
|
}
|
|
Gate* in_gate = name2gate[in];
|
|
|
|
gate->inputs.push_back(in_gate);
|
|
in_gate->outputs.push_back(gate);
|
|
}
|
|
|
|
if(gate_name == "AND") { gate->type = Gate::AND; }
|
|
else if(gate_name == "NAND") { gate->type = Gate::NAND; }
|
|
else if(gate_name == "OR") { gate->type = Gate::OR; }
|
|
else if(gate_name == "NOR") { gate->type = Gate::NOR; }
|
|
else if(gate_name == "XOR") { gate->type = Gate::XOR; }
|
|
else if(gate_name == "XNOR") { gate->type = Gate::XNOR; }
|
|
else if(gate_name == "NOT") { gate->type = Gate::NOT; }
|
|
else if(gate_name == "BUF") { gate->type = Gate::BUF; }
|
|
else {
|
|
printf("Error while reading file: %s is not a valid gate.\n", gate_name.c_str());
|
|
exit(1);
|
|
}
|
|
|
|
} else {
|
|
printf("Error while reading file: \"%s\" is a wrong line.\n", line.c_str());
|
|
exit(1);
|
|
}
|
|
}
|
|
} |