完成 flip 的逻辑

This commit is contained in:
YuhangQ 2023-02-19 19:42:50 +08:00
parent 67443cbde9
commit 87b8d2ab6c
9 changed files with 40569 additions and 62 deletions

BIN
atpg

Binary file not shown.

View File

@ -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;
}

View File

@ -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
View 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
View 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
View File

@ -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);
}
}

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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);
}
}