2023-02-12 16:22:32 +08:00
|
|
|
#include "circuit.h"
|
|
|
|
|
|
|
|
#include <queue>
|
|
|
|
#include <unordered_map>
|
2023-02-19 19:42:50 +08:00
|
|
|
#include <unordered_set>
|
|
|
|
#include "assert.h"
|
2023-02-16 18:51:31 +08:00
|
|
|
|
|
|
|
void Circuit::init_stems() {
|
|
|
|
for(auto& gate: gates) {
|
|
|
|
if(gate->outputs.size() >= 2) {
|
2023-02-19 19:42:50 +08:00
|
|
|
gate->stem = true;
|
|
|
|
}
|
|
|
|
if(gate->stem) {
|
2023-02-16 18:51:31 +08:00
|
|
|
stems.push_back(gate);
|
|
|
|
}
|
|
|
|
}
|
2023-02-19 19:42:50 +08:00
|
|
|
|
|
|
|
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());
|
2023-02-16 18:51:31 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-19 19:42:50 +08:00
|
|
|
|
2023-02-16 18:51:31 +08:00
|
|
|
void Circuit::init_topo_index() {
|
2023-02-12 16:22:32 +08:00
|
|
|
int topo = 1;
|
|
|
|
std::queue<Gate*> q;
|
|
|
|
|
|
|
|
std::unordered_map<Gate*, int> ins;
|
|
|
|
for(Gate* gate : gates) {
|
|
|
|
ins[gate] = gate->inputs.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
for(auto in : PIs) {
|
2023-02-20 13:08:25 +08:00
|
|
|
in->id = topo++;
|
2023-02-12 16:22:32 +08:00
|
|
|
q.push(in);
|
|
|
|
}
|
|
|
|
|
|
|
|
while(!q.empty()) {
|
|
|
|
Gate* g = q.front(); q.pop();
|
|
|
|
for(Gate* out : g->outputs) {
|
|
|
|
ins[out]--;
|
|
|
|
if(ins[out] == 0) {
|
2023-02-20 13:08:25 +08:00
|
|
|
out->id = topo++;
|
2023-02-12 16:22:32 +08:00
|
|
|
q.push(out);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-02-12 18:14:12 +08:00
|
|
|
}
|
|
|
|
|
2023-02-19 19:42:50 +08:00
|
|
|
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() {
|
|
|
|
|
|
|
|
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;
|
2023-02-12 18:14:12 +08:00
|
|
|
}
|
2023-02-19 19:42:50 +08:00
|
|
|
|
|
|
|
g->value = !g->value;
|
|
|
|
|
|
|
|
if(out->cal_value() != out->value) {
|
|
|
|
sa0 |= out->is_propagated() && !g->value;
|
|
|
|
sa1 |= out->is_propagated() && g->value;
|
2023-02-12 18:14:12 +08:00
|
|
|
}
|
2023-02-19 19:42:50 +08:00
|
|
|
|
|
|
|
g->value = !g->value;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(sa0 != g->sa[0] || sa1 != g->sa[1]) {
|
|
|
|
printf("---- %s \n", g->name.c_str());
|
2023-02-20 13:08:25 +08:00
|
|
|
exit(-1);
|
2023-02-19 19:42:50 +08:00
|
|
|
}
|
|
|
|
|
2023-02-12 18:14:12 +08:00
|
|
|
}
|
2023-02-19 19:42:50 +08:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|