Merge pull request #1972 from YosysHQ/eddie/bug1970

abc9_ops: -prep_lut to be more robust
This commit is contained in:
Eddie Hung 2020-04-20 11:39:13 -07:00 committed by GitHub
commit c506da3819
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 52 additions and 16 deletions

View File

@ -467,7 +467,12 @@ void prep_lut(RTLIL::Design *design, int maxlut)
{
TimingInfo timing;
std::vector<std::tuple<int, IdString, int, std::vector<int>>> table;
struct t_lut {
IdString name;
int area;
std::vector<int> delays;
};
std::map<int,t_lut> table;
for (auto module : design->modules()) {
auto it = module->attributes.find(ID::abc9_lut);
if (it == module->attributes.end())
@ -476,40 +481,52 @@ void prep_lut(RTLIL::Design *design, int maxlut)
auto &t = timing.setup_module(module);
TimingInfo::NameBit o;
std::vector<int> specify;
std::vector<int> delays;
for (const auto &i : t.comb) {
auto &d = i.first.second;
if (o == TimingInfo::NameBit())
o = d;
else if (o != d)
log_error("(* abc9_lut *) module '%s' with has more than one output.\n", log_id(module));
specify.push_back(i.second);
log_error("Module '%s' with (* abc9_lut *) has more than one output.\n", log_id(module));
delays.push_back(i.second);
}
if (maxlut && GetSize(specify) > maxlut)
if (GetSize(delays) == 0)
log_error("Module '%s' with (* abc9_lut *) has no specify entries.\n", log_id(module));
if (maxlut && GetSize(delays) > maxlut)
continue;
// ABC requires non-decreasing LUT input delays
std::sort(specify.begin(), specify.end());
table.emplace_back(GetSize(specify), module->name, it->second.as_int(), std::move(specify));
std::sort(delays.begin(), delays.end());
int K = GetSize(delays);
auto entry = t_lut{module->name, it->second.as_int(), std::move(delays)};
auto r = table.emplace(K, entry);
if (!r.second) {
if (r.first->second.area != entry.area)
log_error("Modules '%s' and '%s' have conflicting (* abc9_lut *) values.\n", log_id(module), log_id(r.first->second.name));
if (r.first->second.delays != entry.delays)
log_error("Modules '%s' and '%s' have conflicting specify entries.\n", log_id(module), log_id(r.first->second.name));
}
}
// ABC requires ascending size
std::sort(table.begin(), table.end());
if (table.empty())
log_error("Design does not contain any modules with (* abc9_lut *).\n");
std::stringstream ss;
const auto &first = table.front();
const auto &front = *table.begin();
// If the first entry does not start from a 1-input LUT,
// (as ABC requires) crop the first entry to do so
for (int i = 1; i < std::get<0>(first); i++) {
for (int i = 1; i < front.first; i++) {
ss << "# $__ABC9_LUT" << i << std::endl;
ss << i << " " << std::get<2>(first);
ss << i << " " << front.second.area;
for (int j = 0; j < i; j++)
ss << " " << std::get<3>(first)[j];
ss << " " << front.second.delays[j];
ss << std::endl;
}
for (const auto &i : table) {
ss << "# " << log_id(std::get<1>(i)) << std::endl;
ss << std::get<0>(i) << " " << std::get<2>(i);
for (const auto &j : std::get<3>(i))
ss << "# " << log_id(i.second.name) << std::endl;
ss << i.first << " " << i.second.area;
for (const auto &j : i.second.delays)
ss << " " << j;
ss << std::endl;
}

View File

@ -53,3 +53,22 @@ assign q = w;
endmodule
EOT
abc9 -lut 4 -dff
design -reset
read_verilog -icells -specify <<EOT
(* abc9_lut=1, blackbox *)
module LUT2(input [1:0] i, output o);
parameter [3:0] mask = 0;
assign o = i[0] ? (i[1] ? mask[3] : mask[2])
: (i[1] ? mask[1] : mask[0]);
specify
(i *> o) = 1;
endspecify
endmodule
module top(input [1:0] i, output o);
LUT2 #(.mask(4'b0)) lut (.i(i), .o(o));
endmodule
EOT
abc9