3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2026-07-23 23:52:32 +00:00

Merge from upstream

This commit is contained in:
Akash Levy 2025-08-21 17:56:55 -07:00
commit e54fa487b8
29 changed files with 1314 additions and 793 deletions

View file

@ -44,20 +44,16 @@ struct OptMergeWorker
CellTypes ct;
int total_count;
static vector<pair<SigBit, SigSpec>> sorted_pmux_in(const dict<RTLIL::IdString, RTLIL::SigSpec> &conn)
static Hasher hash_pmux_in(const SigSpec& sig_s, const SigSpec& sig_b, Hasher h)
{
SigSpec sig_s = conn.at(ID::S);
SigSpec sig_b = conn.at(ID::B);
int s_width = GetSize(sig_s);
int width = GetSize(sig_b) / s_width;
vector<pair<SigBit, SigSpec>> sb_pairs;
hashlib::commutative_hash comm;
for (int i = 0; i < s_width; i++)
sb_pairs.push_back(pair<SigBit, SigSpec>(sig_s[i], sig_b.extract(i*width, width)));
comm.eat(hash_ops<std::pair<SigBit, SigSpec>>::hash({sig_s[i], sig_b.extract(i*width, width)}));
std::sort(sb_pairs.begin(), sb_pairs.end());
return sb_pairs;
return comm.hash_into(h);
}
static void sort_pmux_conn(dict<RTLIL::IdString, RTLIL::SigSpec> &conn)
@ -89,12 +85,10 @@ struct OptMergeWorker
// (builtin || stdcell) && (unary || binary) && symmetrical
if (cell->type.in(ID($and), ID($or), ID($xor), ID($xnor), ID($add), ID($mul),
ID($logic_and), ID($logic_or), ID($_AND_), ID($_OR_), ID($_XOR_))) {
std::array<RTLIL::SigSpec, 2> inputs = {
assign_map(cell->getPort(ID::A)),
assign_map(cell->getPort(ID::B))
};
std::sort(inputs.begin(), inputs.end());
h = hash_ops<std::array<RTLIL::SigSpec, 2>>::hash_into(inputs, h);
hashlib::commutative_hash comm;
comm.eat(hash_ops<RTLIL::SigSpec>::hash(assign_map(cell->getPort(ID::A))));
comm.eat(hash_ops<RTLIL::SigSpec>::hash(assign_map(cell->getPort(ID::B))));
h = comm.hash_into(h);
} else if (cell->type.in(ID($reduce_xor), ID($reduce_xnor))) {
SigSpec a = assign_map(cell->getPort(ID::A));
a.sort();
@ -104,44 +98,31 @@ struct OptMergeWorker
a.sort_and_unify();
h = a.hash_into(h);
} else if (cell->type == ID($pmux)) {
dict<RTLIL::IdString, RTLIL::SigSpec> conn = cell->connections();
assign_map.apply(conn.at(ID::A));
assign_map.apply(conn.at(ID::B));
assign_map.apply(conn.at(ID::S));
for (const auto& [s_bit, b_chunk] : sorted_pmux_in(conn)) {
h = s_bit.hash_into(h);
h = b_chunk.hash_into(h);
}
SigSpec sig_s = assign_map(cell->getPort(ID::S));
SigSpec sig_b = assign_map(cell->getPort(ID::B));
h = hash_pmux_in(sig_s, sig_b, h);
h = assign_map(cell->getPort(ID::A)).hash_into(h);
} else {
std::vector<std::pair<IdString, SigSpec>> conns;
for (const auto& conn : cell->connections()) {
conns.push_back(conn);
hashlib::commutative_hash comm;
for (const auto& [port, sig] : cell->connections()) {
if (cell->output(port))
continue;
comm.eat(hash_ops<std::pair<IdString, SigSpec>>::hash({port, assign_map(sig)}));
}
std::sort(conns.begin(), conns.end());
for (const auto& [port, sig] : conns) {
if (!cell->output(port)) {
h = port.hash_into(h);
h = assign_map(sig).hash_into(h);
}
}
h = comm.hash_into(h);
if (RTLIL::builtin_ff_cell_types().count(cell->type))
h = initvals(cell->getPort(ID::Q)).hash_into(h);
}
return h;
}
static Hasher hash_cell_parameters(const RTLIL::Cell *cell, Hasher h)
{
using Paramvec = std::vector<std::pair<IdString, Const>>;
Paramvec params;
hashlib::commutative_hash comm;
for (const auto& param : cell->parameters) {
params.push_back(param);
comm.eat(hash_ops<std::pair<IdString, Const>>::hash(param));
}
std::sort(params.begin(), params.end());
return hash_ops<Paramvec>::hash_into(params, h);
return comm.hash_into(h);
}
Hasher hash_cell_function(const RTLIL::Cell *cell, Hasher h) const
@ -227,7 +208,7 @@ struct OptMergeWorker
}
OptMergeWorker(RTLIL::Design *design, RTLIL::Module *module, bool mode_nomux, bool mode_share_all, bool mode_keepdc) :
design(design), module(module), assign_map(module), mode_share_all(mode_share_all)
design(design), module(module), mode_share_all(mode_share_all)
{
total_count = 0;
ct.setup_internals();

View file

@ -23,6 +23,8 @@
#include "kernel/celltypes.h"
#include <stdlib.h>
#include <stdio.h>
#include <unordered_map>
#include <unordered_set>
#include <set>
USING_YOSYS_NAMESPACE
@ -291,14 +293,14 @@ struct OptMuxtreeWorker
// database of known inactive signals
// the payload is a reference counter used to manage the
// list. when it is non-zero the signal in known to be inactive
vector<int> known_inactive;
std::unordered_map<int, int> known_inactive;
// database of known active signals
vector<int> known_active;
std::unordered_map<int, int> known_active;
// this is just used to keep track of visited muxes in order to prohibit
// endless recursion in mux loops
vector<bool> visited_muxes;
std::unordered_set<int> visited_muxes;
};
void eval_mux_port(knowledge_t &knowledge, int mux_idx, int port_idx, bool do_replace_known, bool do_enable_ports, int abort_count)
@ -315,17 +317,18 @@ struct OptMuxtreeWorker
if (i == port_idx)
continue;
if (muxinfo.ports[i].ctrl_sig >= 0)
knowledge.known_inactive.at(muxinfo.ports[i].ctrl_sig)++;
++knowledge.known_inactive[muxinfo.ports[i].ctrl_sig];
}
if (port_idx < GetSize(muxinfo.ports)-1 && !muxinfo.ports[port_idx].const_activated)
knowledge.known_active.at(muxinfo.ports[port_idx].ctrl_sig)++;
++knowledge.known_active[muxinfo.ports[port_idx].ctrl_sig];
vector<int> parent_muxes;
for (int m : muxinfo.ports[port_idx].input_muxes) {
if (knowledge.visited_muxes[m])
auto it = knowledge.visited_muxes.find(m);
if (it != knowledge.visited_muxes.end())
continue;
knowledge.visited_muxes[m] = true;
knowledge.visited_muxes.insert(it, m);
parent_muxes.push_back(m);
}
for (int m : parent_muxes) {
@ -344,16 +347,24 @@ struct OptMuxtreeWorker
return;
}
for (int m : parent_muxes)
knowledge.visited_muxes[m] = false;
knowledge.visited_muxes.erase(m);
if (port_idx < GetSize(muxinfo.ports)-1 && !muxinfo.ports[port_idx].const_activated)
knowledge.known_active.at(muxinfo.ports[port_idx].ctrl_sig)--;
if (port_idx < GetSize(muxinfo.ports)-1 && !muxinfo.ports[port_idx].const_activated) {
auto it = knowledge.known_active.find(muxinfo.ports[port_idx].ctrl_sig);
if (it != knowledge.known_active.end())
if (--it->second == 0)
knowledge.known_active.erase(it);
}
for (int i = 0; i < GetSize(muxinfo.ports); i++) {
if (i == port_idx)
continue;
if (muxinfo.ports[i].ctrl_sig >= 0)
knowledge.known_inactive.at(muxinfo.ports[i].ctrl_sig)--;
if (muxinfo.ports[i].ctrl_sig >= 0) {
auto it = knowledge.known_inactive.find(muxinfo.ports[i].ctrl_sig);
if (it != knowledge.known_inactive.end())
if (--it->second == 0)
knowledge.known_inactive.erase(it);
}
}
}
@ -373,11 +384,11 @@ struct OptMuxtreeWorker
vector<int> bits = sig2bits(sig, false);
for (int i = 0; i < GetSize(bits); i++) {
if (bits[i] >= 0) {
if (knowledge.known_inactive.at(bits[i])) {
if (knowledge.known_inactive.count(bits[i]) > 0) {
sig[i] = State::S0;
did_something = true;
} else
if (knowledge.known_active.at(bits[i])) {
if (knowledge.known_active.count(bits[i]) > 0) {
sig[i] = State::S1;
did_something = true;
}
@ -435,7 +446,7 @@ struct OptMuxtreeWorker
portinfo_t &portinfo = muxinfo.ports[port_idx];
if (portinfo.const_deactivated)
continue;
if (knowledge.known_active.at(portinfo.ctrl_sig)) {
if (knowledge.known_active.count(portinfo.ctrl_sig) > 0) {
eval_mux_port(knowledge, mux_idx, port_idx, do_replace_known, do_enable_ports, abort_count);
return;
}
@ -449,7 +460,7 @@ struct OptMuxtreeWorker
if (portinfo.const_deactivated)
continue;
if (port_idx < GetSize(muxinfo.ports)-1)
if (knowledge.known_inactive.at(portinfo.ctrl_sig))
if (knowledge.known_inactive.count(portinfo.ctrl_sig) > 0)
continue;
eval_mux_port(knowledge, mux_idx, port_idx, do_replace_known, do_enable_ports, abort_count);
@ -462,10 +473,7 @@ struct OptMuxtreeWorker
{
log_assert(glob_abort_cnt > 0);
knowledge_t knowledge;
knowledge.known_inactive.resize(GetSize(bit2info));
knowledge.known_active.resize(GetSize(bit2info));
knowledge.visited_muxes.resize(GetSize(mux2info));
knowledge.visited_muxes[mux_idx] = true;
knowledge.visited_muxes.insert(mux_idx);
eval_mux(knowledge, mux_idx, true, root_enable_muxes.at(mux_idx), 3);
}
};