3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-12-19 02:33:44 +00:00

proc_mux: add comments

This commit is contained in:
Emil J. Tywoniak 2025-11-15 01:58:16 +01:00
parent a52bf59cb9
commit b79830a80b

View file

@ -28,6 +28,21 @@
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
/**
* Actions are assignments in cases of switches.
* Snippets are non-overlapping slices of signals on the left-hand side
* of actions. For example, if you have these two actions for r[7:0]:
* r = a; r[1:2] = 2'b0;
* you will arrive at three snippets:
* r[0], r[2:1], r[7:3]
* For each snippet, multiplexers ($mux or $pmux) are emitted
* based on the full switch.
* $pmux are only emitted when legal based on whether the cases can be
* evaluated in parallel.
* In that case, instead of a $pmux, you get a chain of $mux.
* Nested switches build branching trees of muxes.
*/
using SnippetSourceMap = std::vector<dict<const RTLIL::CaseRule*, const Const*>>;
struct SnippetSourceMapBuilder {
SnippetSourceMap map;
@ -202,6 +217,7 @@ struct MuxGenCtx {
int current_snippet;
pool<std::string>& snippet_sources;
// Returns signal for the select input of a mux
RTLIL::SigSpec gen_cmp() {
std::stringstream sstr;
sstr << "$procmux$" << (autoidx++);
@ -408,24 +424,9 @@ bool is_simple_parallel_case(RTLIL::SwitchRule* sw, dict<RTLIL::SwitchRule*, boo
return ret;
}
RTLIL::SigSpec signal_to_mux_tree(MuxTreeContext ctx)
std::vector<int> parallel_groups(MuxTreeContext ctx, RTLIL::SwitchRule* sw)
{
RTLIL::SigSpec result = ctx.defval;
for (auto &action : ctx.cs->actions) {
ctx.sig.replace(action.lhs, action.rhs, &result);
action.lhs.remove2(ctx.sig, &action.rhs);
}
for (auto sw : ctx.cs->switches)
{
if (!ctx.swcache.check(sw))
continue;
// detect groups of parallel cases
std::vector<int> pgroups(sw->cases.size());
pool<std::string> case_sources;
if (!is_simple_parallel_case(sw, ctx.swpara)) {
BitPatternPool pool(sw->signal.size());
bool extra_group_for_next_case = false;
@ -452,6 +453,26 @@ RTLIL::SigSpec signal_to_mux_tree(MuxTreeContext ctx)
pool.take(pat);
}
}
return pgroups;
}
RTLIL::SigSpec signal_to_mux_tree(MuxTreeContext ctx)
{
RTLIL::SigSpec result = ctx.defval;
for (auto &action : ctx.cs->actions) {
ctx.sig.replace(action.lhs, action.rhs, &result);
action.lhs.remove2(ctx.sig, &action.rhs);
}
for (auto sw : ctx.cs->switches)
{
if (!ctx.swcache.check(sw))
continue;
// Detect groups of parallel cases
std::vector<int> pgroups = parallel_groups(ctx, sw);
pool<std::string> case_sources;
// Create sources for default cases
for (auto cs2 : sw -> cases) {
if (cs2->compare.empty()) {
@ -466,7 +487,8 @@ RTLIL::SigSpec signal_to_mux_tree(MuxTreeContext ctx)
result[i] = State::Sx;
RTLIL::SigSpec initial_val = result;
MuxGenCtx mux_gen_ctx {ctx.mod,
MuxGenCtx mux_gen_ctx {
ctx.mod,
sw->signal,
nullptr,
nullptr,
@ -477,7 +499,7 @@ RTLIL::SigSpec signal_to_mux_tree(MuxTreeContext ctx)
ctx.swcache.current_snippet,
case_sources
};
// evaluate in reverse order to give the first entry the top priority
// Evaluate in reverse order to give the first entry the top priority
for (size_t i = 0; i < sw->cases.size(); i++) {
int case_idx = sw->cases.size() - i - 1;
MuxTreeContext new_ctx = ctx;