489 if (wr_ports.size() <= 1)
497 std::set<int> considered_ports;
498 std::set<int> considered_port_pairs;
500 for (
int i = 0; i < int(wr_ports.size()); i++) {
501 std::vector<RTLIL::SigBit> bits =
modwalker.
sigmap(wr_ports[i]->getPort(
"\\EN"));
502 for (
auto bit : bits)
504 goto port_is_always_active;
506 considered_ports.insert(i);
507 port_is_always_active:;
510 log(
"Consolidating write ports of memory %s.%s using sat-based resource sharing:\n",
log_id(
module),
log_id(memid));
512 bool cache_clk_enable =
false;
513 bool cache_clk_polarity =
false;
516 for (
int i = 0; i < int(wr_ports.size()); i++)
520 if (cell->
parameters.at(
"\\CLK_ENABLE").as_bool() != cache_clk_enable ||
521 (cache_clk_enable && (
sigmap(cell->
getPort(
"\\CLK")) != cache_clk ||
522 cell->
parameters.at(
"\\CLK_POLARITY").as_bool() != cache_clk_polarity)))
524 cache_clk_enable = cell->
parameters.at(
"\\CLK_ENABLE").as_bool();
525 cache_clk_polarity = cell->
parameters.at(
"\\CLK_POLARITY").as_bool();
528 else if (i > 0 && considered_ports.count(i-1) && considered_ports.count(i))
529 considered_port_pairs.insert(i);
531 if (cache_clk_enable)
532 log(
" Port %d (%s) on %s %s: %s\n", i,
log_id(cell),
533 cache_clk_polarity ?
"posedge" :
"negedge",
log_signal(cache_clk),
534 considered_ports.count(i) ?
"considered" :
"not considered");
536 log(
" Port %d (%s) unclocked: %s\n", i,
log_id(cell),
537 considered_ports.count(i) ?
"considered" :
"not considered");
540 if (considered_port_pairs.size() < 1) {
541 log(
" No two subsequent ports in same clock domain considered -> nothing to consolidate.\n");
547 std::set<RTLIL::Cell*> sat_cells;
548 std::set<RTLIL::SigBit> bits_queue;
549 std::map<int, int> port_to_sat_variable;
551 for (
int i = 0; i < int(wr_ports.size()); i++)
552 if (considered_port_pairs.count(i) || considered_port_pairs.count(i+1))
555 port_to_sat_variable[i] = ez.expression(ez.OpOr, satgen.importSigSpec(sig));
557 std::vector<RTLIL::SigBit> bits = sig;
558 bits_queue.insert(bits.begin(), bits.end());
561 while (!bits_queue.empty())
563 std::set<ModWalker::PortBit> portbits;
567 for (
auto &pbit : portbits)
570 bits_queue.insert(cell_inputs.begin(), cell_inputs.end());
571 sat_cells.insert(pbit.cell);
575 log(
" Common input cone for all EN signals: %d cells.\n",
int(sat_cells.size()));
577 for (
auto cell : sat_cells)
578 satgen.importCell(cell);
580 log(
" Size of unconstrained SAT problem: %d variables, %d clauses\n", ez.numCnfVariables(), ez.numCnfClauses());
584 for (
int i = 0; i < int(wr_ports.size()); i++)
586 if (!considered_port_pairs.count(i))
589 if (ez.solve(port_to_sat_variable.at(i-1), port_to_sat_variable.at(i))) {
590 log(
" According to SAT solver sharing of port %d with port %d is not possible.\n", i-1, i);
594 log(
" Merging port %d into port %d.\n", i-1, i);
595 port_to_sat_variable.at(i) = ez.OR(port_to_sat_variable.at(i-1), port_to_sat_variable.at(i));
599 std::vector<RTLIL::SigBit> last_en =
modwalker.
sigmap(wr_ports[i-1]->getPort(
"\\EN"));
603 std::vector<RTLIL::SigBit> this_en =
modwalker.
sigmap(wr_ports[i]->getPort(
"\\EN"));
607 wr_ports[i]->setPort(
"\\ADDR",
module->
Mux(
NEW_ID, last_addr, this_addr, this_en_active));
608 wr_ports[i]->setPort(
"\\DATA",
module->
Mux(
NEW_ID, last_data, this_data, this_en_active));
610 std::map<std::pair<RTLIL::SigBit, RTLIL::SigBit>,
int> groups_en;
614 for (
int j = 0; j < int(this_en.size()); j++) {
615 std::pair<RTLIL::SigBit, RTLIL::SigBit> key(last_en[j], this_en[j]);
616 if (!groups_en.count(key)) {
619 groups_en[key] = grouped_en->
width;
626 wr_ports[i]->
setPort(
"\\EN", en);
629 wr_ports[i-1] =
NULL;
634 std::vector<RTLIL::Cell*> wr_ports_with_nulls;
635 wr_ports_with_nulls.swap(wr_ports);
637 for (
auto cell : wr_ports_with_nulls)
639 wr_ports.push_back(cell);
bool has_drivers(const T &sig) const
const char * log_signal(const RTLIL::SigSpec &sig, bool autoint)
void setPort(RTLIL::IdString portname, RTLIL::SigSpec signal)
RTLIL::SigSpec Mux(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_s)
std::map< RTLIL::IdString, RTLIL::Const > parameters
bool get_drivers(std::set< PortBit > &result, RTLIL::SigBit bit) const
YOSYS_NAMESPACE_BEGIN typedef ezMiniSAT ezDefaultSAT
bool cell_known(RTLIL::IdString type)
void append_bit(const RTLIL::SigBit &bit)
const RTLIL::SigSpec & getPort(RTLIL::IdString portname) const
RTLIL::Wire * addWire(RTLIL::IdString name, int width=1)
std::map< RTLIL::Cell *, std::set< RTLIL::SigBit > > cell_inputs
void remove(const std::set< RTLIL::Wire * > &wires)
RTLIL::SigSpec ReduceOr(RTLIL::IdString name, RTLIL::SigSpec sig_a, bool is_signed=false)
RTLIL::Cell * addMux(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_s, RTLIL::SigSpec sig_y)
void log(const char *format,...)
void append(const RTLIL::SigSpec &signal)
const char * log_id(RTLIL::IdString str)