diff --git a/atpg b/atpg index 61b9f2d..6c33244 100755 Binary files a/atpg and b/atpg differ diff --git a/circuit.cpp b/circuit.cpp index e69de29..aa9ef8b 100644 --- a/circuit.cpp +++ b/circuit.cpp @@ -0,0 +1,30 @@ +#include "circuit.h" + +#include +#include + +void Circuit::cal_topo_index() { + int topo = 1; + std::queue q; + + std::unordered_map 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); + } + } + } +} \ No newline at end of file diff --git a/circuit.h b/circuit.h index eba71d0..a893714 100644 --- a/circuit.h +++ b/circuit.h @@ -4,6 +4,7 @@ class Gate { public: + int topo; std::string name; enum { AND, NAND, OR, NOR, XOR, XNOR, NOT, BUF, INPUT, OUTPUT } type; enum { VAL_ZERO, VAL_ONE, VAL_X } value; @@ -15,6 +16,9 @@ class Circuit { public: std::vector PIs; std::vector POs; +std::vector gates; std::unordered_map name2gate; void parse_from_file(const char *filename); +void cal_topo_index(); +void cal_headlines(); }; \ No newline at end of file diff --git a/main.cpp b/main.cpp index 1a666f4..e1c8ad7 100644 --- a/main.cpp +++ b/main.cpp @@ -1,5 +1,6 @@ #include #include +#include #include "circuit.h" @@ -16,11 +17,15 @@ int main(int args, char* argv[]) { printf("parsing file %s...\n", argv[1]); circuit.parse_from_file(argv[1]); printf("====== Circuit Statistics ====== \n"); - printf("PI:\t%d\n", circuit.PIs.size()); - printf("PO:\t%d\n", circuit.POs.size()); - printf("Gates:\t%d\n", circuit.name2gate.size()); + printf("PI:\t%ld\n", circuit.PIs.size()); + printf("PO:\t%ld\n", circuit.POs.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; } \ No newline at end of file diff --git a/makefile b/makefile index 386f998..79aab05 100644 --- a/makefile +++ b/makefile @@ -7,7 +7,7 @@ #编译工具用g++,以同时支持C和C++程序,以及二者的混合编译 CC=g++ -CPPFLAGS=-O3 +CPPFLAGS=-O3 -std=c++17 #使用$(winldcard *.c)来获取工作目录下的所有.c文件的列表 #sources:=main.cpp command.c diff --git a/parser.cpp b/parser.cpp index 906798b..fe276e7 100644 --- a/parser.cpp +++ b/parser.cpp @@ -6,10 +6,23 @@ #include #include -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 line2tokens(const std::string &line, std::vector &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) { @@ -23,79 +36,102 @@ void Circuit::parse_from_file(const char *filename) { // buf 10MB file.rdbuf()->pubsetbuf(0, 10 *1024 * 1024); + std::vector bufPO; + 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*"))) { + std::vector tokens; - 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)); + 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 ins; - 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()); + for(int i=4; iname = 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); 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; } + 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", gate_name.c_str()); + printf("Error while reading file: %s is not a valid gate.\n", tokens[2].c_str()); exit(1); } - } else { - printf("Error while reading file: \"%s\" is a wrong line.\n", line.c_str()); + 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->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); - } + } + } + + // 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]); } } \ No newline at end of file diff --git a/res.txt b/res.txt new file mode 100644 index 0000000..66b69eb --- /dev/null +++ b/res.txt @@ -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)