atpg-ls/circuit.cpp

144 lines
4.1 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 ss:%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->stem_satisfied, 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;
}