mirror of https://github.com/YosysHQ/yosys.git
Merge pull request #768 from whitequark/opt_lut_elim
opt_lut: eliminate LUTs evaluating to constants or inputs
This commit is contained in:
commit
4b9f619349
|
@ -187,6 +187,87 @@ struct OptLutWorker
|
||||||
}
|
}
|
||||||
show_stats_by_arity();
|
show_stats_by_arity();
|
||||||
|
|
||||||
|
log("\n");
|
||||||
|
log("Eliminating LUTs.\n");
|
||||||
|
for (auto lut : luts)
|
||||||
|
{
|
||||||
|
SigSpec lut_input = sigmap(lut->getPort("\\A"));
|
||||||
|
pool<int> &lut_dlogic_inputs = luts_dlogic_inputs[lut];
|
||||||
|
|
||||||
|
vector<SigBit> lut_inputs;
|
||||||
|
for (auto &bit : lut_input)
|
||||||
|
{
|
||||||
|
if (bit.wire)
|
||||||
|
lut_inputs.push_back(sigmap(bit));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool const0_match = true;
|
||||||
|
bool const1_match = true;
|
||||||
|
vector<bool> input_matches;
|
||||||
|
for (size_t i = 0; i < lut_inputs.size(); i++)
|
||||||
|
input_matches.push_back(true);
|
||||||
|
|
||||||
|
for (int eval = 0; eval < 1 << lut_inputs.size(); eval++)
|
||||||
|
{
|
||||||
|
dict<SigBit, bool> eval_inputs;
|
||||||
|
for (size_t i = 0; i < lut_inputs.size(); i++)
|
||||||
|
eval_inputs[lut_inputs[i]] = (eval >> i) & 1;
|
||||||
|
bool value = evaluate_lut(lut, eval_inputs);
|
||||||
|
if (value != 0)
|
||||||
|
const0_match = false;
|
||||||
|
if (value != 1)
|
||||||
|
const1_match = false;
|
||||||
|
for (size_t i = 0; i < lut_inputs.size(); i++)
|
||||||
|
{
|
||||||
|
if (value != eval_inputs[lut_inputs[i]])
|
||||||
|
input_matches[i] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int input_match = -1;
|
||||||
|
for (size_t i = 0; i < lut_inputs.size(); i++)
|
||||||
|
if (input_matches[i])
|
||||||
|
input_match = i;
|
||||||
|
|
||||||
|
if (const0_match || const1_match || input_match != -1)
|
||||||
|
{
|
||||||
|
log("Found redundant cell %s.%s.\n", log_id(module), log_id(lut));
|
||||||
|
|
||||||
|
SigBit value;
|
||||||
|
if (const0_match)
|
||||||
|
{
|
||||||
|
log(" Cell evaluates constant 0.\n");
|
||||||
|
value = State::S0;
|
||||||
|
}
|
||||||
|
if (const1_match)
|
||||||
|
{
|
||||||
|
log(" Cell evaluates constant 1.\n");
|
||||||
|
value = State::S1;
|
||||||
|
}
|
||||||
|
if (input_match != -1) {
|
||||||
|
log(" Cell evaluates signal %s.\n", log_signal(lut_inputs[input_match]));
|
||||||
|
value = lut_inputs[input_match];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lut_dlogic_inputs.size())
|
||||||
|
{
|
||||||
|
log(" Not eliminating cell (connected to dedicated logic).\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SigSpec lut_output = lut->getPort("\\Y");
|
||||||
|
module->connect(lut_output, value);
|
||||||
|
|
||||||
|
module->remove(lut);
|
||||||
|
luts.erase(lut);
|
||||||
|
luts_arity.erase(lut);
|
||||||
|
luts_dlogics.erase(lut);
|
||||||
|
luts_dlogic_inputs.erase(lut);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
show_stats_by_arity();
|
||||||
|
|
||||||
log("\n");
|
log("\n");
|
||||||
log("Combining LUTs.\n");
|
log("Combining LUTs.\n");
|
||||||
pool<RTLIL::Cell*> worklist = luts;
|
pool<RTLIL::Cell*> worklist = luts;
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
module \test
|
||||||
|
wire input 1 \i
|
||||||
|
|
||||||
|
wire output 2 \o1
|
||||||
|
cell $lut $1
|
||||||
|
parameter \LUT 16'0110100110010110
|
||||||
|
parameter \WIDTH 4
|
||||||
|
connect \A { \i 3'000 }
|
||||||
|
connect \Y \o1
|
||||||
|
end
|
||||||
|
|
||||||
|
wire output 2 \o2
|
||||||
|
cell $lut $2
|
||||||
|
parameter \LUT 16'0110100010010110
|
||||||
|
parameter \WIDTH 4
|
||||||
|
connect \A { \i 3'000 }
|
||||||
|
connect \Y \o2
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,3 @@
|
||||||
|
read_ilang opt_lut_elim.il
|
||||||
|
opt_lut
|
||||||
|
select -assert-count 0 t:$lut
|
|
@ -1,2 +1,3 @@
|
||||||
read_ilang opt_lut_port.il
|
read_ilang opt_lut_port.il
|
||||||
|
opt_lut
|
||||||
select -assert-count 2 t:$lut
|
select -assert-count 2 t:$lut
|
||||||
|
|
Loading…
Reference in New Issue