atpg-ls/circuit.cpp

144 lines
4.1 KiB
C++
Raw Normal View History

2023-02-12 16:22:32 +08:00
#include "circuit.h"
#include <queue>
#include <unordered_map>
2023-02-19 19:42:50 +08:00
#include <unordered_set>
#include "assert.h"
2023-03-17 05:37:29 +00:00
#include "clause.h"
2023-02-16 18:51:31 +08:00
void Circuit::init_topo_index() {
2023-03-13 05:44:49 +00:00
2023-02-12 16:22:32 +08:00
int topo = 1;
std::queue<Gate*> q;
std::unordered_map<Gate*, int> ins;
2023-03-13 05:44:49 +00:00
// 计算正向拓扑序
2023-02-12 16:22:32 +08:00
for(auto in : PIs) {
2023-02-20 13:08:25 +08:00
in->id = topo++;
2023-02-12 16:22:32 +08:00
q.push(in);
}
while(!q.empty()) {
Gate* g = q.front(); q.pop();
2023-03-13 05:44:49 +00:00
for(Gate* out : g->fan_outs) {
ins[out]++;
if(ins[out] == out->fan_ins.size()) {
2023-02-20 13:08:25 +08:00
out->id = topo++;
2023-02-12 16:22:32 +08:00
q.push(out);
}
}
}
2023-02-12 18:14:12 +08:00
2023-03-17 05:37:29 +00:00
for(Gate* g : gates) {
id2gate[g->id] = g;
}
2023-03-13 05:44:49 +00:00
// 计算反向拓扑序
topo = 1;
std::unordered_map<Gate*, int> outs;
2023-03-09 02:51:10 +00:00
2023-03-13 05:44:49 +00:00
for(auto out : POs) {
out->rtopo = topo++;
q.push(out);
2023-03-09 02:51:10 +00:00
}
while(!q.empty()) {
Gate* g = q.front(); q.pop();
2023-03-13 05:44:49 +00:00
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);
2023-03-09 02:51:10 +00:00
}
}
}
}
2023-03-13 05:44:49 +00:00
void Circuit::print_circuit() {
2023-02-19 19:42:50 +08:00
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]);
2023-03-13 05:44:49 +00:00
for(Gate* in : gate->fan_ins) {
2023-03-06 11:05:30 +00:00
printf(" %s(%d)", in->name.c_str(), gate->is_detected(in));
2023-02-19 19:42:50 +08:00
}
printf("\n");
}
}
bool Circuit::is_valid_circuit() {
2023-03-13 05:44:49 +00:00
ll stem_total_cost = 0;
2023-02-20 14:41:19 +08:00
ll fault_total_weight = 0;
2023-02-21 19:07:40 +08:00
int stem_total_cnt = 0;
int fault_total_cnt = 0;
2023-02-20 14:41:19 +08:00
2023-03-11 07:02:02 +00:00
ll fault_propagate_score = 0;
2023-02-21 19:07:40 +08:00
//printf("flip: %d, stem: %d, fault:%d\n", flip_total_weight, stem_total_weight, fault_total_weight);
2023-02-20 14:41:19 +08:00
2023-02-19 19:42:50 +08:00
for(Gate* g : gates) {
2023-03-13 05:44:49 +00:00
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;
2023-02-20 14:41:19 +08:00
}
2023-03-13 05:44:49 +00:00
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;
2023-02-23 11:00:24 +08:00
}
2023-03-13 05:44:49 +00:00
if(!g->stem && g->recal_value() != g->value) {
printf("Gate: %s Error: value cal wrong\n", g->name.c_str());
return false;
2023-02-20 14:41:19 +08:00
}
2023-03-13 05:44:49 +00:00
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());
2023-03-06 11:05:30 +00:00
return false;
}
2023-03-13 05:44:49 +00:00
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;
2023-02-20 14:41:19 +08:00
}
2023-03-13 05:44:49 +00:00
if(g->stem && g->recal_value() != g->value) {
stem_total_cost += g->stem_weight;
2023-02-20 14:41:19 +08:00
}
2023-03-13 05:44:49 +00:00
if(g->stem && g->recal_value() == g->value) {
stem_total_cnt++;
2023-02-19 19:42:50 +08:00
}
2023-03-13 05:44:49 +00:00
fault_propagate_score += g->fault_propagate_length[0] * g->fault_weight[0];
fault_propagate_score += g->fault_propagate_length[1] * g->fault_weight[1];
2023-02-19 19:42:50 +08:00
2023-03-13 05:44:49 +00:00
if(g->fault_detected[0]) {
fault_total_weight += g->fault_weight[0];
fault_total_cnt += 1;
2023-02-19 19:42:50 +08:00
}
2023-03-13 05:44:49 +00:00
if(g->fault_detected[1]) {
fault_total_weight += g->fault_weight[1];
fault_total_cnt += 1;
2023-02-19 19:42:50 +08:00
}
2023-02-12 18:14:12 +08:00
}
2023-02-19 19:42:50 +08:00
2023-03-13 05:44:49 +00:00
assert(this->stem_total_cost == stem_total_cost);
2023-03-13 10:54:51 +00:00
//assert(this->fault_total_weight == fault_total_weight);
2023-03-13 05:44:49 +00:00
assert(this->stem_total_cnt == stem_total_cnt);
assert(this->fault_total_cnt == fault_total_cnt);
assert(this->fault_propagate_score == fault_propagate_score);
2023-03-11 07:02:02 +00:00
2023-02-19 19:42:50 +08:00
return true;
2023-02-24 16:01:09 +08:00
}