#include "circuit.h" #include #include #include #include "assert.h" void Circuit::init_stems() { for(auto& gate: gates) { if(gate->outputs.size() >= 2) { gate->stem = true; } if(gate->stem) { stems.push_back(gate); } } for(Gate *g : gates) { if(g->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()); } } 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); } while(!q.empty()) { Gate* g = q.front(); q.pop(); for(Gate* out : g->outputs) { ins[out]--; if(ins[out] == 0) { out->id = topo++; q.push(out); } } } } void Circuit::print_gates() { static const char* type2name[9] = {"AND", "NAND", "OR", "NOR", "XOR", "XNOR", "NOT", "BUF", "IN"}; for(Gate* gate : gates) { printf("Gate: %3s (t:%4s v:%d pi:%d po:%d s:%d p:%d s0:%d s1:%d) Inputs:", gate->name.c_str(), type2name[gate->type], gate->value, gate->isPI, gate->isPO, gate->stem, gate->is_propagated(), gate->sa[0], gate->sa[1]); for(Gate* in : gate->inputs) { printf(" %s", in->name.c_str()); } printf("\n"); } } bool Circuit::is_valid_circuit() { ll flip_total_weight = 0; ll stem_total_weight = 0; ll fault_total_weight = 0; //printf("flip: %d, stem: %d, fault:%d\n", flip_total_weight, stem_total_weight, fault_total_weight); for(Gate* g : gates) { if(flip_need_update[g->id]) { flip_total_weight += flip_weight[g->id]; } if(g->stem) { stem_total_weight += (g->cal_value() == g->value); } if(g->sa[0]) { fault_total_weight += fault_weight[g->id][0]; } if(g->sa[1]) { fault_total_weight += fault_weight[g->id][1]; } // 检查门的赋值情况 if(!g->stem && g->cal_value() != g->value) { return false; } // 检查 PO 的传播设定是否正确 if(g->isPO) { if(g->sa[g->value] != 0 || g->sa[!g->value] == 0 ) return false; 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("---- %s \n", g->name.c_str()); exit(-1); } } 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 true; }