更高效的文件解析
This commit is contained in:
parent
16b17596e0
commit
d3b23cbfb4
30
circuit.cpp
30
circuit.cpp
@ -0,0 +1,30 @@
|
|||||||
|
#include "circuit.h"
|
||||||
|
|
||||||
|
#include <queue>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
void Circuit::cal_topo_index() {
|
||||||
|
int topo = 1;
|
||||||
|
std::queue<Gate*> q;
|
||||||
|
|
||||||
|
std::unordered_map<Gate*, int> ins;
|
||||||
|
for(Gate* gate : gates) {
|
||||||
|
ins[gate] = gate->inputs.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto in : PIs) {
|
||||||
|
in->topo = topo++;
|
||||||
|
q.push(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
while(!q.empty()) {
|
||||||
|
Gate* g = q.front(); q.pop();
|
||||||
|
for(Gate* out : g->outputs) {
|
||||||
|
ins[out]--;
|
||||||
|
if(ins[out] == 0) {
|
||||||
|
out->topo = topo++;
|
||||||
|
q.push(out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
class Gate {
|
class Gate {
|
||||||
public:
|
public:
|
||||||
|
int topo;
|
||||||
std::string name;
|
std::string name;
|
||||||
enum { AND, NAND, OR, NOR, XOR, XNOR, NOT, BUF, INPUT, OUTPUT } type;
|
enum { AND, NAND, OR, NOR, XOR, XNOR, NOT, BUF, INPUT, OUTPUT } type;
|
||||||
enum { VAL_ZERO, VAL_ONE, VAL_X } value;
|
enum { VAL_ZERO, VAL_ONE, VAL_X } value;
|
||||||
@ -15,6 +16,9 @@ class Circuit {
|
|||||||
public:
|
public:
|
||||||
std::vector<Gate*> PIs;
|
std::vector<Gate*> PIs;
|
||||||
std::vector<Gate*> POs;
|
std::vector<Gate*> POs;
|
||||||
|
std::vector<Gate*> gates;
|
||||||
std::unordered_map<std::string, Gate*> name2gate;
|
std::unordered_map<std::string, Gate*> name2gate;
|
||||||
void parse_from_file(const char *filename);
|
void parse_from_file(const char *filename);
|
||||||
|
void cal_topo_index();
|
||||||
|
void cal_headlines();
|
||||||
};
|
};
|
13
main.cpp
13
main.cpp
@ -1,5 +1,6 @@
|
|||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
|
||||||
#include "circuit.h"
|
#include "circuit.h"
|
||||||
@ -16,11 +17,15 @@ int main(int args, char* argv[]) {
|
|||||||
printf("parsing file %s...\n", argv[1]);
|
printf("parsing file %s...\n", argv[1]);
|
||||||
circuit.parse_from_file(argv[1]);
|
circuit.parse_from_file(argv[1]);
|
||||||
printf("====== Circuit Statistics ====== \n");
|
printf("====== Circuit Statistics ====== \n");
|
||||||
printf("PI:\t%d\n", circuit.PIs.size());
|
printf("PI:\t%ld\n", circuit.PIs.size());
|
||||||
printf("PO:\t%d\n", circuit.POs.size());
|
printf("PO:\t%ld\n", circuit.POs.size());
|
||||||
printf("Gates:\t%d\n", circuit.name2gate.size());
|
printf("Gates:\t%ld\n", circuit.name2gate.size());
|
||||||
|
|
||||||
|
printf("cal topo index ...\n");
|
||||||
|
circuit.cal_topo_index();
|
||||||
|
for(Gate* gate : circuit.gates) {
|
||||||
|
assert(gate->topo > 0);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
2
makefile
2
makefile
@ -7,7 +7,7 @@
|
|||||||
#编译工具用g++,以同时支持C和C++程序,以及二者的混合编译
|
#编译工具用g++,以同时支持C和C++程序,以及二者的混合编译
|
||||||
CC=g++
|
CC=g++
|
||||||
|
|
||||||
CPPFLAGS=-O3
|
CPPFLAGS=-O3 -std=c++17
|
||||||
|
|
||||||
#使用$(winldcard *.c)来获取工作目录下的所有.c文件的列表
|
#使用$(winldcard *.c)来获取工作目录下的所有.c文件的列表
|
||||||
#sources:=main.cpp command.c
|
#sources:=main.cpp command.c
|
||||||
|
152
parser.cpp
152
parser.cpp
@ -6,10 +6,23 @@
|
|||||||
#include <regex>
|
#include <regex>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
std::string trim(const std::string& s) {
|
void line2tokens(const std::string &line, std::vector<std::string> &tokens) {
|
||||||
auto wsfront = std::find_if_not(s.begin(), s.end(), [](int c){ return std::isspace(c); });
|
std::string token;
|
||||||
auto wsback = std::find_if_not(s.rbegin(), s.rend(), [](int c){ return std::isspace(c); }).base();
|
for(char c : line) {
|
||||||
return (wsback <= wsfront ? std::string() : std::string(wsfront, wsback));
|
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) {
|
void Circuit::parse_from_file(const char *filename) {
|
||||||
@ -23,79 +36,102 @@ void Circuit::parse_from_file(const char *filename) {
|
|||||||
// buf 10MB
|
// buf 10MB
|
||||||
file.rdbuf()->pubsetbuf(0, 10 *1024 * 1024);
|
file.rdbuf()->pubsetbuf(0, 10 *1024 * 1024);
|
||||||
|
|
||||||
|
std::vector<std::string> bufPO;
|
||||||
|
|
||||||
std::string line;
|
std::string line;
|
||||||
while(std::getline(file, line)) {
|
while(std::getline(file, line)) {
|
||||||
if(line[0] == '#') continue;
|
if(line[0] == '#') continue;
|
||||||
if(line == "\r" || line == "") continue;
|
if(line == "\r" || line == "") continue;
|
||||||
|
|
||||||
std::cmatch m;
|
std::vector<std::string> tokens;
|
||||||
if(std::regex_match(line.c_str(), m, std::regex("INPUT\\s*\\(\\s*(.*)\\s*\\)\\s*"))) {
|
|
||||||
|
|
||||||
Gate *input = new Gate();
|
line2tokens(line, tokens);
|
||||||
input->name = m.str(1);
|
// std::cout << line << std::endl;
|
||||||
input->type = Gate::INPUT;
|
// std::cout << "tokens: ";
|
||||||
input->value = Gate::VAL_X;
|
// for(auto &token : tokens) {
|
||||||
name2gate.insert(std::make_pair(input->name, input));
|
// std::cout << "$" << token << "$ ";
|
||||||
|
// }
|
||||||
|
// std::cout << std::endl;
|
||||||
|
|
||||||
|
// gate
|
||||||
|
if(tokens.size() >= 6 && tokens[1] == "=" && tokens[3] == "(" && tokens.back() == ")") {
|
||||||
|
std::vector<std::string> ins;
|
||||||
|
|
||||||
std::cout << "input -> $" << input->name << "$" << std::endl;
|
for(int i=4; i<tokens.size()-1; i+=2) {
|
||||||
|
if(tokens[i] == ",") {
|
||||||
PIs.push_back(input);
|
printf("Error while reading line: %s\n", line.c_str());
|
||||||
} 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);
|
exit(1);
|
||||||
}
|
}
|
||||||
Gate* in_gate = name2gate[in];
|
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->value = Gate::VAL_X;
|
||||||
|
|
||||||
|
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);
|
gate->inputs.push_back(in_gate);
|
||||||
in_gate->outputs.push_back(gate);
|
in_gate->outputs.push_back(gate);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(gate_name == "AND") { gate->type = Gate::AND; }
|
if(tokens[2] == "AND") { gate->type = Gate::AND; }
|
||||||
else if(gate_name == "NAND") { gate->type = Gate::NAND; }
|
else if(tokens[2] == "NAND") { gate->type = Gate::NAND; }
|
||||||
else if(gate_name == "OR") { gate->type = Gate::OR; }
|
else if(tokens[2] == "OR") { gate->type = Gate::OR; }
|
||||||
else if(gate_name == "NOR") { gate->type = Gate::NOR; }
|
else if(tokens[2] == "NOR") { gate->type = Gate::NOR; }
|
||||||
else if(gate_name == "XOR") { gate->type = Gate::XOR; }
|
else if(tokens[2] == "XOR") { gate->type = Gate::XOR; }
|
||||||
else if(gate_name == "XNOR") { gate->type = Gate::XNOR; }
|
else if(tokens[2] == "XNOR") { gate->type = Gate::XNOR; }
|
||||||
else if(gate_name == "NOT") { gate->type = Gate::NOT; }
|
else if(tokens[2] == "NOT") { gate->type = Gate::NOT; }
|
||||||
else if(gate_name == "BUF") { gate->type = Gate::BUF; }
|
else if(tokens[2] == "BUFF") { gate->type = Gate::BUF; }
|
||||||
|
else if(tokens[2] == "BUF") { gate->type = Gate::BUF; }
|
||||||
else {
|
else {
|
||||||
printf("Error while reading file: %s is not a valid gate.\n", gate_name.c_str());
|
printf("Error while reading file: %s is not a valid gate.\n", tokens[2].c_str());
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
name2gate.insert(std::make_pair(gate->name, gate));
|
||||||
printf("Error while reading file: \"%s\" is a wrong line.\n", line.c_str());
|
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->value = Gate::VAL_X;
|
||||||
|
|
||||||
|
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);
|
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);
|
||||||
|
}
|
||||||
|
POs.push_back(name2gate[po_name]);
|
||||||
}
|
}
|
||||||
}
|
}
|
90
res.txt
Normal file
90
res.txt
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
parsing file c432.bench...
|
||||||
|
INPUT(1)
|
||||||
|
tokens: $INPUT$ $($ $1$ $)$
|
||||||
|
INPUT(4)
|
||||||
|
tokens: $INPUT$ $($ $4$ $)$
|
||||||
|
INPUT(8)
|
||||||
|
tokens: $INPUT$ $($ $8$ $)$
|
||||||
|
INPUT(11)
|
||||||
|
tokens: $INPUT$ $($ $11$ $)$
|
||||||
|
INPUT(14)
|
||||||
|
tokens: $INPUT$ $($ $14$ $)$
|
||||||
|
INPUT(17)
|
||||||
|
tokens: $INPUT$ $($ $17$ $)$
|
||||||
|
INPUT(21)
|
||||||
|
tokens: $INPUT$ $($ $21$ $)$
|
||||||
|
INPUT(24)
|
||||||
|
tokens: $INPUT$ $($ $24$ $)$
|
||||||
|
INPUT(27)
|
||||||
|
tokens: $INPUT$ $($ $27$ $)$
|
||||||
|
INPUT(30)
|
||||||
|
tokens: $INPUT$ $($ $30$ $)$
|
||||||
|
INPUT(34)
|
||||||
|
tokens: $INPUT$ $($ $34$ $)$
|
||||||
|
INPUT(37)
|
||||||
|
tokens: $INPUT$ $($ $37$ $)$
|
||||||
|
INPUT(40)
|
||||||
|
tokens: $INPUT$ $($ $40$ $)$
|
||||||
|
INPUT(43)
|
||||||
|
tokens: $INPUT$ $($ $43$ $)$
|
||||||
|
INPUT(47)
|
||||||
|
tokens: $INPUT$ $($ $47$ $)$
|
||||||
|
INPUT(50)
|
||||||
|
tokens: $INPUT$ $($ $50$ $)$
|
||||||
|
INPUT(53)
|
||||||
|
tokens: $INPUT$ $($ $53$ $)$
|
||||||
|
INPUT(56)
|
||||||
|
tokens: $INPUT$ $($ $56$ $)$
|
||||||
|
INPUT(60)
|
||||||
|
tokens: $INPUT$ $($ $60$ $)$
|
||||||
|
INPUT(63)
|
||||||
|
tokens: $INPUT$ $($ $63$ $)$
|
||||||
|
INPUT(66)
|
||||||
|
tokens: $INPUT$ $($ $66$ $)$
|
||||||
|
INPUT(69)
|
||||||
|
tokens: $INPUT$ $($ $69$ $)$
|
||||||
|
INPUT(73)
|
||||||
|
tokens: $INPUT$ $($ $73$ $)$
|
||||||
|
INPUT(76)
|
||||||
|
tokens: $INPUT$ $($ $76$ $)$
|
||||||
|
INPUT(79)
|
||||||
|
tokens: $INPUT$ $($ $79$ $)$
|
||||||
|
INPUT(82)
|
||||||
|
tokens: $INPUT$ $($ $82$ $)$
|
||||||
|
INPUT(86)
|
||||||
|
tokens: $INPUT$ $($ $86$ $)$
|
||||||
|
INPUT(89)
|
||||||
|
tokens: $INPUT$ $($ $89$ $)$
|
||||||
|
INPUT(92)
|
||||||
|
tokens: $INPUT$ $($ $92$ $)$
|
||||||
|
INPUT(95)
|
||||||
|
tokens: $INPUT$ $($ $95$ $)$
|
||||||
|
INPUT(99)
|
||||||
|
tokens: $INPUT$ $($ $99$ $)$
|
||||||
|
INPUT(102)
|
||||||
|
tokens: $INPUT$ $($ $102$ $)$
|
||||||
|
INPUT(105)
|
||||||
|
tokens: $INPUT$ $($ $105$ $)$
|
||||||
|
INPUT(108)
|
||||||
|
tokens: $INPUT$ $($ $108$ $)$
|
||||||
|
INPUT(112)
|
||||||
|
tokens: $INPUT$ $($ $112$ $)$
|
||||||
|
INPUT(115)
|
||||||
|
tokens: $INPUT$ $($ $115$ $)$
|
||||||
|
OUTPUT(223)
|
||||||
|
tokens: $OUTPUT$ $($ $223$ $)$
|
||||||
|
OUTPUT(329)
|
||||||
|
tokens: $OUTPUT$ $($ $329$ $)$
|
||||||
|
OUTPUT(370)
|
||||||
|
tokens: $OUTPUT$ $($ $370$ $)$
|
||||||
|
OUTPUT(421)
|
||||||
|
tokens: $OUTPUT$ $($ $421$ $)$
|
||||||
|
OUTPUT(430)
|
||||||
|
tokens: $OUTPUT$ $($ $430$ $)$
|
||||||
|
OUTPUT(431)
|
||||||
|
tokens: $OUTPUT$ $($ $431$ $)$
|
||||||
|
OUTPUT(432)
|
||||||
|
tokens: $OUTPUT$ $($ $432$ $)$
|
||||||
|
118 = NOT(1)
|
||||||
|
tokens: $118$ $=$ $NOT$ $($ $1$ $)$
|
||||||
|
Error while reading line: 118 = NOT(1)
|
Loading…
x
Reference in New Issue
Block a user