完成 flip 的逻辑
This commit is contained in:
parent
67443cbde9
commit
87b8d2ab6c
133
circuit.cpp
133
circuit.cpp
@ -2,19 +2,42 @@
|
|||||||
|
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <unordered_set>
|
||||||
|
#include "assert.h"
|
||||||
|
|
||||||
void Circuit::init_stems() {
|
void Circuit::init_stems() {
|
||||||
for(auto& gate: gates) {
|
for(auto& gate: gates) {
|
||||||
if(gate->outputs.size() >= 2) {
|
if(gate->outputs.size() >= 2) {
|
||||||
|
gate->stem = true;
|
||||||
|
}
|
||||||
|
if(gate->stem) {
|
||||||
stems.push_back(gate);
|
stems.push_back(gate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(auto &gate : PIs) {
|
|
||||||
stems.push_back(gate);
|
for(Gate *g : gates) {
|
||||||
|
if(g->isPI) continue;
|
||||||
|
std::queue<Gate*> q;
|
||||||
|
std::unordered_map<Gate*, bool> used;
|
||||||
|
q.push(g);
|
||||||
|
|
||||||
|
while(!q.empty()) {
|
||||||
|
Gate* now = q.front();
|
||||||
|
q.pop();
|
||||||
|
for(Gate* in : now->inputs) {
|
||||||
|
if(in->stem) {
|
||||||
|
g->pre_stems.push_back(in);
|
||||||
|
} else if(!used[in]) {
|
||||||
|
used[in] = true;
|
||||||
|
q.push(in);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//printf("pre: %s %d\n", g->name.c_str(), g->pre_stems.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Circuit::init_topo_index() {
|
void Circuit::init_topo_index() {
|
||||||
int topo = 1;
|
int topo = 1;
|
||||||
std::queue<Gate*> q;
|
std::queue<Gate*> q;
|
||||||
@ -41,57 +64,61 @@ void Circuit::init_topo_index() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int Circuit::cal_gate_value(const Gate* &gate) {
|
void Circuit::print_gates() {
|
||||||
int res;
|
static const char* type2name[9] = {"AND", "NAND", "OR", "NOR", "XOR", "XNOR", "NOT", "BUF", "IN"};
|
||||||
|
for(Gate* gate : gates) {
|
||||||
switch(gate->type) {
|
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]);
|
||||||
case Gate::NOT:
|
for(Gate* in : gate->inputs) {
|
||||||
res = !gate->inputs[0]->value;
|
printf(" %s", in->name.c_str());
|
||||||
break;
|
}
|
||||||
case Gate::BUF:
|
printf("\n");
|
||||||
res = gate->inputs[0]->value;
|
|
||||||
break;
|
|
||||||
case Gate::AND:
|
|
||||||
res = gate->inputs[0]->value;
|
|
||||||
for(int i=1; i<gate->inputs.size(); i++) {
|
|
||||||
res &= gate->inputs[i]->value;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Gate::NAND:
|
|
||||||
res = gate->inputs[0]->value;
|
|
||||||
for(int i=1; i<gate->inputs.size(); i++) {
|
|
||||||
res &= gate->inputs[i]->value;
|
|
||||||
}
|
|
||||||
res = !res;
|
|
||||||
break;
|
|
||||||
case Gate::OR:
|
|
||||||
res = gate->inputs[0]->value;
|
|
||||||
for(int i=1; i<gate->inputs.size(); i++) {
|
|
||||||
res |= gate->inputs[i]->value;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Gate::NOR:
|
|
||||||
res = gate->inputs[0]->value;
|
|
||||||
for(int i=1; i<gate->inputs.size(); i++) {
|
|
||||||
res |= gate->inputs[i]->value;
|
|
||||||
}
|
|
||||||
res = !res;
|
|
||||||
break;
|
|
||||||
case Gate::XOR:
|
|
||||||
res = gate->inputs[0]->value;
|
|
||||||
for(int i=1; i<gate->inputs.size(); i++) {
|
|
||||||
res ^= gate->inputs[i]->value;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Gate::XNOR:
|
|
||||||
res = gate->inputs[0]->value;
|
|
||||||
for(int i=1; i<gate->inputs.size(); i++) {
|
|
||||||
res ^= gate->inputs[i]->value;
|
|
||||||
}
|
|
||||||
res = !res;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Circuit::is_valid_circuit() {
|
||||||
|
|
||||||
|
for(Gate* g : gates) {
|
||||||
|
|
||||||
|
// 检查门的赋值情况
|
||||||
|
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());
|
||||||
|
//return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
35
circuit.h
35
circuit.h
@ -3,22 +3,38 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
class Gate {
|
class Gate {
|
||||||
public:
|
public:
|
||||||
int topo;
|
int topo;
|
||||||
std::string name;
|
std::string name;
|
||||||
enum Type { AND, NAND, OR, NOR, XOR, XNOR, NOT, BUF, INPUT, OUTPUT } type;
|
enum Type { AND, NAND, OR, NOR, XOR, XNOR, NOT, BUF, INPUT } type;
|
||||||
int value;
|
int value;
|
||||||
|
bool sa[2];
|
||||||
|
bool stem;
|
||||||
|
bool isPI;
|
||||||
|
bool isPO;
|
||||||
|
|
||||||
|
std::unordered_map<Gate*, std::pair<int, int>> sa_by_out;
|
||||||
|
|
||||||
|
std::vector<Gate*> pre_stems;
|
||||||
|
|
||||||
|
std::vector<Gate*> block;
|
||||||
|
|
||||||
std::vector<Gate*> outputs;
|
std::vector<Gate*> outputs;
|
||||||
std::vector<Gate*> inputs;
|
std::vector<Gate*> inputs;
|
||||||
|
|
||||||
|
bool is_propagated();
|
||||||
|
int cal_value();
|
||||||
};
|
};
|
||||||
|
|
||||||
class Fault {
|
class Fault {
|
||||||
public:
|
public:
|
||||||
Gate* gate;
|
Gate* gate;
|
||||||
enum Type { SA0, SA1 } type;
|
enum Type { SA0, SA1 } type;
|
||||||
Fault(Gate* gate, Type type):gate(gate),type(type) {}
|
bool detected;
|
||||||
|
Fault(Gate* gate, Type type):gate(gate),type(type),detected(0) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class Circuit {
|
class Circuit {
|
||||||
@ -26,19 +42,28 @@ public:
|
|||||||
std::vector<Gate*> PIs;
|
std::vector<Gate*> PIs;
|
||||||
std::vector<Gate*> POs;
|
std::vector<Gate*> POs;
|
||||||
std::vector<Gate*> gates;
|
std::vector<Gate*> gates;
|
||||||
std::vector<Gate*> stems;// PI + stems
|
std::vector<Gate*> stems; // PI + stems
|
||||||
|
|
||||||
std::unordered_map<std::string, Gate*> name2gate;
|
std::unordered_map<std::string, Gate*> name2gate;
|
||||||
|
|
||||||
|
std::queue<Gate*> tmp;
|
||||||
|
std::unordered_map<Gate*, bool> tmp_used;
|
||||||
|
|
||||||
void parse_from_file(const char *filename);
|
void parse_from_file(const char *filename);
|
||||||
int cal_gate_value(const Gate* &gate);
|
void print_gates();
|
||||||
|
|
||||||
|
bool is_valid_circuit();
|
||||||
|
|
||||||
void init_topo_index();
|
void init_topo_index();
|
||||||
void init_stems();
|
void init_stems();
|
||||||
|
|
||||||
|
|
||||||
// local search
|
// local search
|
||||||
|
|
||||||
std::vector<int> local_search(const std::vector<Fault*> &faults);
|
std::vector<int> local_search(const std::vector<Fault*> &faults);
|
||||||
|
|
||||||
void ls_init_circuit();
|
void ls_init_circuit();
|
||||||
void ls_init_vector(std::vector<Gate*> *vec);
|
void ls_init_vector(std::vector<Gate*> *vec);
|
||||||
|
void ls_flip(Gate* stem);
|
||||||
|
|
||||||
};
|
};
|
13
crun
Executable file
13
crun
Executable file
@ -0,0 +1,13 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
clear
|
||||||
|
|
||||||
|
make -j 16
|
||||||
|
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "compile failed."
|
||||||
|
else
|
||||||
|
echo "========================"
|
||||||
|
time ./atpg $1
|
||||||
|
fi
|
||||||
|
|
63
gate.cpp
Normal file
63
gate.cpp
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#include "circuit.h"
|
||||||
|
|
||||||
|
#include "assert.h"
|
||||||
|
|
||||||
|
bool Gate::is_propagated() {
|
||||||
|
return sa[0] || sa[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
int Gate::cal_value() {
|
||||||
|
int res;
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
case NOT:
|
||||||
|
res = !inputs[0]->value;
|
||||||
|
break;
|
||||||
|
case BUF:
|
||||||
|
res = inputs[0]->value;
|
||||||
|
break;
|
||||||
|
case AND:
|
||||||
|
res = inputs[0]->value;
|
||||||
|
for(int i=1; i<inputs.size(); i++) {
|
||||||
|
res &= inputs[i]->value;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NAND:
|
||||||
|
res = inputs[0]->value;
|
||||||
|
for(int i=1; i<inputs.size(); i++) {
|
||||||
|
res &= inputs[i]->value;
|
||||||
|
}
|
||||||
|
res = !res;
|
||||||
|
break;
|
||||||
|
case OR:
|
||||||
|
res = inputs[0]->value;
|
||||||
|
for(int i=1; i<inputs.size(); i++) {
|
||||||
|
res |= inputs[i]->value;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NOR:
|
||||||
|
res = inputs[0]->value;
|
||||||
|
for(int i=1; i<inputs.size(); i++) {
|
||||||
|
res |= inputs[i]->value;
|
||||||
|
}
|
||||||
|
res = !res;
|
||||||
|
break;
|
||||||
|
case XOR:
|
||||||
|
res = inputs[0]->value;
|
||||||
|
for(int i=1; i<inputs.size(); i++) {
|
||||||
|
res ^= inputs[i]->value;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case XNOR:
|
||||||
|
res = inputs[0]->value;
|
||||||
|
for(int i=1; i<inputs.size(); i++) {
|
||||||
|
res ^= inputs[i]->value;
|
||||||
|
}
|
||||||
|
res = !res;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
130
ls.cpp
130
ls.cpp
@ -1,5 +1,10 @@
|
|||||||
#include "circuit.h"
|
#include "circuit.h"
|
||||||
|
|
||||||
|
#include <queue>
|
||||||
|
#include <unordered_set>
|
||||||
|
#include <algorithm>
|
||||||
|
#include "assert.h"
|
||||||
|
|
||||||
std::vector<int> Circuit::local_search(const std::vector<Fault*> &faults) {
|
std::vector<int> Circuit::local_search(const std::vector<Fault*> &faults) {
|
||||||
|
|
||||||
// local search vector
|
// local search vector
|
||||||
@ -7,11 +12,132 @@ std::vector<int> Circuit::local_search(const std::vector<Fault*> &faults) {
|
|||||||
|
|
||||||
printf("local search!\n");
|
printf("local search!\n");
|
||||||
|
|
||||||
|
//ls_flip(PIs[0]);
|
||||||
|
|
||||||
|
print_gates();
|
||||||
|
|
||||||
return std::vector<int>();
|
return std::vector<int>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool cmp(Gate* a, Gate *b) {
|
||||||
|
return a->topo > b->topo;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Circuit::ls_flip(Gate* stem) {
|
||||||
|
|
||||||
|
printf("flip: %s\n", stem->name.c_str());
|
||||||
|
|
||||||
|
//stem->value = !stem->value;
|
||||||
|
|
||||||
|
if(stem->isPO) {
|
||||||
|
stem->sa[!stem->value] = true;
|
||||||
|
stem->sa[stem->value] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::queue<Gate*> q;
|
||||||
|
std::unordered_map<Gate*, int> used;
|
||||||
|
std::vector<Gate*> suc_stems;
|
||||||
|
|
||||||
|
q.push(stem);
|
||||||
|
|
||||||
|
while(!q.empty()) {
|
||||||
|
Gate* g = q.front();
|
||||||
|
q.pop();
|
||||||
|
used[g] = false;
|
||||||
|
for(Gate* out : g->outputs) {
|
||||||
|
if(out->stem) {
|
||||||
|
suc_stems.push_back(out);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
out->value = out->cal_value();
|
||||||
|
if(!used[out]) {
|
||||||
|
used[out] = true;
|
||||||
|
q.push(out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(q.empty());
|
||||||
|
used.clear();
|
||||||
|
|
||||||
|
// update path info
|
||||||
|
std::vector<Gate*> update_list;
|
||||||
|
|
||||||
|
|
||||||
|
for(Gate* stem : suc_stems) {
|
||||||
|
q.push(stem);
|
||||||
|
//printf("suc: %s\n", stem->name.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
while(!q.empty()) {
|
||||||
|
Gate *g = q.front();
|
||||||
|
q.pop();
|
||||||
|
|
||||||
|
used[g] = false;
|
||||||
|
|
||||||
|
bool right_value = (g->cal_value() == g->value);
|
||||||
|
for(Gate* in : g->inputs) {
|
||||||
|
in->value = !in->value;
|
||||||
|
bool input_detected = (g->cal_value() != g->value);
|
||||||
|
in->value = !in->value;
|
||||||
|
|
||||||
|
bool sa0 = right_value && input_detected && g->sa[!g->value] && in->value;
|
||||||
|
bool sa1 = right_value && input_detected && g->sa[!g->value] && !in->value;
|
||||||
|
|
||||||
|
//printf("gate: %s -> %s rv: %d id: %d p:%d sa0: %d sa1: %d\n", in->name.c_str(), g->name.c_str(), right_value, input_detected, g->is_propagated(), sa0, sa1);
|
||||||
|
|
||||||
|
in->sa_by_out[g] = std::make_pair(sa0, sa1);
|
||||||
|
|
||||||
|
bool old_sa[2];
|
||||||
|
old_sa[0] = in->sa[0];
|
||||||
|
old_sa[1] = in->sa[1];
|
||||||
|
|
||||||
|
in->sa[0] = in->sa[1] = 0;
|
||||||
|
for(Gate* out : in->outputs) {
|
||||||
|
auto &p = in->sa_by_out[out];
|
||||||
|
//printf("%d %d\n", p.first, p.second);
|
||||||
|
in->sa[0] |= p.first;
|
||||||
|
in->sa[1] |= p.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(in->stem && (in->sa[0] != old_sa[0] || in->sa[0] != old_sa[0])) {
|
||||||
|
for(Gate* pre : in->pre_stems) {
|
||||||
|
if(!tmp_used[pre]) {
|
||||||
|
tmp_used[pre] = true;
|
||||||
|
tmp.push(pre);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//printf("gate: %s -> %s rv: %d id: %d p:%d sa0: %d sa1: %d\n", in->name.c_str(), g->name.c_str(), right_value, input_detected, g->is_propagated(), in->sa[0], in->sa[1]);
|
||||||
|
|
||||||
|
if(!in->stem && !used[in]) {
|
||||||
|
used[in] = true;
|
||||||
|
q.push(in);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Circuit::ls_init_circuit() {
|
void Circuit::ls_init_circuit() {
|
||||||
for(auto pi : PIs) {
|
// for(auto pi : PIs) {
|
||||||
pi->value = rand() % 2;
|
// pi->value = rand() % 2;
|
||||||
|
// }
|
||||||
|
|
||||||
|
for(Gate* s : stems) {
|
||||||
|
s->value = rand() % 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i=stems.size()-1; i>=0; i--) {
|
||||||
|
stems[i]->value = !stems[i]->value;
|
||||||
|
ls_flip(stems[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
while(!tmp.empty()) {
|
||||||
|
Gate* g = tmp.front();
|
||||||
|
tmp.pop();
|
||||||
|
tmp_used[g] = false;
|
||||||
|
ls_flip(g);
|
||||||
}
|
}
|
||||||
}
|
}
|
5
main.cpp
5
main.cpp
@ -38,5 +38,10 @@ int main(int args, char* argv[]) {
|
|||||||
|
|
||||||
auto pattern = circuit.local_search(faults);
|
auto pattern = circuit.local_search(faults);
|
||||||
|
|
||||||
|
printf("checking valid circuit ...");
|
||||||
|
printf(" result: %d.\n", circuit.is_valid_circuit());
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
40235
output.txt
Normal file
40235
output.txt
Normal file
File diff suppressed because it is too large
Load Diff
17
parser.cpp
17
parser.cpp
@ -73,6 +73,11 @@ void Circuit::parse_from_file(const char *filename) {
|
|||||||
|
|
||||||
Gate* gate = new Gate();
|
Gate* gate = new Gate();
|
||||||
gate->name = tokens[0];
|
gate->name = tokens[0];
|
||||||
|
gate->sa[0] = gate->sa[1] = false;
|
||||||
|
gate->stem = false;
|
||||||
|
gate->isPI = false;
|
||||||
|
gate->isPO = false;
|
||||||
|
|
||||||
|
|
||||||
for(auto &in : ins) {
|
for(auto &in : ins) {
|
||||||
if(!name2gate.count(in)) {
|
if(!name2gate.count(in)) {
|
||||||
@ -108,9 +113,13 @@ void Circuit::parse_from_file(const char *filename) {
|
|||||||
Gate* gate = new Gate();
|
Gate* gate = new Gate();
|
||||||
gate->name = tokens[2];
|
gate->name = tokens[2];
|
||||||
gate->type = Gate::INPUT;
|
gate->type = Gate::INPUT;
|
||||||
|
gate->sa[0] = gate->sa[1] = false;
|
||||||
|
gate->stem = true;
|
||||||
|
gate->isPI = true;
|
||||||
|
gate->isPO = false;
|
||||||
|
|
||||||
name2gate.insert(std::make_pair(gate->name, gate));
|
name2gate.insert(std::make_pair(gate->name, gate));
|
||||||
// gates.push_back(gate);
|
gates.push_back(gate);
|
||||||
PIs.push_back(gate);
|
PIs.push_back(gate);
|
||||||
}
|
}
|
||||||
// gate
|
// gate
|
||||||
@ -130,6 +139,10 @@ void Circuit::parse_from_file(const char *filename) {
|
|||||||
printf("Error while reading file: po %s is not a exist gate.\n", po_name.c_str());
|
printf("Error while reading file: po %s is not a exist gate.\n", po_name.c_str());
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
POs.push_back(name2gate[po_name]);
|
|
||||||
|
Gate* po = name2gate[po_name];
|
||||||
|
po->isPO = true;
|
||||||
|
po->stem = true;
|
||||||
|
POs.push_back(po);
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user