newc
This commit is contained in:
parent
7a9f51f50e
commit
9fdc584fe6
0
.gitignore
vendored
Normal file → Executable file
0
.gitignore
vendored
Normal file → Executable file
0
.vscode/c_cpp_properties.json
vendored
Normal file → Executable file
0
.vscode/c_cpp_properties.json
vendored
Normal file → Executable file
0
.vscode/launch.json
vendored
Normal file → Executable file
0
.vscode/launch.json
vendored
Normal file → Executable file
3
.vscode/settings.json
vendored
Normal file → Executable file
3
.vscode/settings.json
vendored
Normal file → Executable file
@ -90,6 +90,7 @@
|
||||
"csignal": "cpp",
|
||||
"strstream": "cpp",
|
||||
"codecvt": "cpp",
|
||||
"cfenv": "cpp"
|
||||
"cfenv": "cpp",
|
||||
"*.ipp": "cpp"
|
||||
}
|
||||
}
|
0
.vscode/tasks.json
vendored
Normal file → Executable file
0
.vscode/tasks.json
vendored
Normal file → Executable file
0
CMakeLists.txt
Normal file → Executable file
0
CMakeLists.txt
Normal file → Executable file
0
benchmark/b01.bench
Normal file → Executable file
0
benchmark/b01.bench
Normal file → Executable file
0
benchmark/b03.bench
Normal file → Executable file
0
benchmark/b03.bench
Normal file → Executable file
0
benchmark/b04.bench
Normal file → Executable file
0
benchmark/b04.bench
Normal file → Executable file
0
benchmark/b06.bench
Normal file → Executable file
0
benchmark/b06.bench
Normal file → Executable file
0
benchmark/b07.bench
Normal file → Executable file
0
benchmark/b07.bench
Normal file → Executable file
0
benchmark/b08.bench
Normal file → Executable file
0
benchmark/b08.bench
Normal file → Executable file
0
benchmark/b09.bench
Normal file → Executable file
0
benchmark/b09.bench
Normal file → Executable file
0
benchmark/b10.bench
Normal file → Executable file
0
benchmark/b10.bench
Normal file → Executable file
0
benchmark/b11.bench
Normal file → Executable file
0
benchmark/b11.bench
Normal file → Executable file
0
benchmark/b12.bench
Normal file → Executable file
0
benchmark/b12.bench
Normal file → Executable file
0
benchmark/b13.bench
Normal file → Executable file
0
benchmark/b13.bench
Normal file → Executable file
0
benchmark/b17.bench
Normal file → Executable file
0
benchmark/b17.bench
Normal file → Executable file
0
benchmark/b20.bench
Normal file → Executable file
0
benchmark/b20.bench
Normal file → Executable file
0
benchmark/b21.bench
Normal file → Executable file
0
benchmark/b21.bench
Normal file → Executable file
0
benchmark/b22.bench
Normal file → Executable file
0
benchmark/b22.bench
Normal file → Executable file
0
benchmark/c1355.bench
Normal file → Executable file
0
benchmark/c1355.bench
Normal file → Executable file
0
benchmark/c17.bench
Normal file → Executable file
0
benchmark/c17.bench
Normal file → Executable file
0
benchmark/c1908.bench
Normal file → Executable file
0
benchmark/c1908.bench
Normal file → Executable file
0
benchmark/c2670.bench
Normal file → Executable file
0
benchmark/c2670.bench
Normal file → Executable file
0
benchmark/c3540.bench
Normal file → Executable file
0
benchmark/c3540.bench
Normal file → Executable file
0
benchmark/c432.bench
Normal file → Executable file
0
benchmark/c432.bench
Normal file → Executable file
0
benchmark/c499.bench
Normal file → Executable file
0
benchmark/c499.bench
Normal file → Executable file
0
benchmark/c5315.bench
Normal file → Executable file
0
benchmark/c5315.bench
Normal file → Executable file
0
benchmark/c6288.bench
Normal file → Executable file
0
benchmark/c6288.bench
Normal file → Executable file
0
benchmark/c7552.bench
Normal file → Executable file
0
benchmark/c7552.bench
Normal file → Executable file
0
benchmark/c880.bench
Normal file → Executable file
0
benchmark/c880.bench
Normal file → Executable file
0
report/atalanta_b10000_iscas85.txt
Normal file → Executable file
0
report/atalanta_b10000_iscas85.txt
Normal file → Executable file
0
report/atalanta_b1000_itc99.txt
Normal file → Executable file
0
report/atalanta_b1000_itc99.txt
Normal file → Executable file
0
report/atalanta_b20_itc99.txt
Normal file → Executable file
0
report/atalanta_b20_itc99.txt
Normal file → Executable file
0
report/atalanta_itc99.txt
Normal file → Executable file
0
report/atalanta_itc99.txt
Normal file → Executable file
0
report/atpg-ls-动态增量-仿真.txt
Normal file → Executable file
0
report/atpg-ls-动态增量-仿真.txt
Normal file → Executable file
0
report/atpg-ls-动态增量.txt
Normal file → Executable file
0
report/atpg-ls-动态增量.txt
Normal file → Executable file
0
report/atpg-ls.txt
Normal file → Executable file
0
report/atpg-ls.txt
Normal file → Executable file
0
report/tgpro_iscas85.txt
Normal file → Executable file
0
report/tgpro_iscas85.txt
Normal file → Executable file
0
report/tgpro_itc99.txt
Normal file → Executable file
0
report/tgpro_itc99.txt
Normal file → Executable file
0
report/tgpro_itc99_cutoff1000.txt
Normal file → Executable file
0
report/tgpro_itc99_cutoff1000.txt
Normal file → Executable file
0
src/CMakeLists.txt
Normal file → Executable file
0
src/CMakeLists.txt
Normal file → Executable file
16
src/checker.cpp
Normal file → Executable file
16
src/checker.cpp
Normal file → Executable file
@ -8,7 +8,7 @@ namespace atpg_ls {
|
||||
Circuit *right_circuit;
|
||||
Circuit *wrong_circuit;
|
||||
|
||||
int check_fault(const Pattern &p, const TMP_FAULT &f) {
|
||||
int check_fault(const Pattern &p, const Fault &f) {
|
||||
for(int i=0; i<p.input_vector.size(); i++) {
|
||||
right_circuit->PIs[i]->value = p.input_vector[i];
|
||||
wrong_circuit->PIs[i]->value = p.input_vector[i];
|
||||
@ -19,7 +19,7 @@ int check_fault(const Pattern &p, const TMP_FAULT &f) {
|
||||
}
|
||||
|
||||
for(Gate* gate : wrong_circuit->gates) {
|
||||
if(gate->name == f.g->name) {
|
||||
if(gate->name == f.gate->name) {
|
||||
gate->value = f.stuck_at;
|
||||
continue;
|
||||
}
|
||||
@ -34,14 +34,14 @@ int check_fault(const Pattern &p, const TMP_FAULT &f) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int final_check(const std::set<TMP_FAULT> &faults, const std::vector<Pattern> &patterns) {
|
||||
int final_check(const std::set<Fault> &faults, const std::vector<Pattern> &patterns) {
|
||||
|
||||
std::set<TMP_FAULT> detected_faults;
|
||||
std::set<Fault> detected_faults;
|
||||
|
||||
for(auto &p : patterns) {
|
||||
for(auto &f : p.detected_faults) {
|
||||
|
||||
printf("checking fault %s %d ... ", f.g->name.c_str(), f.stuck_at);
|
||||
// printf("checking fault %s %d ... ", f.g->name.c_str(), f.stuck_at);
|
||||
|
||||
assert(faults.count(f));
|
||||
assert(detected_faults.count(f) == 0);
|
||||
@ -56,16 +56,16 @@ int final_check(const std::set<TMP_FAULT> &faults, const std::vector<Pattern> &p
|
||||
int detected = check_fault(p, f);
|
||||
|
||||
if(detected) {
|
||||
printf("detected\n");
|
||||
// printf("detected\n");
|
||||
detected_faults.insert(f);
|
||||
} else {
|
||||
printf("undetected\n");
|
||||
// printf("undetected\n");
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf("final coverage: %d/%d(%.2f) pattern: %d\n", detected_faults.size(), faults.size(), (double)detected_faults.size()/faults.size(), patterns.size());
|
||||
printf("final coverage: (%.2f)%d/%d pattern: %d\n", (double)detected_faults.size()/faults.size() * 100,detected_faults.size(), faults.size(), , patterns.size());
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
4
src/checker.h
Normal file → Executable file
4
src/checker.h
Normal file → Executable file
@ -8,8 +8,8 @@
|
||||
|
||||
namespace atpg_ls {
|
||||
|
||||
int check_fault(const Pattern &p, const TMP_FAULT &f);
|
||||
int final_check(const std::set<TMP_FAULT> &faults, const std::vector<Pattern> &patterns);
|
||||
int check_fault(const Pattern &p, const Fault &f);
|
||||
int final_check(const std::set<Fault> &faults, const std::vector<Pattern> &patterns);
|
||||
void init_final_checker();
|
||||
|
||||
};
|
||||
|
500
src/circuit.cpp
Normal file → Executable file
500
src/circuit.cpp
Normal file → Executable file
@ -1,159 +1,230 @@
|
||||
#include <set>
|
||||
#include <assert.h>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "circuit.h"
|
||||
#include "simulator.h"
|
||||
#include "paras.h"
|
||||
|
||||
using namespace atpg_ls;
|
||||
|
||||
void LUTCircuit::print() {
|
||||
|
||||
std::set<Gate*> st;
|
||||
|
||||
int total_gate = 0;
|
||||
|
||||
printf("PIs: ( ");
|
||||
for(LUT* lut : PIs) {
|
||||
printf("%s ", lut->gate->name.c_str());
|
||||
}
|
||||
printf(")\n");
|
||||
printf("POs: ( ");
|
||||
for(LUT* lut : POs) {
|
||||
printf("%s ", lut->gate->name.c_str());
|
||||
}
|
||||
printf(")\n");
|
||||
|
||||
|
||||
|
||||
for(LUT* lut : luts) {
|
||||
|
||||
printf("[v:%d vs:%d fd0:%d fd1:%d] ", lut->value, lut->vsat, lut->fd[0], lut->fd[1]);
|
||||
printf("lut: %s inputs: ( ", lut->gate->name.c_str());
|
||||
|
||||
total_gate += lut->inner_gates.size();
|
||||
|
||||
for(LUT* in : lut->fanins) {
|
||||
printf("%s ", in->gate->name.c_str());
|
||||
}
|
||||
printf(")\n");
|
||||
}
|
||||
|
||||
printf("total gate: %d\n", total_gate);
|
||||
std::string gen_name() {
|
||||
static int i = 0;
|
||||
return "E" + std::to_string(++i);
|
||||
}
|
||||
|
||||
Gate* create_not_gate(Gate* gate) {
|
||||
Gate* not_gate = new Gate();
|
||||
not_gate->name = gen_name();
|
||||
not_gate->is_extra_gate = 1;
|
||||
not_gate->type = Gate::NOT;
|
||||
not_gate->fanins.push_back(gate);
|
||||
gate->fanouts.push_back(not_gate);
|
||||
return not_gate;
|
||||
}
|
||||
|
||||
void Circuit::rebuild_atpg_circuit() {
|
||||
|
||||
int sz = gates.size();
|
||||
assert(sz == simulator->gates.size());
|
||||
|
||||
for(Gate* gate : rtopo_gates) {
|
||||
|
||||
LUTCircuit* Circuit::build_lut_circuit() {
|
||||
// 对于 PO 直接可以输出 SA0 = value 和 SA1 = NOT(value)
|
||||
if(gate->isPO) {
|
||||
Gate* extra_gate0 = new Gate();
|
||||
extra_gate0->type = Gate::BUF;
|
||||
extra_gate0->fanins.push_back(gate);
|
||||
gate->fanouts.push_back(extra_gate0);
|
||||
extra_gate0->is_extra_gate = 1;
|
||||
gates.push_back(extra_gate0);
|
||||
extra_gate0->name = "SA0_" + gate->name;
|
||||
|
||||
LUTCircuit* C = new LUTCircuit();
|
||||
C->C = this;
|
||||
Gate* extra_gate1 = new Gate();
|
||||
extra_gate1->type = Gate::NOT;
|
||||
extra_gate1->fanins.push_back(gate);
|
||||
gate->fanouts.push_back(extra_gate1);
|
||||
extra_gate1->is_extra_gate = 1;
|
||||
gates.push_back(extra_gate1);
|
||||
extra_gate1->name = "SA1_" + gate->name;
|
||||
|
||||
std::unordered_map<Gate*, LUT*> gate2LUT;
|
||||
// gate->isPO = false;
|
||||
|
||||
std::queue<Gate*> q;
|
||||
std::set<Gate*> done;
|
||||
|
||||
for(Gate* gate : gates) {
|
||||
// assert fanouts >= 2
|
||||
if(gate->fanouts.size() >= 2 || gate->isPI || (gate->isPO && gate->fanouts.size() == 0)) {
|
||||
q.push(gate);
|
||||
done.insert(gate);
|
||||
gate->stuck_at_gate[0] = extra_gate0;
|
||||
gate->stuck_at_gate[1] = extra_gate1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
while(!q.empty()) {
|
||||
Gate* gate = q.front();
|
||||
q.pop();
|
||||
// create a gate for SA_i
|
||||
|
||||
LUT* lut = new LUT(gate, C);
|
||||
|
||||
gate2LUT[gate] = lut;
|
||||
|
||||
// printf("size: %d lut: %s inputs: ( ", lut->inner_gates.size(), lut->gate->name.c_str());
|
||||
// for(Gate* in : lut->__gate_fanins) {
|
||||
// printf("%s ", in->name.c_str());
|
||||
// }
|
||||
// printf(") [");
|
||||
std::vector<Gate*> or_inputs;
|
||||
|
||||
// for(Gate* inner : lut->inner_gates) {
|
||||
// printf("%s ", inner->name.c_str());
|
||||
// }
|
||||
// printf("]\n");
|
||||
for(Gate *out : gate->fanouts) {
|
||||
|
||||
for(Gate* in : lut->__gate_fanins) {
|
||||
if(in->fanouts.size() < 2 && !in->isPI && done.count(in) == 0) {
|
||||
done.insert(in);
|
||||
q.push(in);
|
||||
if(out->is_extra_gate) continue;
|
||||
|
||||
// if the fault SA(!out->value) can be detected
|
||||
Gate* out_detected = new Gate();
|
||||
out_detected->name = gen_name();
|
||||
out_detected->is_extra_gate = 1;
|
||||
out_detected->type = Gate::OR;
|
||||
out_detected->fanins.push_back(out->stuck_at_gate[0]);
|
||||
out_detected->fanins.push_back(out->stuck_at_gate[1]);
|
||||
|
||||
assert(out->stuck_at_gate[0]);
|
||||
assert(out->stuck_at_gate[1]);
|
||||
|
||||
out->stuck_at_gate[0]->fanouts.push_back(out_detected);
|
||||
out->stuck_at_gate[1]->fanouts.push_back(out_detected);
|
||||
|
||||
gates.push_back(out_detected);
|
||||
|
||||
if(out->type == Gate::XOR || out->type == Gate::XNOR || out->type == Gate::NOT || out->type == Gate::BUF || out->type == Gate::LINE) {
|
||||
or_inputs.push_back(out_detected);
|
||||
continue;
|
||||
}
|
||||
|
||||
Gate *extra_gate = new Gate();
|
||||
extra_gate->is_extra_gate = 1;
|
||||
extra_gate->type = Gate::AND;
|
||||
extra_gate->name = gen_name();
|
||||
gates.push_back(extra_gate);
|
||||
|
||||
|
||||
for(Gate *in_of_out : out->fanins) {
|
||||
if(in_of_out == gate) continue;
|
||||
|
||||
if(out->type == Gate::AND || out->type == Gate::NAND) {
|
||||
|
||||
in_of_out->fanouts.push_back(extra_gate);
|
||||
extra_gate->fanins.push_back(in_of_out);
|
||||
|
||||
} else if(out->type == Gate::OR || out->type == Gate::NOR) {
|
||||
|
||||
Gate* not_gate = create_not_gate(in_of_out);
|
||||
not_gate->name = gen_name();
|
||||
gates.push_back(not_gate);
|
||||
not_gate->fanouts.push_back(extra_gate);
|
||||
extra_gate->fanins.push_back(not_gate);
|
||||
|
||||
} else {
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
extra_gate->fanins.push_back(out_detected);
|
||||
out_detected->fanouts.push_back(extra_gate);
|
||||
|
||||
or_inputs.push_back(extra_gate);
|
||||
}
|
||||
|
||||
Gate* or_gate;
|
||||
if(or_inputs.size() == 1) {
|
||||
or_gate = or_inputs[0];
|
||||
} else {
|
||||
or_gate = new Gate();
|
||||
gates.push_back(or_gate);
|
||||
or_gate->name = gen_name();
|
||||
or_gate->is_extra_gate = 1;
|
||||
or_gate->type = Gate::OR;
|
||||
for(Gate* in : or_inputs) {
|
||||
or_gate->fanins.push_back(in);
|
||||
in->fanouts.push_back(or_gate);
|
||||
}
|
||||
}
|
||||
|
||||
C->luts.push_back(lut);
|
||||
Gate* p_sa0 = new Gate();
|
||||
gates.push_back(p_sa0);
|
||||
p_sa0->is_extra_gate = 1;
|
||||
p_sa0->type = Gate::AND;
|
||||
p_sa0->fanins.push_back(or_gate);
|
||||
p_sa0->fanins.push_back(gate);
|
||||
or_gate->fanouts.push_back(p_sa0);
|
||||
gate->fanouts.push_back(p_sa0);
|
||||
|
||||
Gate* p_sa1 = new Gate();
|
||||
gates.push_back(p_sa1);
|
||||
p_sa1->is_extra_gate = 1;
|
||||
p_sa1->type = Gate::AND;
|
||||
p_sa1->fanins.push_back(or_gate);
|
||||
or_gate->fanouts.push_back(p_sa1);
|
||||
|
||||
Gate* not_gate = create_not_gate(gate);
|
||||
not_gate->name = gen_name();
|
||||
gates.push_back(not_gate);
|
||||
|
||||
p_sa1->fanins.push_back(not_gate);
|
||||
not_gate->fanouts.push_back(p_sa1);
|
||||
|
||||
gate->stuck_at_gate[0] = p_sa0;
|
||||
gate->stuck_at_gate[1] = p_sa1;
|
||||
|
||||
p_sa0->name = "SA0_" + gate->name;
|
||||
p_sa1->name = "SA1_" + gate->name;
|
||||
}
|
||||
|
||||
for(LUT* lut : C->luts) {
|
||||
// for(Gate* po : POs) {
|
||||
// po->isPO = false;
|
||||
// }
|
||||
// POs.clear();
|
||||
|
||||
lut->name = lut->gate->name.c_str();
|
||||
for(Gate* g : gates) {
|
||||
if(g->is_extra_gate) continue;
|
||||
|
||||
assert(g->stuck_at_gate[0]);
|
||||
assert(g->stuck_at_gate[1]);
|
||||
|
||||
std::sort(lut->inner_gates.begin(), lut->inner_gates.end(), [](Gate* a, Gate* b) {
|
||||
return a->id < b->id;
|
||||
});
|
||||
g->stuck_at_gate[0]->isPO = 1;
|
||||
g->stuck_at_gate[1]->isPO = 1;
|
||||
|
||||
for(Gate* in : lut->__gate_fanins) {
|
||||
assert(gate2LUT.count(in) > 0);
|
||||
|
||||
lut->fanins.push_back(gate2LUT[in]);
|
||||
gate2LUT[in]->fanouts.push_back(lut);
|
||||
}
|
||||
POs.push_back(g->stuck_at_gate[0]);
|
||||
POs.push_back(g->stuck_at_gate[1]);
|
||||
|
||||
if(lut->isPI) {
|
||||
C->PIs.push_back(lut);
|
||||
lut->isPI = 1;
|
||||
}
|
||||
if(lut->isPO) {
|
||||
C->POs.push_back(lut);
|
||||
lut->isPO = 1;
|
||||
}
|
||||
|
||||
init_topo_index();
|
||||
|
||||
for(Gate* pi : PIs) {
|
||||
pi->value = rand() % 2;
|
||||
}
|
||||
|
||||
for(Gate* g : gates) {
|
||||
g->value = g->cal_value();
|
||||
}
|
||||
|
||||
for(Gate* g : rtopo_gates) {
|
||||
if(g->is_extra_gate) continue;
|
||||
|
||||
g->fault_detected[0] = g->cal_fault_detected(0);
|
||||
g->fault_detected[1] = g->cal_fault_detected(1);
|
||||
|
||||
assert(g->fault_detected[0] == g->stuck_at_gate[0]->value);
|
||||
assert(g->fault_detected[1] == g->stuck_at_gate[1]->value);
|
||||
}
|
||||
|
||||
for(Gate* g : gates) {
|
||||
if(g->is_extra_gate) continue;
|
||||
original_gates.push_back(g);
|
||||
}
|
||||
|
||||
for(int i=0; i<original_gates.size(); i++) {
|
||||
original_gates[i]->index = i;
|
||||
simulator->name2gate[original_gates[i]->name]->index = i;
|
||||
}
|
||||
|
||||
std::vector<Gate*> t_POs;
|
||||
|
||||
for(Gate* po : POs) {
|
||||
if(po->is_extra_gate) {
|
||||
t_POs.push_back(po);
|
||||
}
|
||||
}
|
||||
|
||||
for(LUT* lut : C->luts) {
|
||||
C->rtopo_luts.push_back(lut);
|
||||
}
|
||||
|
||||
std::sort(C->luts.begin(), C->luts.end(), [](LUT* a, LUT* b) {
|
||||
return a->gate->id < b->gate->id;
|
||||
});
|
||||
|
||||
std::sort(C->rtopo_luts.begin(), C->rtopo_luts.end(), [](LUT* a, LUT* b) {
|
||||
return a->gate->rtopo < b->gate->rtopo;
|
||||
});
|
||||
|
||||
for(LUT* lut : C->luts) {
|
||||
for(int i=0; i<lut->inner_gates.size(); i++) {
|
||||
Gate *g = lut->inner_gates[i];
|
||||
g->parent_lut = lut;
|
||||
g->id_in_lut = lut->fanins.size() + i;
|
||||
}
|
||||
}
|
||||
|
||||
for(LUT* lut : C->luts) {
|
||||
for(int i=0; i<lut->fanins.size(); i++) {
|
||||
LUT* in = lut->fanins[i];
|
||||
in->fanouts_with_id.push_back(std::make_pair(lut, i));
|
||||
}
|
||||
}
|
||||
|
||||
for(LUT* lut : C->luts) {
|
||||
assert(lut->fanouts.size() == lut->fanouts_with_id.size());
|
||||
}
|
||||
|
||||
return C;
|
||||
POs = t_POs;
|
||||
assert(original_gates.size() * 2 == POs.size());
|
||||
assert(original_gates.size() == sz);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Circuit::insert_lines_for_stem() {
|
||||
|
||||
for(int j=0; j<gates.size(); j++) {
|
||||
@ -184,26 +255,27 @@ void Circuit::insert_lines_for_stem() {
|
||||
name2gate.insert(std::make_pair(line->name, line));
|
||||
}
|
||||
|
||||
printf(">>>> now: %s\n", g->name.c_str());
|
||||
// printf(">>>> now: %s\n", g->name.c_str());
|
||||
|
||||
printf("outs: [ ");
|
||||
for(Gate* out :g->fanouts){
|
||||
printf("%s ", out->name.c_str());
|
||||
}
|
||||
printf("]\n");
|
||||
// printf("outs: [ ");
|
||||
// for(Gate* out :g->fanouts){
|
||||
// printf("%s ", out->name.c_str());
|
||||
// }
|
||||
// printf("]\n");
|
||||
|
||||
for(int i=0; i<g->fanouts.size(); i++) {
|
||||
Gate* out = g->fanouts[i];
|
||||
|
||||
if(out->type == Gate::LINE) break;
|
||||
|
||||
printf(" g_name: %s outname: %s\n", g->name.c_str(), out->name.c_str());
|
||||
// printf(" g_name: %s outname: %s\n", g->name.c_str(), out->name.c_str());
|
||||
|
||||
Gate* line = new Gate();
|
||||
line->name = g->name + "_line_" + out->name;
|
||||
line->type = Gate::LINE;
|
||||
line->isPI = false;
|
||||
line->isPO = false;
|
||||
line->is_stem = false;
|
||||
|
||||
line->fanins.push_back(g);
|
||||
line->fanouts.push_back(out);
|
||||
@ -224,72 +296,6 @@ void Circuit::insert_lines_for_stem() {
|
||||
|
||||
}
|
||||
|
||||
void Circuit::init_avg_dist() {
|
||||
|
||||
int *now_dist = new int[gates.size() + 1] { 0 };
|
||||
int *total_dist = new int[gates.size() + 1] { 0 };
|
||||
int *total_cnt = new int[gates.size() + 1] { 0 };
|
||||
// int *topo_cnt = new int[gates.size() + 1] { 0 };
|
||||
|
||||
// memset(total_dist, 0, sizeof(int) * (gates.size() + 1));
|
||||
|
||||
for(Gate* po : POs) {
|
||||
// memset(topo_cnt, 0, sizeof(int) * (gates.size() + 1));
|
||||
// memset(now_dist, 0x3f, sizeof(int) * (gates.size() + 1));
|
||||
for(Gate* g : gates) {
|
||||
if(g->isPO) {
|
||||
now_dist[g->id] = 0;
|
||||
} else {
|
||||
now_dist[g->id] = 0x3f3f3f3f;
|
||||
}
|
||||
}
|
||||
|
||||
// printf(">> po: %s\n", po->name.c_str());
|
||||
|
||||
std::queue<Gate*> q;
|
||||
q.push(po);
|
||||
|
||||
while(!q.empty()) {
|
||||
Gate* u = q.front(); q.pop();
|
||||
|
||||
total_dist[u->id] += now_dist[u->id];
|
||||
total_cnt[u->id] ++;
|
||||
|
||||
// printf("now: %s\n", u->name.c_str());
|
||||
|
||||
for(Gate* in : u->fanins) {
|
||||
if(now_dist[u->id] + 1 < now_dist[in->id]) {
|
||||
now_dist[in->id] = now_dist[u->id] + 1;
|
||||
q.push(in);
|
||||
}
|
||||
}
|
||||
|
||||
// printf("dist: %d\n", total_dist[name2gate["G132"]->id]);
|
||||
}
|
||||
}
|
||||
|
||||
for(Gate* g : gates) {
|
||||
|
||||
if(total_cnt[g->id] <= 0) {
|
||||
printf("ERROR: gate: %s total: %d cnt: %d\n", g->name.c_str(), total_dist[g->id], total_cnt[g->id]);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
assert(total_cnt[g->id] > 0);
|
||||
|
||||
g->avg_dist = total_dist[g->id] / total_cnt[g->id];
|
||||
|
||||
printf("ERROR: gate: %s total: %d cnt: %d\n", g->name.c_str(), total_dist[g->id], total_cnt[g->id]);
|
||||
|
||||
// if(g->id)
|
||||
if(!g->isPO) assert(g->avg_dist > 0);
|
||||
}
|
||||
|
||||
delete [] now_dist;
|
||||
delete [] total_dist;
|
||||
delete [] total_cnt;
|
||||
}
|
||||
|
||||
void Circuit::init_topo_index() {
|
||||
int topo = 1;
|
||||
std::queue<Gate*> q;
|
||||
@ -315,6 +321,8 @@ void Circuit::init_topo_index() {
|
||||
}
|
||||
}
|
||||
|
||||
rtopo_gates.clear();
|
||||
|
||||
// 计算反向拓扑序
|
||||
topo = 1;
|
||||
std::unordered_map<Gate*, int> outs;
|
||||
@ -346,6 +354,8 @@ void Circuit::init_topo_index() {
|
||||
}
|
||||
}
|
||||
|
||||
assert(gates.size() == rtopo_gates.size());
|
||||
|
||||
std::sort(gates.begin(), gates.end(), [](Gate* a, Gate* b) {
|
||||
return a->id < b->id;
|
||||
});
|
||||
@ -362,8 +372,14 @@ void Circuit::print() {
|
||||
|
||||
const char *name[10] = {"AND", "NAND", "OR", "NOR", "XOR", "XNOR", "NOT", "BUF", "INPUT", "LINE"};
|
||||
|
||||
|
||||
|
||||
for(Gate* g : gates) {
|
||||
printf("[sa0: %d sa1: %d v: %d vsat: %d] %s = %s (",g->fault_detected[0], g->fault_detected[1], g->value, g->cal_value() == g->value, g->name.c_str(), name[g->type]);
|
||||
std::string out_name = "unknown";
|
||||
if(g->name != "") {
|
||||
out_name = g->name;
|
||||
}
|
||||
printf("[sa0: %d sa1: %d v: %d vsat: %d] %s = %s (",g->fault_detected[0], g->fault_detected[1], g->value, g->cal_value() == g->value, out_name.c_str(), name[g->type]);
|
||||
for(Gate* in : g->fanins) {
|
||||
printf("%s ", in->name.c_str());
|
||||
}
|
||||
@ -377,76 +393,64 @@ void Circuit::print() {
|
||||
printf(")\n");
|
||||
}
|
||||
|
||||
double LUTCircuit::check() {
|
||||
|
||||
// static bool init = 0;
|
||||
// static std::unordered_set<Gate*> dt;
|
||||
|
||||
printf("checking circuit ...\n");
|
||||
void Circuit::init_faults() {
|
||||
|
||||
double score_value_unsatisfied_cost = 0;
|
||||
double score_fault_detected_weight = 0;
|
||||
double score_fault_propagated_weight = 0;
|
||||
double score_fault_update_cost = 0;
|
||||
int unsatisfied_lut = 0;
|
||||
int sz = gates.size();
|
||||
assert(sz == simulator->gates.size());
|
||||
for(int i=0; i<sz; i++) {
|
||||
assert(gates[i]->name == simulator->gates[i]->name);
|
||||
simulator->gates[i]->ori_gate = gates[i];
|
||||
gates[i]->sim_gate = simulator->gates[i];
|
||||
}
|
||||
|
||||
for(LUT* lut : luts) {
|
||||
assert(lut->vsat == (lut->value == lut->cal_value()));
|
||||
std::vector<TMP_FAULT> faults;
|
||||
|
||||
if(!lut->vsat) {
|
||||
score_value_unsatisfied_cost += lut->vunat_cost;
|
||||
unsatisfied_lut++;
|
||||
// printf("vunsat: %s\n", lut->name);
|
||||
}
|
||||
for(Gate* g : gates) {
|
||||
|
||||
if(lut->uptag) {
|
||||
score_fault_update_cost += lut->up_cost;
|
||||
std::string name = g->name;
|
||||
|
||||
if(g->is_stem) {
|
||||
faults.push_back(TMP_FAULT{g, name, 0, 1, 0});
|
||||
faults.push_back(TMP_FAULT{g, name, 1, 1, 0});
|
||||
} else {
|
||||
int t_fd[2], t_fpl[2];
|
||||
lut->cal_fault_info(t_fd, t_fpl);
|
||||
assert(t_fd[0] == lut->fd[0]);
|
||||
assert(t_fd[1] == lut->fd[1]);
|
||||
assert(t_fpl[0] == lut->fpl[0]);
|
||||
assert(t_fpl[1] == lut->fpl[1]);
|
||||
}
|
||||
|
||||
int input = 0;
|
||||
for(int i=0; i<lut->fanins.size(); i++) {
|
||||
input |= (lut->fanins[i]->value << i);
|
||||
}
|
||||
input <<= 1;
|
||||
input |= lut->value;
|
||||
if(g->isPO) {
|
||||
faults.push_back(TMP_FAULT{g, name, 0, g->type != Gate::LINE, g->type == Gate::LINE});
|
||||
faults.push_back(TMP_FAULT{g, name, 1, g->type != Gate::LINE, g->type == Gate::LINE});
|
||||
continue;
|
||||
}
|
||||
|
||||
for(int i=lut->fanins.size(); i<lut->fanins.size()+lut->inner_gates.size(); i++) {
|
||||
LUT::FaultInfo &info = lut->fault_table[i][input];
|
||||
Gate* g = lut->inner_gates[i-lut->fanins.size()];
|
||||
|
||||
int t_fd[2], t_fpl[2];
|
||||
t_fd[0] = info.fd[0] && lut->fd[!lut->value];
|
||||
t_fd[1] = info.fd[1] && lut->fd[!lut->value];
|
||||
t_fpl[0] = info.fpl[0] + info.fd[0] * lut->fpl[!lut->value];
|
||||
t_fpl[1] = info.fpl[1] + info.fd[1] * lut->fpl[!lut->value];
|
||||
assert(g->fanouts.size() == 1);
|
||||
|
||||
score_fault_detected_weight += t_fd[0] * g->fault_detected_weight[0];
|
||||
score_fault_detected_weight += t_fd[1] * g->fault_detected_weight[1];
|
||||
Gate *fanout = g->fanouts[0];
|
||||
|
||||
if(!g->isPO) {
|
||||
score_fault_propagated_weight += (double)t_fpl[0] / g->avg_dist * g->fault_detected_weight[0];
|
||||
score_fault_propagated_weight += (double)t_fpl[1] / g->avg_dist * g->fault_detected_weight[1];
|
||||
int stem = (!g->isPI) && (g->type != Gate::LINE);
|
||||
|
||||
if(fanout->type == Gate::Type::BUF || fanout->type == Gate::Type::NOT) {
|
||||
continue;
|
||||
} else if(fanout->type == Gate::Type::XOR || fanout->type == Gate::Type::XNOR) {
|
||||
faults.push_back(TMP_FAULT{g, name, 0, stem, 0});
|
||||
faults.push_back(TMP_FAULT{g, name, 1, stem, 0});
|
||||
} else if(fanout->type == Gate::Type::NAND || fanout->type == Gate::Type::AND) {
|
||||
faults.push_back(TMP_FAULT{g, name, 1, stem, 0});
|
||||
} else if(fanout->type == Gate::Type::NOR || fanout->type == Gate::Type::OR) {
|
||||
faults.push_back(TMP_FAULT{g, name, 0, stem, 0});
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf("=====================================\n");
|
||||
printf("unsat_lut: %d\n", unsatisfied_lut);
|
||||
printf("score_value_unsatisfied_cost: %.2f\n", score_value_unsatisfied_cost);
|
||||
printf("score_fault_detected_weight: %.2f\n", score_fault_detected_weight);
|
||||
printf("score_fault_propagated_weight: %.2f\n", score_fault_propagated_weight);
|
||||
printf("score_fault_update_cost: %.2f\n", score_fault_update_cost);
|
||||
|
||||
double score = - score_value_unsatisfied_cost + score_fault_detected_weight + score_fault_propagated_weight - score_fault_update_cost;
|
||||
printf("fault-size: %d\n", faults.size());
|
||||
|
||||
printf("score: %d\n", score);
|
||||
for(TMP_FAULT &f : faults) {
|
||||
mp[Fault{f.g, f.stuck_at}] = f;
|
||||
this->faults.insert(Fault{f.g, f.stuck_at});
|
||||
}
|
||||
|
||||
return score;
|
||||
this->unknown_faults = this->faults;
|
||||
|
||||
assert(faults.size() == mp.size());
|
||||
}
|
68
src/circuit.h
Normal file → Executable file
68
src/circuit.h
Normal file → Executable file
@ -1,44 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include "fault.h"
|
||||
#include "lut.h"
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
using ll = long long;
|
||||
|
||||
namespace atpg_ls {
|
||||
|
||||
class Simulator;
|
||||
class Circuit;
|
||||
|
||||
class LUTCircuit {
|
||||
public:
|
||||
std::vector<LUT*> PIs;
|
||||
std::vector<LUT*> POs;
|
||||
std::vector<LUT*> luts;
|
||||
std::vector<LUT*> rtopo_luts;
|
||||
|
||||
int** fault_detected;
|
||||
|
||||
void print();
|
||||
|
||||
// local search
|
||||
void ls_update(std::vector<LUT*> &unsat);
|
||||
LUT* ls_pick();
|
||||
void ls_flip(LUT *lut);
|
||||
void ls_main();
|
||||
void ls_init();
|
||||
void ls_random_sol();
|
||||
void ls_gen_sol(const TMP_FAULT &target);
|
||||
|
||||
// checker
|
||||
double check();
|
||||
|
||||
Simulator *simulator;
|
||||
Circuit *C;
|
||||
|
||||
int step;
|
||||
|
||||
};
|
||||
|
||||
class Circuit {
|
||||
public:
|
||||
@ -46,18 +17,45 @@ std::vector<Gate*> PIs;
|
||||
std::vector<Gate*> POs;
|
||||
std::vector<Gate*> gates;
|
||||
std::vector<Gate*> rtopo_gates;
|
||||
std::vector<Gate*> original_gates;
|
||||
|
||||
// std::vector<Gate*> test;
|
||||
|
||||
std::unordered_map<std::string, Gate*> name2gate;
|
||||
|
||||
void parse_from_file(const char *filename);
|
||||
void insert_lines_for_stem();
|
||||
void rebuild_atpg_circuit();
|
||||
void init_faults();
|
||||
int cal_circuit_score();
|
||||
|
||||
void print();
|
||||
|
||||
LUTCircuit* build_lut_circuit();
|
||||
|
||||
void init_topo_index();
|
||||
void init_avg_dist();
|
||||
|
||||
// atpg info
|
||||
|
||||
std::set<Fault> detected_faults;
|
||||
std::set<Fault> undetected_faults;
|
||||
std::set<Fault> unknown_faults;
|
||||
std::set<Fault> faults;
|
||||
|
||||
std::map<Fault, TMP_FAULT> mp;
|
||||
|
||||
void ls_update();
|
||||
Gate* ls_pick();
|
||||
void ls_flip(Gate *gate);
|
||||
void ls_main();
|
||||
void ls_init();
|
||||
void ls_random_sol();
|
||||
void ls_gen_sol(const Fault &f);
|
||||
|
||||
// checker
|
||||
double check();
|
||||
|
||||
// simulator
|
||||
|
||||
Simulator *simulator;
|
||||
|
||||
};
|
||||
|
||||
|
0
src/cmdline.h
Normal file → Executable file
0
src/cmdline.h
Normal file → Executable file
15
src/fault.h
Normal file → Executable file
15
src/fault.h
Normal file → Executable file
@ -4,6 +4,21 @@
|
||||
|
||||
namespace atpg_ls {
|
||||
|
||||
struct Fault {
|
||||
Gate* gate;
|
||||
int stuck_at;
|
||||
|
||||
friend bool operator < (const Fault &lhs, const Fault &rhs) {
|
||||
if(lhs.gate != rhs.gate) {
|
||||
return lhs.gate < rhs.gate;
|
||||
}
|
||||
if(lhs.stuck_at != rhs.stuck_at) {
|
||||
return lhs.stuck_at < rhs.stuck_at;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
struct TMP_FAULT {
|
||||
/* data */
|
||||
Gate *g;
|
||||
|
2
src/gate.cpp
Normal file → Executable file
2
src/gate.cpp
Normal file → Executable file
@ -15,6 +15,7 @@ int Gate::cal_propagate_len(bool x) {
|
||||
}
|
||||
|
||||
for(Gate* out : fanouts) {
|
||||
if(out->is_extra_gate) continue;
|
||||
if(!out->is_detected(this)) continue;
|
||||
fpl[!value] = std::max(fpl[!value], out->fault_propagated_len[!out->value] + 1);
|
||||
}
|
||||
@ -45,6 +46,7 @@ bool Gate::cal_fault_detected(bool x) {
|
||||
for(Gate* out : fanouts) {
|
||||
if(!out->is_propagated()) continue;
|
||||
if(out->cal_value() != out->value) continue;
|
||||
if(out->is_extra_gate) continue;
|
||||
|
||||
this->value = !this->value;
|
||||
bool detect = (out->cal_value() != out->value);
|
||||
|
31
src/gate.h
Normal file → Executable file
31
src/gate.h
Normal file → Executable file
@ -17,9 +17,19 @@ public:
|
||||
|
||||
// gate basic info
|
||||
|
||||
Gate() {
|
||||
is_extra_gate = 0;
|
||||
sim_gate = 0;
|
||||
ori_gate = 0;
|
||||
isPI = 0;
|
||||
isPO = 0;
|
||||
}
|
||||
|
||||
int id;
|
||||
int level;
|
||||
int rtopo;
|
||||
int index;
|
||||
|
||||
std::string name;
|
||||
enum Type { AND, NAND, OR, NOR, XOR, XNOR, NOT, BUF, INPUT, LINE } type;
|
||||
int value;
|
||||
@ -28,6 +38,15 @@ public:
|
||||
std::vector<Gate*> fanouts;
|
||||
std::vector<Gate*> fanins;
|
||||
std::vector<Gate*> reigon;
|
||||
|
||||
int weight;
|
||||
|
||||
bool is_extra_gate;
|
||||
Gate* stuck_at_gate[2];
|
||||
|
||||
int v_sat;
|
||||
int unsat_cost;
|
||||
int is_good_var;
|
||||
|
||||
int avg_dist;
|
||||
|
||||
@ -41,18 +60,24 @@ public:
|
||||
|
||||
int cal_value();
|
||||
|
||||
int score;
|
||||
void cal_score();
|
||||
|
||||
bool cal_fault_detected(bool x);
|
||||
|
||||
bool is_detected(Gate* one_of_input);
|
||||
|
||||
int cal_propagate_len(bool x);
|
||||
|
||||
LUT* parent_lut;
|
||||
int id_in_lut;
|
||||
|
||||
int is_stem;
|
||||
|
||||
void cal_fault_info(int fd[2], int fpl[2]);
|
||||
|
||||
int CC;
|
||||
|
||||
// for simulate;
|
||||
Gate* ori_gate;
|
||||
Gate* sim_gate;
|
||||
|
||||
// ( partical ) score
|
||||
|
||||
|
770
src/ls.cpp
Normal file → Executable file
770
src/ls.cpp
Normal file → Executable file
@ -12,279 +12,325 @@
|
||||
|
||||
using namespace atpg_ls;
|
||||
|
||||
LUT* LUTCircuit::ls_pick() {
|
||||
std::set<Gate*> unjust_gates;
|
||||
|
||||
LUT* pick = nullptr;
|
||||
|
||||
// 采样
|
||||
for(int i=0; i<OPT(t); i++) {
|
||||
LUT* lut = luts[rand() % luts.size()];
|
||||
if(!lut->CC) continue;
|
||||
lut->cal_score();
|
||||
if(lut->score <= 0) continue;
|
||||
if(pick == nullptr || lut->score > pick->score) {
|
||||
pick = lut;
|
||||
// score > 0 && CC = 1;
|
||||
std::vector<Gate*> good_gates;
|
||||
|
||||
int Circuit::cal_circuit_score() {
|
||||
int score = 0;
|
||||
|
||||
for(Gate* g : gates) {
|
||||
if(g->value == 1) {
|
||||
score += g->weight;
|
||||
}
|
||||
|
||||
assert(g->v_sat == (g->value == g->cal_value()));
|
||||
|
||||
if(!g->v_sat) {
|
||||
score -= g->unsat_cost;
|
||||
}
|
||||
|
||||
if(g->v_sat) {
|
||||
assert(unjust_gates.count(g) == 0);
|
||||
} else {
|
||||
assert(unjust_gates.count(g));
|
||||
}
|
||||
}
|
||||
|
||||
if(pick != nullptr) {
|
||||
return pick;
|
||||
return score;
|
||||
}
|
||||
|
||||
void Circuit::ls_init() {
|
||||
unjust_gates.clear();
|
||||
good_gates.clear();
|
||||
}
|
||||
|
||||
void Circuit::ls_random_sol() {
|
||||
for(Gate* gate : gates) {
|
||||
gate->value = rand() % 2;
|
||||
}
|
||||
for(Gate* gate : gates) {
|
||||
gate->v_sat = (gate->value == gate->cal_value());
|
||||
gate->weight = 0;
|
||||
gate->CC = 1;
|
||||
gate->unsat_cost = 1;
|
||||
gate->is_good_var = 0;
|
||||
}
|
||||
|
||||
std::vector<LUT*> unsat;
|
||||
for(Fault f : unknown_faults) {
|
||||
Gate* g_sai = f.gate->stuck_at_gate[f.stuck_at];
|
||||
assert(g_sai != nullptr);
|
||||
g_sai->weight = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// 动态加权
|
||||
ls_update(unsat);
|
||||
Gate* Circuit::ls_pick() {
|
||||
Gate* pick = nullptr;
|
||||
|
||||
if(unsat.size() == 0) return nullptr;
|
||||
if(!good_gates.empty()) {
|
||||
pick = good_gates[rand() % good_gates.size()];
|
||||
if(pick->score > 0 && pick->CC) {
|
||||
return pick;
|
||||
} else {
|
||||
std::vector<Gate*> tmp = good_gates;
|
||||
good_gates.clear();
|
||||
for(Gate* gate : tmp) {
|
||||
if(gate->score > 0 && gate->CC == 1) {
|
||||
good_gates.push_back(gate);
|
||||
} else {
|
||||
gate->is_good_var = 0;
|
||||
}
|
||||
}
|
||||
|
||||
pick = unsat[rand() % unsat.size()];
|
||||
|
||||
if(pick->fanins.size() == 0) {
|
||||
return pick;
|
||||
if(!good_gates.empty()) {
|
||||
pick = good_gates[rand() % good_gates.size()];
|
||||
return pick;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(rand() % 10000 < 3000) {
|
||||
return pick->fanins[rand() % pick->fanins.size()];
|
||||
ls_update();
|
||||
|
||||
std::vector<Gate*> uj;
|
||||
uj.insert(uj.end(), unjust_gates.begin(), unjust_gates.end());
|
||||
|
||||
if(!unjust_gates.empty()) {
|
||||
pick = uj[rand() % uj.size()];
|
||||
|
||||
if(rand() % 10000 <= 0.7 * 10000) {
|
||||
return pick->fanins[rand() % pick->fanins.size()];
|
||||
} else {
|
||||
return pick;
|
||||
}
|
||||
}
|
||||
|
||||
pick = gates[rand() % gates.size()];
|
||||
|
||||
return pick;
|
||||
}
|
||||
|
||||
void LUTCircuit::ls_flip(LUT *lut) {
|
||||
void Circuit::ls_flip(Gate *gate) {
|
||||
// for(Gate* g : gates) {
|
||||
// int old = g->score;
|
||||
// g->cal_score();
|
||||
// assert(old == g->score);
|
||||
// }
|
||||
|
||||
lut->CC = 0;
|
||||
lut->uptag = 0;
|
||||
lut->flip_value();
|
||||
if(!lut->isPI) lut->vsat = !lut->vsat;
|
||||
gate->value ^= 1;
|
||||
gate->CC = 0;
|
||||
gate->is_good_var = 0;
|
||||
|
||||
for(LUT* out : lut->fanouts) {
|
||||
out->CC = 1;
|
||||
out->vsat = (out->cal_value() == out->value);
|
||||
}
|
||||
if(!gate->isPI) {
|
||||
|
||||
lut->cal_fault_info(lut->fd, lut->fpl);
|
||||
gate->v_sat ^= 1;
|
||||
assert(gate->v_sat == (gate->value == gate->cal_value()));
|
||||
// printf("test: %d %d\n", gate->v_sat, (gate->value == gate->cal_value()));
|
||||
|
||||
for(LUT* r : lut->reigon) {
|
||||
r->CC = 1;
|
||||
int t_fd[2], t_fpl[2];
|
||||
r->cal_fault_info(t_fd, t_fpl);
|
||||
|
||||
if(t_fd[0] != r->fd[0] || t_fd[1] != r->fd[1] || t_fpl[0] != r->fpl[0] || t_fpl[1] != r->fpl[1]) {
|
||||
r->uptag = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LUTCircuit::ls_update(std::vector<LUT*> &unsat) {
|
||||
|
||||
if(rand() % 10000 <= OPT(sp) * 10000) {
|
||||
|
||||
for(LUT* lut : luts) {
|
||||
if(lut->vsat) {
|
||||
if(lut->vunat_cost - OPT(vsat_inc) >= 1) {
|
||||
lut->vunat_cost -= OPT(vsat_inc);
|
||||
}
|
||||
}
|
||||
if(!lut->vsat) {
|
||||
unsat.push_back(lut);
|
||||
}
|
||||
if(!lut->uptag) {
|
||||
if(lut->up_cost - OPT(up_inc) >= 1) {
|
||||
lut->up_cost -= OPT(up_inc);
|
||||
}
|
||||
}
|
||||
for(int i=lut->fanins.size(); i<lut->fanins.size()+lut->inner_gates.size(); i++) {
|
||||
Gate* g = lut->inner_gates[i-lut->fanins.size()];
|
||||
LUT::FaultInfo &fi = lut->fault_table[i][lut->input_var];
|
||||
if(fi.fd[0] && g->fault_detected_weight[0] - OPT(fw_inc) >= 1) {
|
||||
g->fault_detected_weight[0] -= OPT(fw_inc);
|
||||
}
|
||||
if(fi.fd[1] && g->fault_detected_weight[1] - OPT(fw_inc) >= 1) {
|
||||
g->fault_detected_weight[1] -= OPT(fw_inc);
|
||||
}
|
||||
if(fi.fd[0] && g->fault_propagated_weight[0] - OPT(fw_inc) >= 1) {
|
||||
g->fault_propagated_weight[0] -= OPT(fw_inc);
|
||||
}
|
||||
if(fi.fd[1] && g->fault_propagated_weight[1] + OPT(fw_inc) >= 1) {
|
||||
g->fault_propagated_weight[1] -= OPT(fw_inc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
for(LUT* lut : luts) {
|
||||
if(!lut->vsat) {
|
||||
|
||||
// printf("ocost: %d add: %d\n", lut->vunat_cost);
|
||||
if(lut->vunat_cost + OPT(vsat_inc) > OPT(vsat_max)) {
|
||||
lut->vunat_cost = OPT(vsat_max);
|
||||
} else {
|
||||
lut->vunat_cost += OPT(vsat_inc);
|
||||
}
|
||||
// printf("cost: %d add: %d\n", lut->vunat_cost, OPT(vsat_inc));
|
||||
|
||||
// for(LUT* out : lut->fanouts) {
|
||||
// if(out->vunat_cost -= OPT(vsat_inc) > 1) {
|
||||
// out->vunat_cost -= OPT(vsat_inc);
|
||||
// } else {
|
||||
// out->vunat_cost = 1;
|
||||
// }
|
||||
// }
|
||||
|
||||
unsat.push_back(lut);
|
||||
}
|
||||
if(lut->uptag) {
|
||||
if(lut->up_cost + OPT(up_inc) > OPT(up_max)) {
|
||||
lut->up_cost = OPT(up_max);
|
||||
} else {
|
||||
lut->up_cost += OPT(up_inc);
|
||||
}
|
||||
}
|
||||
for(int i=lut->fanins.size(); i<lut->fanins.size()+lut->inner_gates.size(); i++) {
|
||||
Gate* g = lut->inner_gates[i-lut->fanins.size()];
|
||||
LUT::FaultInfo &fi = lut->fault_table[i][lut->input_var];
|
||||
if(!fi.fd[0] && g->fault_detected_weight[0] > 0 && g->fault_detected_weight[0] + OPT(fw_inc) <= OPT(fw_max)) {
|
||||
g->fault_detected_weight[0] += OPT(fw_inc);
|
||||
}
|
||||
if(!fi.fd[1] && g->fault_detected_weight[1] > 0 && g->fault_detected_weight[1] + OPT(fw_inc) <= OPT(fw_max)) {
|
||||
g->fault_detected_weight[1] += OPT(fw_inc);
|
||||
}
|
||||
if(!fi.fd[0] && g->fault_propagated_weight[0] > 0 && g->fault_propagated_weight[0] + OPT(fw_inc) <= OPT(fw_max)) {
|
||||
g->fault_propagated_weight[0] += OPT(fw_inc);
|
||||
}
|
||||
if(!fi.fd[1] && g->fault_propagated_weight[0] > 0 && g->fault_propagated_weight[1] + OPT(fw_inc) <= OPT(fw_max)) {
|
||||
g->fault_propagated_weight[1] += OPT(fw_inc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LUTCircuit::ls_main() {
|
||||
|
||||
printf("====== local search start ======\n");
|
||||
|
||||
printf("initing lookup table ...\n");
|
||||
ls_init();
|
||||
|
||||
printf("ganerating fault info ...\n");
|
||||
|
||||
int num_gates = 0;
|
||||
int num_total_fault = 0;
|
||||
int num_detected_fault = 0;
|
||||
int num_undetected_fault = 0;
|
||||
int num_pattern = 0;
|
||||
|
||||
for(LUT* lut : luts) {
|
||||
num_gates += lut->inner_gates.size();
|
||||
}
|
||||
assert(num_gates == C->gates.size());
|
||||
fault_detected = new int*[num_gates];
|
||||
for(int i=0; i<num_gates; i++) {
|
||||
fault_detected[i] = new int[2];
|
||||
fault_detected[i][0] = fault_detected[i][1] = 0;
|
||||
}
|
||||
num_total_fault = num_undetected_fault = num_gates * 2;
|
||||
|
||||
printf("staring local search ...\n");
|
||||
|
||||
std::queue<TMP_FAULT> faults;
|
||||
|
||||
for(Gate* g : C->gates) {
|
||||
|
||||
std::string name = g->name;
|
||||
|
||||
if(g->is_stem) {
|
||||
faults.push(TMP_FAULT{g, name, 0, 1, 0});
|
||||
faults.push(TMP_FAULT{g, name, 1, 1, 0});
|
||||
if(gate->v_sat) {
|
||||
unjust_gates.erase(gate);
|
||||
} else {
|
||||
unjust_gates.insert(gate);
|
||||
}
|
||||
}
|
||||
|
||||
if(g->isPO) {
|
||||
faults.push(TMP_FAULT{g, name, 0, g->type != Gate::LINE, g->type == Gate::LINE});
|
||||
faults.push(TMP_FAULT{g, name, 1, g->type != Gate::LINE, g->type == Gate::LINE});
|
||||
continue;
|
||||
}
|
||||
for(Gate* in : gate->fanins) {
|
||||
in->cal_score();
|
||||
in->CC = 1;
|
||||
if(!in->is_good_var && in->score > 0) {
|
||||
in->is_good_var = 1;
|
||||
good_gates.push_back(in);
|
||||
}
|
||||
}
|
||||
|
||||
assert(g->fanouts.size() == 1);
|
||||
Gate *fanout = g->fanouts[0];
|
||||
for(Gate* out : gate->fanouts) {
|
||||
|
||||
int stem = (!g->isPI) && (g->type != Gate::LINE);
|
||||
if(out->v_sat && (out->value != out->cal_value())) {
|
||||
out->v_sat = 0;
|
||||
unjust_gates.insert(out);
|
||||
}
|
||||
if(!out->v_sat && (out->value == out->cal_value())) {
|
||||
out->v_sat = 1;
|
||||
unjust_gates.erase(out);
|
||||
}
|
||||
|
||||
if(fanout->type == Gate::Type::BUF || fanout->type == Gate::Type::NOT) {
|
||||
continue;
|
||||
} else if(fanout->type == Gate::Type::XOR || fanout->type == Gate::Type::XNOR) {
|
||||
faults.push(TMP_FAULT{g, name, 0, stem, 0});
|
||||
faults.push(TMP_FAULT{g, name, 1, stem, 0});
|
||||
} else if(fanout->type == Gate::Type::NAND || fanout->type == Gate::Type::AND) {
|
||||
faults.push(TMP_FAULT{g, name, 1, stem, 0});
|
||||
} else if(fanout->type == Gate::Type::NOR || fanout->type == Gate::Type::OR) {
|
||||
faults.push(TMP_FAULT{g, name, 0, stem, 0});
|
||||
} else {
|
||||
assert(false);
|
||||
out->cal_score();
|
||||
out->CC = 1;
|
||||
if(!out->is_good_var && out->score > 0) {
|
||||
out->is_good_var = 1;
|
||||
good_gates.push_back(out);
|
||||
}
|
||||
|
||||
for(Gate* in : out->fanins) {
|
||||
if(in == gate) continue;
|
||||
in->CC = 1;
|
||||
in->cal_score();
|
||||
if(!in->is_good_var && in->score > 0) {
|
||||
in->is_good_var = 1;
|
||||
good_gates.push_back(in);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf("fault-size: %d\n", faults.size());
|
||||
gate->cal_score();
|
||||
}
|
||||
|
||||
std::vector<TMP_FAULT> t_faults;
|
||||
std::set<TMP_FAULT> t_verify_set;
|
||||
void Circuit::ls_update() {
|
||||
|
||||
while(!faults.empty()) {
|
||||
TMP_FAULT f = faults.front();
|
||||
faults.pop();
|
||||
std::set<Gate*> reigon;
|
||||
|
||||
assert(t_verify_set.count(f) == 0);
|
||||
for(Gate* g : unjust_gates) {
|
||||
g->unsat_cost += OPT(vsat_inc);
|
||||
|
||||
t_faults.push_back(f);
|
||||
t_verify_set.insert(f);
|
||||
for(Gate* in : g->fanins) {
|
||||
reigon.insert(in);
|
||||
}
|
||||
for(Gate* out : g->fanouts) {
|
||||
reigon.insert(out);
|
||||
for(Gate* in : out->fanins) {
|
||||
reigon.insert(in);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::map<std::pair<std::string, int>, std::pair<int, int>> mp;
|
||||
|
||||
for(TMP_FAULT &f : t_faults) {
|
||||
faults.push(f);
|
||||
mp[std::make_pair(f.g->name, f.stuck_at)] = std::make_pair(f.is_stem, f.is_PO);
|
||||
for(Fault f : unknown_faults) {
|
||||
Gate* g = f.gate->stuck_at_gate[f.stuck_at];
|
||||
assert(g != nullptr);
|
||||
g->weight += OPT(fw_inc) * 100;
|
||||
for(Gate* in : g->fanins) {
|
||||
reigon.insert(in);
|
||||
}
|
||||
for(Gate* out : g->fanouts) {
|
||||
reigon.insert(out);
|
||||
for(Gate* in : out->fanins) {
|
||||
reigon.insert(in);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf("fault-size: %d\n", t_faults.size());
|
||||
printf("verify-size: %d\n", t_verify_set.size());
|
||||
assert(t_faults.size() == t_verify_set.size());
|
||||
for(Gate* g : reigon) {
|
||||
g->cal_score();
|
||||
if(!g->is_good_var && g->score > 0 && g->CC) {
|
||||
g->is_good_var = 1;
|
||||
good_gates.push_back(g);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Pattern> patterns;
|
||||
void Circuit::ls_gen_sol(const Fault &f) {
|
||||
|
||||
std::vector<int> best_sol;
|
||||
int best_score = -1;
|
||||
simulator->simulate(PIs, best_score, unknown_faults);
|
||||
for(Gate* gate : PIs) {
|
||||
best_sol.push_back(gate->value);
|
||||
}
|
||||
|
||||
for(Gate* gate : gates) {
|
||||
gate->value = gate->cal_value();
|
||||
gate->v_sat = 1;
|
||||
gate->CC = 1;
|
||||
gate->is_good_var = 0;
|
||||
}
|
||||
|
||||
for(Gate* gate : gates) {
|
||||
gate->cal_score();
|
||||
if(gate->score > 0) {
|
||||
gate->is_good_var = 1;
|
||||
good_gates.push_back(gate);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for(int step=0; step<OPT(max_step_coeff)*original_gates.size(); step++) {
|
||||
|
||||
// assert(unjust_gates.size() == 0);
|
||||
// printf("step: %d\n", step);
|
||||
|
||||
Gate* pick = ls_pick();
|
||||
|
||||
// int score1 = cal_circuit_score();
|
||||
|
||||
pick->cal_score();
|
||||
int delta = pick->score;
|
||||
// printf("flip: %s score: %d\n", pick->name.c_str(), delta);
|
||||
|
||||
ls_flip(pick);
|
||||
|
||||
// int score2 = cal_circuit_score();
|
||||
|
||||
// printf("score: %d %d %d\n", score1, score2, delta);
|
||||
// assert((score2 - score1) == delta);
|
||||
|
||||
if(pick->isPI) {
|
||||
|
||||
Pattern p;
|
||||
for(Gate* gate : PIs) {
|
||||
p.input_vector.push_back(gate->value);
|
||||
}
|
||||
|
||||
int res = check_fault(p, f);
|
||||
|
||||
if(!res) {
|
||||
ls_flip(pick);
|
||||
pick->CC = 0;
|
||||
} else {
|
||||
|
||||
printf("succsss-flip-pi: %s\n", pick->name.c_str());
|
||||
int score;
|
||||
simulator->simulate(PIs, score, unknown_faults);
|
||||
if(score > best_score) {
|
||||
printf("update_best_score: %d\n", best_score);
|
||||
best_score = score;
|
||||
best_sol.clear();
|
||||
for(Gate* gate : PIs) {
|
||||
p.input_vector.push_back(gate->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// printf("====== test end\n");
|
||||
// exit(0);
|
||||
|
||||
assert(best_score != -1);
|
||||
|
||||
for(int i=0; i<PIs.size(); i++) {
|
||||
PIs[i]->value = best_sol[i];
|
||||
}
|
||||
}
|
||||
|
||||
void Circuit::ls_main() {
|
||||
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
|
||||
while(!faults.empty()) {
|
||||
printf("====== local search start ======\n");
|
||||
|
||||
while(!faults.empty()) {
|
||||
TMP_FAULT f = faults.front();
|
||||
if(fault_detected[f.g->id-1][f.stuck_at]) {
|
||||
faults.pop();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
std::vector<Pattern> patterns;
|
||||
|
||||
if(faults.empty()) break;
|
||||
while(!unknown_faults.empty()) {
|
||||
|
||||
Fault f = *unknown_faults.begin(); unknown_faults.erase(unknown_faults.begin());
|
||||
|
||||
ls_init();
|
||||
|
||||
ls_random_sol();
|
||||
|
||||
TMP_FAULT f = faults.front(); faults.pop();
|
||||
Gate* g = f.g;
|
||||
Gate* g = f.gate;
|
||||
int stuck_at = f.stuck_at;
|
||||
|
||||
printf("start with fault: %s SA%d\t", g->name.c_str(), stuck_at);
|
||||
|
||||
std::vector<int> inputs;
|
||||
|
||||
printf("verify ...");
|
||||
|
||||
int res1 = sat_atpg(f, inputs);
|
||||
std::vector<int> inputs;
|
||||
|
||||
int res1 = sat_atpg(mp[f], inputs);
|
||||
|
||||
if(res1 == 0) {
|
||||
printf(" unsat!\n");
|
||||
undetected_faults.insert(f);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -296,295 +342,65 @@ void LUTCircuit::ls_main() {
|
||||
PIs[i]->value = inputs[i];
|
||||
}
|
||||
|
||||
printf("sim: %s %d\n", g->name.c_str(), stuck_at);
|
||||
for(int i=0; i<inputs.size(); i++) {
|
||||
printf("%d ", inputs[i]);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
for(LUT* lut : luts) {
|
||||
lut->input_var = 0;
|
||||
for(int i=0; i<lut->fanins.size(); i++) {
|
||||
LUT* in = lut->fanins[i];
|
||||
lut->input_var |= (in->value << i);
|
||||
}
|
||||
}
|
||||
|
||||
ls_gen_sol(f);
|
||||
|
||||
int score;
|
||||
simulator->simulate(PIs, score, fault_detected);
|
||||
simulator->simulate(PIs, score, unknown_faults);
|
||||
|
||||
Pattern pattern;
|
||||
for(LUT* lut : PIs) {
|
||||
pattern.input_vector.push_back(lut->value);
|
||||
for(Gate* g : PIs) {
|
||||
pattern.input_vector.push_back(g->value);
|
||||
}
|
||||
|
||||
assert(check_fault(pattern, f));
|
||||
|
||||
simulator->name2gate[g->name]->fault_detected[stuck_at] = 1;
|
||||
assert(fault_detected[g->id-1][stuck_at] == 0);
|
||||
detected_faults.insert(f);
|
||||
pattern.detected_faults.push_back(f);
|
||||
|
||||
int num_fault = 0;
|
||||
int num_fault = 1;
|
||||
|
||||
// check if real detected
|
||||
for(Gate* g : simulator->gates) {
|
||||
for(int i=0; i<=1; i++) {
|
||||
if(g->fault_detected[i] && !fault_detected[g->id-1][i]) {
|
||||
fault_detected[g->id-1][i] = 1;
|
||||
std::vector<Fault> remove_faults;
|
||||
|
||||
if(mp.count(std::make_pair(g->name, i))) {
|
||||
auto [is_tem, is_PO] = mp[std::make_pair(g->name, i)];
|
||||
for(Fault f : unknown_faults) {
|
||||
|
||||
TMP_FAULT f = TMP_FAULT{g, g->name, i, is_tem, is_PO};
|
||||
Gate* gate = f.gate;
|
||||
int stuck_at = f.stuck_at;
|
||||
|
||||
int res = check_fault(pattern, f);
|
||||
if(!res) {
|
||||
printf("fault: %s SA%d is not real detected!\n", g->name.c_str(), i);
|
||||
fault_detected[g->id-1][i] = 0;
|
||||
} else {
|
||||
pattern.detected_faults.push_back(f);
|
||||
}
|
||||
}
|
||||
assert(gate->sim_gate != nullptr);
|
||||
|
||||
if(fault_detected[g->id-1][i]) {
|
||||
num_detected_fault++;
|
||||
num_undetected_fault--;
|
||||
num_fault++;
|
||||
}
|
||||
if(gate->sim_gate->fault_detected[stuck_at]) {
|
||||
|
||||
int res = check_fault(pattern, f);
|
||||
|
||||
if(!res) {
|
||||
printf("fault: %s SA%d is not real detected!\n", gate->name.c_str(), stuck_at);
|
||||
} else {
|
||||
pattern.detected_faults.push_back(f);
|
||||
num_fault++;
|
||||
detected_faults.insert(f);
|
||||
remove_faults.push_back(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
patterns.push_back(pattern);
|
||||
assert(num_fault > 0);
|
||||
|
||||
if(num_fault > 0) {
|
||||
num_pattern++;
|
||||
for(Fault f : remove_faults) {
|
||||
unknown_faults.erase(f);
|
||||
}
|
||||
|
||||
patterns.push_back(pattern);
|
||||
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
|
||||
|
||||
// cnt++;
|
||||
printf("Cover: %.2f%% pattern: %d new_detected: %d undected: %d time: %.2fs\n", (double)num_detected_fault / num_total_fault * 100, num_pattern, num_fault, num_undetected_fault, (double)duration/1000);
|
||||
printf("Cover: %.2f%% pattern: %d new_detected: %d undected: %d time: %.2fs\n", (double)detected_faults.size() / faults.size() * 100, patterns.size(), num_fault, unknown_faults.size(), (double)duration/1000);
|
||||
|
||||
// break;
|
||||
}
|
||||
|
||||
for(int i=0; i<num_gates; i++) {
|
||||
if(fault_detected[i][0] == 0) {
|
||||
printf("undetected: %s SA0\n", simulator->gates[i]->name.c_str());
|
||||
}
|
||||
if(fault_detected[i][1] == 0) {
|
||||
printf("undetected: %s SA1\n", simulator->gates[i]->name.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
printf("====== local search end ======\n");
|
||||
|
||||
final_check(t_verify_set, patterns);
|
||||
final_check(faults, patterns);
|
||||
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
|
||||
std::cout << "Execution time: " << duration << " milliseconds" << std::endl;
|
||||
}
|
||||
|
||||
void LUTCircuit::ls_gen_sol(const TMP_FAULT &target) {
|
||||
|
||||
std::vector<int> best_sol;
|
||||
int best_score = -1;
|
||||
simulator->simulate(PIs, best_score, fault_detected);
|
||||
for(LUT* lut : PIs) {
|
||||
best_sol.push_back(lut->value);
|
||||
}
|
||||
|
||||
for(int step=0; step<OPT(max_step_coeff)*luts.size(); step++) {
|
||||
// printf("step: %d\n", step);
|
||||
|
||||
LUT* pick = ls_pick();
|
||||
|
||||
if(pick == nullptr) {
|
||||
pick = luts[rand() % luts.size()];
|
||||
}
|
||||
|
||||
// pick->cal_score();
|
||||
|
||||
// double t1 = check();
|
||||
|
||||
// printf(">>>>>>>>>>>>>\n");
|
||||
// printf("dert_score: %.2f\n", pick->score);
|
||||
// printf("dert_unsat_cost: %.2f\n", pick->score_value_unsatisfied_cost);
|
||||
// printf("dert_fault_detected_weight: %.2f\n", pick->score_fault_detected_weight);
|
||||
// printf("dert_fault_propagated_weight: %.2f\n", pick->score_fault_propagated_weight);
|
||||
// printf("dert_up_cost: %.2f\n", pick->score_fault_update_cost);
|
||||
|
||||
ls_flip(pick);
|
||||
|
||||
// double t2 = check();
|
||||
// assert(((t2 - t1) - pick->score) < 1e-6);
|
||||
|
||||
|
||||
if(pick->isPI) {
|
||||
|
||||
// printf("step: %d score: %d\n", step, score);
|
||||
|
||||
Pattern p;
|
||||
for(LUT* lut : PIs) {
|
||||
p.input_vector.push_back(lut->value);
|
||||
}
|
||||
int res = check_fault(p, target);
|
||||
|
||||
if(!res) {
|
||||
ls_flip(pick);
|
||||
pick->CC = 0;
|
||||
} else {
|
||||
int score;
|
||||
simulator->simulate(PIs, score, fault_detected);
|
||||
if(score > best_score) {
|
||||
best_score = score;
|
||||
best_sol.clear();
|
||||
for(LUT* lut : PIs) {
|
||||
best_sol.push_back(lut->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert(best_score != -1);
|
||||
|
||||
for(int i=0; i<PIs.size(); i++) {
|
||||
PIs[i]->value = best_sol[i];
|
||||
}
|
||||
|
||||
for(LUT* lut : luts) {
|
||||
lut->input_var = 0;
|
||||
for(int i=0; i<lut->fanins.size(); i++) {
|
||||
LUT* in = lut->fanins[i];
|
||||
lut->input_var |= (in->value << i);
|
||||
}
|
||||
lut->value = lut->cal_value();
|
||||
lut->vsat = 1;
|
||||
}
|
||||
|
||||
for(LUT* lut : rtopo_luts) {
|
||||
lut->cal_fault_info(lut->fd, lut->fpl);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LUTCircuit::ls_init() {
|
||||
for(LUT* lut : luts) {
|
||||
static int cnt = 0;
|
||||
printf("[%d/%d]\n", ++cnt, luts.size());
|
||||
lut->init_lookup_table();
|
||||
}
|
||||
|
||||
for(LUT* lut : luts) {
|
||||
for(LUT* out :lut->fanouts) {
|
||||
for(int i=0; i<out->fanins.size(); i++) {
|
||||
if(out->fanins[i] == lut) {
|
||||
lut->fault_info.push_back(out->fault_table[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(LUT* lut : luts) {
|
||||
std::set<LUT*> t_reigon;
|
||||
for(LUT* out : lut->fanouts) {
|
||||
for(LUT* in : out->fanins) {
|
||||
t_reigon.insert(in);
|
||||
}
|
||||
}
|
||||
for(LUT* in : lut->fanins) {
|
||||
t_reigon.insert(in);
|
||||
}
|
||||
t_reigon.erase(lut);
|
||||
for(LUT* r : t_reigon) {
|
||||
lut->reigon.push_back(r);
|
||||
}
|
||||
}
|
||||
|
||||
for(LUT* lut : luts) {
|
||||
std::set<LUT*> t_reigon;
|
||||
for(LUT* r: lut->reigon) {
|
||||
t_reigon.insert(r);
|
||||
for(LUT* out2 : r->fanouts) {
|
||||
t_reigon.insert(out2);
|
||||
for(LUT* in2 : out2->fanins) {
|
||||
t_reigon.insert(in2);
|
||||
}
|
||||
}
|
||||
}
|
||||
for(LUT* r : lut->fanouts) {
|
||||
t_reigon.insert(r);
|
||||
}
|
||||
for(LUT* r : t_reigon) {
|
||||
lut->update_reigon.push_back(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LUTCircuit::ls_random_sol() {
|
||||
|
||||
step = 0;
|
||||
|
||||
std::vector<int*> t_focus;
|
||||
|
||||
for(LUT* lut : luts) {
|
||||
lut->up_cost = 1;
|
||||
|
||||
lut->vunat_cost = 1;
|
||||
if(lut->isPI) {
|
||||
lut->vunat_cost = OPT(vsat_inc) * 100;
|
||||
}
|
||||
|
||||
lut->CC = 1;
|
||||
for(Gate* g : lut->inner_gates) {
|
||||
|
||||
g->fault_detected_weight[0] = !fault_detected[g->id-1][0];
|
||||
g->fault_detected_weight[1] = !fault_detected[g->id-1][1];
|
||||
|
||||
if(g->fault_detected_weight[0]) {
|
||||
t_focus.push_back(&g->fault_detected_weight[0]);
|
||||
}
|
||||
|
||||
if(g->fault_detected_weight[1]) {
|
||||
t_focus.push_back(&g->fault_detected_weight[1]);
|
||||
}
|
||||
|
||||
g->fault_propagated_weight[0] = !fault_detected[g->id-1][0];
|
||||
g->fault_propagated_weight[1] = !fault_detected[g->id-1][1];
|
||||
}
|
||||
}
|
||||
|
||||
int *tw = t_focus[rand()%t_focus.size()];
|
||||
*tw = 100000;
|
||||
|
||||
for(LUT* lut : luts) {
|
||||
lut->uptag = 0;
|
||||
lut->value = rand() % 2;
|
||||
}
|
||||
|
||||
for(LUT* lut : luts) {
|
||||
lut->input_var = 0;
|
||||
for(int i=0; i<lut->fanins.size(); i++) {
|
||||
LUT* in = lut->fanins[i];
|
||||
lut->input_var |= (in->value << i);
|
||||
}
|
||||
}
|
||||
|
||||
for(LUT* lut : luts) {
|
||||
lut->vsat = (lut->value == lut->cal_value());
|
||||
}
|
||||
|
||||
for(LUT* lut : rtopo_luts) {
|
||||
lut->cal_fault_info(lut->fd, lut->fpl);
|
||||
}
|
||||
|
||||
for(LUT* lut : luts) {
|
||||
lut->cal_score();
|
||||
}
|
||||
}
|
205
src/lut.cpp
205
src/lut.cpp
@ -1,205 +0,0 @@
|
||||
#include <set>
|
||||
|
||||
#include "lut.h"
|
||||
#include "paras.h"
|
||||
|
||||
using namespace atpg_ls;
|
||||
|
||||
void LUT::flip_value() {
|
||||
value ^= 1;
|
||||
for(auto&[out, id] : fanouts_with_id) {
|
||||
out->input_var ^= (1 << id);
|
||||
}
|
||||
}
|
||||
|
||||
void LUT::cal_fault_info(int *fd, int* fpl) {
|
||||
|
||||
fd[0] = fd[1] = fpl[0] = fpl[1] = 0;
|
||||
if(isPO) {
|
||||
fd[!value] = 1;
|
||||
fd[value] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
for(auto&[out, id] : fanouts_with_id) {
|
||||
if(!out->vsat) continue;
|
||||
|
||||
FaultInfo &info = out->fault_table[id][out->input_var << 1 | out->value];
|
||||
|
||||
int t_fd[2], t_fpl[2];
|
||||
|
||||
t_fd[0] = info.fd[0] && out->fd[!out->value];
|
||||
t_fd[1] = info.fd[1] && out->fd[!out->value];
|
||||
|
||||
t_fpl[0] = info.fpl[0] + info.fd[0] * out->fpl[!out->value];
|
||||
t_fpl[1] = info.fpl[1] + info.fd[1] * out->fpl[!out->value];
|
||||
|
||||
fd[0] |= t_fd[0];
|
||||
fd[1] |= t_fd[1];
|
||||
|
||||
fpl[0] = std::max(fpl[0], t_fpl[0]);
|
||||
fpl[1] = std::max(fpl[1], t_fpl[1]);
|
||||
}
|
||||
|
||||
// std::vector<Gate*> reigon;
|
||||
|
||||
// std::priority_queue<std::pair<Gate*, int>, std::vector<std::pair<Gate*, int>>,
|
||||
// std::function<bool(const std::pair<Gate*, int>&, const std::pair<Gate*, int>&)>> pq([](const std::pair<Gate*, int>& p1, const std::pair<Gate*, int>& p2) {
|
||||
// return p1.first->id < p2.first->id;
|
||||
// });
|
||||
|
||||
// for(Gate* out : gate->fanouts) {
|
||||
// if(!out->vsat) continue;
|
||||
// pq.push(std::make_pair(out, 0));
|
||||
// }
|
||||
|
||||
// pq.push(std::make_pair(gate, 0));
|
||||
|
||||
// while(!q.empty()) {
|
||||
// auto [now, level] = q.front(); q.pop();
|
||||
|
||||
// for(Gate* out : now->fanouts) {
|
||||
// if(!out->is_detected(now)) continue;
|
||||
|
||||
// if(level + 1 < OPT(lut)) {
|
||||
// q.push(std::make_pair(out, level + 1));
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
int LUT::cal_value() {
|
||||
if(isPI) return value;
|
||||
return value_table[input_var];
|
||||
}
|
||||
|
||||
LUT::LUT(Gate *gate, LUTCircuit *circuit):gate(gate), value(gate->value), name(gate->name.c_str()) {
|
||||
|
||||
C = circuit;
|
||||
|
||||
isPI = gate->isPI;
|
||||
isPO = gate->isPO;
|
||||
|
||||
inner_gates.push_back(gate);
|
||||
|
||||
std::set<Gate*> fanins;
|
||||
|
||||
for(Gate* g : gate->fanins) {
|
||||
fanins.insert(g);
|
||||
}
|
||||
|
||||
while(true) {
|
||||
|
||||
std::vector<Gate*> candidates;
|
||||
for(Gate* fanin : fanins) {
|
||||
if(fanin->fanouts.size() >= 2) continue;
|
||||
if(fanin->isPI) continue;
|
||||
|
||||
int add = 0;
|
||||
for(Gate* in : fanin->fanins) {
|
||||
if(fanins.count(in) == 0) {
|
||||
add++;
|
||||
}
|
||||
}
|
||||
|
||||
if(fanins.size() - 1 + add <= OPT(lut)) {
|
||||
candidates.push_back(fanin);
|
||||
}
|
||||
}
|
||||
|
||||
if(candidates.size() == 0) break;
|
||||
|
||||
Gate* random_gate = candidates[rand()%candidates.size()];
|
||||
|
||||
inner_gates.push_back(random_gate);
|
||||
fanins.erase(random_gate);
|
||||
|
||||
for(Gate* in : random_gate->fanins) {
|
||||
fanins.insert(in);
|
||||
}
|
||||
}
|
||||
|
||||
for(Gate* in : fanins) {
|
||||
__gate_fanins.push_back(in);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LUT::init_lookup_table() {
|
||||
value_table = new int[1 << fanins.size()];
|
||||
fault_table = new FaultInfo *[fanins.size() + inner_gates.size()];
|
||||
for (int i = 0; i < (fanins.size() + inner_gates.size()); i++) {
|
||||
fault_table[i] = new FaultInfo[1 << (fanins.size() + 1)];
|
||||
}
|
||||
|
||||
std::unordered_map<Gate*, int> gate2index;
|
||||
|
||||
for(int i=0; i<fanins.size(); i++) {
|
||||
gate2index[fanins[i]->gate] = i;
|
||||
}
|
||||
for(int i=0; i<inner_gates.size(); i++) {
|
||||
gate2index[inner_gates[i]] = i + fanins.size();
|
||||
}
|
||||
|
||||
for (int i = 0; i < (1 << fanins.size()); i++) {
|
||||
for (int j = 0; j < fanins.size(); j++) {
|
||||
fanins[j]->gate->value = (i >> j) & 1;
|
||||
}
|
||||
for (Gate *g : inner_gates) {
|
||||
g->value = g->cal_value();
|
||||
}
|
||||
|
||||
assert(inner_gates[inner_gates.size() - 1] == gate);
|
||||
|
||||
value_table[i] = gate->value;
|
||||
|
||||
for(gate->value=0; gate->value<=1; gate->value++) {
|
||||
|
||||
for(auto&[g, index] : gate2index) {
|
||||
g->fault_detected[0] = g->fault_detected[1] = 0;
|
||||
g->fault_propagated_len[0] = g->fault_propagated_len[1] = 0;
|
||||
}
|
||||
|
||||
gate->fault_detected[!gate->value] = 1;
|
||||
gate->fault_detected[gate->value] = 0;
|
||||
gate->fault_propagated_len[0] = 0;
|
||||
gate->fault_propagated_len[1] = 0;
|
||||
|
||||
std::queue<Gate*> q;
|
||||
q.push(gate);
|
||||
|
||||
while(!q.empty()) {
|
||||
Gate *now = q.front(); q.pop();
|
||||
|
||||
FaultInfo *info = &fault_table[gate2index[now]][(i<<1)|gate->value];
|
||||
info->fd[0] = now->fault_detected[0];
|
||||
info->fd[1] = now->fault_detected[1];
|
||||
info->fpl[0] = now->fault_propagated_len[0];
|
||||
info->fpl[1] = now->fault_propagated_len[1];
|
||||
info->value = now->value;
|
||||
|
||||
// if(now->name == "new_n22_") {
|
||||
// printf("Gate: %s value: %d inputs: [ ", now->name.c_str(), now->value);
|
||||
// for(Gate *in : now->fanins) {
|
||||
// printf("%s ", in->name.c_str());
|
||||
// }
|
||||
// printf("]\n");
|
||||
// }
|
||||
|
||||
for(Gate *in : now->fanins) {
|
||||
if(gate2index.count(in) == 0) continue;
|
||||
|
||||
if(now->is_detected(in)) {
|
||||
in->fault_detected[!in->value] = std::max(in->fault_detected[!in->value], now->fault_detected[!now->value]);
|
||||
in->fault_propagated_len[!in->value] = std::max(in->fault_propagated_len[!in->value], now->fault_propagated_len[!now->value] + 1);
|
||||
}
|
||||
|
||||
q.push(in);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
78
src/lut.h
78
src/lut.h
@ -1,78 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "gate.h"
|
||||
|
||||
namespace atpg_ls {
|
||||
|
||||
class LUTCircuit;
|
||||
|
||||
class LUT {
|
||||
public:
|
||||
LUT(Gate *gate, LUTCircuit *circuit);
|
||||
|
||||
LUTCircuit *C;
|
||||
|
||||
Gate *gate;
|
||||
|
||||
bool isPI, isPO;
|
||||
|
||||
uint32_t input_var;
|
||||
|
||||
std::vector<LUT *> fanins;
|
||||
|
||||
std::vector<LUT *> fanouts;
|
||||
std::vector<std::pair<LUT*, int>> fanouts_with_id;
|
||||
|
||||
std::vector<LUT *> reigon;
|
||||
std::vector<LUT *> update_reigon;
|
||||
|
||||
std::vector<Gate *> inner_gates;
|
||||
|
||||
std::vector<Gate *> __gate_fanins;
|
||||
|
||||
std::unordered_map<Gate *, int> input_id;
|
||||
|
||||
int &value;
|
||||
void flip_value();
|
||||
|
||||
const char *name;
|
||||
|
||||
int *value_table;
|
||||
|
||||
struct FaultInfo {
|
||||
int fd[2];
|
||||
int fpl[2];
|
||||
int value;
|
||||
} **fault_table;
|
||||
|
||||
std::vector<FaultInfo *> fault_info;
|
||||
|
||||
void init_lookup_table();
|
||||
|
||||
// local search
|
||||
|
||||
bool vsat;
|
||||
int vunat_cost;
|
||||
bool uptag;
|
||||
int up_cost;
|
||||
int fd[2];
|
||||
int fpl[2];
|
||||
// int is_good_var;
|
||||
int CC;
|
||||
|
||||
int cal_value();
|
||||
void cal_fault_info(int *t_fd, int *t_fpl);
|
||||
void get_fault_info(Gate *gate, int *t_fd, int *t_fpl);
|
||||
|
||||
// score
|
||||
double score;
|
||||
double score_value_unsatisfied_cost;
|
||||
double score_fault_detected_weight;
|
||||
double score_fault_propagated_weight;
|
||||
double score_fault_update_cost;
|
||||
|
||||
void cal_score();
|
||||
void cal_update();
|
||||
};
|
||||
|
||||
}
|
26
src/main.cpp
Normal file → Executable file
26
src/main.cpp
Normal file → Executable file
@ -18,19 +18,18 @@ int main(int argc, char *argv[]) {
|
||||
Simulator* simulator = new Simulator();
|
||||
|
||||
printf("parsing file %s ...\n", OPT(instance).c_str());
|
||||
circuit->parse_from_file(OPT(instance).c_str());
|
||||
circuit->insert_lines_for_stem();
|
||||
|
||||
simulator->parse_from_file(OPT(instance).c_str());
|
||||
simulator->insert_lines_for_stem();
|
||||
|
||||
circuit->init_topo_index();
|
||||
simulator->init_topo_index();
|
||||
|
||||
|
||||
circuit->init_avg_dist();
|
||||
circuit->parse_from_file(OPT(instance).c_str());
|
||||
circuit->insert_lines_for_stem();
|
||||
circuit->init_topo_index();
|
||||
|
||||
circuit->print();
|
||||
circuit->simulator = simulator;
|
||||
circuit->init_faults();
|
||||
circuit->rebuild_atpg_circuit();
|
||||
|
||||
init_final_checker();
|
||||
|
||||
@ -54,17 +53,16 @@ int main(int argc, char *argv[]) {
|
||||
// circuit->
|
||||
|
||||
printf("building lut circuit ...\n");
|
||||
LUTCircuit *C = circuit->build_lut_circuit();
|
||||
C->simulator = simulator;
|
||||
|
||||
|
||||
printf("====== Circuit Statistics ====== \n");
|
||||
printf("PI:\t%ld\n", circuit->PIs.size());
|
||||
printf("PO:\t%ld\n", circuit->POs.size());
|
||||
printf("Gate:\t%ld\n", circuit->gates.size());
|
||||
printf("LUT:\t%ld\n", C->luts.size());
|
||||
printf("PIs:\t%ld\n", circuit->PIs.size());
|
||||
printf("POs:\t%ld\n", circuit->POs.size());
|
||||
printf("ori-Gate:\t%ld\n", circuit->original_gates.size());
|
||||
printf("new-Gate:\t%ld\n", circuit->gates.size());
|
||||
printf("================================ \n");
|
||||
|
||||
C->ls_main();
|
||||
circuit->ls_main();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
0
src/paras.cpp
Normal file → Executable file
0
src/paras.cpp
Normal file → Executable file
0
src/paras.h
Normal file → Executable file
0
src/paras.h
Normal file → Executable file
0
src/parse.cpp
Normal file → Executable file
0
src/parse.cpp
Normal file → Executable file
2
src/pattern.h
Normal file → Executable file
2
src/pattern.h
Normal file → Executable file
@ -10,7 +10,7 @@ class Pattern {
|
||||
public:
|
||||
|
||||
std::vector<int> input_vector;
|
||||
std::vector<TMP_FAULT> detected_faults;
|
||||
std::vector<Fault> detected_faults;
|
||||
|
||||
};
|
||||
|
||||
|
5
src/sat_atpg.cpp
Normal file → Executable file
5
src/sat_atpg.cpp
Normal file → Executable file
@ -27,6 +27,7 @@ std::map<TMP_FAULT, Fault> fault_map;
|
||||
|
||||
bool sat_atpg(const TMP_FAULT &fal, std::vector<int> &input_vector) {
|
||||
|
||||
// printf(">?> Fault: %s stuck-at: %d is_stem: %d is_po: %d\n", fal.name.c_str(), fal.stuck_at, fal.is_stem, fal.is_PO);
|
||||
assert(fault_map.count(fal) != 0);
|
||||
|
||||
Fault f = fault_map[fal];
|
||||
@ -90,7 +91,7 @@ void sat_atpg_init(const char* file) {
|
||||
|
||||
if(f.is_stem || (f.line->source == nullptr && f.line->destinations.size() == 1)) {
|
||||
|
||||
printf("Fault: %s stuck-at: %d is_stem: %d is_po: %d dest: %d\n", f.line->name.c_str(), f.stuck_at, f.is_stem, f.is_primary_output, f.line->destinations.size());
|
||||
// printf("Fault: %s stuck-at: %d is_stem: %d is_po: %d dest: %d\n", f.line->name.c_str(), f.stuck_at, f.is_stem, f.is_primary_output, f.line->destinations.size());
|
||||
TMP_FAULT tf = TMP_FAULT{nullptr, f.line->name, f.stuck_at, f.is_stem, f.is_primary_output};
|
||||
assert(fault_map.count(tf) == 0);
|
||||
fault_map[tf] = f;
|
||||
@ -105,7 +106,7 @@ void sat_atpg_init(const char* file) {
|
||||
name = f.line->name + "_line_" + f.connection.gate->get_output()->name;
|
||||
}
|
||||
|
||||
printf("Fault: %s stuck-at: %d is_stem: %d is_po: %d dest: %d\n", name.c_str(), f.stuck_at, f.is_stem, f.is_primary_output, f.line->destinations.size());
|
||||
// printf("Fault: %s stuck-at: %d is_stem: %d is_po: %d dest: %d\n", name.c_str(), f.stuck_at, f.is_stem, f.is_primary_output, f.line->destinations.size());
|
||||
|
||||
TMP_FAULT tf = TMP_FAULT{nullptr, name, f.stuck_at, f.is_stem, f.is_primary_output};
|
||||
assert(fault_map.count(tf) == 0);
|
||||
|
0
src/sat_atpg.h
Normal file → Executable file
0
src/sat_atpg.h
Normal file → Executable file
143
src/score.cpp
Normal file → Executable file
143
src/score.cpp
Normal file → Executable file
@ -1,141 +1,34 @@
|
||||
#include "lut.h"
|
||||
#include "circuit.h"
|
||||
|
||||
using namespace atpg_ls;
|
||||
|
||||
void LUT::cal_score() {
|
||||
|
||||
void Gate::cal_score() {
|
||||
score = 0;
|
||||
score_value_unsatisfied_cost = 0;
|
||||
score_fault_detected_weight = 0;
|
||||
score_fault_propagated_weight = 0;
|
||||
score_fault_update_cost = 0;
|
||||
|
||||
// value = !value;
|
||||
this->flip_value();
|
||||
|
||||
if(uptag) {
|
||||
score_fault_update_cost -= up_cost;
|
||||
if(value == 1) {
|
||||
score -= weight;
|
||||
} else {
|
||||
score += weight;
|
||||
}
|
||||
|
||||
// value sat score
|
||||
|
||||
|
||||
if(!isPI) {
|
||||
if(vsat) score_value_unsatisfied_cost += vunat_cost;
|
||||
else score_value_unsatisfied_cost -= vunat_cost;
|
||||
vsat = !vsat;
|
||||
}
|
||||
|
||||
for(LUT* out : fanouts) {
|
||||
if(!out->vsat && out->cal_value() == out->value) {
|
||||
score_value_unsatisfied_cost -= out->vunat_cost;
|
||||
out->vsat = 1;
|
||||
}
|
||||
if(out->vsat && out->cal_value() != out->value){
|
||||
score_value_unsatisfied_cost += out->vunat_cost;
|
||||
out->vsat = 0;
|
||||
if(v_sat) {
|
||||
score -= unsat_cost;
|
||||
} else {
|
||||
score += unsat_cost;
|
||||
}
|
||||
}
|
||||
|
||||
int old_fd[2], old_fpl[2];
|
||||
old_fd[0] = fd[0];
|
||||
old_fd[1] = fd[1];
|
||||
old_fpl[0] = fpl[0];
|
||||
old_fpl[1] = fpl[1];
|
||||
value ^= 1;
|
||||
|
||||
// fault detected score
|
||||
|
||||
cal_fault_info(fd, fpl);
|
||||
|
||||
// printf("fd: %d %d %d %d\n", fd[0], fd[1], old_fd[0], old_fd[1]);
|
||||
|
||||
for(auto&[out, id] : fanouts_with_id) {
|
||||
uint32_t in1 = out->input_var, in2 = out->input_var;
|
||||
in1 ^= (1 << id);
|
||||
|
||||
in1 = (in1 << 1) | out->value;
|
||||
in2 = (in2 << 1) | out->value;
|
||||
|
||||
for(int i=out->fanins.size(); i<out->fanins.size()+out->inner_gates.size(); i++) {
|
||||
Gate* g = out->inner_gates[i-out->fanins.size()];
|
||||
|
||||
int t_fd1[2], t_fpl1[2];
|
||||
int t_fd2[2], t_fpl2[2];
|
||||
|
||||
t_fd1[0] = out->fault_table[i][in1].fd[0] && out->fd[!out->value];
|
||||
t_fd1[1] = out->fault_table[i][in1].fd[1] && out->fd[!out->value];
|
||||
|
||||
t_fd2[0] = out->fault_table[i][in2].fd[0] && out->fd[!out->value];
|
||||
t_fd2[1] = out->fault_table[i][in2].fd[1] && out->fd[!out->value];
|
||||
|
||||
t_fpl1[0] = out->fault_table[i][in1].fpl[0] + out->fault_table[i][in1].fd[0] * out->fpl[!out->value];
|
||||
t_fpl1[1] = out->fault_table[i][in1].fpl[1] + out->fault_table[i][in1].fd[1] * out->fpl[!out->value];
|
||||
|
||||
t_fpl2[0] = out->fault_table[i][in2].fpl[0] + out->fault_table[i][in2].fd[0] * out->fpl[!out->value];
|
||||
t_fpl2[1] = out->fault_table[i][in2].fpl[1] + out->fault_table[i][in2].fd[1] * out->fpl[!out->value];
|
||||
|
||||
score_fault_detected_weight += (t_fd2[0] - t_fd1[0]) * g->fault_detected_weight[0];
|
||||
score_fault_detected_weight += (t_fd2[1] - t_fd1[1]) * g->fault_detected_weight[1];
|
||||
|
||||
if(!g->isPO) {
|
||||
score_fault_propagated_weight += (double)(t_fpl2[0] - t_fpl1[0]) / g->avg_dist * g->fault_detected_weight[0];
|
||||
score_fault_propagated_weight += (double)(t_fpl2[1] - t_fpl1[1]) / g->avg_dist * g->fault_detected_weight[1];
|
||||
}
|
||||
for(Gate* out : fanouts) {
|
||||
if(out->v_sat && (out->value != out->cal_value())) {
|
||||
score -= out->unsat_cost;
|
||||
}
|
||||
if(!out->v_sat && (out->value == out->cal_value())) {
|
||||
score += out->unsat_cost;
|
||||
}
|
||||
}
|
||||
|
||||
int in1 = this->input_var, in2 = this->input_var;
|
||||
in1 = (in1 << 1) | !value;
|
||||
in2 = (in2 << 1) | value;
|
||||
|
||||
for(int i=fanins.size(); i<fanins.size()+inner_gates.size(); i++) {
|
||||
Gate* g = inner_gates[i-fanins.size()];
|
||||
|
||||
int t_fd1[2], t_fpl1[2];
|
||||
int t_fd2[2], t_fpl2[2];
|
||||
|
||||
t_fd1[0] = fault_table[i][in1].fd[0] && old_fd[value];
|
||||
t_fd1[1] = fault_table[i][in1].fd[1] && old_fd[value];
|
||||
|
||||
t_fd2[0] = fault_table[i][in2].fd[0] && fd[!value];
|
||||
t_fd2[1] = fault_table[i][in2].fd[1] && fd[!value];
|
||||
|
||||
t_fpl1[0] = fault_table[i][in1].fpl[0] + fault_table[i][in1].fd[0] * old_fpl[value];
|
||||
t_fpl1[1] = fault_table[i][in1].fpl[1] + fault_table[i][in1].fd[1] * old_fpl[value];
|
||||
|
||||
t_fpl2[0] = fault_table[i][in2].fpl[0] + fault_table[i][in2].fd[0] * fpl[!value];
|
||||
t_fpl2[1] = fault_table[i][in2].fpl[1] + fault_table[i][in2].fd[1] * fpl[!value];
|
||||
|
||||
score_fault_detected_weight += (t_fd2[0] - t_fd1[0]) * g->fault_detected_weight[0];
|
||||
score_fault_detected_weight += (t_fd2[1] - t_fd1[1]) * g->fault_detected_weight[1];
|
||||
|
||||
if(!g->isPO) {
|
||||
score_fault_propagated_weight += (double)(t_fpl2[0] - t_fpl1[0]) / g->avg_dist * g->fault_detected_weight[0];
|
||||
score_fault_propagated_weight += (double)(t_fpl2[1] - t_fpl1[1]) / g->avg_dist * g->fault_detected_weight[1];
|
||||
}
|
||||
}
|
||||
|
||||
// update cost score
|
||||
for(LUT* r : reigon) {
|
||||
int t_fd[2], t_fpl[2];
|
||||
r->cal_fault_info(t_fd, t_fpl);
|
||||
if(t_fd[0] == r->fd[0] && t_fd[1] == r->fd[1] && t_fpl[0] == r->fpl[0] && t_fpl[1] == r->fpl[1]) continue;
|
||||
if(!r->uptag) {
|
||||
score_fault_update_cost += r->up_cost;
|
||||
}
|
||||
}
|
||||
|
||||
this->flip_value();
|
||||
if(!isPI) vsat = !vsat;
|
||||
|
||||
fd[0] = old_fd[0];
|
||||
fd[1] = old_fd[1];
|
||||
fpl[0] = old_fpl[0];
|
||||
fpl[1] = old_fpl[1];
|
||||
|
||||
for(LUT* out : fanouts) {
|
||||
out->vsat = ( out->cal_value() == out->value );
|
||||
}
|
||||
|
||||
score = - score_value_unsatisfied_cost + score_fault_detected_weight + score_fault_propagated_weight - score_fault_update_cost;
|
||||
value ^= 1;
|
||||
}
|
94
src/simulator.cpp
Normal file → Executable file
94
src/simulator.cpp
Normal file → Executable file
@ -2,86 +2,30 @@
|
||||
|
||||
using namespace atpg_ls;
|
||||
|
||||
int Simulator::verify(LUTCircuit *lut_circuit, int** fault_detected) {
|
||||
// int Simulator::verify(Circuit *circuit, int** fault_detected) {
|
||||
|
||||
// lut_circuit->check();
|
||||
// // lut_circuit->check();
|
||||
|
||||
// for(LUT* lut : lut_circuit->PIs) {
|
||||
// printf("PI: %s = %d\n", lut->name, lut->value);
|
||||
// }
|
||||
// // for(LUT* lut : lut_circuit->PIs) {
|
||||
// // printf("PI: %s = %d\n", lut->name, lut->value);
|
||||
// // }
|
||||
|
||||
int score;
|
||||
simulate(lut_circuit->PIs, score, fault_detected);
|
||||
// int score;
|
||||
// simulate(circuit->PIs, score, fault_detected);
|
||||
|
||||
for(LUT* lut : lut_circuit->luts) {
|
||||
assert(lut->value == lut->cal_value());
|
||||
}
|
||||
// for(Gate* gate : circuit->gates) {
|
||||
// assert(gate->value == gate->cal_value());
|
||||
// }
|
||||
|
||||
for(LUT* lut : lut_circuit->rtopo_luts) {
|
||||
lut->cal_fault_info(lut->fd, lut->fpl);
|
||||
}
|
||||
// std::unordered_map<int, Gate*> id2gate;
|
||||
// for(Gate* gate : gates) {
|
||||
// id2gate[gate->id] = gate;
|
||||
// }
|
||||
|
||||
// lut_circuit->print();
|
||||
// return 1;
|
||||
// }
|
||||
|
||||
std::unordered_map<int, Gate*> id2gate;
|
||||
for(Gate* gate : gates) {
|
||||
id2gate[gate->id] = gate;
|
||||
}
|
||||
|
||||
for(LUT* lut : lut_circuit->luts) {
|
||||
|
||||
int input_var = 0;
|
||||
for(int i=0; i<lut->fanins.size(); i++) {
|
||||
LUT* l = lut->fanins[i];
|
||||
input_var |= l->value << i;
|
||||
}
|
||||
|
||||
assert(input_var == lut->input_var);
|
||||
|
||||
if(!lut->isPI) assert(lut->value_table[lut->input_var] == lut->value);
|
||||
|
||||
// printf(">> LUT: %s\n", lut->name);
|
||||
|
||||
// assert(lut->fd[0] == id2gate[lut->gate->id]->fault_detected[0]);
|
||||
// assert(lut->fd[1] == id2gate[lut->gate->id]->fault_detected[1]);
|
||||
// assert(lut->fpl[0] == id2gate[lut->gate->id]->fault_propagated_len[0]);
|
||||
// assert(lut->fpl[1] == id2gate[lut->gate->id]->fault_propagated_len[1]);
|
||||
|
||||
for(int i=lut->fanins.size(); i<lut->fanins.size()+lut->inner_gates.size(); i++) {
|
||||
|
||||
LUT::FaultInfo &info = lut->fault_table[i][(lut->input_var<<1)|lut->value];
|
||||
|
||||
Gate* g = lut->inner_gates[i-lut->fanins.size()];
|
||||
|
||||
int t_fd[2], t_fpl[2];
|
||||
t_fd[0] = info.fd[0] && lut->fd[!lut->value];
|
||||
t_fd[1] = info.fd[1] && lut->fd[!lut->value];
|
||||
t_fpl[0] = info.fpl[0] + info.fd[0] * lut->fpl[!lut->value];
|
||||
t_fpl[1] = info.fpl[1] + info.fd[1] * lut->fpl[!lut->value];
|
||||
|
||||
Gate* sim_g = id2gate[g->id];
|
||||
assert(g->name == sim_g->name);
|
||||
|
||||
// if(g->name == "new_n32_" || g->name == "new_n33_") {
|
||||
// printf("Gate: %s value: %d %d\n", g->name.c_str(), info.value, sim_g->value);
|
||||
// printf("l_fd[0]: %d, l_fd[1]: %d, l_fpl[0]: %d, l_fpl[1]: %d\n", lut->fd[0], lut->fd[1], lut->fpl[0], lut->fpl[1]);
|
||||
// printf("i_fd[0]: %d, i_fd[1]: %d, i_fpl[0]: %d, i_fpl[1]: %d\n", info.fd[0], info.fd[1], info.fpl[0], info.fpl[1]);
|
||||
// printf("t_fd[0]: %d, t_fd[1]: %d, t_fpl[0]: %d, t_fpl[1]: %d\n", t_fd[0], t_fd[1], t_fpl[0], t_fpl[1]);
|
||||
// printf("s_fd[0]: %d, s_fd[1]: %d, s_fpl[0]: %d, s_fpl[1]: %d\n\n", sim_g->fault_detected[0], sim_g->fault_detected[1], sim_g->fault_propagated_len[0], sim_g->fault_propagated_len[1]);
|
||||
// }
|
||||
|
||||
assert(info.value == sim_g->value);
|
||||
assert(t_fd[0] == sim_g->fault_detected[0]);
|
||||
assert(t_fd[1] == sim_g->fault_detected[1]);
|
||||
// assert(t_fpl[0] == sim_g->fault_propagated_len[0]);
|
||||
// assert(t_fpl[1] == sim_g->fault_propagated_len[1]);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void Simulator::simulate(std::vector<LUT*> &inputs, int &score, int** fault_detected) {
|
||||
void Simulator::simulate(std::vector<Gate*> &inputs, int &score, std::set<Fault> &unknown_faults) {
|
||||
|
||||
assert(inputs.size() == this->PIs.size());
|
||||
|
||||
@ -103,10 +47,10 @@ void Simulator::simulate(std::vector<LUT*> &inputs, int &score, int** fault_dete
|
||||
score = 0;
|
||||
|
||||
for(auto gate : gates) {
|
||||
if(gate->fault_detected[0] && !fault_detected[gate->id-1][0]) {
|
||||
if(gate->fault_detected[0] && unknown_faults.count(Fault{gate->ori_gate, 0})) {
|
||||
score++;
|
||||
}
|
||||
if(gate->fault_detected[1] && !fault_detected[gate->id-1][1]) {
|
||||
if(gate->fault_detected[1] && unknown_faults.count(Fault{gate->ori_gate, 1})) {
|
||||
score++;
|
||||
}
|
||||
}
|
||||
|
4
src/simulator.h
Normal file → Executable file
4
src/simulator.h
Normal file → Executable file
@ -6,8 +6,8 @@ namespace atpg_ls {
|
||||
|
||||
class Simulator : public Circuit {
|
||||
public:
|
||||
void simulate(std::vector<LUT*> &inputs, int &score, int** fault_detected);
|
||||
int verify(LUTCircuit *lut_circuit, int** fault_detected);
|
||||
void simulate(std::vector<Gate*> &inputs, int &score, std::set<Fault> &unknown_faults);
|
||||
// int verify(Circuit *circuit, int** fault_detected);
|
||||
};
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user