ACEC/circuit.cpp

150 lines
4.3 KiB
C++

#include "circuit.h"
const char* GateName[4] = {"XOR", "MAJ", "AND", "OR"};
CircuitGate* Gates;
std::vector<int> circuit_inputs;
int circuit_output;
void read_verilog_from_file(const char *filename) {
using namespace std;
ifstream file(filename);
cmatch m;
string line;
// skip I/Os
getline(file, line);
//cout << "inputs: " << endl;
getline(file, line);
while(regex_search(line.c_str(), m, regex("[x|y]\\d+"))) {
//cout << atoi(m.str(0).substr(1).c_str()) << " ";
circuit_inputs.push_back(atoi(m.str(0).substr(1).c_str()) + 1);
line = m.suffix().str();
}
//cout << endl;
// skip outputs;
getline(file, line);
int maxvar = 0;
// all wires
//cout << "wires: " << endl;
getline(file, line);
while(regex_search(line.c_str(), m, regex("n\\d+"))) {
string wire = m.str(0);
//cout << wire << " ";
maxvar = max(maxvar, std::atoi(wire.substr(1).c_str()));
line = m.suffix().str();
}
//cout << endl;
assert(maxvar);
//cout << "maxvar: " << maxvar + 1 << endl;
// allcate for global gates table
Gates = new CircuitGate[maxvar + 2];
while(true) {
getline(file, line);
if(line == "endmodule") break;
//cout << line << endl;
std::vector<int> vars;
string copy = line;
while(regex_search(copy.c_str(), m, regex("~?[xyn]\\d+"))) {
string str = m.str(0);
int sign = 1;
if(str[0] == '~') {
sign = -1;
str = str.substr(1);
}
// remove x , y or n
str = str.substr(1);
vars.push_back(sign * (atoi(str.c_str()) + 1));
copy = m.suffix().str();
}
int id = vars[0];
vars.erase(vars.begin());
CircuitGate &gate = Gates[id];
if(regex_match(line.c_str(), m, regex(" assign ~?[xyn]\\d+ = ~?[xyn]\\d+ (& ~?[xyn]\\d+)+ ;"))) {
//cout << "MATCH AND: " ;
gate.type = AND;
gate.inputs.insert(gate.inputs.end(), vars.begin(), vars.end());
} else if(regex_match(line.c_str(), m, regex(" assign ~?[xyn]\\d+ = ~?[xyn]\\d+ (\\^ ~?[xyn]\\d+)+ (\\^ 1\\'b0)+ ;"))) {
//cout << "MATCH XOR: " ;
gate.type = XOR;
gate.inputs.insert(gate.inputs.end(), vars.begin(), vars.end());
} else if(regex_match(line.c_str(), m, regex(" assign ~?[xyn]\\d+ = ~?[xyn]\\d+ (\\| ~?[xyn]\\d+)+ ;"))) {
//cout << "MATCH OR: " ;
gate.type = OR;
gate.inputs.insert(gate.inputs.end(), vars.begin(), vars.end());
} else if(regex_match(line.c_str(), m, regex(" assign ~?y\\d+ = ~?[xyn]\\d+ ;"))) {
//cout << "MATCH OUTPUT: " ;
circuit_output = vars[0];
} else {
//cout << "MATCH MAJ: " ;
set<int> tmp;
for(auto& var : vars) tmp.insert(var);
assert(tmp.size() == 3);
gate.type = MAJ;
gate.inputs.insert(gate.inputs.end(), tmp.begin(), tmp.end());
}
// for(auto& var : vars) {
// cout << var << " ";
// }
// cout << endl;
}
recalulate_fanouts();
calulate_topo_index();
}
void calulate_topo_index() {
int topo_count[circuit_output + 1];
memset(topo_count, 0, sizeof(topo_count));
std::queue<int> q;
int cnt = 0;
for(auto& in : circuit_inputs) {
Gates[in].topo_index = ++cnt;
q.push(in);
}
while(!q.empty()) {
int u = q.front(); q.pop();
for(auto &fanout : Gates[u].fanouts) {
topo_count[fanout]++;
if(topo_count[fanout] == Gates[fanout].inputs.size()) {
Gates[fanout].topo_index = ++cnt;
q.push(fanout);
}
}
}
}
void recalulate_fanouts() {
for(int i=1; i<=circuit_output; i++) {
Gates[i].fanouts.clear();
}
for(int i=1; i<=circuit_output; i++) {
for(int in : Gates[i].inputs) {
Gates[abs(in)].fanouts.push_back(i);
}
}
}
void print_circuit_structure() {
for(int i=1; i<=circuit_output; i++) {
printf(" Gate %d = %s (", i, GateName[Gates[i].type]);
for(auto& in : Gates[i].inputs) {
printf(" %d", in);
}
printf(" ) topo: %d \n", Gates[i].topo_index);
}
}