atpg-ls/src/lut.cpp

203 lines
5.7 KiB
C++
Raw Normal View History

2023-07-18 04:05:32 +00:00
#include <set>
2023-07-03 06:52:47 +00:00
#include "lut.h"
2023-07-18 04:05:32 +00:00
#include "paras.h"
2023-07-18 10:52:51 +00:00
void LUT::get_fault_info(Gate* gate, int *t_fd, int* t_fpl) {
}
2023-07-18 04:05:32 +00:00
void LUT::cal_fault_info(int *fd, int* fpl) {
fd[0] = fd[1] = fpl[0] = fpl[1] = 0;
if(isPO) {
fd[0] = value;
fd[1] = !value;
return;
}
for(int i=0; i<fanouts.size(); i++) {
LUT* out = fanouts[i];
if(!out->vsat) continue;
FaultInfo* info = nullptr;
int input = 0;
for(int j=0; j<out->fanins.size(); j++) {
if(out->fanins[j] == this) {
info = out->fault_table[j];
}
input |= (out->fanins[j]->value << j);
}
input <<= 1;
input |= out->value;
assert(info != nullptr);
int t_fd[2], t_fpl[2];
t_fd[0] = info[input].fd[0] && out->fd[!value];
t_fd[1] = info[input].fd[1] && out->fd[!value];
t_fpl[0] = info[input].fpl[0] + info[input].fd[0] * out->fpl[!value];
t_fpl[1] = info[input].fpl[1] + info[input].fd[1] * out->fpl[!value];
fd[0] = std::max(fd[0], t_fd[0]);
fd[1] = std::max(fd[1], t_fd[1]);
fpl[0] = std::max(fpl[0], t_fpl[0]);
fpl[1] = std::max(fpl[1], t_fpl[1]);
}
}
int LUT::cal_value() {
if(isPI) return value;
int input = 0;
for(int i=0; i<fanins.size(); i++) {
input |= (fanins[i]->value << i);
}
return value_table[input];
}
2023-07-31 05:55:25 +00:00
LUT::LUT(Gate *gate, LUTCircuit *circuit):gate(gate), value(gate->value), name(gate->name.c_str()) {
C = circuit;
2023-07-18 04:05:32 +00:00
isPI = gate->isPI;
isPO = gate->isPO;
inner_gates.push_back(gate);
std::set<Gate*> fanins;
for(Gate* g : gate->fanins) {
fanins.insert(g);
// printf("init fanins: %s\n", g->name.c_str());
}
while(true) {
std::vector<Gate*> candidates;
for(Gate* fanin : fanins) {
if(fanin->fanouts.size() >= 2) continue;
if(fanin->isPI) continue;
int add = 0;
for(Gate* in : fanin->fanins) {
if(fanins.count(in) == 0) {
add++;
}
}
if(fanins.size() - 1 + add <= OPT(lut)) {
candidates.push_back(fanin);
}
}
if(candidates.size() == 0) break;
Gate* random_gate = candidates[rand()%candidates.size()];
inner_gates.push_back(random_gate);
fanins.erase(random_gate);
for(Gate* in : random_gate->fanins) {
fanins.insert(in);
}
}
for(Gate* in : fanins) {
__gate_fanins.push_back(in);
}
}
void LUT::init_lookup_table() {
value_table = new int[1 << fanins.size()];
fault_table = new FaultInfo *[fanins.size() + inner_gates.size()];
for (int i = 0; i < (fanins.size() + inner_gates.size()); i++) {
fault_table[i] = new FaultInfo[1 << (fanins.size() + 1)];
}
std::unordered_map<Gate*, int> gate_to_index;
for(int i=0; i<fanins.size(); i++) {
gate_to_index[fanins[i]->gate] = i;
}
for(int i=0; i<inner_gates.size(); i++) {
gate_to_index[inner_gates[i]] = i + fanins.size();
}
for (int i = 0; i < (1 << fanins.size()); i++) {
for (int j = 0; j < fanins.size(); j++) {
fanins[j]->gate->value = (i >> j) & 1;
}
for (Gate *g : inner_gates) {
g->value = g->cal_value();
}
assert(inner_gates[inner_gates.size() - 1] == gate);
value_table[i] = gate->value;
gate->value = 0;
gate->fault_detected[0] = 0;
gate->fault_detected[1] = 1;
gate->fault_propagated_len[0] = 0;
gate->fault_propagated_len[1] = 0;
// continue;
std::queue<Gate *> q;
q.push(gate);
while (!q.empty()) {
Gate *g = q.front();
q.pop();
fault_table[gate_to_index[g]][(i<<1)|gate->value].fd[0] = g->fault_detected[0];
fault_table[gate_to_index[g]][(i<<1)|gate->value].fd[1] = g->fault_detected[1];
fault_table[gate_to_index[g]][(i<<1)|gate->value].fpl[0] = g->fault_propagated_len[0];
fault_table[gate_to_index[g]][(i<<1)|gate->value].fpl[1] = g->fault_propagated_len[1];
for (Gate *fanin : g->fanins) {
fanin->fault_detected[0] = fanin->cal_fault_detected(0);
fanin->fault_detected[1] = fanin->cal_fault_detected(1);
fanin->fault_propagated_len[0] = fanin->cal_propagate_len(0);
fanin->fault_propagated_len[1] = fanin->cal_propagate_len(1);
if(gate_to_index.count(fanin)) q.push(fanin);
}
}
gate->value = 1;
gate->fault_detected[0] = 1;
gate->fault_detected[1] = 0;
gate->fault_propagated_len[0] = 0;
gate->fault_propagated_len[1] = 0;
q.push(gate);
while (!q.empty()) {
Gate *g = q.front();
q.pop();
fault_table[gate_to_index[g]][(i<<1)|gate->value].fd[0] = g->fault_detected[0];
fault_table[gate_to_index[g]][(i<<1)|gate->value].fd[1] = g->fault_detected[1];
fault_table[gate_to_index[g]][(i<<1)|gate->value].fpl[0] = g->fault_propagated_len[0];
fault_table[gate_to_index[g]][(i<<1)|gate->value].fpl[1] = g->fault_propagated_len[1];
2023-07-03 06:52:47 +00:00
2023-07-18 04:05:32 +00:00
for (Gate *fanin : g->fanins) {
fanin->fault_detected[0] = fanin->cal_fault_detected(0);
fanin->fault_detected[1] = fanin->cal_fault_detected(1);
fanin->fault_propagated_len[0] = fanin->cal_propagate_len(0);
fanin->fault_propagated_len[1] = fanin->cal_propagate_len(1);
2023-07-03 06:52:47 +00:00
2023-07-18 04:05:32 +00:00
if(gate_to_index.count(fanin)) q.push(fanin);
}
}
}
}