144 lines
4.0 KiB
C++
144 lines
4.0 KiB
C++
#include "circuit.h"
|
|
|
|
#include <queue>
|
|
#include <unordered_map>
|
|
#include <unordered_set>
|
|
#include "assert.h"
|
|
#include "clause.h"
|
|
|
|
void Circuit::init_topo_index() {
|
|
|
|
int topo = 1;
|
|
std::queue<Gate*> q;
|
|
std::unordered_map<Gate*, int> ins;
|
|
|
|
// 计算正向拓扑序
|
|
for(auto in : PIs) {
|
|
in->id = topo++;
|
|
q.push(in);
|
|
}
|
|
|
|
while(!q.empty()) {
|
|
Gate* g = q.front(); q.pop();
|
|
for(Gate* out : g->fan_outs) {
|
|
ins[out]++;
|
|
if(ins[out] == out->fan_ins.size()) {
|
|
out->id = topo++;
|
|
q.push(out);
|
|
}
|
|
}
|
|
}
|
|
|
|
for(Gate* g : gates) {
|
|
id2gate[g->id] = g;
|
|
}
|
|
|
|
// 计算反向拓扑序
|
|
topo = 1;
|
|
std::unordered_map<Gate*, int> outs;
|
|
|
|
for(auto out : POs) {
|
|
out->rtopo = topo++;
|
|
q.push(out);
|
|
}
|
|
|
|
while(!q.empty()) {
|
|
Gate* g = q.front(); q.pop();
|
|
rtopo_gates.push_back(g);
|
|
for(Gate* in : g->fan_ins) {
|
|
outs[in]++;
|
|
if(outs[in] == in->fan_outs.size()) {
|
|
in->rtopo = topo++;
|
|
q.push(in);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void Circuit::print_circuit() {
|
|
static const char* type2name[9] = {"AND", "NAND", "OR", "NOR", "XOR", "XNOR", "NOT", "BUF", "IN"};
|
|
for(Gate* gate : gates) {
|
|
printf("Gate: %3s (t:%4s v:%d pi:%d po:%d s:%d p:%d s0:%d s1:%d fpl0:%d fpl1:%d) Inputs:", gate->name.c_str(), type2name[gate->type], gate->value, gate->pi, gate->po, gate->stem, gate->propagate, gate->fault_detected[0], gate->fault_detected[1], gate->fault_propagate_length[0], gate->fault_propagate_length[1]);
|
|
for(Gate* in : gate->fan_ins) {
|
|
printf(" %s(%d)", in->name.c_str(), gate->is_detected(in));
|
|
}
|
|
printf("\n");
|
|
}
|
|
}
|
|
|
|
bool Circuit::is_valid_circuit() {
|
|
|
|
ll stem_total_cost = 0;
|
|
ll fault_total_weight = 0;
|
|
|
|
int stem_total_cnt = 0;
|
|
int fault_total_cnt = 0;
|
|
|
|
ll fault_propagate_score = 0;
|
|
|
|
//printf("flip: %d, stem: %d, fault:%d\n", flip_total_weight, stem_total_weight, fault_total_weight);
|
|
|
|
for(Gate* g : gates) {
|
|
|
|
if(g->propagate != (g->fault_detected[0] || g->fault_detected[1])) {
|
|
printf("Gate: %s Error: propagte varible wrong\n", g->name.c_str());
|
|
return false;
|
|
}
|
|
|
|
if(g->stem && (g->recal_value() == g->value) != g->stem_satisfied) {
|
|
printf("Gate: %s Error: stem satisfied wrong\n", g->name.c_str());
|
|
return false;
|
|
}
|
|
|
|
if(!g->stem && g->recal_value() != g->value) {
|
|
printf("Gate: %s Error: value cal wrong\n", g->name.c_str());
|
|
return false;
|
|
}
|
|
|
|
int fpl[2];
|
|
g->recal_propagate_len(fpl);
|
|
if(g->fault_propagate_length[0] != fpl[0] || g->fault_propagate_length[1] != fpl[1]) {
|
|
printf("Gate: %s Error: fpl cal wrong\n", g->name.c_str());
|
|
return false;
|
|
}
|
|
|
|
bool fd[2];
|
|
g->recal_fault(fd);
|
|
if(g->fault_detected[0] != fd[0] || g->fault_detected[1] != fd[1]) {
|
|
printf("Gate: %s Error: fpl cal wrong\n", g->name.c_str());
|
|
return false;
|
|
}
|
|
|
|
if(g->stem && g->recal_value() != g->value) {
|
|
stem_total_cost += g->stem_weight;
|
|
}
|
|
|
|
if(g->stem && g->recal_value() == g->value) {
|
|
stem_total_cnt++;
|
|
}
|
|
|
|
fault_propagate_score += g->fault_propagate_length[0] * g->fault_weight[0];
|
|
fault_propagate_score += g->fault_propagate_length[1] * g->fault_weight[1];
|
|
|
|
if(g->fault_detected[0]) {
|
|
fault_total_weight += g->fault_weight[0];
|
|
fault_total_cnt += 1;
|
|
}
|
|
|
|
if(g->fault_detected[1]) {
|
|
fault_total_weight += g->fault_weight[1];
|
|
fault_total_cnt += 1;
|
|
}
|
|
}
|
|
|
|
assert(this->stem_total_cost == stem_total_cost);
|
|
//assert(this->fault_total_weight == fault_total_weight);
|
|
assert(this->stem_total_cnt == stem_total_cnt);
|
|
assert(this->fault_total_cnt == fault_total_cnt);
|
|
assert(this->fault_propagate_score == fault_propagate_score);
|
|
|
|
return true;
|
|
}
|
|
|
|
|