atpg-ls/src/lut.cpp

206 lines
5.6 KiB
C++

#include <set>
#include "lut.h"
#include "paras.h"
using namespace atpg_ls;
void LUT::flip_value() {
value ^= 1;
for(auto&[out, id] : fanouts_with_id) {
out->input_var ^= (1 << id);
}
}
void LUT::cal_fault_info(int *fd, int* fpl) {
fd[0] = fd[1] = fpl[0] = fpl[1] = 0;
if(isPO) {
fd[!value] = 1;
fd[value] = 0;
return;
}
for(auto&[out, id] : fanouts_with_id) {
if(!out->vsat) continue;
FaultInfo &info = out->fault_table[id][out->input_var << 1 | out->value];
int t_fd[2], t_fpl[2];
t_fd[0] = info.fd[0] && out->fd[!out->value];
t_fd[1] = info.fd[1] && out->fd[!out->value];
t_fpl[0] = info.fpl[0] + info.fd[0] * out->fpl[!out->value];
t_fpl[1] = info.fpl[1] + info.fd[1] * out->fpl[!out->value];
fd[0] |= t_fd[0];
fd[1] |= t_fd[1];
fpl[0] = std::max(fpl[0], t_fpl[0]);
fpl[1] = std::max(fpl[1], t_fpl[1]);
}
// std::vector<Gate*> reigon;
// std::priority_queue<std::pair<Gate*, int>, std::vector<std::pair<Gate*, int>>,
// std::function<bool(const std::pair<Gate*, int>&, const std::pair<Gate*, int>&)>> pq([](const std::pair<Gate*, int>& p1, const std::pair<Gate*, int>& p2) {
// return p1.first->id < p2.first->id;
// });
// for(Gate* out : gate->fanouts) {
// if(!out->vsat) continue;
// pq.push(std::make_pair(out, 0));
// }
// pq.push(std::make_pair(gate, 0));
// while(!q.empty()) {
// auto [now, level] = q.front(); q.pop();
// for(Gate* out : now->fanouts) {
// if(!out->is_detected(now)) continue;
// if(level + 1 < OPT(lut)) {
// q.push(std::make_pair(out, level + 1));
// }
// }
// }
}
int LUT::cal_value() {
if(isPI) return value;
return value_table[input_var];
}
LUT::LUT(Gate *gate, LUTCircuit *circuit):gate(gate), value(gate->value), name(gate->name.c_str()) {
C = circuit;
isPI = gate->isPI;
isPO = gate->isPO;
inner_gates.push_back(gate);
std::set<Gate*> fanins;
for(Gate* g : gate->fanins) {
fanins.insert(g);
}
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> gate2index;
for(int i=0; i<fanins.size(); i++) {
gate2index[fanins[i]->gate] = i;
}
for(int i=0; i<inner_gates.size(); i++) {
gate2index[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;
for(gate->value=0; gate->value<=1; gate->value++) {
for(auto&[g, index] : gate2index) {
g->fault_detected[0] = g->fault_detected[1] = 0;
g->fault_propagated_len[0] = g->fault_propagated_len[1] = 0;
}
gate->fault_detected[!gate->value] = 1;
gate->fault_detected[gate->value] = 0;
gate->fault_propagated_len[0] = 0;
gate->fault_propagated_len[1] = 0;
std::queue<Gate*> q;
q.push(gate);
while(!q.empty()) {
Gate *now = q.front(); q.pop();
FaultInfo *info = &fault_table[gate2index[now]][(i<<1)|gate->value];
info->fd[0] = now->fault_detected[0];
info->fd[1] = now->fault_detected[1];
info->fpl[0] = now->fault_propagated_len[0];
info->fpl[1] = now->fault_propagated_len[1];
info->value = now->value;
// if(now->name == "new_n22_") {
// printf("Gate: %s value: %d inputs: [ ", now->name.c_str(), now->value);
// for(Gate *in : now->fanins) {
// printf("%s ", in->name.c_str());
// }
// printf("]\n");
// }
for(Gate *in : now->fanins) {
if(gate2index.count(in) == 0) continue;
if(now->is_detected(in)) {
in->fault_detected[!in->value] = std::max(in->fault_detected[!in->value], now->fault_detected[!now->value]);
in->fault_propagated_len[!in->value] = std::max(in->fault_propagated_len[!in->value], now->fault_propagated_len[!now->value] + 1);
}
q.push(in);
}
}
}
}
}