atpg-ls/circuit.cpp
2023-03-04 10:39:33 +00:00

204 lines
6.1 KiB
C++

#include "circuit.h"
#include <queue>
#include <unordered_map>
#include <unordered_set>
#include "assert.h"
ll Circuit::stem_total_cost;
int Circuit::stem_falsified_cnt;
ll Circuit::propagate_total_cost;
int Circuit::propagate_falsified_cnt;
ll Circuit::fault_total_cost;
int Circuit::fault_falsified_cnt;
void Circuit::init_stems() {
for(auto& gate: gates) {
if(gate->outputs.size() >= 2) {
gate->stem = true;
}
if(gate->stem) {
stems.push_back(gate);
}
}
for(Gate *g : gates) {
if(g->pi) continue;
std::queue<Gate*> q;
std::unordered_map<Gate*, bool> used;
q.push(g);
while(!q.empty()) {
Gate* now = q.front();
q.pop();
for(Gate* in : now->inputs) {
if(in->stem) {
g->pre_stems.push_back(in);
} else if(!used[in]) {
used[in] = true;
q.push(in);
}
}
}
//printf("pre: %s %d\n", g->name.c_str(), g->pre_stems.size());
}
for(Gate *g : gates) {
if(g->po) continue;
std::queue<Gate*> q;
std::unordered_map<Gate*, bool> used;
q.push(g);
while(!q.empty()) {
Gate* now = q.front();
q.pop();
for(Gate* out : now->outputs) {
if(out->stem) {
g->suc_stems.push_back(out);
} else if(!used[out]) {
used[out] = true;
q.push(out);
}
}
}
//printf("pre: %s %d\n", g->name.c_str(), g->pre_stems.size());
}
}
void Circuit::init_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->id = 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->id = topo++;
q.push(out);
}
}
}
}
void Circuit::print_gates() {
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) Inputs:", gate->name.c_str(), type2name[gate->type], gate->value, gate->pi, gate->po, gate->stem, gate->propagate, gate->fault_satisfied[0], gate->fault_satisfied[1]);
for(Gate* in : gate->inputs) {
printf(" %s", in->name.c_str());
}
printf("\n");
}
}
bool Circuit::is_valid_circuit() {
ll stem_total_cost = 0;
int stem_falsified_cnt = 0;
ll propagate_total_cost = 0;
int propagate_falsified_cnt = 0;
ll fault_total_cost = 0;
int fault_falsified_cnt = 0;
//printf("propagate: %d, stem: %d, fault:%d\n", propagate_total_cost, stem_total_cost, fault_total_cost);
for(Gate* g : gates) {
if(g->stem && !g->propagate_satisfied) {
propagate_total_cost += g->propagate_cost;
propagate_falsified_cnt += 1;
}
bool pro_sat = (g->cal_sa(0) == g->fault_satisfied[0] && g->cal_sa(1) == g->fault_satisfied[1]);
if(g->stem && g->propagate_satisfied != pro_sat) {
printf("WRONG-fault_satisfied: %s \n", g->name.c_str());
return false;
}
if(g->stem && g->stem_satisified != (g->cal_value() == g->value)) {
printf("WRONG-STEM_SATIS: %s \n", g->name.c_str());
return false;
}
if(g->stem && g->cal_value() != g->value) {
stem_total_cost += g->stem_cost;
stem_falsified_cnt += 1;
}
if(!g->fault_satisfied[0]) {
fault_total_cost += g->fault_cost[0];
fault_falsified_cnt += 1;
}
if(!g->fault_satisfied[1]) {
fault_total_cost += g->fault_cost[1];
fault_falsified_cnt += 1;
}
// 检查门的赋值情况
if(!g->stem && g->cal_value() != g->value) {
printf("WRONG-ASSGIN: %s \n", g->name.c_str());
return false;
}
// 检查 fault_satified 和 value propagate 的关系
int sa0 = g->propagate && g->value;
int sa1 = g->propagate && !g->value;
assert(g->fault_satisfied[0] == sa0);
assert(g->fault_satisfied[1] == sa1);
// 检查 PO 的传播设定是否正确
if(g->po) {
if(g->fault_satisfied[g->value] || !g->fault_satisfied[!g->value] || !g->propagate) {
printf("WRONG-PO: %s \n", g->name.c_str());
}
continue;
}
// 非 PO 情况下检查故障传播是否正确
if(!g->stem && (g->cal_sa(0) != g->fault_satisfied[0] || g->cal_sa(1) != g->fault_satisfied[1])) {
printf("WRONG-SA: %s \n", g->name.c_str());
return false;
}
}
if(Circuit::propagate_total_cost != propagate_total_cost || Circuit::stem_total_cost != stem_total_cost || Circuit::fault_total_cost != fault_total_cost) {
printf("CIRCUIT CHECK FAILED!\n");
printf("[wrong] propagate: %lld, stem: %lld, fault:%lld\n", Circuit::propagate_total_cost, Circuit::stem_total_cost, Circuit::fault_total_cost);
printf("[right] propagate: %lld, stem: %lld, fault:%lld\n", propagate_total_cost, stem_total_cost, fault_total_cost);
return false;
}
if(Circuit::propagate_falsified_cnt != propagate_falsified_cnt || Circuit::stem_falsified_cnt != stem_falsified_cnt || Circuit::fault_falsified_cnt != fault_falsified_cnt) {
printf("CIRCUIT CHECK FAILED!\n");
printf("[wrong] propagate_cnt: %d, stem_cnt: %d, fault_cnt:%d\n", Circuit::propagate_falsified_cnt, Circuit::stem_falsified_cnt, Circuit::fault_falsified_cnt);
printf("[right] propagate_cnt: %d, stem_cnt: %d, fault_cnt:%d\n", propagate_falsified_cnt, stem_falsified_cnt, fault_falsified_cnt);
return false;
}
return true;
}