3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-11-03 13:07:58 +00:00

rtlil: replace SigSig actions with new type SyncAction

This commit is contained in:
Emil J. Tywoniak 2025-11-02 11:22:03 +01:00
parent 37875fdedf
commit 1eb696c786
19 changed files with 305 additions and 252 deletions

View file

@ -494,8 +494,8 @@ struct FlowGraph {
void add_case_rule_defs_uses(Node *node, const RTLIL::CaseRule *case_)
{
for (auto &action : case_->actions) {
add_defs(node, action.first, /*is_ff=*/false, /*inlinable=*/false);
add_uses(node, action.second);
add_defs(node, action.lhs, /*is_ff=*/false, /*inlinable=*/false);
add_uses(node, action.rhs);
}
for (auto sub_switch : case_->switches) {
add_uses(node, sub_switch->signal);
@ -512,10 +512,10 @@ struct FlowGraph {
for (auto sync : process->syncs) {
for (auto &action : sync->actions) {
if (sync->type == RTLIL::STp || sync->type == RTLIL::STn || sync->type == RTLIL::STe)
add_defs(node, action.first, /*is_ff=*/true, /*inlinable=*/false);
add_defs(node, action.lhs, /*is_ff=*/true, /*inlinable=*/false);
else
add_defs(node, action.first, /*is_ff=*/false, /*inlinable=*/false);
add_uses(node, action.second);
add_defs(node, action.lhs, /*is_ff=*/false, /*inlinable=*/false);
add_uses(node, action.rhs);
}
for (auto &memwr : sync->mem_write_actions) {
add_uses(node, memwr.address);
@ -1623,12 +1623,12 @@ struct CxxrtlWorker {
collect_sigspec_rhs(port.second, for_debug, cells);
}
void dump_assign(const RTLIL::SigSig &sigsig, bool for_debug = false)
void dump_assign(const RTLIL::SyncAction &action, bool for_debug = false)
{
f << indent;
dump_sigspec_lhs(sigsig.first, for_debug);
dump_sigspec_lhs(action.lhs, for_debug);
f << " = ";
dump_sigspec_rhs(sigsig.second, for_debug);
dump_sigspec_rhs(action.rhs, for_debug);
f << ";\n";
}

View file

@ -189,7 +189,7 @@ void RTLIL_BACKEND::dump_cell(std::ostream &f, std::string indent, const RTLIL::
void RTLIL_BACKEND::dump_proc_case_body(std::ostream &f, std::string indent, const RTLIL::CaseRule *cs)
{
for (const auto& [lhs, rhs] : cs->actions) {
for (const auto& [lhs, rhs, _] : cs->actions) {
f << stringf("%s" "assign ", indent);
dump_sigspec(f, lhs);
f << stringf(" ");
@ -243,7 +243,7 @@ void RTLIL_BACKEND::dump_proc_sync(std::ostream &f, std::string indent, const RT
case RTLIL::STi: f << stringf("init\n"); break;
}
for (const auto& [lhs, rhs] : sy->actions) {
for (const auto& [lhs, rhs, _] : sy->actions) {
f << stringf("%s update ", indent);
dump_sigspec(f, lhs);
f << stringf(" ");
@ -375,8 +375,11 @@ void RTLIL_BACKEND::dump_design(std::ostream &f, RTLIL::Design *design, bool onl
for (auto* module : design->modules()) {
if (design->selected_whole_module(module->name))
flag_m = true;
if (design->selected(module))
if (design->selected(module)) {
count_selected_mods++;
if (module->has_processes())
log_warning("Module %s contains processes. Case action sources attributes will be lost.\n", log_id(module));
}
}
if (count_selected_mods > 1)
flag_m = true;

View file

@ -2122,13 +2122,14 @@ void dump_proc_switch(std::ostream &f, std::string indent, RTLIL::SwitchRule *sw
void dump_case_actions(std::ostream &f, std::string indent, RTLIL::CaseRule *cs)
{
for (auto it = cs->actions.begin(); it != cs->actions.end(); ++it) {
if (it->first.size() == 0)
if (it->lhs.size() == 0)
continue;
f << stringf("%s ", indent);
dump_sigspec(f, it->first);
dump_sigspec(f, it->lhs);
f << stringf(" = ");
dump_sigspec(f, it->second);
dump_sigspec(f, it->rhs);
f << stringf(";\n");
// TODO
}
}
@ -2259,7 +2260,7 @@ void case_body_find_regs(RTLIL::CaseRule *cs)
case_body_find_regs(*it2);
for (auto it = cs->actions.begin(); it != cs->actions.end(); ++it) {
for (auto &c : it->first.chunks())
for (auto &c : it->lhs.chunks())
if (c.wire != NULL)
reg_wires.insert(c.wire->name);
}
@ -2271,7 +2272,7 @@ void dump_process(std::ostream &f, std::string indent, RTLIL::Process *proc, boo
case_body_find_regs(&proc->root_case);
for (auto it = proc->syncs.begin(); it != proc->syncs.end(); ++it)
for (auto it2 = (*it)->actions.begin(); it2 != (*it)->actions.end(); it2++) {
for (auto &c : it2->first.chunks())
for (auto &c : it2->lhs.chunks())
if (c.wire != NULL)
reg_wires.insert(c.wire->name);
}
@ -2328,12 +2329,12 @@ void dump_process(std::ostream &f, std::string indent, RTLIL::Process *proc, boo
}
for (auto it = sync->actions.begin(); it != sync->actions.end(); ++it) {
if (it->first.size() == 0)
if (it->lhs.size() == 0)
continue;
f << stringf("%s ", indent);
dump_sigspec(f, it->first);
dump_sigspec(f, it->lhs);
f << stringf(" <= ");
dump_sigspec(f, it->second);
dump_sigspec(f, it->rhs);
f << stringf(";\n");
}

View file

@ -382,7 +382,7 @@ struct AST_INTERNAL::ProcessGenerator
if (found_anyedge_syncs) {
if (found_global_syncs)
always->input_error("Found non-synthesizable event list!\n");
log("Note: Assuming pure combinatorial block at %s in\n", always->loc_string());
log("Note: Assuming pure combinatorial block at %s in\n", always->location.to_string());
log("compliance with IEC 62142(E):2005 / IEEE Std. 1364.1(E):2002. Recommending\n");
log("use of @* instead of @(...) for better match of synthesis and simulation.\n");
}
@ -402,14 +402,14 @@ struct AST_INTERNAL::ProcessGenerator
syncrule->signal = child->children[0]->genRTLIL();
if (GetSize(syncrule->signal) != 1)
always->input_error("Found posedge/negedge event on a signal that is not 1 bit wide!\n");
addChunkActions(syncrule->actions, subst_lvalue_from, subst_lvalue_to, true);
addChunkActions(syncrule->actions, subst_lvalue_from, subst_lvalue_to, child.get(), true);
proc->syncs.push_back(syncrule);
}
if (proc->syncs.empty()) {
RTLIL::SyncRule *syncrule = new RTLIL::SyncRule;
syncrule->type = found_global_syncs ? RTLIL::STg : RTLIL::STa;
syncrule->signal = RTLIL::SigSpec();
addChunkActions(syncrule->actions, subst_lvalue_from, subst_lvalue_to, true);
addChunkActions(syncrule->actions, subst_lvalue_from, subst_lvalue_to, always.get(), true);
proc->syncs.push_back(syncrule);
}
@ -417,7 +417,7 @@ struct AST_INTERNAL::ProcessGenerator
if ((flag_nolatches || always->get_bool_attribute(ID::nolatches) || current_module->get_bool_attribute(ID::nolatches)) && !found_clocked_sync) {
subst_rvalue_map = subst_lvalue_from.to_sigbit_dict(RTLIL::SigSpec(RTLIL::State::Sx, GetSize(subst_lvalue_from)));
} else {
addChunkActions(current_case->actions, subst_lvalue_to, subst_lvalue_from);
addChunkActions(current_case->actions, subst_lvalue_to, subst_lvalue_from, always.get());
}
// process the AST
@ -441,7 +441,7 @@ struct AST_INTERNAL::ProcessGenerator
RTLIL::SigSpec lhs = init_lvalue_c;
RTLIL::SigSpec rhs = init_rvalue.extract(offset, init_lvalue_c.width);
remove_unwanted_lvalue_bits(lhs, rhs);
sync->actions.push_back(RTLIL::SigSig(lhs, rhs));
sync->actions.push_back({lhs, rhs});
offset += lhs.size();
}
}
@ -548,7 +548,7 @@ struct AST_INTERNAL::ProcessGenerator
void removeSignalFromCaseTree(const RTLIL::SigSpec &pattern, RTLIL::CaseRule *cs)
{
for (auto it = cs->actions.begin(); it != cs->actions.end(); it++)
it->first.remove2(pattern, &it->second);
it->lhs.remove2(pattern, &it->rhs);
for (auto it = cs->switches.begin(); it != cs->switches.end(); it++)
for (auto it2 = (*it)->cases.begin(); it2 != (*it)->cases.end(); it2++)
@ -557,7 +557,7 @@ struct AST_INTERNAL::ProcessGenerator
// add an assignment (aka "action") but split it up in chunks. this way huge assignments
// are avoided and the generated $mux cells have a more "natural" size.
void addChunkActions(std::vector<RTLIL::SigSig> &actions, RTLIL::SigSpec lvalue, RTLIL::SigSpec rvalue, bool inSyncRule = false)
void addChunkActions(std::vector<RTLIL::SyncAction> &actions, RTLIL::SigSpec lvalue, RTLIL::SigSpec rvalue, AstNode* ast, bool inSyncRule = false)
{
if (inSyncRule && initSyncSignals.size() > 0) {
init_lvalue.append(lvalue.extract(initSyncSignals));
@ -573,7 +573,7 @@ struct AST_INTERNAL::ProcessGenerator
if (inSyncRule && lvalue_c.wire && lvalue_c.wire->get_bool_attribute(ID::nosync))
rhs = RTLIL::SigSpec(RTLIL::State::Sx, rhs.size());
remove_unwanted_lvalue_bits(lhs, rhs);
actions.push_back(RTLIL::SigSig(lhs, rhs));
actions.push_back({lhs, rhs});
offset += lhs.size();
}
}
@ -613,7 +613,7 @@ struct AST_INTERNAL::ProcessGenerator
removeSignalFromCaseTree(lvalue, current_case);
remove_unwanted_lvalue_bits(lvalue, rvalue);
current_case->actions.push_back(RTLIL::SigSig(lvalue, rvalue));
current_case->actions.push_back({lvalue, rvalue});
}
break;
@ -657,10 +657,11 @@ struct AST_INTERNAL::ProcessGenerator
subst_lvalue_map.set(this_case_eq_lvalue[i], this_case_eq_ltemp[i]);
RTLIL::CaseRule *backup_case = current_case;
// here
current_case = new RTLIL::CaseRule;
set_src_attr(current_case, child.get());
last_generated_case = current_case;
addChunkActions(current_case->actions, this_case_eq_ltemp, this_case_eq_rvalue);
addChunkActions(current_case->actions, this_case_eq_ltemp, this_case_eq_rvalue, child.get());
for (auto& node : child->children) {
if (node->type == AST_DEFAULT)
default_case = current_case;
@ -687,13 +688,13 @@ struct AST_INTERNAL::ProcessGenerator
last_generated_case->compare.clear();
#else
default_case = new RTLIL::CaseRule;
addChunkActions(default_case->actions, this_case_eq_ltemp, SigSpec(State::Sx, GetSize(this_case_eq_rvalue)));
addChunkActions(default_case->actions, this_case_eq_ltemp, SigSpec(State::Sx, GetSize(this_case_eq_rvalue)), ast);
sw->cases.push_back(default_case);
#endif
} else {
if (default_case == nullptr) {
default_case = new RTLIL::CaseRule;
addChunkActions(default_case->actions, this_case_eq_ltemp, this_case_eq_rvalue);
addChunkActions(default_case->actions, this_case_eq_ltemp, this_case_eq_rvalue, ast);
}
sw->cases.push_back(default_case);
}
@ -703,7 +704,7 @@ struct AST_INTERNAL::ProcessGenerator
this_case_eq_lvalue.replace(subst_lvalue_map.stdmap());
removeSignalFromCaseTree(this_case_eq_lvalue, current_case);
addChunkActions(current_case->actions, this_case_eq_lvalue, this_case_eq_ltemp);
addChunkActions(current_case->actions, this_case_eq_lvalue, this_case_eq_ltemp, ast);
}
break;
@ -728,8 +729,8 @@ struct AST_INTERNAL::ProcessGenerator
Wire *en = current_module->addWire(sstr.str() + "_EN", 1);
set_src_attr(en, ast);
proc->root_case.actions.push_back(SigSig(en, false));
current_case->actions.push_back(SigSig(en, true));
proc->root_case.actions.push_back({en, SigSpec(false)});
current_case->actions.push_back({en, SigSpec(true)});
RTLIL::SigSpec triggers;
RTLIL::Const::Builder polarity_builder;
@ -826,8 +827,8 @@ struct AST_INTERNAL::ProcessGenerator
Wire *en = current_module->addWire(cellname.str() + "_EN", 1);
set_src_attr(en, ast);
proc->root_case.actions.push_back(SigSig(en, false));
current_case->actions.push_back(SigSig(en, true));
proc->root_case.actions.push_back({en, SigSpec(false)});
current_case->actions.push_back({en, SigSpec(true)});
RTLIL::SigSpec triggers;
RTLIL::Const::Builder polarity_builder;

View file

@ -23,6 +23,7 @@
#include "kernel/register.h"
#include "kernel/log.h"
#include "kernel/rtlil.h"
#include "kernel/utils.h"
#include <charconv>
#include <deque>
@ -623,7 +624,7 @@ struct RTLILFrontendWorker {
"The assign statement is reordered to come before all switch statements.");
RTLIL::SigSpec s1 = parse_sigspec();
RTLIL::SigSpec s2 = parse_sigspec();
current_case->actions.push_back(RTLIL::SigSig(std::move(s1), std::move(s2)));
current_case->actions.push_back({std::move(s1), std::move(s2)});
expect_eol();
} else
return;
@ -714,7 +715,7 @@ struct RTLILFrontendWorker {
if (try_parse_keyword("update")) {
RTLIL::SigSpec s1 = parse_sigspec();
RTLIL::SigSpec s2 = parse_sigspec();
rule->actions.push_back(RTLIL::SigSig(std::move(s1), std::move(s2)));
rule->actions.push_back({std::move(s1), std::move(s2)});
expect_eol();
continue;
}

View file

@ -116,6 +116,7 @@ namespace RTLIL
struct CaseRule;
struct SwitchRule;
struct MemWriteAction;
struct SyncAction;
struct SyncRule;
struct Process;
struct Binding;
@ -1113,6 +1114,13 @@ struct RTLIL::AttrObject
std::string get_src_attribute() const {
return get_string_attribute(ID::src);
}
void transfer_attribute(const AttrObject* from, const IdString& attr) {
if (from->has_attribute(attr))
attributes[attr] = from->attributes.at(attr);
}
void transfer_src_attribute(const AttrObject* from) {
transfer_attribute(from, ID::src);
}
void set_hdlname_attribute(const vector<string> &hierarchy);
vector<string> get_hdlname_attribute() const;
@ -2194,7 +2202,7 @@ public:
struct RTLIL::CaseRule : public RTLIL::AttrObject
{
std::vector<RTLIL::SigSpec> compare;
std::vector<RTLIL::SigSig> actions;
std::vector<RTLIL::SyncAction> actions;
std::vector<RTLIL::SwitchRule*> switches;
~CaseRule();
@ -2229,11 +2237,17 @@ struct RTLIL::MemWriteAction : RTLIL::AttrObject
RTLIL::Const priority_mask;
};
struct RTLIL::SyncAction
{
RTLIL::SigSpec lhs;
RTLIL::SigSpec rhs;
};
struct RTLIL::SyncRule
{
RTLIL::SyncType type;
RTLIL::SigSpec signal;
std::vector<RTLIL::SigSig> actions;
std::vector<RTLIL::SyncAction> actions;
std::vector<RTLIL::MemWriteAction> mem_write_actions;
template<typename T> void rewrite_sigspecs(T &functor);
@ -2363,8 +2377,8 @@ void RTLIL::CaseRule::rewrite_sigspecs(T &functor) {
for (auto &it : compare)
functor(it);
for (auto &it : actions) {
functor(it.first);
functor(it.second);
functor(it.lhs);
functor(it.rhs);
}
for (auto it : switches)
it->rewrite_sigspecs(functor);
@ -2375,7 +2389,7 @@ void RTLIL::CaseRule::rewrite_sigspecs2(T &functor) {
for (auto &it : compare)
functor(it);
for (auto &it : actions) {
functor(it.first, it.second);
functor(it.lhs, it.rhs);
}
for (auto it : switches)
it->rewrite_sigspecs2(functor);
@ -2402,8 +2416,8 @@ void RTLIL::SyncRule::rewrite_sigspecs(T &functor)
{
functor(signal);
for (auto &it : actions) {
functor(it.first);
functor(it.second);
functor(it.lhs);
functor(it.rhs);
}
for (auto &it : mem_write_actions) {
functor(it.address);
@ -2417,7 +2431,7 @@ void RTLIL::SyncRule::rewrite_sigspecs2(T &functor)
{
functor(signal);
for (auto &it : actions) {
functor(it.first, it.second);
functor(it.lhs, it.rhs);
}
for (auto &it : mem_write_actions) {
functor(it.address);

View file

@ -361,7 +361,7 @@ struct BugpointPass : public Pass {
{
if (index++ == seed)
{
log_header(design, "Trying to remove assign %s %s in %s.%s.\n", log_signal(it->first), log_signal(it->second), log_id(mod), log_id(pr.first));
log_header(design, "Trying to remove assign %s %s in %s.%s.\n", log_signal(it->lhs), log_signal(it->rhs), log_id(mod), log_id(pr.first));
cs->actions.erase(it);
return design_copy;
}
@ -387,7 +387,7 @@ struct BugpointPass : public Pass {
{
if (index++ == seed)
{
log_header(design, "Trying to remove sync %s update %s %s in %s.%s.\n", log_signal(sy->signal), log_signal(it->first), log_signal(it->second), log_id(mod), log_id(pr.first));
log_header(design, "Trying to remove sync %s update %s %s in %s.%s.\n", log_signal(sy->signal), log_signal(it->lhs), log_signal(it->rhs), log_id(mod), log_id(pr.first));
sy->actions.erase(it);
return design_copy;
}

View file

@ -130,12 +130,12 @@ struct CheckPass : public Pass {
std::vector<RTLIL::CaseRule*> all_cases = {&proc_it.second->root_case};
for (size_t i = 0; i < all_cases.size(); i++) {
for (auto action : all_cases[i]->actions) {
for (auto bit : sigmap(action.first))
for (auto bit : sigmap(action.lhs))
wire_drivers[bit].push_back(
stringf("action %s <= %s (case rule) in process %s",
log_signal(action.first), log_signal(action.second), log_id(proc_it.first)));
log_signal(action.lhs), log_signal(action.rhs), log_id(proc_it.first)));
for (auto bit : sigmap(action.second))
for (auto bit : sigmap(action.rhs))
if (bit.wire) used_wires.insert(bit);
}
for (auto switch_ : all_cases[i]->switches) {
@ -151,11 +151,11 @@ struct CheckPass : public Pass {
for (auto bit : sigmap(sync->signal))
if (bit.wire) used_wires.insert(bit);
for (auto action : sync->actions) {
for (auto bit : sigmap(action.first))
for (auto bit : sigmap(action.lhs))
wire_drivers[bit].push_back(
stringf("action %s <= %s (sync rule) in process %s",
log_signal(action.first), log_signal(action.second), log_id(proc_it.first)));
for (auto bit : sigmap(action.second))
log_signal(action.lhs), log_signal(action.rhs), log_id(proc_it.first)));
for (auto bit : sigmap(action.rhs))
if (bit.wire) used_wires.insert(bit);
}
for (auto memwr : sync->mem_write_actions) {

View file

@ -17,6 +17,7 @@
*
*/
#include "kernel/rtlil.h"
#include "kernel/yosys.h"
#include "kernel/celltypes.h"
#include "kernel/mem.h"
@ -40,9 +41,9 @@ struct CleanZeroWidthPass : public Pass {
void clean_case(RTLIL::CaseRule *cs)
{
std::vector<SigSig> new_actions;
std::vector<RTLIL::SyncAction> new_actions;
for (auto &action : cs->actions)
if (GetSize(action.first) != 0)
if (GetSize(action.lhs) != 0)
new_actions.push_back(action);
std::swap(new_actions, cs->actions);
for (auto sw : cs->switches)
@ -167,9 +168,9 @@ struct CleanZeroWidthPass : public Pass {
new_memwr_actions.push_back(memwr);
}
std::swap(new_memwr_actions, sync->mem_write_actions);
std::vector<SigSig> new_actions;
std::vector<RTLIL::SyncAction> new_actions;
for (auto &action : sync->actions)
if (GetSize(action.first) != 0)
if (GetSize(action.lhs) != 0)
new_actions.push_back(action);
std::swap(new_actions, sync->actions);
}

View file

@ -17,6 +17,7 @@
*
*/
#include "kernel/rtlil.h"
#include "kernel/yosys.h"
#include "kernel/celltypes.h"
#include "kernel/log_help.h"
@ -370,12 +371,12 @@ struct ShowWorker
signals.insert(it);
}
void collect_proc_signals(std::vector<RTLIL::SigSig> &obj, std::set<RTLIL::SigSpec> &input_signals, std::set<RTLIL::SigSpec> &output_signals)
void collect_proc_signals(std::vector<RTLIL::SyncAction> &obj, std::set<RTLIL::SigSpec> &input_signals, std::set<RTLIL::SigSpec> &output_signals)
{
for (auto &it : obj) {
output_signals.insert(it.first);
if (!it.second.is_fully_const())
input_signals.insert(it.second);
output_signals.insert(it.lhs);
if (!it.rhs.is_fully_const())
input_signals.insert(it.rhs);
}
}

View file

@ -18,6 +18,7 @@
*/
#include "kernel/register.h"
#include "kernel/rtlil.h"
#include "kernel/sigtools.h"
#include "kernel/log.h"
#include <stdlib.h>
@ -89,9 +90,9 @@ void apply_const(RTLIL::Module *mod, const RTLIL::SigSpec rspec, RTLIL::SigSpec
{
for (auto &action : cs->actions) {
if (unknown)
rspec.replace(action.first, RTLIL::SigSpec(RTLIL::State::Sm, action.second.size()), &rval);
rspec.replace(action.lhs, RTLIL::SigSpec(RTLIL::State::Sm, action.rhs.size()), &rval);
else
rspec.replace(action.first, action.second, &rval);
rspec.replace(action.lhs, action.rhs, &rval);
}
for (auto sw : cs->switches) {
@ -209,7 +210,7 @@ void proc_arst(RTLIL::Module *mod, RTLIL::Process *proc, SigMap &assign_map)
arst_syncs.push_back(sync);
edge_syncs.erase(it);
for (auto &action : sync->actions) {
action.second = apply_reset(mod, proc, sync, assign_map, root_sig, polarity, action.second, action.first);
action.rhs = apply_reset(mod, proc, sync, assign_map, root_sig, polarity, action.rhs, action.lhs);
}
for (auto &memwr : sync->mem_write_actions) {
RTLIL::SigSpec en = apply_reset(mod, proc, sync, assign_map, root_sig, polarity, memwr.enable, memwr.enable);
@ -294,12 +295,12 @@ struct ProcArstPass : public Pass {
proc_arst(mod, proc, assign_map);
if (global_arst.empty() || mod->wire(global_arst) == nullptr)
continue;
std::vector<RTLIL::SigSig> arst_actions;
std::vector<RTLIL::SyncAction> arst_actions;
for (auto sync : proc->syncs)
if (sync->type == RTLIL::SyncType::STp || sync->type == RTLIL::SyncType::STn)
for (auto &act : sync->actions) {
RTLIL::SigSpec arst_sig, arst_val;
for (auto &chunk : act.first.chunks())
for (auto &chunk : act.lhs.chunks())
if (chunk.wire && chunk.wire->attributes.count(ID::init)) {
RTLIL::SigSpec value = chunk.wire->attributes.at(ID::init);
value.extend_u0(chunk.wire->width, false);
@ -310,7 +311,7 @@ struct ProcArstPass : public Pass {
if (arst_sig.size()) {
log("Added global reset to process %s: %s <- %s\n",
proc->name.c_str(), log_signal(arst_sig), log_signal(arst_val));
arst_actions.push_back(RTLIL::SigSig(arst_sig, arst_val));
arst_actions.push_back({arst_sig, arst_val});
}
}
if (!arst_actions.empty()) {

View file

@ -133,7 +133,7 @@ YOSYS_NAMESPACE_BEGIN
void proc_clean_case(RTLIL::CaseRule *cs, bool &did_something, int &count, int max_depth)
{
for (size_t i = 0; i < cs->actions.size(); i++) {
if (cs->actions[i].first.size() == 0) {
if (cs->actions[i].lhs.size() == 0) {
did_something = true;
cs->actions.erase(cs->actions.begin() + (i--));
}
@ -159,7 +159,7 @@ void proc_clean(RTLIL::Module *mod, RTLIL::Process *proc, int &total_count, bool
bool did_something = true;
for (size_t i = 0; i < proc->syncs.size(); i++) {
for (size_t j = 0; j < proc->syncs[i]->actions.size(); j++)
if (proc->syncs[i]->actions[j].first.size() == 0)
if (proc->syncs[i]->actions[j].lhs.size() == 0)
proc->syncs[i]->actions.erase(proc->syncs[i]->actions.begin() + (j--));
if (proc->syncs[i]->actions.size() == 0 && proc->syncs[i]->mem_write_actions.size() == 0) {
delete proc->syncs[i];

View file

@ -34,8 +34,8 @@ RTLIL::SigSpec find_any_lvalue(const RTLIL::Process *proc)
for (auto sync : proc->syncs)
for (auto &action : sync->actions)
if (action.first.size() > 0) {
lvalue = action.first;
if (action.lhs.size() > 0) {
lvalue = action.lhs;
lvalue.sort_and_unify();
break;
}
@ -43,7 +43,7 @@ RTLIL::SigSpec find_any_lvalue(const RTLIL::Process *proc)
for (auto sync : proc->syncs) {
RTLIL::SigSpec this_lvalue;
for (auto &action : sync->actions)
this_lvalue.append(action.first);
this_lvalue.append(action.lhs);
this_lvalue.sort_and_unify();
RTLIL::SigSpec common_sig = this_lvalue.extract(lvalue);
if (common_sig.size() > 0)
@ -172,35 +172,35 @@ void proc_dff(RTLIL::Module *mod, RTLIL::Process *proc, ConstEval &ce)
for (auto sync : proc->syncs)
for (auto &action : sync->actions)
{
if (action.first.extract(sig).size() == 0)
if (action.lhs.extract(sig).size() == 0)
continue;
if (sync->type == RTLIL::SyncType::ST0 || sync->type == RTLIL::SyncType::ST1) {
RTLIL::SigSpec rstval = RTLIL::SigSpec(RTLIL::State::Sz, sig.size());
sig.replace(action.first, action.second, &rstval);
sig.replace(action.lhs, action.rhs, &rstval);
async_rules.emplace_back(rstval, sync);
}
else if (sync->type == RTLIL::SyncType::STp || sync->type == RTLIL::SyncType::STn) {
if (sync_edge != NULL && sync_edge != sync)
log_error("Multiple edge sensitive events found for this signal!\n");
sig.replace(action.first, action.second, &insig);
sig.replace(action.lhs, action.rhs, &insig);
sync_edge = sync;
}
else if (sync->type == RTLIL::SyncType::STa) {
if (sync_always != NULL && sync_always != sync)
log_error("Multiple always events found for this signal!\n");
sig.replace(action.first, action.second, &insig);
sig.replace(action.lhs, action.rhs, &insig);
sync_always = sync;
}
else if (sync->type == RTLIL::SyncType::STg) {
sig.replace(action.first, action.second, &insig);
sig.replace(action.lhs, action.rhs, &insig);
global_clock = true;
}
else {
log_error("Event with any-edge sensitivity found for this signal!\n");
}
action.first.remove2(sig, &action.second);
action.lhs.remove2(sig, &action.rhs);
}
// If all async rules assign the same value, priority ordering between
@ -223,7 +223,8 @@ void proc_dff(RTLIL::Module *mod, RTLIL::Process *proc, ConstEval &ce)
// as ones coming from the module
single_async_rule.type = RTLIL::SyncType::ST1;
single_async_rule.signal = mod->ReduceOr(NEW_ID, triggers);
single_async_rule.actions.push_back(RTLIL::SigSig(sig, rstval));
// TODO
single_async_rule.actions.push_back({sig, rstval});
// Replace existing rules with this new rule
async_rules.clear();

View file

@ -364,17 +364,17 @@ void proc_dlatch(proc_dlatch_db_t &db, RTLIL::Process *proc)
for (auto ss : sr->actions)
{
db.sigmap.apply(ss.first);
db.sigmap.apply(ss.second);
db.sigmap.apply(ss.lhs);
db.sigmap.apply(ss.rhs);
if (!db.quickcheck(ss.second, ss.first)) {
nolatches_bits.first.append(ss.first);
nolatches_bits.second.append(ss.second);
if (!db.quickcheck(ss.rhs, ss.lhs)) {
nolatches_bits.first.append(ss.lhs);
nolatches_bits.second.append(ss.rhs);
continue;
}
for (int i = 0; i < GetSize(ss.first); i++)
latches_out_in[ss.first[i]] = ss.second[i];
for (int i = 0; i < GetSize(ss.lhs); i++)
latches_out_in[ss.lhs[i]] = ss.rhs[i];
}
sr->actions.clear();
}

View file

@ -35,8 +35,8 @@ void proc_init(RTLIL::Module *mod, SigMap &sigmap, RTLIL::Process *proc)
for (auto &action : sync->actions)
{
RTLIL::SigSpec lhs = action.first;
RTLIL::SigSpec rhs = sigmap(action.second);
RTLIL::SigSpec lhs = action.lhs;
RTLIL::SigSpec rhs = sigmap(action.rhs);
if (!rhs.is_fully_const())
log_cmd_error("Failed to get a constant init value for %s: %s\n", log_signal(lhs), log_signal(rhs));

View file

@ -98,7 +98,7 @@ struct SigSnippets
void insert(const RTLIL::CaseRule *cs)
{
for (auto &action : cs->actions)
insert(action.first);
insert(action.lhs);
for (auto sw : cs->switches)
for (auto cs2 : sw->cases)
@ -121,7 +121,7 @@ struct SnippetSwCache
void insert(const RTLIL::CaseRule *cs, vector<RTLIL::SwitchRule*> &sw_stack)
{
for (auto &action : cs->actions)
for (auto bit : action.first) {
for (auto bit : action.lhs) {
int sn = snippets->bit2snippet.at(bit, -1);
if (sn < 0)
continue;
@ -150,130 +150,138 @@ void apply_attrs(RTLIL::Cell *cell, const RTLIL::SwitchRule *sw, const RTLIL::Ca
cell->add_strpool_attribute(ID::src, cs->get_strpool_attribute(ID::src));
}
RTLIL::SigSpec gen_cmp(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::vector<RTLIL::SigSpec> &compare, RTLIL::SwitchRule *sw, RTLIL::CaseRule *cs, bool ifxmode)
{
std::stringstream sstr;
sstr << "$procmux$" << (autoidx++);
struct MuxGenCtx {
RTLIL::Module *mod;
const RTLIL::SigSpec &signal;
const std::vector<RTLIL::SigSpec> *compare;
RTLIL::Cell *last_mux_cell;
RTLIL::SwitchRule *sw;
RTLIL::CaseRule *cs;
bool ifxmode;
RTLIL::Wire *cmp_wire = mod->addWire(sstr.str() + "_CMP", 0);
RTLIL::SigSpec gen_cmp() {
std::stringstream sstr;
sstr << "$procmux$" << (autoidx++);
for (auto comp : compare)
{
RTLIL::SigSpec sig = signal;
RTLIL::Wire *cmp_wire = mod->addWire(sstr.str() + "_CMP", 0);
// get rid of don't-care bits
log_assert(sig.size() == comp.size());
for (int i = 0; i < comp.size(); i++)
if (comp[i] == RTLIL::State::Sa) {
sig.remove(i);
comp.remove(i--);
}
if (comp.size() == 0)
return RTLIL::SigSpec();
if (sig.size() == 1 && comp == RTLIL::SigSpec(1,1) && !ifxmode)
for (auto comp : *compare)
{
mod->connect(RTLIL::SigSig(RTLIL::SigSpec(cmp_wire, cmp_wire->width++), sig));
RTLIL::SigSpec sig = signal;
// get rid of don't-care bits
log_assert(sig.size() == comp.size());
for (int i = 0; i < comp.size(); i++)
if (comp[i] == RTLIL::State::Sa) {
sig.remove(i);
comp.remove(i--);
}
if (comp.size() == 0)
return RTLIL::SigSpec();
if (sig.size() == 1 && comp == RTLIL::SigSpec(1,1) && !ifxmode)
{
mod->connect(RTLIL::SigSig(RTLIL::SigSpec(cmp_wire, cmp_wire->width++), sig));
}
else
{
// create compare cell
RTLIL::Cell *eq_cell = mod->addCell(stringf("%s_CMP%d", sstr.str(), cmp_wire->width), ifxmode ? ID($eqx) : ID($eq));
apply_attrs(eq_cell, sw, cs);
eq_cell->parameters[ID::A_SIGNED] = RTLIL::Const(0);
eq_cell->parameters[ID::B_SIGNED] = RTLIL::Const(0);
eq_cell->parameters[ID::A_WIDTH] = RTLIL::Const(sig.size());
eq_cell->parameters[ID::B_WIDTH] = RTLIL::Const(comp.size());
eq_cell->parameters[ID::Y_WIDTH] = RTLIL::Const(1);
eq_cell->setPort(ID::A, sig);
eq_cell->setPort(ID::B, comp);
eq_cell->setPort(ID::Y, RTLIL::SigSpec(cmp_wire, cmp_wire->width++));
}
}
RTLIL::Wire *ctrl_wire;
if (cmp_wire->width == 1)
{
ctrl_wire = cmp_wire;
}
else
{
// create compare cell
RTLIL::Cell *eq_cell = mod->addCell(stringf("%s_CMP%d", sstr.str(), cmp_wire->width), ifxmode ? ID($eqx) : ID($eq));
apply_attrs(eq_cell, sw, cs);
ctrl_wire = mod->addWire(sstr.str() + "_CTRL");
eq_cell->parameters[ID::A_SIGNED] = RTLIL::Const(0);
eq_cell->parameters[ID::B_SIGNED] = RTLIL::Const(0);
// reduce cmp vector to one logic signal
RTLIL::Cell *any_cell = mod->addCell(sstr.str() + "_ANY", ID($reduce_or));
apply_attrs(any_cell, sw, cs);
eq_cell->parameters[ID::A_WIDTH] = RTLIL::Const(sig.size());
eq_cell->parameters[ID::B_WIDTH] = RTLIL::Const(comp.size());
eq_cell->parameters[ID::Y_WIDTH] = RTLIL::Const(1);
any_cell->parameters[ID::A_SIGNED] = RTLIL::Const(0);
any_cell->parameters[ID::A_WIDTH] = RTLIL::Const(cmp_wire->width);
any_cell->parameters[ID::Y_WIDTH] = RTLIL::Const(1);
eq_cell->setPort(ID::A, sig);
eq_cell->setPort(ID::B, comp);
eq_cell->setPort(ID::Y, RTLIL::SigSpec(cmp_wire, cmp_wire->width++));
any_cell->setPort(ID::A, cmp_wire);
any_cell->setPort(ID::Y, RTLIL::SigSpec(ctrl_wire));
}
return RTLIL::SigSpec(ctrl_wire);
}
RTLIL::Wire *ctrl_wire;
if (cmp_wire->width == 1)
{
ctrl_wire = cmp_wire;
}
else
{
ctrl_wire = mod->addWire(sstr.str() + "_CTRL");
RTLIL::SigSpec gen_mux(RTLIL::SigSpec when_signal, RTLIL::SigSpec else_signal) {
log_assert(when_signal.size() == else_signal.size());
// reduce cmp vector to one logic signal
RTLIL::Cell *any_cell = mod->addCell(sstr.str() + "_ANY", ID($reduce_or));
apply_attrs(any_cell, sw, cs);
std::stringstream sstr;
sstr << "$procmux$" << (autoidx++);
any_cell->parameters[ID::A_SIGNED] = RTLIL::Const(0);
any_cell->parameters[ID::A_WIDTH] = RTLIL::Const(cmp_wire->width);
any_cell->parameters[ID::Y_WIDTH] = RTLIL::Const(1);
// the trivial cases
if (compare->size() == 0 || when_signal == else_signal)
return when_signal;
any_cell->setPort(ID::A, cmp_wire);
any_cell->setPort(ID::Y, RTLIL::SigSpec(ctrl_wire));
// compare results
RTLIL::SigSpec ctrl_sig = gen_cmp();
if (ctrl_sig.size() == 0)
return when_signal;
log_assert(ctrl_sig.size() == 1);
// prepare multiplexer output signal
RTLIL::Wire *result_wire = mod->addWire(sstr.str() + "_Y", when_signal.size());
// create the multiplexer itself
RTLIL::Cell *mux_cell = mod->addCell(sstr.str(), ID($mux));
apply_attrs(mux_cell, sw, cs);
mux_cell->parameters[ID::WIDTH] = RTLIL::Const(when_signal.size());
mux_cell->setPort(ID::A, else_signal);
mux_cell->setPort(ID::B, when_signal);
mux_cell->setPort(ID::S, ctrl_sig);
mux_cell->setPort(ID::Y, RTLIL::SigSpec(result_wire));
last_mux_cell = mux_cell;
return RTLIL::SigSpec(result_wire);
}
return RTLIL::SigSpec(ctrl_wire);
}
void append_pmux(RTLIL::SigSpec when_signal) {
log_assert(last_mux_cell != NULL);
log_assert(when_signal.size() == last_mux_cell->getPort(ID::A).size());
RTLIL::SigSpec gen_mux(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::vector<RTLIL::SigSpec> &compare, RTLIL::SigSpec when_signal, RTLIL::SigSpec else_signal, RTLIL::Cell *&last_mux_cell, RTLIL::SwitchRule *sw, RTLIL::CaseRule *cs, bool ifxmode)
{
log_assert(when_signal.size() == else_signal.size());
if (when_signal == last_mux_cell->getPort(ID::A))
return;
std::stringstream sstr;
sstr << "$procmux$" << (autoidx++);
RTLIL::SigSpec ctrl_sig = gen_cmp();
log_assert(ctrl_sig.size() == 1);
last_mux_cell->type = ID($pmux);
// the trivial cases
if (compare.size() == 0 || when_signal == else_signal)
return when_signal;
RTLIL::SigSpec new_s = last_mux_cell->getPort(ID::S);
new_s.append(ctrl_sig);
last_mux_cell->setPort(ID::S, new_s);
// compare results
RTLIL::SigSpec ctrl_sig = gen_cmp(mod, signal, compare, sw, cs, ifxmode);
if (ctrl_sig.size() == 0)
return when_signal;
log_assert(ctrl_sig.size() == 1);
RTLIL::SigSpec new_b = last_mux_cell->getPort(ID::B);
new_b.append(when_signal);
last_mux_cell->setPort(ID::B, new_b);
// prepare multiplexer output signal
RTLIL::Wire *result_wire = mod->addWire(sstr.str() + "_Y", when_signal.size());
last_mux_cell->parameters[ID::S_WIDTH] = last_mux_cell->getPort(ID::S).size();
}
// create the multiplexer itself
RTLIL::Cell *mux_cell = mod->addCell(sstr.str(), ID($mux));
apply_attrs(mux_cell, sw, cs);
mux_cell->parameters[ID::WIDTH] = RTLIL::Const(when_signal.size());
mux_cell->setPort(ID::A, else_signal);
mux_cell->setPort(ID::B, when_signal);
mux_cell->setPort(ID::S, ctrl_sig);
mux_cell->setPort(ID::Y, RTLIL::SigSpec(result_wire));
last_mux_cell = mux_cell;
return RTLIL::SigSpec(result_wire);
}
void append_pmux(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::vector<RTLIL::SigSpec> &compare, RTLIL::SigSpec when_signal, RTLIL::Cell *last_mux_cell, RTLIL::SwitchRule *sw, RTLIL::CaseRule *cs, bool ifxmode)
{
log_assert(last_mux_cell != NULL);
log_assert(when_signal.size() == last_mux_cell->getPort(ID::A).size());
if (when_signal == last_mux_cell->getPort(ID::A))
return;
RTLIL::SigSpec ctrl_sig = gen_cmp(mod, signal, compare, sw, cs, ifxmode);
log_assert(ctrl_sig.size() == 1);
last_mux_cell->type = ID($pmux);
RTLIL::SigSpec new_s = last_mux_cell->getPort(ID::S);
new_s.append(ctrl_sig);
last_mux_cell->setPort(ID::S, new_s);
RTLIL::SigSpec new_b = last_mux_cell->getPort(ID::B);
new_b.append(when_signal);
last_mux_cell->setPort(ID::B, new_b);
last_mux_cell->parameters[ID::S_WIDTH] = last_mux_cell->getPort(ID::S).size();
}
};
const pool<SigBit> &get_full_case_bits(SnippetSwCache &swcache, RTLIL::SwitchRule *sw)
{
@ -290,7 +298,7 @@ const pool<SigBit> &get_full_case_bits(SnippetSwCache &swcache, RTLIL::SwitchRul
pool<SigBit> case_bits;
for (auto it : cs->actions) {
for (auto bit : it.first)
for (auto bit : it.lhs)
case_bits.insert(bit);
}
@ -317,20 +325,28 @@ const pool<SigBit> &get_full_case_bits(SnippetSwCache &swcache, RTLIL::SwitchRul
return swcache.full_case_bits_cache.at(sw);
}
struct MuxTreeContext {
RTLIL::Module* mod;
SnippetSwCache& swcache;
dict<RTLIL::SwitchRule*, bool> &swpara;
RTLIL::CaseRule *cs;
const RTLIL::SigSpec &sig;
RTLIL::SigSpec defval;
const bool ifxmode;
};
RTLIL::SigSpec signal_to_mux_tree(RTLIL::Module *mod, SnippetSwCache &swcache, dict<RTLIL::SwitchRule*, bool> &swpara,
RTLIL::CaseRule *cs, const RTLIL::SigSpec &sig, const RTLIL::SigSpec &defval, bool ifxmode)
RTLIL::SigSpec signal_to_mux_tree(MuxTreeContext ctx)
{
RTLIL::SigSpec result = defval;
RTLIL::SigSpec result = ctx.defval;
for (auto &action : cs->actions) {
sig.replace(action.first, action.second, &result);
action.first.remove2(sig, &action.second);
for (auto &action : ctx.cs->actions) {
ctx.sig.replace(action.lhs, action.rhs, &result);
action.lhs.remove2(ctx.sig, &action.rhs);
}
for (auto sw : cs->switches)
for (auto sw : ctx.cs->switches)
{
if (!swcache.check(sw))
if (!ctx.swcache.check(sw))
continue;
// detect groups of parallel cases
@ -338,7 +354,7 @@ RTLIL::SigSpec signal_to_mux_tree(RTLIL::Module *mod, SnippetSwCache &swcache, d
bool is_simple_parallel_case = true;
if (!sw->get_bool_attribute(ID::parallel_case)) {
if (!swpara.count(sw)) {
if (!ctx.swpara.count(sw)) {
pool<Const> case_values;
for (size_t i = 0; i < sw->cases.size(); i++) {
RTLIL::CaseRule *cs2 = sw->cases[i];
@ -354,9 +370,9 @@ RTLIL::SigSpec signal_to_mux_tree(RTLIL::Module *mod, SnippetSwCache &swcache, d
if (0)
not_simple_parallel_case:
is_simple_parallel_case = false;
swpara[sw] = is_simple_parallel_case;
ctx.swpara[sw] = is_simple_parallel_case;
} else {
is_simple_parallel_case = swpara.at(sw);
is_simple_parallel_case = ctx.swpara.at(sw);
}
}
@ -382,28 +398,40 @@ RTLIL::SigSpec signal_to_mux_tree(RTLIL::Module *mod, SnippetSwCache &swcache, d
for (auto pat : cs2->compare)
if (!pat.is_fully_const())
extra_group_for_next_case = true;
else if (!ifxmode)
else if (!ctx.ifxmode)
pool.take(pat);
}
}
// mask default bits that are irrelevant because the output is driven by a full case
const pool<SigBit> &full_case_bits = get_full_case_bits(swcache, sw);
for (int i = 0; i < GetSize(sig); i++)
if (full_case_bits.count(sig[i]))
const pool<SigBit> &full_case_bits = get_full_case_bits(ctx.swcache, sw);
for (int i = 0; i < GetSize(ctx.sig); i++)
if (full_case_bits.count(ctx.sig[i]))
result[i] = State::Sx;
// evaluate in reverse order to give the first entry the top priority
RTLIL::SigSpec initial_val = result;
RTLIL::Cell *last_mux_cell = NULL;
MuxGenCtx mux_gen_ctx {ctx.mod,
sw->signal,
nullptr,
nullptr,
sw,
nullptr,
ctx.ifxmode
};
// 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;
RTLIL::CaseRule *cs2 = sw->cases[case_idx];
RTLIL::SigSpec value = signal_to_mux_tree(mod, swcache, swpara, cs2, sig, initial_val, ifxmode);
if (last_mux_cell && pgroups[case_idx] == pgroups[case_idx+1])
append_pmux(mod, sw->signal, cs2->compare, value, last_mux_cell, sw, cs2, ifxmode);
else
result = gen_mux(mod, sw->signal, cs2->compare, value, result, last_mux_cell, sw, cs2, ifxmode);
MuxTreeContext new_ctx = ctx;
new_ctx.cs = sw->cases[case_idx];
new_ctx.defval = initial_val;
RTLIL::SigSpec value = signal_to_mux_tree(new_ctx);
mux_gen_ctx.cs = new_ctx.cs;
mux_gen_ctx.compare = &new_ctx.cs->compare;
if (mux_gen_ctx.last_mux_cell && pgroups[case_idx] == pgroups[case_idx+1]) {
mux_gen_ctx.append_pmux(value);
} else {
result = mux_gen_ctx.gen_mux(value, result);
}
}
}
@ -429,9 +457,17 @@ void proc_mux(RTLIL::Module *mod, RTLIL::Process *proc, bool ifxmode)
swcache.current_snippet = idx;
RTLIL::SigSpec sig = sigsnip.sigidx[idx];
log("%6d/%d: %s\n", ++cnt, GetSize(sigsnip.snippets), log_signal(sig));
log_debug("%6d/%d: %s\n", ++cnt, GetSize(sigsnip.snippets), log_signal(sig));
RTLIL::SigSpec value = signal_to_mux_tree(mod, swcache, swpara, &proc->root_case, sig, RTLIL::SigSpec(RTLIL::State::Sx, sig.size()), ifxmode);
RTLIL::SigSpec value = signal_to_mux_tree({
mod,
swcache,
swpara,
&proc->root_case,
sig,
RTLIL::SigSpec(RTLIL::State::Sx, sig.size()),
ifxmode
});
mod->connect(RTLIL::SigSig(sig, value));
}
}

View file

@ -66,8 +66,8 @@ struct PruneWorker
assigned.insert(sw_assigned.begin(), sw_assigned.end());
}
for (auto it = cs->actions.rbegin(); it != cs->actions.rend(); ) {
RTLIL::SigSpec lhs = sigmap(it->first);
RTLIL::SigSpec rhs = sigmap(it->second);
RTLIL::SigSpec lhs = sigmap(it->lhs);
RTLIL::SigSpec rhs = sigmap(it->rhs);
SigSpec new_lhs, new_rhs;
SigSpec conn_lhs, conn_rhs;
for (int i = 0; i < GetSize(lhs); i++) {
@ -93,8 +93,8 @@ struct PruneWorker
removed_count++;
it = decltype(cs->actions)::reverse_iterator(cs->actions.erase(it.base() - 1));
} else {
it->first = new_lhs;
it->second = new_rhs;
it->lhs = new_lhs;
it->rhs = new_rhs;
it++;
}
}

View file

@ -58,7 +58,7 @@ struct RomWorker
SigSpec lhs;
dict<SigBit, int> lhs_lookup;
for (auto &it: sw->cases[0]->actions) {
for (auto bit: it.first) {
for (auto bit: it.lhs) {
if (!lhs_lookup.count(bit)) {
lhs_lookup[bit] = GetSize(lhs);
lhs.append(bit);
@ -87,17 +87,17 @@ struct RomWorker
}
Const val = Const(State::Sm, GetSize(lhs));
for (auto &it: cs->actions) {
if (!it.second.is_fully_const()) {
if (!it.rhs.is_fully_const()) {
log_debug("rejecting switch: rhs not const\n");
return;
}
for (int i = 0; i < GetSize(it.first); i++) {
auto it2 = lhs_lookup.find(it.first[i]);
for (int i = 0; i < GetSize(it.lhs); i++) {
auto it2 = lhs_lookup.find(it.lhs[i]);
if (it2 == lhs_lookup.end()) {
log_debug("rejecting switch: lhs not uniform\n");
return;
}
val.set(it2->second, it.second[i].data);
val.set(it2->second, it.rhs[i].data);
}
}
for (auto bit: val) {
@ -193,19 +193,20 @@ struct RomWorker
delete cs;
sw->cases.clear();
sw->signal = sw->signal.extract(0, swsigbits);
Const action_src = mem.has_attribute(ID::src) ? mem.attributes[ID::src] : Const("");
if (abits == GetSize(sw->signal)) {
sw->signal = SigSpec();
RTLIL::CaseRule *cs = new RTLIL::CaseRule;
cs->actions.push_back(SigSig(lhs, rdata));
cs->actions.push_back({lhs, rdata});
sw->cases.push_back(cs);
} else {
sw->signal = sw->signal.extract_end(abits);
RTLIL::CaseRule *cs = new RTLIL::CaseRule;
cs->compare.push_back(Const(State::S0, GetSize(sw->signal)));
cs->actions.push_back(SigSig(lhs, rdata));
cs->actions.push_back({lhs, rdata});
sw->cases.push_back(cs);
RTLIL::CaseRule *cs2 = new RTLIL::CaseRule;
cs2->actions.push_back(SigSig(lhs, default_val));
cs2->actions.push_back({lhs, default_val});
sw->cases.push_back(cs2);
}

View file

@ -27,14 +27,6 @@
USING_YOSYS_NAMESPACE
YOSYS_NAMESPACE_BEGIN
static void transfer_attr (Cell* to, const Cell* from, const IdString& attr) {
if (from->has_attribute(attr))
to->attributes[attr] = from->attributes.at(attr);
}
static void transfer_src (Cell* to, const Cell* from) {
transfer_attr(to, from, ID::src);
}
void simplemap_not(RTLIL::Module *module, RTLIL::Cell *cell)
{
RTLIL::SigSpec sig_a = cell->getPort(ID::A);
@ -44,7 +36,7 @@ void simplemap_not(RTLIL::Module *module, RTLIL::Cell *cell)
for (int i = 0; i < GetSize(sig_y); i++) {
RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_NOT_));
transfer_src(gate, cell);
gate->transfer_src_attribute(cell);
gate->setPort(ID::A, sig_a[i]);
gate->setPort(ID::Y, sig_y[i]);
}
@ -104,7 +96,7 @@ void simplemap_bitop(RTLIL::Module *module, RTLIL::Cell *cell)
for (int i = 0; i < GetSize(sig_y); i++) {
RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type);
transfer_src(gate, cell);
gate->transfer_src_attribute(cell);
gate->setPort(ID::A, sig_a[i]);
gate->setPort(ID::B, sig_b[i]);
gate->setPort(ID::Y, sig_y[i]);
@ -155,7 +147,7 @@ void simplemap_reduce(RTLIL::Module *module, RTLIL::Cell *cell)
}
RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type);
transfer_src(gate, cell);
gate->transfer_src_attribute(cell);
gate->setPort(ID::A, sig_a[i]);
gate->setPort(ID::B, sig_a[i+1]);
gate->setPort(ID::Y, sig_t[i/2]);
@ -168,7 +160,7 @@ void simplemap_reduce(RTLIL::Module *module, RTLIL::Cell *cell)
if (cell->type == ID($reduce_xnor)) {
RTLIL::SigSpec sig_t = module->addWire(NEW_ID);
RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_NOT_));
transfer_src(gate, cell);
gate->transfer_src_attribute(cell);
gate->setPort(ID::A, sig_a);
gate->setPort(ID::Y, sig_t);
last_output_cell = gate;
@ -196,7 +188,7 @@ static void logic_reduce(RTLIL::Module *module, RTLIL::SigSpec &sig, RTLIL::Cell
}
RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_OR_));
transfer_src(gate, cell);
gate->transfer_src_attribute(cell);
gate->setPort(ID::A, sig[i]);
gate->setPort(ID::B, sig[i+1]);
gate->setPort(ID::Y, sig_t[i/2]);
@ -225,7 +217,7 @@ void simplemap_lognot(RTLIL::Module *module, RTLIL::Cell *cell)
}
RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_NOT_));
transfer_src(gate, cell);
gate->transfer_src_attribute(cell);
gate->setPort(ID::A, sig_a);
gate->setPort(ID::Y, sig_y);
}
@ -254,7 +246,7 @@ void simplemap_logbin(RTLIL::Module *module, RTLIL::Cell *cell)
log_assert(!gate_type.empty());
RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type);
transfer_src(gate, cell);
gate->transfer_src_attribute(cell);
gate->setPort(ID::A, sig_a);
gate->setPort(ID::B, sig_b);
gate->setPort(ID::Y, sig_y);
@ -270,19 +262,19 @@ void simplemap_eqne(RTLIL::Module *module, RTLIL::Cell *cell)
RTLIL::SigSpec xor_out = module->addWire(NEW_ID, max(GetSize(sig_a), GetSize(sig_b)));
RTLIL::Cell *xor_cell = module->addXor(NEW_ID, sig_a, sig_b, xor_out, is_signed);
transfer_src(xor_cell, cell);
xor_cell->transfer_src_attribute(cell);
simplemap_bitop(module, xor_cell);
module->remove(xor_cell);
RTLIL::SigSpec reduce_out = is_ne ? sig_y : module->addWire(NEW_ID);
RTLIL::Cell *reduce_cell = module->addReduceOr(NEW_ID, xor_out, reduce_out);
transfer_src(reduce_cell, cell);
reduce_cell->transfer_src_attribute(cell);
simplemap_reduce(module, reduce_cell);
module->remove(reduce_cell);
if (!is_ne) {
RTLIL::Cell *not_cell = module->addLogicNot(NEW_ID, reduce_out, sig_y);
transfer_src(not_cell, cell);
not_cell->transfer_src_attribute(cell);
simplemap_lognot(module, not_cell);
module->remove(not_cell);
}
@ -296,7 +288,7 @@ void simplemap_mux(RTLIL::Module *module, RTLIL::Cell *cell)
for (int i = 0; i < GetSize(sig_y); i++) {
RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_MUX_));
transfer_src(gate, cell);
gate->transfer_src_attribute(cell);
gate->setPort(ID::A, sig_a[i]);
gate->setPort(ID::B, sig_b[i]);
gate->setPort(ID::S, cell->getPort(ID::S));
@ -313,7 +305,7 @@ void simplemap_bwmux(RTLIL::Module *module, RTLIL::Cell *cell)
for (int i = 0; i < GetSize(sig_y); i++) {
RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_MUX_));
transfer_src(gate, cell);
gate->transfer_src_attribute(cell);
gate->setPort(ID::A, sig_a[i]);
gate->setPort(ID::B, sig_b[i]);
gate->setPort(ID::S, sig_s[i]);
@ -329,7 +321,7 @@ void simplemap_tribuf(RTLIL::Module *module, RTLIL::Cell *cell)
for (int i = 0; i < GetSize(sig_y); i++) {
RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_TBUF_));
transfer_src(gate, cell);
gate->transfer_src_attribute(cell);
gate->setPort(ID::A, sig_a[i]);
gate->setPort(ID::E, sig_e);
gate->setPort(ID::Y, sig_y[i]);
@ -347,7 +339,7 @@ void simplemap_bmux(RTLIL::Module *module, RTLIL::Cell *cell)
for (int i = 0; i < GetSize(new_data); i += width) {
for (int k = 0; k < width; k++) {
RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_MUX_));
transfer_src(gate, cell);
gate->transfer_src_attribute(cell);
gate->setPort(ID::A, data[i*2+k]);
gate->setPort(ID::B, data[i*2+width+k]);
gate->setPort(ID::S, sel[idx]);
@ -370,7 +362,7 @@ void simplemap_lut(RTLIL::Module *module, RTLIL::Cell *cell)
SigSpec new_lut_data = module->addWire(NEW_ID, GetSize(lut_data)/2);
for (int i = 0; i < GetSize(lut_data); i += 2) {
RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_MUX_));
transfer_src(gate, cell);
gate->transfer_src_attribute(cell);
gate->setPort(ID::A, lut_data[i]);
gate->setPort(ID::B, lut_data[i+1]);
gate->setPort(ID::S, lut_ctrl[idx]);