mirror of https://github.com/YosysHQ/yosys.git
opt_reduce: Add $bmux and $demux optimization patterns.
This commit is contained in:
parent
772d137bfa
commit
07a657fb0c
|
@ -100,7 +100,7 @@ struct OptReduceWorker
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void opt_mux(RTLIL::Cell *cell)
|
void opt_pmux(RTLIL::Cell *cell)
|
||||||
{
|
{
|
||||||
RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A));
|
RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A));
|
||||||
RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID::B));
|
RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID::B));
|
||||||
|
@ -141,20 +141,20 @@ struct OptReduceWorker
|
||||||
handled_sig.insert(this_b);
|
handled_sig.insert(this_b);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new_sig_s.size() != sig_s.size()) {
|
if (new_sig_s.size() == 0)
|
||||||
|
{
|
||||||
|
module->connect(cell->getPort(ID::Y), cell->getPort(ID::A));
|
||||||
|
assign_map.add(cell->getPort(ID::Y), cell->getPort(ID::A));
|
||||||
|
module->remove(cell);
|
||||||
|
did_something = true;
|
||||||
|
total_count++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_sig_s.size() != sig_s.size() || (new_sig_s.size() == 1 && cell->type == ID($pmux))) {
|
||||||
log(" New ctrl vector for %s cell %s: %s\n", cell->type.c_str(), cell->name.c_str(), log_signal(new_sig_s));
|
log(" New ctrl vector for %s cell %s: %s\n", cell->type.c_str(), cell->name.c_str(), log_signal(new_sig_s));
|
||||||
did_something = true;
|
did_something = true;
|
||||||
total_count++;
|
total_count++;
|
||||||
}
|
|
||||||
|
|
||||||
if (new_sig_s.size() == 0)
|
|
||||||
{
|
|
||||||
module->connect(RTLIL::SigSig(cell->getPort(ID::Y), cell->getPort(ID::A)));
|
|
||||||
assign_map.add(cell->getPort(ID::Y), cell->getPort(ID::A));
|
|
||||||
module->remove(cell);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cell->setPort(ID::B, new_sig_b);
|
cell->setPort(ID::B, new_sig_b);
|
||||||
cell->setPort(ID::S, new_sig_s);
|
cell->setPort(ID::S, new_sig_s);
|
||||||
if (new_sig_s.size() > 1) {
|
if (new_sig_s.size() > 1) {
|
||||||
|
@ -166,81 +166,347 @@ struct OptReduceWorker
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void opt_mux_bits(RTLIL::Cell *cell)
|
void opt_bmux(RTLIL::Cell *cell)
|
||||||
{
|
{
|
||||||
std::vector<RTLIL::SigBit> sig_a = assign_map(cell->getPort(ID::A)).to_sigbit_vector();
|
RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A));
|
||||||
std::vector<RTLIL::SigBit> sig_b = assign_map(cell->getPort(ID::B)).to_sigbit_vector();
|
RTLIL::SigSpec sig_s = assign_map(cell->getPort(ID::S));
|
||||||
std::vector<RTLIL::SigBit> sig_y = assign_map(cell->getPort(ID::Y)).to_sigbit_vector();
|
int width = cell->getParam(ID::WIDTH).as_int();
|
||||||
|
|
||||||
|
RTLIL::SigSpec new_sig_a, new_sig_s;
|
||||||
|
dict<RTLIL::SigBit, int> handled_bits;
|
||||||
|
|
||||||
|
// 0 and up: index of new_sig_s bit
|
||||||
|
// -1: const 0
|
||||||
|
// -2: const 1
|
||||||
|
std::vector<int> swizzle;
|
||||||
|
|
||||||
|
for (int i = 0; i < sig_s.size(); i++)
|
||||||
|
{
|
||||||
|
SigBit bit = sig_s[i];
|
||||||
|
if (bit == State::S0) {
|
||||||
|
swizzle.push_back(-1);
|
||||||
|
} else if (bit == State::S1) {
|
||||||
|
swizzle.push_back(-2);
|
||||||
|
} else {
|
||||||
|
auto it = handled_bits.find(bit);
|
||||||
|
if (it == handled_bits.end()) {
|
||||||
|
int new_idx = GetSize(new_sig_s);
|
||||||
|
new_sig_s.append(bit);
|
||||||
|
handled_bits[bit] = new_idx;
|
||||||
|
swizzle.push_back(new_idx);
|
||||||
|
} else {
|
||||||
|
swizzle.push_back(it->second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < (1 << GetSize(new_sig_s)); i++) {
|
||||||
|
int idx = 0;
|
||||||
|
for (int j = 0; j < GetSize(sig_s); j++) {
|
||||||
|
if (swizzle[j] == -1) {
|
||||||
|
// const 0.
|
||||||
|
} else if (swizzle[j] == -2) {
|
||||||
|
// const 1.
|
||||||
|
idx |= 1 << j;
|
||||||
|
} else {
|
||||||
|
if (i & 1 << swizzle[j])
|
||||||
|
idx |= 1 << j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
new_sig_a.append(sig_a.extract(idx * width, width));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_sig_s.size() == 0)
|
||||||
|
{
|
||||||
|
module->connect(cell->getPort(ID::Y), new_sig_a);
|
||||||
|
assign_map.add(cell->getPort(ID::Y), new_sig_a);
|
||||||
|
module->remove(cell);
|
||||||
|
did_something = true;
|
||||||
|
total_count++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_sig_s.size() == 1)
|
||||||
|
{
|
||||||
|
cell->type = ID($mux);
|
||||||
|
cell->setPort(ID::A, new_sig_a.extract(0, width));
|
||||||
|
cell->setPort(ID::B, new_sig_a.extract(width, width));
|
||||||
|
cell->setPort(ID::S, new_sig_s);
|
||||||
|
cell->parameters.erase(ID::S_WIDTH);
|
||||||
|
did_something = true;
|
||||||
|
total_count++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_sig_s.size() != sig_s.size()) {
|
||||||
|
log(" New ctrl vector for %s cell %s: %s\n", cell->type.c_str(), cell->name.c_str(), log_signal(new_sig_s));
|
||||||
|
did_something = true;
|
||||||
|
total_count++;
|
||||||
|
cell->setPort(ID::A, new_sig_a);
|
||||||
|
cell->setPort(ID::S, new_sig_s);
|
||||||
|
cell->parameters[ID::S_WIDTH] = RTLIL::Const(new_sig_s.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void opt_demux(RTLIL::Cell *cell)
|
||||||
|
{
|
||||||
|
RTLIL::SigSpec sig_y = assign_map(cell->getPort(ID::Y));
|
||||||
|
RTLIL::SigSpec sig_s = assign_map(cell->getPort(ID::S));
|
||||||
|
int width = cell->getParam(ID::WIDTH).as_int();
|
||||||
|
|
||||||
|
RTLIL::SigSpec new_sig_y, new_sig_s;
|
||||||
|
dict<RTLIL::SigBit, int> handled_bits;
|
||||||
|
|
||||||
|
// 0 and up: index of new_sig_s bit
|
||||||
|
// -1: const 0
|
||||||
|
// -2: const 1
|
||||||
|
std::vector<int> swizzle;
|
||||||
|
|
||||||
|
for (int i = 0; i < sig_s.size(); i++)
|
||||||
|
{
|
||||||
|
SigBit bit = sig_s[i];
|
||||||
|
if (bit == State::S0) {
|
||||||
|
swizzle.push_back(-1);
|
||||||
|
} else if (bit == State::S1) {
|
||||||
|
swizzle.push_back(-2);
|
||||||
|
} else {
|
||||||
|
auto it = handled_bits.find(bit);
|
||||||
|
if (it == handled_bits.end()) {
|
||||||
|
int new_idx = GetSize(new_sig_s);
|
||||||
|
new_sig_s.append(bit);
|
||||||
|
handled_bits[bit] = new_idx;
|
||||||
|
swizzle.push_back(new_idx);
|
||||||
|
} else {
|
||||||
|
swizzle.push_back(it->second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pool<int> nonzero_idx;
|
||||||
|
|
||||||
|
for (int i = 0; i < (1 << GetSize(new_sig_s)); i++) {
|
||||||
|
int idx = 0;
|
||||||
|
for (int j = 0; j < GetSize(sig_s); j++) {
|
||||||
|
if (swizzle[j] == -1) {
|
||||||
|
// const 0.
|
||||||
|
} else if (swizzle[j] == -2) {
|
||||||
|
// const 1.
|
||||||
|
idx |= 1 << j;
|
||||||
|
} else {
|
||||||
|
if (i & 1 << swizzle[j])
|
||||||
|
idx |= 1 << j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log_assert(!nonzero_idx.count(idx));
|
||||||
|
nonzero_idx.insert(idx);
|
||||||
|
new_sig_y.append(sig_y.extract(idx * width, width));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_sig_s.size() == sig_s.size() && sig_s.size() > 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
log(" New ctrl vector for %s cell %s: %s\n", cell->type.c_str(), cell->name.c_str(), log_signal(new_sig_s));
|
||||||
|
did_something = true;
|
||||||
|
total_count++;
|
||||||
|
|
||||||
|
for (int i = 0; i < (1 << GetSize(sig_s)); i++) {
|
||||||
|
if (!nonzero_idx.count(i)) {
|
||||||
|
SigSpec slice = sig_y.extract(i * width, width);
|
||||||
|
module->connect(slice, Const(State::S0, width));
|
||||||
|
assign_map.add(slice, Const(State::S0, width));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_sig_s.size() == 0)
|
||||||
|
{
|
||||||
|
module->connect(new_sig_y, cell->getPort(ID::A));
|
||||||
|
assign_map.add(new_sig_y, cell->getPort(ID::A));
|
||||||
|
module->remove(cell);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cell->setPort(ID::S, new_sig_s);
|
||||||
|
cell->setPort(ID::Y, new_sig_y);
|
||||||
|
cell->parameters[ID::S_WIDTH] = RTLIL::Const(new_sig_s.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool opt_mux_bits(RTLIL::Cell *cell)
|
||||||
|
{
|
||||||
|
SigSpec sig_a = assign_map(cell->getPort(ID::A));
|
||||||
|
SigSpec sig_b;
|
||||||
|
SigSpec sig_y = assign_map(cell->getPort(ID::Y));
|
||||||
|
int width = GetSize(sig_y);
|
||||||
|
|
||||||
|
if (cell->type != ID($bmux))
|
||||||
|
sig_b = assign_map(cell->getPort(ID::B));
|
||||||
|
|
||||||
std::vector<RTLIL::SigBit> new_sig_y;
|
|
||||||
RTLIL::SigSig old_sig_conn;
|
RTLIL::SigSig old_sig_conn;
|
||||||
|
|
||||||
std::vector<std::vector<RTLIL::SigBit>> consolidated_in_tuples;
|
dict<SigSpec, SigBit> consolidated_in_tuples;
|
||||||
std::map<std::vector<RTLIL::SigBit>, RTLIL::SigBit> consolidated_in_tuples_map;
|
std::vector<int> swizzle;
|
||||||
|
|
||||||
for (int i = 0; i < int(sig_y.size()); i++)
|
for (int i = 0; i < width; i++)
|
||||||
{
|
{
|
||||||
std::vector<RTLIL::SigBit> in_tuple;
|
SigSpec in_tuple;
|
||||||
bool all_tuple_bits_same = true;
|
bool all_tuple_bits_same = true;
|
||||||
|
|
||||||
in_tuple.push_back(sig_a.at(i));
|
in_tuple.append(sig_a[i]);
|
||||||
for (int j = i; j < int(sig_b.size()); j += int(sig_a.size())) {
|
for (int j = i; j < GetSize(sig_a); j += width) {
|
||||||
if (sig_b.at(j) != sig_a.at(i))
|
in_tuple.append(sig_a[j]);
|
||||||
|
if (sig_a[j] != in_tuple[0])
|
||||||
|
all_tuple_bits_same = false;
|
||||||
|
}
|
||||||
|
for (int j = i; j < GetSize(sig_b); j += width) {
|
||||||
|
in_tuple.append(sig_b[j]);
|
||||||
|
if (sig_b[j] != in_tuple[0])
|
||||||
all_tuple_bits_same = false;
|
all_tuple_bits_same = false;
|
||||||
in_tuple.push_back(sig_b.at(j));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (all_tuple_bits_same)
|
if (all_tuple_bits_same)
|
||||||
{
|
{
|
||||||
old_sig_conn.first.append(sig_y.at(i));
|
old_sig_conn.first.append(sig_y[i]);
|
||||||
old_sig_conn.second.append(sig_a.at(i));
|
old_sig_conn.second.append(sig_a[i]);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
else if (consolidated_in_tuples_map.count(in_tuple))
|
|
||||||
|
auto it = consolidated_in_tuples.find(in_tuple);
|
||||||
|
if (it == consolidated_in_tuples.end())
|
||||||
{
|
{
|
||||||
old_sig_conn.first.append(sig_y.at(i));
|
consolidated_in_tuples[in_tuple] = sig_y[i];
|
||||||
old_sig_conn.second.append(consolidated_in_tuples_map.at(in_tuple));
|
swizzle.push_back(i);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
consolidated_in_tuples_map[in_tuple] = sig_y.at(i);
|
old_sig_conn.first.append(sig_y[i]);
|
||||||
consolidated_in_tuples.push_back(in_tuple);
|
old_sig_conn.second.append(it->second);
|
||||||
new_sig_y.push_back(sig_y.at(i));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new_sig_y.size() != sig_y.size())
|
if (GetSize(swizzle) != width)
|
||||||
{
|
{
|
||||||
log(" Consolidated identical input bits for %s cell %s:\n", cell->type.c_str(), cell->name.c_str());
|
log(" Consolidated identical input bits for %s cell %s:\n", cell->type.c_str(), cell->name.c_str());
|
||||||
log(" Old ports: A=%s, B=%s, Y=%s\n", log_signal(cell->getPort(ID::A)),
|
if (cell->type != ID($bmux)) {
|
||||||
log_signal(cell->getPort(ID::B)), log_signal(cell->getPort(ID::Y)));
|
log(" Old ports: A=%s, B=%s, Y=%s\n", log_signal(cell->getPort(ID::A)),
|
||||||
|
log_signal(cell->getPort(ID::B)), log_signal(cell->getPort(ID::Y)));
|
||||||
cell->setPort(ID::A, RTLIL::SigSpec());
|
} else {
|
||||||
for (auto &in_tuple : consolidated_in_tuples) {
|
log(" Old ports: A=%s, Y=%s\n", log_signal(cell->getPort(ID::A)),
|
||||||
RTLIL::SigSpec new_a = cell->getPort(ID::A);
|
log_signal(cell->getPort(ID::Y)));
|
||||||
new_a.append(in_tuple.at(0));
|
|
||||||
cell->setPort(ID::A, new_a);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cell->setPort(ID::B, RTLIL::SigSpec());
|
if (swizzle.empty()) {
|
||||||
for (int i = 1; i <= cell->getPort(ID::S).size(); i++)
|
module->remove(cell);
|
||||||
for (auto &in_tuple : consolidated_in_tuples) {
|
} else {
|
||||||
RTLIL::SigSpec new_b = cell->getPort(ID::B);
|
SigSpec new_sig_a;
|
||||||
new_b.append(in_tuple.at(i));
|
for (int i = 0; i < GetSize(sig_a); i += width)
|
||||||
cell->setPort(ID::B, new_b);
|
for (int j: swizzle)
|
||||||
|
new_sig_a.append(sig_a[i+j]);
|
||||||
|
cell->setPort(ID::A, new_sig_a);
|
||||||
|
|
||||||
|
if (cell->type != ID($bmux)) {
|
||||||
|
SigSpec new_sig_b;
|
||||||
|
for (int i = 0; i < GetSize(sig_b); i += width)
|
||||||
|
for (int j: swizzle)
|
||||||
|
new_sig_b.append(sig_b[i+j]);
|
||||||
|
cell->setPort(ID::B, new_sig_b);
|
||||||
}
|
}
|
||||||
|
|
||||||
cell->parameters[ID::WIDTH] = RTLIL::Const(new_sig_y.size());
|
SigSpec new_sig_y;
|
||||||
cell->setPort(ID::Y, new_sig_y);
|
for (int j: swizzle)
|
||||||
|
new_sig_y.append(sig_y[j]);
|
||||||
|
cell->setPort(ID::Y, new_sig_y);
|
||||||
|
|
||||||
|
cell->parameters[ID::WIDTH] = RTLIL::Const(GetSize(swizzle));
|
||||||
|
|
||||||
|
if (cell->type != ID($bmux)) {
|
||||||
|
log(" New ports: A=%s, B=%s, Y=%s\n", log_signal(cell->getPort(ID::A)),
|
||||||
|
log_signal(cell->getPort(ID::B)), log_signal(cell->getPort(ID::Y)));
|
||||||
|
} else {
|
||||||
|
log(" New ports: A=%s, Y=%s\n", log_signal(cell->getPort(ID::A)),
|
||||||
|
log_signal(cell->getPort(ID::Y)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
log(" New ports: A=%s, B=%s, Y=%s\n", log_signal(cell->getPort(ID::A)),
|
|
||||||
log_signal(cell->getPort(ID::B)), log_signal(cell->getPort(ID::Y)));
|
|
||||||
log(" New connections: %s = %s\n", log_signal(old_sig_conn.first), log_signal(old_sig_conn.second));
|
log(" New connections: %s = %s\n", log_signal(old_sig_conn.first), log_signal(old_sig_conn.second));
|
||||||
|
|
||||||
module->connect(old_sig_conn);
|
module->connect(old_sig_conn);
|
||||||
|
|
||||||
did_something = true;
|
did_something = true;
|
||||||
total_count++;
|
total_count++;
|
||||||
}
|
}
|
||||||
|
return swizzle.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool opt_demux_bits(RTLIL::Cell *cell) {
|
||||||
|
SigSpec sig_a = assign_map(cell->getPort(ID::A));
|
||||||
|
SigSpec sig_y = assign_map(cell->getPort(ID::Y));
|
||||||
|
int width = GetSize(sig_a);
|
||||||
|
|
||||||
|
RTLIL::SigSig old_sig_conn;
|
||||||
|
|
||||||
|
dict<SigBit, int> handled_bits;
|
||||||
|
std::vector<int> swizzle;
|
||||||
|
|
||||||
|
for (int i = 0; i < width; i++)
|
||||||
|
{
|
||||||
|
if (sig_a[i] == State::S0)
|
||||||
|
{
|
||||||
|
for (int j = i; j < GetSize(sig_y); j += width)
|
||||||
|
{
|
||||||
|
old_sig_conn.first.append(sig_y[j]);
|
||||||
|
old_sig_conn.second.append(State::S0);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto it = handled_bits.find(sig_a[i]);
|
||||||
|
if (it == handled_bits.end())
|
||||||
|
{
|
||||||
|
handled_bits[sig_a[i]] = i;
|
||||||
|
swizzle.push_back(i);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int j = 0; j < GetSize(sig_y); j += width)
|
||||||
|
{
|
||||||
|
old_sig_conn.first.append(sig_y[i+j]);
|
||||||
|
old_sig_conn.second.append(sig_y[it->second+j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetSize(swizzle) != width)
|
||||||
|
{
|
||||||
|
log(" Consolidated identical input bits for %s cell %s:\n", cell->type.c_str(), cell->name.c_str());
|
||||||
|
log(" Old ports: A=%s, Y=%s\n", log_signal(cell->getPort(ID::A)),
|
||||||
|
log_signal(cell->getPort(ID::Y)));
|
||||||
|
|
||||||
|
if (swizzle.empty()) {
|
||||||
|
module->remove(cell);
|
||||||
|
} else {
|
||||||
|
SigSpec new_sig_a;
|
||||||
|
for (int j: swizzle)
|
||||||
|
new_sig_a.append(sig_a[j]);
|
||||||
|
cell->setPort(ID::A, new_sig_a);
|
||||||
|
|
||||||
|
SigSpec new_sig_y;
|
||||||
|
for (int i = 0; i < GetSize(sig_y); i += width)
|
||||||
|
for (int j: swizzle)
|
||||||
|
new_sig_y.append(sig_y[i+j]);
|
||||||
|
cell->setPort(ID::Y, new_sig_y);
|
||||||
|
|
||||||
|
cell->parameters[ID::WIDTH] = RTLIL::Const(GetSize(swizzle));
|
||||||
|
|
||||||
|
log(" New ports: A=%s, Y=%s\n", log_signal(cell->getPort(ID::A)),
|
||||||
|
log_signal(cell->getPort(ID::Y)));
|
||||||
|
}
|
||||||
|
|
||||||
|
log(" New connections: %s = %s\n", log_signal(old_sig_conn.first), log_signal(old_sig_conn.second));
|
||||||
|
module->connect(old_sig_conn);
|
||||||
|
|
||||||
|
did_something = true;
|
||||||
|
total_count++;
|
||||||
|
}
|
||||||
|
return swizzle.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
OptReduceWorker(RTLIL::Design *design, RTLIL::Module *module, bool do_fine) :
|
OptReduceWorker(RTLIL::Design *design, RTLIL::Module *module, bool do_fine) :
|
||||||
|
@ -309,20 +575,31 @@ struct OptReduceWorker
|
||||||
|
|
||||||
// merge identical inputs on $mux and $pmux cells
|
// merge identical inputs on $mux and $pmux cells
|
||||||
|
|
||||||
std::vector<RTLIL::Cell*> cells;
|
for (auto cell : module->selected_cells())
|
||||||
|
|
||||||
for (auto &it : module->cells_)
|
|
||||||
if ((it.second->type == ID($mux) || it.second->type == ID($pmux)) && design->selected(module, it.second))
|
|
||||||
cells.push_back(it.second);
|
|
||||||
|
|
||||||
for (auto cell : cells)
|
|
||||||
{
|
{
|
||||||
|
if (!cell->type.in(ID($mux), ID($pmux), ID($bmux), ID($demux)))
|
||||||
|
continue;
|
||||||
|
|
||||||
// this optimization is to aggressive for most coarse-grain applications.
|
// this optimization is to aggressive for most coarse-grain applications.
|
||||||
// but we always want it for multiplexers driving write enable ports.
|
// but we always want it for multiplexers driving write enable ports.
|
||||||
if (do_fine || mem_wren_sigs.check_any(assign_map(cell->getPort(ID::Y))))
|
if (do_fine || mem_wren_sigs.check_any(assign_map(cell->getPort(ID::Y)))) {
|
||||||
opt_mux_bits(cell);
|
if (cell->type == ID($demux)) {
|
||||||
|
if (opt_demux_bits(cell))
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
if (opt_mux_bits(cell))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
opt_mux(cell);
|
if (cell->type.in(ID($mux), ID($pmux)))
|
||||||
|
opt_pmux(cell);
|
||||||
|
|
||||||
|
if (cell->type == ID($bmux))
|
||||||
|
opt_bmux(cell);
|
||||||
|
|
||||||
|
if (cell->type == ID($demux))
|
||||||
|
opt_demux(cell);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,117 @@
|
||||||
|
read_ilang << EOT
|
||||||
|
|
||||||
|
module \top
|
||||||
|
wire width 12 input 0 \A
|
||||||
|
wire width 2 input 1 \S
|
||||||
|
wire width 6 output 2 \Y
|
||||||
|
|
||||||
|
cell $bmux $0
|
||||||
|
parameter \WIDTH 6
|
||||||
|
parameter \S_WIDTH 2
|
||||||
|
connect \A { \A [11:10] \A [3:2] \A [10:9] \A [7] \A [7] \A [8] \A [2] \A [7:6] \A [5] \A [5] \A [3:2] \A [5:4] \A [1] \A [1] \A [3:0] }
|
||||||
|
connect \S \S
|
||||||
|
connect \Y \Y
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
EOT
|
||||||
|
|
||||||
|
equiv_opt -assert opt_reduce -fine
|
||||||
|
opt_reduce -fine
|
||||||
|
select -assert-count 1 t:$bmux r:WIDTH=4 %i
|
||||||
|
|
||||||
|
design -reset
|
||||||
|
|
||||||
|
read_ilang << EOT
|
||||||
|
|
||||||
|
module \top
|
||||||
|
wire width 6 input 0 \A
|
||||||
|
wire width 2 input 1 \S
|
||||||
|
wire width 6 output 2 \Y
|
||||||
|
|
||||||
|
cell $bmux $0
|
||||||
|
parameter \WIDTH 6
|
||||||
|
parameter \S_WIDTH 2
|
||||||
|
connect \A { \A [5:0] \A [5:0] \A [5:0] \A [5:0] }
|
||||||
|
connect \S \S
|
||||||
|
connect \Y \Y
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
EOT
|
||||||
|
|
||||||
|
equiv_opt -assert opt_reduce -fine
|
||||||
|
opt_reduce -fine
|
||||||
|
select -assert-count 0 t:$bmux
|
||||||
|
|
||||||
|
design -reset
|
||||||
|
|
||||||
|
read_ilang << EOT
|
||||||
|
|
||||||
|
module \top
|
||||||
|
wire width 160 input 0 \A
|
||||||
|
wire width 2 input 1 \S
|
||||||
|
wire width 5 output 2 \Y
|
||||||
|
|
||||||
|
cell $bmux $0
|
||||||
|
parameter \WIDTH 5
|
||||||
|
parameter \S_WIDTH 5
|
||||||
|
connect \A \A
|
||||||
|
connect \S { \S [1] 1'1 \S [0] \S [1] 1'0 }
|
||||||
|
connect \Y \Y
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
EOT
|
||||||
|
|
||||||
|
equiv_opt -assert opt_reduce -fine
|
||||||
|
opt_reduce -fine
|
||||||
|
select -assert-count 1 t:$bmux r:S_WIDTH=2 %i
|
||||||
|
|
||||||
|
design -reset
|
||||||
|
|
||||||
|
read_ilang << EOT
|
||||||
|
|
||||||
|
module \top
|
||||||
|
wire width 10 input 0 \A
|
||||||
|
wire input 1 \S
|
||||||
|
wire width 5 output 2 \Y
|
||||||
|
|
||||||
|
cell $bmux $0
|
||||||
|
parameter \WIDTH 5
|
||||||
|
parameter \S_WIDTH 1
|
||||||
|
connect \A \A
|
||||||
|
connect \S \S
|
||||||
|
connect \Y \Y
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
EOT
|
||||||
|
|
||||||
|
equiv_opt -assert opt_reduce -fine
|
||||||
|
opt_reduce -fine
|
||||||
|
select -assert-count 0 t:$bmux
|
||||||
|
select -assert-count 1 t:$mux
|
||||||
|
|
||||||
|
design -reset
|
||||||
|
|
||||||
|
read_ilang << EOT
|
||||||
|
|
||||||
|
module \top
|
||||||
|
wire width 5 input 0 \A
|
||||||
|
wire width 5 output 1 \Y
|
||||||
|
|
||||||
|
cell $bmux $0
|
||||||
|
parameter \WIDTH 5
|
||||||
|
parameter \S_WIDTH 0
|
||||||
|
connect \A \A
|
||||||
|
connect \S { }
|
||||||
|
connect \Y \Y
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
EOT
|
||||||
|
|
||||||
|
equiv_opt -assert opt_reduce -fine
|
||||||
|
opt_reduce -fine
|
||||||
|
select -assert-count 0 t:$bmux
|
|
@ -0,0 +1,91 @@
|
||||||
|
read_ilang << EOT
|
||||||
|
|
||||||
|
module \top
|
||||||
|
wire width 4 input 0 \A
|
||||||
|
wire width 2 input 1 \S
|
||||||
|
wire width 24 output 2 \Y
|
||||||
|
|
||||||
|
cell $demux $0
|
||||||
|
parameter \WIDTH 6
|
||||||
|
parameter \S_WIDTH 2
|
||||||
|
connect \A { \A [3] \A [1] 1'0 \A [2:0] }
|
||||||
|
connect \S \S
|
||||||
|
connect \Y \Y
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
EOT
|
||||||
|
|
||||||
|
equiv_opt -assert opt_reduce -fine
|
||||||
|
opt_reduce -fine
|
||||||
|
select -assert-count 1 t:$demux r:WIDTH=4 %i
|
||||||
|
|
||||||
|
design -reset
|
||||||
|
|
||||||
|
read_ilang << EOT
|
||||||
|
|
||||||
|
module \top
|
||||||
|
wire width 2 input 1 \S
|
||||||
|
wire width 24 output 2 \Y
|
||||||
|
|
||||||
|
cell $demux $0
|
||||||
|
parameter \WIDTH 6
|
||||||
|
parameter \S_WIDTH 2
|
||||||
|
connect \A 6'000000
|
||||||
|
connect \S \S
|
||||||
|
connect \Y \Y
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
EOT
|
||||||
|
|
||||||
|
equiv_opt -assert opt_reduce -fine
|
||||||
|
opt_reduce -fine
|
||||||
|
select -assert-count 0 t:$demux
|
||||||
|
|
||||||
|
design -reset
|
||||||
|
|
||||||
|
read_ilang << EOT
|
||||||
|
|
||||||
|
module \top
|
||||||
|
wire width 5 input 0 \A
|
||||||
|
wire width 2 input 1 \S
|
||||||
|
wire width 160 output 2 \Y
|
||||||
|
|
||||||
|
cell $demux $0
|
||||||
|
parameter \WIDTH 5
|
||||||
|
parameter \S_WIDTH 5
|
||||||
|
connect \A \A
|
||||||
|
connect \S { \S [0] \S [1] 1'1 \S [0] 1'0 }
|
||||||
|
connect \Y \Y
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
EOT
|
||||||
|
|
||||||
|
equiv_opt -assert opt_reduce -fine
|
||||||
|
opt_reduce -fine
|
||||||
|
select -assert-count 1 t:$demux r:S_WIDTH=2 %i
|
||||||
|
|
||||||
|
design -reset
|
||||||
|
|
||||||
|
read_ilang << EOT
|
||||||
|
|
||||||
|
module \top
|
||||||
|
wire width 5 input 0 \A
|
||||||
|
wire width 20 output 2 \Y
|
||||||
|
|
||||||
|
cell $demux $0
|
||||||
|
parameter \WIDTH 5
|
||||||
|
parameter \S_WIDTH 2
|
||||||
|
connect \A \A
|
||||||
|
connect \S { 2'10 }
|
||||||
|
connect \Y \Y
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
EOT
|
||||||
|
|
||||||
|
equiv_opt -assert opt_reduce -fine
|
||||||
|
opt_reduce -fine
|
||||||
|
select -assert-count 0 t:$demux
|
Loading…
Reference in New Issue