atpg-ls/circuit.cpp

124 lines
3.0 KiB
C++
Raw Normal View History

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) {
in->topo = 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->topo = topo++;
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());
//return false;
}
2023-02-12 18:14:12 +08:00
}
2023-02-19 19:42:50 +08:00
return true;
2023-02-16 18:51:31 +08:00
2023-02-19 19:42:50 +08:00
}