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