diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..ef04be4 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,29 @@ +{ + "files.associations": { + "*.tcc": "cpp", + "cctype": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "compare": "cpp", + "concepts": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cwchar": "cpp", + "deque": "cpp", + "unordered_map": "cpp", + "unordered_set": "cpp", + "vector": "cpp", + "exception": "cpp", + "initializer_list": "cpp", + "iosfwd": "cpp", + "limits": "cpp", + "new": "cpp", + "numbers": "cpp", + "string": "cpp", + "string_view": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "typeinfo": "cpp" + } +} \ No newline at end of file diff --git a/atpg b/atpg index 1f210c7..16002dd 100755 Binary files a/atpg and b/atpg differ diff --git a/circuit.cpp b/circuit.cpp index 4376100..3fc1ca4 100644 --- a/circuit.cpp +++ b/circuit.cpp @@ -5,73 +5,13 @@ #include #include "assert.h" -void Circuit::init_stems() { - for(auto& gate: gates) { - if(gate->outputs.size() >= 2) { - gate->stem = true; - } - // gate->stem = true; - // if(rand() % 1000 <= 100) { - // gate->stem = true; - // } - if(gate->stem) { - stems.push_back(gate); - } - } - - for(Gate *g : gates) { - if(g->isPI) continue; - std::queue q; - std::unordered_map 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->isPO) continue; - std::queue q; - std::unordered_map 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 q; - std::unordered_map ins; - for(Gate* gate : gates) { - ins[gate] = gate->inputs.size(); - } + // 计算正向拓扑序 for(auto in : PIs) { in->id = topo++; q.push(in); @@ -79,52 +19,42 @@ void Circuit::init_topo_index() { while(!q.empty()) { Gate* g = q.front(); q.pop(); - for(Gate* out : g->outputs) { - ins[out]--; - if(ins[out] == 0) { + for(Gate* out : g->fan_outs) { + ins[out]++; + if(ins[out] == out->fan_ins.size()) { out->id = topo++; q.push(out); } } } -} -void Circuit::init_gate_level() { - MAX_GATE_LEVEL = 0; - std::queue q; + // 计算反向拓扑序 + topo = 1; + std::unordered_map outs; - for(Gate* gate : gates) { - gate->level = -1; - } - - for(auto pi: PIs) { - pi->level = 0; - q.push(pi); + for(auto out : POs) { + out->rtopo = topo++; + q.push(out); } while(!q.empty()) { Gate* g = q.front(); q.pop(); - - MAX_GATE_LEVEL = std::max(MAX_GATE_LEVEL, g->level); - - for(Gate* out : g->outputs) { - if(out->level == -1) { - out->level = g->level + 1; - q.push(out); + 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); } } } - - for(Gate* g : gates) { - assert(g->level != -1); - } } -void Circuit::print_gates() { +void Circuit::print_circuit() { static const char* type2name[9] = {"AND", "NAND", "OR", "NOR", "XOR", "XNOR", "NOT", "BUF", "IN"}; for(Gate* gate : gates) { - printf("Gate: %3s (t:%4s v:%d pi:%d po:%d s:%d p:%d s0:%d s1:%d fpl0:%d fpl1:%d) Inputs:", gate->name.c_str(), type2name[gate->type], gate->value, gate->isPI, gate->isPO, gate->stem, gate->is_propagated(), gate->sa[0], gate->sa[1], gate->fault_propagate_len[0], gate->fault_propagate_len[1]); - for(Gate* in : gate->inputs) { + printf("Gate: %3s (t:%4s v:%d pi:%d po:%d s:%d p:%d s0:%d s1:%d fpl0:%d fpl1:%d) Inputs:", gate->name.c_str(), type2name[gate->type], gate->value, gate->pi, gate->po, gate->stem, gate->propagate, gate->fault_detected[0], gate->fault_detected[1], gate->fault_propagate_length[0], gate->fault_propagate_length[1]); + for(Gate* in : gate->fan_ins) { printf(" %s(%d)", in->name.c_str(), gate->is_detected(in)); } printf("\n"); @@ -133,11 +63,9 @@ void Circuit::print_gates() { bool Circuit::is_valid_circuit() { - ll flip_total_weight = 0; - ll stem_total_weight = 0; + ll stem_total_cost = 0; ll fault_total_weight = 0; - int flip_total_cnt = 0; int stem_total_cnt = 0; int fault_total_cnt = 0; @@ -147,95 +75,62 @@ bool Circuit::is_valid_circuit() { for(Gate* g : gates) { - fault_propagate_score += g->fault_propagate_len[0] * fault_weight[g->id][0]; - fault_propagate_score += g->fault_propagate_len[1] * fault_weight[g->id][1]; - - if(flip_need_update[g->id]) { - flip_total_weight += flip_weight[g->id]; - flip_total_cnt++; + 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->cal_value() != g->value) { - stem_total_weight += stem_weight[g->id]; + 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->cal_value() == g->value) { + 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++; } - if(g->cal_propagate_len(0) != g->fault_propagate_len[0] || g->cal_propagate_len(1) != g->fault_propagate_len[1]) { - printf("WRONG-PRO-LEN: %s \n", g->name.c_str()); - print_gates(); - return false; - } + 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->sa[0]) { - fault_total_weight += fault_weight[g->id][0]; + if(g->fault_detected[0]) { + fault_total_weight += g->fault_weight[0]; fault_total_cnt += 1; } - if(g->sa[1]) { - fault_total_weight += fault_weight[g->id][1]; + if(g->fault_detected[1]) { + fault_total_weight += g->fault_weight[1]; fault_total_cnt += 1; } - - // 检查门的赋值情况 - if(g->cal_value() != g->value) { - printf("WRONG-ASSGIN: %s \n", g->name.c_str()); - return false; - } - - // 检查 PO 的传播设定是否正确 - if(g->isPO) { - if(g->sa[g->value] != 0 || g->sa[!g->value] == 0 ) { - printf("WRONG-PO: %s \n", g->name.c_str()); - } - continue; - } - - // 非 PO 情况下检查故障传播是否正确 - - bool sa0 = false; - bool sa1 = false; - - for(Gate* out : g->outputs) { - if(out->cal_value() != out->value) { - assert(out->stem); - continue; - } - - g->value = !g->value; - - if(out->cal_value() != out->value) { - sa0 |= out->is_propagated() && !g->value; - sa1 |= out->is_propagated() && g->value; - } - - g->value = !g->value; - } - - if(sa0 != g->sa[0] || sa1 != g->sa[1]) { - printf("WRONG-SA: %s \n", g->name.c_str()); - return false; - } } - if(this->flip_total_weight != flip_total_weight || this->stem_total_weight != stem_total_weight || this->fault_total_weight != fault_total_weight) { - printf("CIRCUIT CHECK FAILED!\n"); - printf("[wrong] flip: %d, stem: %d, fault:%d\n", this->flip_total_weight, this->stem_total_weight, this->fault_total_weight); - printf("[right] flip: %d, stem: %d, fault:%d\n", flip_total_weight, stem_total_weight, fault_total_weight); - return false; - } - - if(this->flip_total_cnt != flip_total_cnt || this->stem_total_cnt != stem_total_cnt || this->fault_total_cnt != fault_total_cnt) { - printf("CIRCUIT CHECK FAILED!\n"); - printf("[wrong] flip_cnt: %d, stem_cnt: %d, fault_cnt:%d\n", this->flip_total_cnt, this->stem_total_cnt, this->fault_total_cnt); - printf("[right] flip_cnt: %d, stem_cnt: %d, fault_cnt:%d\n", flip_total_cnt, stem_total_cnt, fault_total_weight); - return false; - } - - printf("%lld %lld\n", fault_propagate_score , this->fault_propagate_score); - assert(fault_propagate_score == this->fault_propagate_score); + 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; } diff --git a/circuit.h b/circuit.h index d883458..f1bdf1d 100644 --- a/circuit.h +++ b/circuit.h @@ -1,129 +1,117 @@ #pragma once +#include "option.h" + #include #include #include #include #include + using ll = long long; class Gate { public: + // 门的原始信息 int id; - int level; + int rtopo; std::string name; enum Type { AND, NAND, OR, NOR, XOR, XNOR, NOT, BUF, INPUT } type; int value; - bool sa[2]; - bool stem; - bool isPI; - bool isPO; - - int fault_propagate_len[2]; + bool pi; + bool po; + std::vector fan_outs; + std::vector fan_ins; std::vector pre_stems; std::vector suc_stems; - std::vector outputs; - std::vector inputs; + // 记录全局已经发现的错误 + bool global_fault_detected[2]; - bool is_propagated(); - int cal_value(); - bool cal_sa(bool x); + // atpg-ls 附加信息 + int CC; + bool stem; + bool propagate; + + int stem_weight; + bool stem_satisfied; + + int fault_weight[2]; + bool fault_detected[2]; + + int fault_propagate_length[2]; + + // 计算此门的信息 + int recal_value(); + void recal_fault(bool fd[2]); + void recal_propagate_len(int fpl[2]); + + // 门的某个输入产生的错误是否可以通过这个门传播 bool is_detected(Gate* one_of_input); - int cal_propagate_len(bool x); -}; - -class Fault { -public: - Gate* gate; - enum Type { SA0, SA1 } type; - Fault(Gate* gate, Type type):gate(gate),type(type) {} }; class Circuit { public: + +// 电路的基本信息 std::vector PIs; std::vector POs; std::vector gates; -std::vector stems; // PI + stems +std::vector rtopo_gates; +std::vector stems; // PIs and POs are stems by default std::unordered_map name2gate; -std::queue tmp; -std::unordered_map tmp_used; - +// 读入和输出电路 void parse_from_file(const char *filename); -void print_gates(); +void print_circuit(); -bool is_valid_circuit(); +// 初始化电路统计信息 +int MAX_GATE_LEVEL; void init_topo_index(); -int MAX_GATE_LEVEL; -void init_gate_level(); -void init_stems(); +// 电路状态 checker +bool is_valid_circuit(); // local search -bool local_search(std::unordered_set &faults); +bool local_search(); -// incremental flip struct +int global_fault_undetected_count; -const double SP = 0.01; - -const int FLIP_INC = 1; -const int FLIP_WEIGHT_MAX = 1e9; - -int* CC; - -ll flip_total_weight; -int flip_total_cnt; -int* flip_weight; -int* flip_need_update; -std::vector flip_update_queue; - -// incremental stem struct -int STEM_INC = 0; -const int STEM_WEIGHT_MAX = 1e9; -ll stem_total_weight; +ll stem_total_cost; int stem_total_cnt; -int* stem_weight; -int* stem_satisfied; -int fault_propagate_tatal_len; ll fault_propagate_score; -const int FAULT_INC = 1; -const int FAULT_WEIGHT_MAX = 20; ll fault_total_weight; int fault_total_cnt; -int** fault_weight; -int** fault_detected; -void ls_init_circuit(); -void ls_init_weight(const std::unordered_set &faults); +void ls_reset_data(); +void ls_init_stems(); +void ls_init_weight(); + +void ls_random_circuit(); + +void ls_statistics(); + void ls_update_weight(); -void ls_init_data_structs(); -void ls_block_recal(Gate* stem); +Gate* ls_pick(); +Gate* ls_pick_falsified(); void ls_flip(Gate* stem); -void ls_update(Gate* stem); + ll ls_pick_score(Gate* stem); -ll ls_score(); - -int** simulate(); - - -// time status +ll ls_circuit_score(); int flip_cnt = 0; double flip_time = 0; int update_cnt = 0; double update_time = 0; - }; \ No newline at end of file diff --git a/gate.cpp b/gate.cpp index 5b79081..868d07d 100644 --- a/gate.cpp +++ b/gate.cpp @@ -3,103 +3,93 @@ #include "assert.h" -int Gate::cal_propagate_len(bool x) { - - int fpl[2]; +void Gate::recal_propagate_len(int fpl[2]) { fpl[0] = fpl[1] = 0; - - for(Gate* out : outputs) { + for(Gate* out : fan_outs) { if(!out->is_detected(this)) continue; - - fpl[!value] = std::max(fpl[!value], out->fault_propagate_len[!out->value] + 1); + fpl[!value] = std::max(fpl[!value], out->fault_propagate_length[!out->value] + 1); } - - return fpl[x]; } bool Gate::is_detected(Gate* one_of_input) { one_of_input->value = !one_of_input->value; - bool detect = cal_value() != value; + bool detect = (recal_value() != value); one_of_input->value = !one_of_input->value; - return (cal_value() == value) && detect; + return (recal_value() == value) && detect; } -bool Gate::is_propagated() { - return sa[0] || sa[1]; -} +void Gate::recal_fault(bool fd[2]) { -bool Gate::cal_sa(bool x) { - if(isPO) { - if(x == 0) return value; - else return !value; + if(po) { + fd[!value] = true; + fd[value] = false; + return; } - bool sa0 = 0; - bool sa1 = 0; + fd[0] = fd[1] = 0; - for(Gate* out : outputs) { - if(!out->is_propagated()) continue; + for(Gate* out : fan_outs) { + if(!out->propagate) continue; - if(out->cal_value() != out->value) continue; + if(out->recal_value() != out->value) continue; this->value = !this->value; - bool detect = out->cal_value() != out->value; + bool detect = (out->recal_value() != out->value); this->value = !this->value; if(!detect) continue; - sa0 |= this->value; - sa1 |= !this->value; + fd[0] |= this->value; + fd[1] |= !this->value; } - if(x == 0) return sa0; - else return sa1; + return; } -int Gate::cal_value() { +int Gate::recal_value() { int res; switch(type) { case NOT: - res = !inputs[0]->value; + res = !fan_ins[0]->value; break; case BUF: - res = inputs[0]->value; + res = fan_ins[0]->value; break; case AND: - res = inputs[0]->value; - for(int i=1; ivalue; + res = fan_ins[0]->value; + for(int i=1; ivalue; } break; case NAND: - res = inputs[0]->value; - for(int i=1; ivalue; + res = fan_ins[0]->value; + for(int i=1; ivalue; } res = !res; break; case OR: - res = inputs[0]->value; - for(int i=1; ivalue; + res = fan_ins[0]->value; + for(int i=1; ivalue; } break; case NOR: - res = inputs[0]->value; - for(int i=1; ivalue; + res = fan_ins[0]->value; + for(int i=1; ivalue; } res = !res; break; case XOR: - res = inputs[0]->value; - for(int i=1; ivalue; + res = fan_ins[0]->value; + for(int i=1; ivalue; } break; case XNOR: - res = inputs[0]->value; - for(int i=1; ivalue; + res = fan_ins[0]->value; + for(int i=1; ivalue; } res = !res; break; diff --git a/ls.cpp b/ls.cpp index 4757042..6f73e33 100644 --- a/ls.cpp +++ b/ls.cpp @@ -7,557 +7,467 @@ #include "assert.h" #include +bool Circuit::local_search() { + ls_reset_data(); -bool Circuit::local_search(std::unordered_set &faults) { + ls_init_stems(); - // 初始化并重置所有 ls 数据结构 - ls_init_data_structs(); + ls_init_weight(); - // 赋值初始权重 - ls_init_weight(faults); + ls_random_circuit(); - // 随机生成初始电路 - ls_init_circuit(); - - //printf("local search!\n"); - - while(true) { + for(int i=0; i stems_random; - std::vector candidates; + printf("[FLIP] stem: %lld, fault:%lld, stem_cnt: %lld, fault_cnt:%lld, fpl_score: %lld\n", stem_total_cost, fault_total_weight, stem_total_cnt, fault_total_cnt, fault_propagate_score); - for(int i=0; iid]) { - stems_random.push_back(stems[i]); - } - } - for(int i=0; i max_score) { - max_score = t_score; - stem = t_stem; - } - if(t_score > 0) t++; - if(i >= T) break; - } - - if(max_score > 0) { - // printf("FLIP: %s (+%lld)\n", stem->name.c_str(), max_score); - // printf("[LS] flip: %lld, stem: %lld, fault:%lld. flip_cnt: %d, stem_cnt: %d, fault_cnt:%d\n", flip_total_weight, stem_total_weight, fault_total_weight, flip_total_cnt, stem_total_cnt, fault_total_cnt); - ls_flip(stem); - - CC[stem->id] = 0; - - for(Gate* pre : stem->pre_stems) { - CC[pre->id] = 1; - } - - for(Gate* suc : stem->suc_stems) { - CC[suc->id] = 1; - } - - auto end = std::chrono::system_clock::now(); - std::chrono::duration elapsed_seconds = end - start; - flip_cnt++; - flip_time += elapsed_seconds.count(); - - } else { + if(stem == nullptr) { + printf("[UP] stem: %lld, fault:%lld, stem_cnt: %lld, fault_cnt:%lld, fpl_score: %lld\n", stem_total_cost, fault_total_weight, stem_total_cnt, fault_total_cnt, fault_propagate_score); ls_update_weight(); - - while(!flip_update_queue.empty()) { - Gate* g = flip_update_queue.back(); - flip_update_queue.pop_back(); - if(!flip_need_update[g->id]) continue; - flip_need_update[g->id] = false; - flip_total_weight -= flip_weight[g->id]; - flip_total_cnt -= 1; - ls_update(g); - } - - if(stem_total_cnt == stems.size() && flip_total_cnt == 0) { - //printf("FIND SOLUTION!\n"); - printf("[SOL] flip: %lld, stem: %lld, fault:%lld. flip_cnt: %d, stem_cnt: %d, fault_cnt:%d\n", flip_total_weight, stem_total_weight, fault_total_weight, flip_total_cnt, stem_total_cnt, fault_total_cnt); - break; - } - - std::vector candidates; - for(Gate *g : stems) { - if(g->isPO) continue; - if(stem_satisfied[g->id]) continue; - candidates.push_back(g); - } - - if(candidates.size() == 0) { - candidates.push_back(stems[rand()%stems.size()]); - } - - Gate* pick = candidates[rand()%candidates.size()]; - - ls_flip(pick); - - CC[pick->id] = 0; - - for(Gate* pre : pick->pre_stems) { - CC[pre->id] = 1; - } - - for(Gate* suc : pick->suc_stems) { - CC[suc->id] = 1; - } - - auto end = std::chrono::system_clock::now(); - std::chrono::duration elapsed_seconds = end - start; - update_cnt++; - update_time += elapsed_seconds.count(); - - //printf("[UP] flip: %lld, stem: %lld, fault:%lld. flip_cnt: %lld, stem_cnt: %lld, fault_cnt:%lld\n", flip_total_weight, stem_total_weight, fault_total_weight, flip_total_cnt, stem_total_cnt, fault_total_cnt); + stem = ls_pick_falsified(); } - } - static int original_faults = -1; - if(original_faults == - 1) { - original_faults = faults.size(); - } - static int pattern = 0; - - std::unordered_set tmp = faults; - - for(Fault* f : tmp) { - if(f->gate->sa[f->type]) { - faults.erase(f); + if(stem_total_cnt == stems.size()) { + //printf("FIND SOLUTION!\n"); + //printf("[SOL] flip: %lld, stem: %lld, fault:%lld. flip_cnt: %d, stem_cnt: %d, fault_cnt:%d\n", flip_total_weight, stem_total_weight, fault_total_weight, flip_total_cnt, stem_total_cnt, fault_total_cnt); + break; } + + assert(is_valid_circuit()); + + auto end = std::chrono::system_clock::now(); + std::chrono::duration elapsed_seconds = end - start; + update_cnt++; + update_time += elapsed_seconds.count(); + + //printf("[UP] flip: %lld, stem: %lld, fault:%lld. flip_cnt: %lld, stem_cnt: %lld, fault_cnt:%lld\n", flip_total_weight, stem_total_weight, fault_total_weight, flip_total_cnt, stem_total_cnt, fault_total_cnt); } - if(tmp.size() == faults.size()) pattern--; - - printf("coverage: %.3f%%\tpattern: %d\tbefore: %d\tnow: %d\n", (double)(original_faults - faults.size()) / (original_faults) * 100, ++pattern, tmp.size(), faults.size()); - - printf("flip-cnt: %d flip-time: %.3fs update-cnt: %d update-time: %.3fs\n", flip_cnt, flip_time, update_cnt, update_time); - printf("time-per-flip: %.2fms time-per-update: %.2fms\n", flip_time / flip_cnt * 1000, update_time / update_cnt * 1000); - - //if(tmp.size() == faults.size()) return false; + ls_statistics(); return true; } -void Circuit::ls_update_weight() { +void Circuit::ls_statistics() { - STEM_INC += 1; + int last_undetect = global_fault_undetected_count; + + for(Gate* g : gates) { + if(g->fault_detected[0] && !g->global_fault_detected[0]) { + global_fault_undetected_count--; + g->global_fault_detected[0] = 1; + } + if(g->fault_detected[1] && !g->global_fault_detected[1]) { + global_fault_undetected_count--; + g->global_fault_detected[1] = 1; + } + } + + printf("coverage: %.2f%% undected_fault: %d delta: %d\n", + (gates.size() * 2.0 - global_fault_undetected_count) / (gates.size() * 2.0) * 100, + global_fault_undetected_count, global_fault_undetected_count - last_undetect); +} + +void Circuit::ls_update_weight() { if(rand() % 10000 <= SP * 10000) { for(Gate* g : gates) { - if(g->stem && stem_satisfied[g->id] && (stem_weight[g->id] - STEM_INC >= 1)) { - stem_weight[g->id] -= STEM_INC; - for(Gate* suc : g->suc_stems) { - if(stem_weight[suc->id] + STEM_INC <= STEM_WEIGHT_MAX) { - stem_weight[suc->id] += STEM_INC; - if(!stem_satisfied[suc->id]) { - stem_total_weight += STEM_INC; - } - } - } + if(g->stem && g->stem_satisfied && (g->stem_weight - STEM_INC >= 1)) { + g->stem_weight -= STEM_INC; + } + + if(g->fault_detected[0] && g->fault_weight[0] - FAULT_INC >= 1) { + g->fault_weight[0] -= FAULT_INC; + fault_propagate_score -= FAULT_INC * (g->fault_propagate_length[0]); + } + + if(g->fault_detected[1] && g->fault_weight[1] - FAULT_INC >= 1) { + g->fault_weight[1] -= FAULT_INC; + fault_propagate_score -= FAULT_INC * (g->fault_propagate_length[1]); } } } else { for(Gate* g : gates) { - if(flip_need_update[g->id] && (flip_weight[g->id] + FLIP_INC < FLIP_WEIGHT_MAX)) { - flip_weight[g->id] += FLIP_INC; - flip_total_weight += FLIP_INC; + if(g->stem && !g->stem_satisfied && (g->stem_weight + STEM_INC < STEM_WEIGHT_MAX)) { + g->stem_weight += STEM_INC; + stem_total_cost += STEM_INC; } - if(g->stem && !stem_satisfied[g->id] && (stem_weight[g->id] + STEM_INC < STEM_WEIGHT_MAX)) { - stem_weight[g->id] += STEM_INC; - stem_total_weight += STEM_INC; - - for(Gate* suc : g->suc_stems) { - if(stem_weight[suc->id] - STEM_INC > 1) { - stem_weight[suc->id] -= STEM_INC; - if(!stem_satisfied[suc->id]) { - stem_total_weight -= STEM_INC; - } - } - } + if(!g->fault_detected[0] && g->fault_weight[0] > 0 && (g->fault_weight[0] + FAULT_INC < FAULT_WEIGHT_MAX)) { + g->fault_weight[0] += FAULT_INC; + fault_propagate_score += FAULT_INC * (g->fault_propagate_length[0]); } - if(!g->sa[0] && fault_weight[g->id][0] > 0 && (fault_weight[g->id][0] + FAULT_INC < FAULT_WEIGHT_MAX)) { - fault_weight[g->id][0] += FAULT_INC; - fault_propagate_score += FAULT_INC * (g->fault_propagate_len[0]); - } - - if(!g->sa[1] && fault_weight[g->id][1] > 0 && (fault_weight[g->id][1] + FAULT_INC < FAULT_WEIGHT_MAX)) { - fault_weight[g->id][1] += FAULT_INC; - fault_propagate_score += FAULT_INC * (g->fault_propagate_len[1]); + if(!g->fault_detected[1] && g->fault_weight[1] > 0 && (g->fault_weight[1] + FAULT_INC < FAULT_WEIGHT_MAX)) { + g->fault_weight[1] += FAULT_INC; + fault_propagate_score += FAULT_INC * (g->fault_propagate_length[1]); } } } } +Gate* Circuit::ls_pick() { + Gate* stem = nullptr; + ll max_score = 0; + + std::vector stems_random; + std::vector candidates; -bool cmp(Gate* a, Gate *b) { - return a->id > b->id; + for(int i=0; iCC) { + stems_random.push_back(stems[i]); + } + } + + for(int i=0; i max_score) { + max_score = t_score; + stem = t_stem; + } + } + + return stem; } -void Circuit::ls_flip(Gate* stem) { - stem->value = !stem->value; - ls_block_recal(stem); +Gate* Circuit::ls_pick_falsified() { + std::vector candidates; + for(Gate *g : stems) { + if(g->stem_satisfied) continue; + + for(Gate* pre : g->pre_stems) + candidates.push_back(pre); + + for(Gate* suc : g->suc_stems) + candidates.push_back(suc); + + candidates.push_back(g); + } + + if(candidates.size() == 0) { + candidates.push_back(stems[rand()%stems.size()]); + } + + return candidates[rand()%candidates.size()]; } -void Circuit::ls_update(Gate* stem) { - ls_block_recal(stem); +void Circuit::ls_init_stems() { + stems.clear(); + + for(Gate* g : gates) { + if(g->pi || g->po) { + g->stem = true; + } + + if(!g->global_fault_detected[0] || !g->global_fault_detected[0]) { + g->stem = true; + } + + if(g->fan_outs.size() >= 2) { + g->stem = true; + } + + if(g->stem) { + stems.push_back(g); + } + } + + for(Gate *g : gates) { + if(g->pi) continue; + std::queue q; + std::unordered_map used; + q.push(g); + + while(!q.empty()) { + Gate* now = q.front(); + q.pop(); + for(Gate* in : now->fan_ins) { + if(in->stem) { + g->pre_stems.push_back(in); + } else if(!used[in]) { + used[in] = true; + q.push(in); + } + } + } + } + + for(Gate *g : gates) { + if(g->po) continue; + std::queue q; + std::unordered_map used; + q.push(g); + + while(!q.empty()) { + Gate* now = q.front(); + q.pop(); + for(Gate* out : now->fan_outs) { + if(out->stem) { + g->suc_stems.push_back(out); + } else if(!used[out]) { + used[out] = true; + q.push(out); + } + } + } + } } ll Circuit::ls_pick_score(Gate* stem) { - ll old_score = ls_score(); + ll old_score = ls_circuit_score(); ls_flip(stem); - ll new_score = ls_score(); - - ls_flip(stem); - - old_score = std::max(old_score, ls_score()); + ll new_score = ls_circuit_score(); return new_score - old_score; } -ll Circuit::ls_score() { - //ll score = - flip_total_weight - stem_total_weight + fault_total_weight + fault_propagate_tatal_len; - ll score = - flip_total_weight - stem_total_weight + fault_propagate_score; +ll Circuit::ls_circuit_score() { + ll score = - stem_total_cost + fault_propagate_score; return score; } -void Circuit::ls_init_weight(const std::unordered_set &faults) { +void Circuit::ls_init_weight() { for(Gate* s : stems) { - stem_weight[s->id] = 1; - stem_total_weight += stem_weight[s->id]; + s->stem_weight = 1; + stem_total_cost += s->stem_weight; } - for(Fault* f : faults) { - fault_weight[f->gate->id][f->type] = 1; - } - - int r = rand() % faults.size(); - auto it = faults.begin(); - std::advance(it, r); - - fault_weight[(*it)->gate->id][(*it)->type] = 1000000; - - for(Gate* s: stems) { - flip_weight[s->id] = 1; + for(Gate* g : gates) { + g->fault_weight[0] = !g->global_fault_detected[0]; + g->fault_weight[1] = !g->global_fault_detected[1]; } } -void Circuit::ls_init_circuit() { - - for(Gate* g : gates) { - g->sa[0] = 0; - g->sa[1] = 0; - } +void Circuit::ls_random_circuit() { + // init assignment for(Gate* s : stems) { s->value = rand() % 2; } - for(int i=stems.size()-1; i>=0; i--) { - ls_update(stems[i]); + // recal value by topo + for(Gate *g : gates) { + if(g->stem) { + g->stem_satisfied = (g->recal_value() == g->value); + if(g->stem_satisfied) { + stem_total_cost -= g->stem_weight; + stem_total_cnt++; + } + } else { + g->value = g->recal_value(); + } } - while(!flip_update_queue.empty()) { - Gate* g = flip_update_queue.back(); - flip_update_queue.pop_back(); - if(!flip_need_update[g->id]) continue; - flip_need_update[g->id] = false; - flip_total_weight -= flip_weight[g->id]; - flip_total_cnt -= 1; - ls_update(g); + // recal fault by rtopo + for(Gate* g : rtopo_gates) { + g->recal_fault(g->fault_detected); + if(g->fault_detected[0]) { + fault_total_weight += g->fault_weight[0]; + fault_total_cnt++; + } + if(g->fault_detected[1]) { + fault_total_weight += g->fault_weight[1]; + fault_total_cnt++; + } + + g->propagate = (g->fault_detected[0] || g->fault_detected[1]); + + g->recal_propagate_len(g->fault_propagate_length); + + fault_propagate_score += g->fault_weight[0] * g->fault_propagate_length[0]; + fault_propagate_score += g->fault_weight[1] * g->fault_propagate_length[1]; + } + + assert(is_valid_circuit()); } -void Circuit::ls_init_data_structs() { - const int MAX_LEN = gates.size() + 1; +void Circuit::ls_reset_data() { - if(flip_weight == nullptr) { - CC = new int[MAX_LEN]; - - flip_weight = new int[MAX_LEN]; - flip_need_update = new int[MAX_LEN]; - - stem_weight = new int[MAX_LEN]; - stem_satisfied = new int[MAX_LEN]; - - fault_weight = new int*[MAX_LEN]; - for(int i=0; ifault_propagate_len[0] = 0; - g->fault_propagate_len[1] = 0; + g->CC = 1; + g->stem = 0; + g->propagate = 0; + g->stem_weight = 0; + g->stem_satisfied = 0; + + g->fault_weight[0] = g->fault_weight[1] = 0; + g->fault_detected[0] = g->fault_detected[1] = 0; + + g->fault_propagate_length[0] = 0; + g->fault_propagate_length[1] = 0; } } -void Circuit::ls_block_recal(Gate* stem) { - if(flip_need_update[stem->id]) { - flip_need_update[stem->id] = false; - flip_total_weight -= flip_weight[stem->id]; - flip_total_cnt -= 1; +void Circuit::ls_flip(Gate* stem) { + + // update CC + stem->CC = 0; + for(Gate* pre : stem->pre_stems) { + pre->CC = 1; + } + for(Gate* suc : stem->suc_stems) { + suc->CC = 1; } - if(stem->cal_value() == stem->value && !stem_satisfied[stem->id]){ - stem_satisfied[stem->id] = true; - stem_total_weight -= stem_weight[stem->id]; + // update value + bool new_stem_satisfied = (stem->recal_value() == stem->value); + + if(new_stem_satisfied && !stem->stem_satisfied){ + stem->stem_satisfied = true; + stem_total_cost -= stem->stem_weight; stem_total_cnt += 1; - for(Gate* pre : stem->pre_stems) { - if(flip_need_update[pre->id]) continue; - - flip_need_update[pre->id] = true; - flip_update_queue.push_back(pre); - - flip_total_weight += flip_weight[pre->id]; - flip_total_cnt += 1; - } } - - if(stem->cal_value() != stem->value && stem_satisfied[stem->id]) { - stem_satisfied[stem->id] = false; - stem_total_weight += stem_weight[stem->id]; + + if(!new_stem_satisfied && stem->stem_satisfied){ + stem->stem_satisfied = false; + stem_total_cost += stem->stem_weight; stem_total_cnt -= 1; - for(Gate* pre : stem->pre_stems) { - if(flip_need_update[pre->id]) continue; - - flip_need_update[pre->id] = true; - flip_update_queue.push_back(pre); - - flip_total_weight += flip_weight[pre->id]; - flip_total_cnt += 1; - } } - if(stem->isPO) { - if(stem->sa[!stem->value] == false) { - fault_total_weight += fault_weight[stem->id][!stem->value]; + // update po fault + if(stem->po) { + stem->propagate = true; + if(!stem->fault_detected[!stem->value]) { + fault_total_weight += stem->fault_weight[!stem->value]; fault_total_cnt += 1; - stem->sa[!stem->value] = true; - - for(Gate* pre : stem->pre_stems) { - if(flip_need_update[pre->id]) continue; - - flip_need_update[pre->id] = true; - flip_update_queue.push_back(pre); - - flip_total_weight += flip_weight[pre->id]; - flip_total_cnt += 1; - } + stem->fault_detected[!stem->value] = true; } - if(stem->sa[stem->value] == true) { - fault_total_weight -= fault_weight[stem->id][stem->value]; + if(stem->fault_detected[stem->value]) { + fault_total_weight -= stem->fault_weight[stem->value]; fault_total_cnt -= 1; - stem->sa[stem->value] = false; - - for(Gate* pre : stem->pre_stems) { - if(flip_need_update[pre->id]) continue; - - flip_need_update[pre->id] = true; - flip_update_queue.push_back(pre); - - flip_total_weight += flip_weight[pre->id]; - flip_total_cnt += 1; - } + stem->fault_detected[stem->value] = false; } } - static std::queue q; - static std::unordered_map used; - assert(q.empty()); - used.clear(); + static std::queue q1; + static std::unordered_map used1; + static std::queue q2; + static std::unordered_map used2; + used1.clear(); + used2.clear(); - q.push(stem); + q1.push(stem); - while(!q.empty()) { - Gate* g = q.front(); - q.pop(); - used[g] = false; - for(Gate* out : g->outputs) { + while(!q1.empty()) { + Gate* g = q1.front(); + q1.pop(); + used1[g] = false; + + for(Gate* suc : g->suc_stems) { + if(!used2[suc]) { + used2[suc] = true; + q2.push(suc); + } + } + + for(Gate* out : g->fan_outs) { if(out->stem) { + Gate* stem = out; + bool new_stem_satisfied = (stem->recal_value() == stem->value); + if(new_stem_satisfied && !stem->stem_satisfied){ + stem->stem_satisfied = true; + stem_total_cost -= stem->stem_weight; + stem_total_cnt += 1; + } + + if(!new_stem_satisfied && stem->stem_satisfied){ + stem->stem_satisfied = false; + stem_total_cost += stem->stem_weight; + stem_total_cnt -= 1; + } continue; } - out->value = out->cal_value(); - if(!used[out]) { - used[out] = true; - q.push(out); + int new_value = out->recal_value(); + if(new_value == out->value) continue; + out->value = new_value; + if(!used1[out]) { + used1[out] = true; + q1.push(out); } } } - assert(q.empty()); - used.clear(); + while(!q2.empty()) { + Gate *g = q2.front(); + q2.pop(); - for(Gate* stem : stem->suc_stems) { - q.push(stem); + used2[g] = false; - int fpl0 = stem->cal_propagate_len(0); - int fpl1 = stem->cal_propagate_len(1); + for(Gate* in : g->fan_ins) { - if(fault_weight[stem->id][0]) { - fault_propagate_tatal_len += (fpl0 - stem->fault_propagate_len[0]); - } + bool update = false; - if(fault_weight[stem->id][1]) { - fault_propagate_tatal_len += (fpl1 - stem->fault_propagate_len[1]); - } + bool fd[2]; + in->recal_fault(fd); - fault_propagate_score += (fault_weight[stem->id][0] * (fpl0 - stem->fault_propagate_len[0])); - fault_propagate_score += (fault_weight[stem->id][1] * (fpl1 - stem->fault_propagate_len[1])); - - stem->fault_propagate_len[0] = fpl0; - stem->fault_propagate_len[1] = fpl1; - - if(stem->cal_value() == stem->value && !stem_satisfied[stem->id]){ - stem_satisfied[stem->id] = true; - stem_total_weight -= stem_weight[stem->id]; - stem_total_cnt += 1; - } - - if(stem->cal_value() != stem->value && stem_satisfied[stem->id]) { - stem_satisfied[stem->id] = false; - stem_total_weight += stem_weight[stem->id]; - stem_total_cnt -= 1; - } - } - - while(!q.empty()) { - Gate *g = q.front(); - q.pop(); - - used[g] = false; - - for(Gate* in : g->inputs) { - - bool old_sa[2]; - old_sa[0] = in->sa[0]; - old_sa[1] = in->sa[1]; - - in->sa[0] = in->cal_sa(0); - in->sa[1] = in->cal_sa(1); - - if(in->stem && !in->isPI && (in->sa[0] != old_sa[0] || in->sa[1] != old_sa[1])) { - for(Gate* pre : in->pre_stems) { - if(flip_need_update[pre->id]) continue; - - flip_need_update[pre->id] = true; - flip_update_queue.push_back(pre); - - flip_total_weight += flip_weight[pre->id]; - flip_total_cnt += 1; - } - } - - int fpl0 = in->cal_propagate_len(0); - int fpl1 = in->cal_propagate_len(1); - - // if(in->name == "422") { - // printf("%s changed: %d fpl0: %d fpl1: %d \n", in->name.c_str(), (in->fault_propagate_len[0] != fpl0 || in->fault_propagate_len[1] != fpl1), fpl0, fpl1); - // } - - if(in->stem && !in->isPI && (in->fault_propagate_len[0] != fpl0 || in->fault_propagate_len[1] != fpl1)) { - - for(Gate* pre : in->pre_stems) { - if(flip_need_update[pre->id]) continue; - - flip_need_update[pre->id] = true; - flip_update_queue.push_back(pre); - - flip_total_weight += flip_weight[pre->id]; - flip_total_cnt += 1; - } - } - - if(fault_weight[in->id][0]) { - fault_propagate_tatal_len += fpl0 - in->fault_propagate_len[0]; - } - - if(fault_weight[in->id][1]) { - fault_propagate_tatal_len += fpl1 - in->fault_propagate_len[1]; - } - - fault_propagate_score += fault_weight[in->id][0] * (fpl0 - in->fault_propagate_len[0]); - fault_propagate_score += fault_weight[in->id][1] * (fpl1 - in->fault_propagate_len[1]); - - in->fault_propagate_len[0] = fpl0; - in->fault_propagate_len[1] = fpl1; - - if(old_sa[0] != in->sa[0]) { - if(in->sa[0]) { - fault_total_weight += fault_weight[in->id][0]; + if(fd[0] != in->fault_detected[0]) { + update = true; + if(in->fault_detected[0]) { + fault_total_weight += in->fault_weight[0]; fault_total_cnt += 1; } else { - fault_total_weight -= fault_weight[in->id][0]; + fault_total_weight -= in->fault_weight[9]; fault_total_cnt -= 1; } + in->fault_detected[0] = fd[0]; } - if(old_sa[1] != in->sa[1]) { - if(in->sa[1]) { - fault_total_weight += fault_weight[in->id][1]; + if(fd[1] != in->fault_detected[1]) { + update = true; + if(in->fault_detected[1]) { + fault_total_weight += in->fault_weight[1]; fault_total_cnt += 1; } else { - fault_total_weight -= fault_weight[in->id][1]; + fault_total_weight -= in->fault_weight[1]; fault_total_cnt -= 1; } + in->fault_detected[1] = fd[1]; + } + + in->propagate = (in->fault_detected[0] || in->fault_detected[1]); + + int fpl[2]; + in->recal_propagate_len(fpl); + + if(fpl[0] != in->fault_propagate_length[0] || fpl[1] != in->fault_propagate_length[1]) { + update = true; + fault_propagate_score += in->fault_weight[0] * (fpl[0] - in->fault_propagate_length[0]); + fault_propagate_score += in->fault_weight[1] * (fpl[1] - in->fault_propagate_length[1]); + + in->fault_propagate_length[0] = fpl[0]; + in->fault_propagate_length[1] = fpl[1]; } - if(!in->stem && !used[in]) { - used[in] = true; - q.push(in); + if(!used2[in]) { + used2[in] = true; + q2.push(in); } } } diff --git a/main.cpp b/main.cpp index e842258..98258e3 100644 --- a/main.cpp +++ b/main.cpp @@ -17,9 +17,7 @@ int main(int args, char* argv[]) { printf("parsing file %s ...", argv[1]); circuit->parse_from_file(argv[1]); - circuit->init_stems(); circuit->init_topo_index(); - circuit->init_gate_level(); printf(" Done.\n"); printf("====== Circuit Statistics ====== \n"); @@ -27,31 +25,20 @@ int main(int args, char* argv[]) { printf("PO:\t%ld\n", circuit->POs.size()); printf("Gate:\t%ld\n", circuit->name2gate.size()); printf("Stem:\t%ld\n", circuit->stems.size()); - printf("Level:\t%d\n", circuit->MAX_GATE_LEVEL); printf("================================ \n"); - std::unordered_set faults; - - // init faults - for(auto g : circuit->gates) { - faults.insert(new Fault(g, Fault::SA0)); - faults.insert(new Fault(g, Fault::SA1)); - } + circuit->global_fault_undetected_count = circuit->gates.size() * 2; while(true) { - bool ls = circuit->local_search(faults); + bool ls = circuit->local_search(); bool is_valid = circuit->is_valid_circuit(); printf("checking valid circuit ..."); printf(" result: %d.\n", is_valid); if(!ls) break; if(!is_valid) break; - if(faults.size() == 0) break; - //circuit->print_gates(); - //break; + if(circuit->global_fault_undetected_count == 0) break; } - //printf("[final] flip: %d, stem: %d, fault:%d\n", circuit->flip_total_weight, circuit->stem_total_weight, circuit->fault_total_weight); - return 0; } \ No newline at end of file diff --git a/makefile b/makefile index ae4c441..149a295 100644 --- a/makefile +++ b/makefile @@ -7,7 +7,7 @@ #编译工具用g++,以同时支持C和C++程序,以及二者的混合编译 CC=g++ -CPPFLAGS=-O3 -std=c++17 -g +CPPFLAGS=-O0 -std=c++17 -g #使用$(winldcard *.c)来获取工作目录下的所有.c文件的列表 #sources:=main.cpp command.c diff --git a/option.h b/option.h new file mode 100644 index 0000000..2ac3ba9 --- /dev/null +++ b/option.h @@ -0,0 +1,12 @@ +#pragma once + +const double SP = 0.01; +const int MAX_STEPS = 10000; +const int SAMPLING_COUNT = 25; + +const int STEM_INC = 1; +const int STEM_WEIGHT_MAX = 1e9; + +const int FAULT_INC = 1; +const int FAULT_WEIGHT_MAX = 20; + diff --git a/parser.cpp b/parser.cpp index 438d432..8781a20 100644 --- a/parser.cpp +++ b/parser.cpp @@ -46,12 +46,6 @@ void Circuit::parse_from_file(const char *filename) { std::vector tokens; line2tokens(line, tokens); - // std::cout << line << std::endl; - // std::cout << "tokens: "; - // for(auto &token : tokens) { - // std::cout << "$" << token << "$ "; - // } - // std::cout << std::endl; // gate if(tokens.size() >= 6 && tokens[1] == "=" && tokens[3] == "(" && tokens.back() == ")") { @@ -73,10 +67,10 @@ void Circuit::parse_from_file(const char *filename) { Gate* gate = new Gate(); gate->name = tokens[0]; - gate->sa[0] = gate->sa[1] = false; + gate->fault_detected[0] = gate->fault_detected[1] = false; gate->stem = false; - gate->isPI = false; - gate->isPO = false; + gate->pi = false; + gate->po = false; for(auto &in : ins) { @@ -87,8 +81,8 @@ void Circuit::parse_from_file(const char *filename) { auto in_gate = name2gate[in]; - gate->inputs.push_back(in_gate); - in_gate->outputs.push_back(gate); + gate->fan_ins.push_back(in_gate); + in_gate->fan_outs.push_back(gate); } if(tokens[2] == "AND") { gate->type = Gate::AND; } @@ -113,10 +107,10 @@ void Circuit::parse_from_file(const char *filename) { Gate* gate = new Gate(); gate->name = tokens[2]; gate->type = Gate::INPUT; - gate->sa[0] = gate->sa[1] = false; + gate->fault_detected[0] = gate->fault_detected[1] = false; gate->stem = true; - gate->isPI = true; - gate->isPO = false; + gate->pi = true; + gate->po = false; name2gate.insert(std::make_pair(gate->name, gate)); gates.push_back(gate); @@ -141,7 +135,7 @@ void Circuit::parse_from_file(const char *filename) { } Gate* po = name2gate[po_name]; - po->isPO = true; + po->po = true; po->stem = true; POs.push_back(po); } diff --git a/simulator.cpp b/simulator.cpp deleted file mode 100644 index 41be410..0000000 --- a/simulator.cpp +++ /dev/null @@ -1,150 +0,0 @@ -#include "circuit.h" - -#include -#include - -int cal_value(Gate *g, int *value) { - int res; - - switch(g->type) { - case Gate::NOT: - res = !value[g->inputs[0]->id]; - break; - case Gate::BUF: - res = value[g->inputs[0]->id]; - break; - case Gate::AND: - res = value[g->inputs[0]->id]; - for(int i=1; iinputs.size(); i++) { - res &= value[g->inputs[i]->id]; - } - break; - case Gate::NAND: - res = value[g->inputs[0]->id]; - for(int i=1; iinputs.size(); i++) { - res &= value[g->inputs[i]->id]; - } - res = !res; - break; - case Gate::OR: - res = value[g->inputs[0]->id]; - for(int i=1; iinputs.size(); i++) { - res |= value[g->inputs[i]->id]; - } - break; - case Gate::NOR: - res = value[g->inputs[0]->id]; - for(int i=1; iinputs.size(); i++) { - res |= value[g->inputs[i]->id]; - } - res = !res; - break; - case Gate::XOR: - res = value[g->inputs[0]->id]; - for(int i=1; iinputs.size(); i++) { - res ^= value[g->inputs[i]->id]; - } - break; - case Gate::XNOR: - res = value[g->inputs[0]->id]; - for(int i=1; iinputs.size(); i++) { - res ^= value[g->inputs[i]->id]; - } - res = !res; - break; - case Gate::INPUT: - res = value[g->id]; - break; - default: - assert(false); - break; - } - return res; -} - -bool cal_sa(Gate* g, bool x, int** sa, int *value) { - if(g->isPO) { - if(x == 0) return value[g->id]; - else return !value[g->id]; - } - - bool sa0 = 0; - bool sa1 = 0; - - for(Gate* out : g->outputs) { - if(!sa[out->id][0] && !sa[out->id][1]) continue; - - if(cal_value(out, value) != value[out->id]) continue; - - value[g->id] = !value[g->id]; - bool detect = cal_value(out, value) != value[out->id]; - value[g->id] = !value[g->id]; - if(!detect) continue; - - sa0 |= value[g->id]; - sa1 |= !value[g->id]; - } - if(x == 0) return sa0; - else return sa1; -} - - -int** Circuit::simulate() { - - static bool init = false; - static int** sa = nullptr; - static int* value = nullptr; - - if(!init) { - const int MAXN = gates.size() + 1; - init = true; - sa = new int*[MAXN]; - for(int i=0; iid] = pi->value; - } - - for(Gate *g : gates) { - if(g->isPI) continue; - value[g->id] = cal_value(g, value); - } - - for(Gate *g : gates) { - assert(value[g->id] == cal_value(g, value)); - } - - std::queue q; - std::unordered_map topo; - - // init PO - for(Gate* po : POs) { - sa[po->id][!value[po->id]] = 1; - sa[po->id][value[po->id]] = 0; - q.push(po); - } - - while(!q.empty()) { - Gate* g = q.front(); - q.pop(); - for(Gate* in : g->inputs) { - if(++topo[in] == in->outputs.size()) { - sa[in->id][0] = cal_sa(in, 0, sa, value); - sa[in->id][1] = cal_sa(in, 1, sa, value); - q.push(in); - } - } - } - - for(Gate* g : gates) { - assert(sa[g->id][0] == cal_sa(g, 0, sa, value)); - assert(sa[g->id][1] == cal_sa(g, 1, sa, value)); - } - - return sa; -} \ No newline at end of file