完成 flip 的逻辑
This commit is contained in:
parent
67443cbde9
commit
87b8d2ab6c
133
circuit.cpp
133
circuit.cpp
@ -2,19 +2,42 @@
|
||||
|
||||
#include <queue>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <unordered_set>
|
||||
#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(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() {
|
||||
int topo = 1;
|
||||
std::queue<Gate*> q;
|
||||
@ -41,57 +64,61 @@ void Circuit::init_topo_index() {
|
||||
}
|
||||
}
|
||||
|
||||
int Circuit::cal_gate_value(const Gate* &gate) {
|
||||
int res;
|
||||
|
||||
switch(gate->type) {
|
||||
case Gate::NOT:
|
||||
res = !gate->inputs[0]->value;
|
||||
break;
|
||||
case Gate::BUF:
|
||||
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;
|
||||
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");
|
||||
}
|
||||
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 <vector>
|
||||
#include <unordered_map>
|
||||
#include <queue>
|
||||
|
||||
class Gate {
|
||||
public:
|
||||
int topo;
|
||||
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;
|
||||
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*> inputs;
|
||||
|
||||
bool is_propagated();
|
||||
int cal_value();
|
||||
};
|
||||
|
||||
class Fault {
|
||||
public:
|
||||
Gate* gate;
|
||||
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 {
|
||||
@ -26,19 +42,28 @@ public:
|
||||
std::vector<Gate*> PIs;
|
||||
std::vector<Gate*> POs;
|
||||
std::vector<Gate*> gates;
|
||||
std::vector<Gate*> stems;// PI + stems
|
||||
std::vector<Gate*> stems; // PI + stems
|
||||
|
||||
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);
|
||||
int cal_gate_value(const Gate* &gate);
|
||||
void print_gates();
|
||||
|
||||
bool is_valid_circuit();
|
||||
|
||||
void init_topo_index();
|
||||
void init_stems();
|
||||
|
||||
|
||||
// local search
|
||||
|
||||
std::vector<int> local_search(const std::vector<Fault*> &faults);
|
||||
|
||||
void ls_init_circuit();
|
||||
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 <queue>
|
||||
#include <unordered_set>
|
||||
#include <algorithm>
|
||||
#include "assert.h"
|
||||
|
||||
std::vector<int> Circuit::local_search(const std::vector<Fault*> &faults) {
|
||||
|
||||
// local search vector
|
||||
@ -7,11 +12,132 @@ std::vector<int> Circuit::local_search(const std::vector<Fault*> &faults) {
|
||||
|
||||
printf("local search!\n");
|
||||
|
||||
//ls_flip(PIs[0]);
|
||||
|
||||
print_gates();
|
||||
|
||||
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() {
|
||||
for(auto pi : PIs) {
|
||||
pi->value = rand() % 2;
|
||||
// for(auto pi : PIs) {
|
||||
// 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);
|
||||
|
||||
printf("checking valid circuit ...");
|
||||
printf(" result: %d.\n", circuit.is_valid_circuit());
|
||||
|
||||
|
||||
|
||||
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->name = tokens[0];
|
||||
gate->sa[0] = gate->sa[1] = false;
|
||||
gate->stem = false;
|
||||
gate->isPI = false;
|
||||
gate->isPO = false;
|
||||
|
||||
|
||||
for(auto &in : ins) {
|
||||
if(!name2gate.count(in)) {
|
||||
@ -108,9 +113,13 @@ 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->stem = true;
|
||||
gate->isPI = true;
|
||||
gate->isPO = false;
|
||||
|
||||
name2gate.insert(std::make_pair(gate->name, gate));
|
||||
// gates.push_back(gate);
|
||||
gates.push_back(gate);
|
||||
PIs.push_back(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());
|
||||
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