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:
parent
37875fdedf
commit
1eb696c786
19 changed files with 305 additions and 252 deletions
|
|
@ -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";
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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()) {
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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++;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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]);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue