mirror of
https://github.com/YosysHQ/yosys
synced 2025-08-25 04:26:01 +00:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
fe651922cb
73 changed files with 1321 additions and 444 deletions
|
@ -393,44 +393,112 @@ struct SetundefPass : public Pass {
|
|||
ffbits.insert(bit);
|
||||
}
|
||||
|
||||
for (auto wire : module->wires())
|
||||
auto process_initwires = [&]()
|
||||
{
|
||||
if (!wire->attributes.count("\\init"))
|
||||
continue;
|
||||
dict<Wire*, int> wire_weights;
|
||||
|
||||
for (auto bit : sigmap(wire))
|
||||
ffbits.erase(bit);
|
||||
|
||||
initwires.insert(wire);
|
||||
}
|
||||
|
||||
for (int wire_types = 0; wire_types < 2; wire_types++)
|
||||
for (auto wire : module->wires())
|
||||
for (auto wire : initwires)
|
||||
{
|
||||
if (wire->name[0] == (wire_types ? '\\' : '$'))
|
||||
next_wire:
|
||||
continue;
|
||||
int weight = 0;
|
||||
|
||||
for (auto bit : sigmap(wire))
|
||||
if (!ffbits.count(bit))
|
||||
goto next_wire;
|
||||
weight += ffbits.count(bit) ? +1 : -1;
|
||||
|
||||
for (auto bit : sigmap(wire))
|
||||
ffbits.erase(bit);
|
||||
|
||||
initwires.insert(wire);
|
||||
wire_weights[wire] = weight;
|
||||
}
|
||||
|
||||
for (auto wire : initwires)
|
||||
{
|
||||
Const &initval = wire->attributes["\\init"];
|
||||
initwires.sort([&](Wire *a, Wire *b) { return wire_weights.at(a) > wire_weights.at(b); });
|
||||
|
||||
for (int i = 0; i < GetSize(wire); i++)
|
||||
if (GetSize(initval) <= i)
|
||||
initval.bits.push_back(worker.next_bit());
|
||||
else if (initval.bits[i] == State::Sx)
|
||||
initval.bits[i] = worker.next_bit();
|
||||
for (auto wire : initwires)
|
||||
{
|
||||
Const &initval = wire->attributes["\\init"];
|
||||
initval.bits.resize(GetSize(wire), State::Sx);
|
||||
|
||||
for (int i = 0; i < GetSize(wire); i++) {
|
||||
SigBit bit = sigmap(SigBit(wire, i));
|
||||
if (initval[i] == State::Sx && ffbits.count(bit)) {
|
||||
initval[i] = worker.next_bit();
|
||||
ffbits.erase(bit);
|
||||
}
|
||||
}
|
||||
|
||||
if (initval.is_fully_undef())
|
||||
wire->attributes.erase("\\init");
|
||||
}
|
||||
|
||||
initwires.clear();
|
||||
};
|
||||
|
||||
for (int wire_types = 0; wire_types < 2; wire_types++)
|
||||
{
|
||||
// prioritize wires that already have an init attribute
|
||||
if (!ffbits.empty())
|
||||
{
|
||||
for (auto wire : module->wires())
|
||||
{
|
||||
if (wire->name[0] == (wire_types ? '\\' : '$'))
|
||||
continue;
|
||||
|
||||
if (!wire->attributes.count("\\init"))
|
||||
continue;
|
||||
|
||||
Const &initval = wire->attributes["\\init"];
|
||||
initval.bits.resize(GetSize(wire), State::Sx);
|
||||
|
||||
if (initval.is_fully_undef()) {
|
||||
wire->attributes.erase("\\init");
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int i = 0; i < GetSize(wire); i++)
|
||||
if (initval[i] != State::Sx)
|
||||
ffbits.erase(sigmap(SigBit(wire, i)));
|
||||
|
||||
initwires.insert(wire);
|
||||
}
|
||||
|
||||
process_initwires();
|
||||
}
|
||||
|
||||
// next consider wires that completely contain bits to be initialized
|
||||
if (!ffbits.empty())
|
||||
{
|
||||
for (auto wire : module->wires())
|
||||
{
|
||||
if (wire->name[0] == (wire_types ? '\\' : '$'))
|
||||
continue;
|
||||
|
||||
for (auto bit : sigmap(wire))
|
||||
if (!ffbits.count(bit))
|
||||
goto next_wire;
|
||||
|
||||
initwires.insert(wire);
|
||||
|
||||
next_wire:
|
||||
continue;
|
||||
}
|
||||
|
||||
process_initwires();
|
||||
}
|
||||
|
||||
// finally use whatever wire we can find.
|
||||
if (!ffbits.empty())
|
||||
{
|
||||
for (auto wire : module->wires())
|
||||
{
|
||||
if (wire->name[0] == (wire_types ? '\\' : '$'))
|
||||
continue;
|
||||
|
||||
for (auto bit : sigmap(wire))
|
||||
if (ffbits.count(bit))
|
||||
initwires.insert(wire);
|
||||
}
|
||||
|
||||
process_initwires();
|
||||
}
|
||||
}
|
||||
|
||||
log_assert(ffbits.empty());
|
||||
}
|
||||
|
||||
module->rewrite_sigspecs(worker);
|
||||
|
|
|
@ -52,7 +52,9 @@ struct TeePass : public Pass {
|
|||
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||
{
|
||||
std::vector<FILE*> backup_log_files, files_to_close;
|
||||
std::vector<std::ostream*> backup_log_streams;
|
||||
int backup_log_verbose_level = log_verbose_level;
|
||||
backup_log_streams = log_streams;
|
||||
backup_log_files = log_files;
|
||||
|
||||
size_t argidx;
|
||||
|
@ -60,6 +62,7 @@ struct TeePass : public Pass {
|
|||
{
|
||||
if (args[argidx] == "-q" && files_to_close.empty()) {
|
||||
log_files.clear();
|
||||
log_streams.clear();
|
||||
continue;
|
||||
}
|
||||
if ((args[argidx] == "-o" || args[argidx] == "-a") && argidx+1 < args.size()) {
|
||||
|
@ -89,6 +92,7 @@ struct TeePass : public Pass {
|
|||
for (auto cf : files_to_close)
|
||||
fclose(cf);
|
||||
log_files = backup_log_files;
|
||||
log_streams = backup_log_streams;
|
||||
throw;
|
||||
}
|
||||
|
||||
|
@ -97,6 +101,7 @@ struct TeePass : public Pass {
|
|||
|
||||
log_verbose_level = backup_log_verbose_level;
|
||||
log_files = backup_log_files;
|
||||
log_streams = backup_log_streams;
|
||||
}
|
||||
} TeePass;
|
||||
|
||||
|
|
|
@ -562,7 +562,8 @@ struct HierarchyPass : public Pass {
|
|||
log("In parametric designs, a module might exists in several variations with\n");
|
||||
log("different parameter values. This pass looks at all modules in the current\n");
|
||||
log("design an re-runs the language frontends for the parametric modules as\n");
|
||||
log("needed.\n");
|
||||
log("needed. It also resolves assignments to wired logic data types (wand/wor),\n");
|
||||
log("resolves positional module parameters, unroll array instances, and more.\n");
|
||||
log("\n");
|
||||
log(" -check\n");
|
||||
log(" also check the design hierarchy. this generates an error when\n");
|
||||
|
@ -943,62 +944,178 @@ struct HierarchyPass : public Pass {
|
|||
std::vector<Module*> design_modules = design->modules();
|
||||
|
||||
for (auto module : design_modules)
|
||||
for (auto cell : module->cells())
|
||||
{
|
||||
Module *m = design->module(cell->type);
|
||||
pool<Wire*> wand_wor_index;
|
||||
dict<Wire*, SigSpec> wand_map, wor_map;
|
||||
vector<SigSig> new_connections;
|
||||
|
||||
if (m == nullptr)
|
||||
continue;
|
||||
|
||||
if (m->get_blackbox_attribute() && !cell->parameters.empty() && m->get_bool_attribute("\\dynports")) {
|
||||
IdString new_m_name = m->derive(design, cell->parameters, true);
|
||||
if (new_m_name.empty())
|
||||
continue;
|
||||
if (new_m_name != m->name) {
|
||||
m = design->module(new_m_name);
|
||||
blackbox_derivatives.insert(m);
|
||||
for (auto wire : module->wires())
|
||||
{
|
||||
if (wire->get_bool_attribute("\\wand")) {
|
||||
wand_map[wire] = SigSpec();
|
||||
wand_wor_index.insert(wire);
|
||||
}
|
||||
if (wire->get_bool_attribute("\\wor")) {
|
||||
wor_map[wire] = SigSpec();
|
||||
wand_wor_index.insert(wire);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &conn : cell->connections())
|
||||
for (auto &conn : module->connections())
|
||||
{
|
||||
Wire *w = m->wire(conn.first);
|
||||
SigSig new_conn;
|
||||
int cursor = 0;
|
||||
|
||||
if (w == nullptr || w->port_id == 0)
|
||||
continue;
|
||||
|
||||
if (GetSize(conn.second) == 0)
|
||||
continue;
|
||||
|
||||
SigSpec sig = conn.second;
|
||||
|
||||
if (!keep_portwidths && GetSize(w) != GetSize(conn.second))
|
||||
for (auto c : conn.first.chunks())
|
||||
{
|
||||
if (GetSize(w) < GetSize(conn.second))
|
||||
{
|
||||
int n = GetSize(conn.second) - GetSize(w);
|
||||
if (!w->port_input && w->port_output)
|
||||
module->connect(sig.extract(GetSize(w), n), Const(0, n));
|
||||
sig.remove(GetSize(w), n);
|
||||
Wire *w = c.wire;
|
||||
SigSpec rhs = conn.second.extract(cursor, GetSize(c));
|
||||
|
||||
if (wand_wor_index.count(w) == 0) {
|
||||
new_conn.first.append(c);
|
||||
new_conn.second.append(rhs);
|
||||
} else {
|
||||
if (wand_map.count(w)) {
|
||||
SigSpec sig = SigSpec(State::S1, GetSize(w));
|
||||
sig.replace(c.offset, rhs);
|
||||
wand_map.at(w).append(sig);
|
||||
} else {
|
||||
SigSpec sig = SigSpec(State::S0, GetSize(w));
|
||||
sig.replace(c.offset, rhs);
|
||||
wor_map.at(w).append(sig);
|
||||
}
|
||||
}
|
||||
else
|
||||
cursor += GetSize(c);
|
||||
}
|
||||
new_connections.push_back(new_conn);
|
||||
}
|
||||
module->new_connections(new_connections);
|
||||
|
||||
for (auto cell : module->cells())
|
||||
{
|
||||
if (!cell->known())
|
||||
continue;
|
||||
|
||||
for (auto &conn : cell->connections())
|
||||
{
|
||||
if (!cell->output(conn.first))
|
||||
continue;
|
||||
|
||||
SigSpec new_sig;
|
||||
bool update_port = false;
|
||||
|
||||
for (auto c : conn.second.chunks())
|
||||
{
|
||||
int n = GetSize(w) - GetSize(conn.second);
|
||||
if (w->port_input && !w->port_output)
|
||||
sig.append(Const(0, n));
|
||||
else
|
||||
sig.append(module->addWire(NEW_ID, n));
|
||||
Wire *w = c.wire;
|
||||
|
||||
if (wand_wor_index.count(w) == 0) {
|
||||
new_sig.append(c);
|
||||
continue;
|
||||
}
|
||||
|
||||
Wire *t = module->addWire(NEW_ID, GetSize(c));
|
||||
new_sig.append(t);
|
||||
update_port = true;
|
||||
|
||||
if (wand_map.count(w)) {
|
||||
SigSpec sig = SigSpec(State::S1, GetSize(w));
|
||||
sig.replace(c.offset, t);
|
||||
wand_map.at(w).append(sig);
|
||||
} else {
|
||||
SigSpec sig = SigSpec(State::S0, GetSize(w));
|
||||
sig.replace(c.offset, t);
|
||||
wor_map.at(w).append(sig);
|
||||
}
|
||||
}
|
||||
|
||||
if (!conn.second.is_fully_const() || !w->port_input || w->port_output)
|
||||
log_warning("Resizing cell port %s.%s.%s from %d bits to %d bits.\n", log_id(module), log_id(cell),
|
||||
log_id(conn.first), GetSize(conn.second), GetSize(sig));
|
||||
cell->setPort(conn.first, sig);
|
||||
if (update_port)
|
||||
cell->setPort(conn.first, new_sig);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto w : wand_wor_index)
|
||||
{
|
||||
bool wand = wand_map.count(w);
|
||||
SigSpec sigs = wand ? wand_map.at(w) : wor_map.at(w);
|
||||
|
||||
if (GetSize(sigs) == 0)
|
||||
continue;
|
||||
|
||||
if (GetSize(w) == 1) {
|
||||
if (wand)
|
||||
module->addReduceAnd(NEW_ID, sigs, w);
|
||||
else
|
||||
module->addReduceOr(NEW_ID, sigs, w);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (w->port_output && !w->port_input && sig.has_const())
|
||||
log_error("Output port %s.%s.%s (%s) is connected to constants: %s\n",
|
||||
log_id(module), log_id(cell), log_id(conn.first), log_id(cell->type), log_signal(sig));
|
||||
SigSpec s = sigs.extract(0, GetSize(w));
|
||||
for (int i = GetSize(w); i < GetSize(sigs); i += GetSize(w)) {
|
||||
if (wand)
|
||||
s = module->And(NEW_ID, s, sigs.extract(i, GetSize(w)));
|
||||
else
|
||||
s = module->Or(NEW_ID, s, sigs.extract(i, GetSize(w)));
|
||||
}
|
||||
module->connect(w, s);
|
||||
}
|
||||
|
||||
for (auto cell : module->cells())
|
||||
{
|
||||
Module *m = design->module(cell->type);
|
||||
|
||||
if (m == nullptr)
|
||||
continue;
|
||||
|
||||
if (m->get_blackbox_attribute() && !cell->parameters.empty() && m->get_bool_attribute("\\dynports")) {
|
||||
IdString new_m_name = m->derive(design, cell->parameters, true);
|
||||
if (new_m_name.empty())
|
||||
continue;
|
||||
if (new_m_name != m->name) {
|
||||
m = design->module(new_m_name);
|
||||
blackbox_derivatives.insert(m);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &conn : cell->connections())
|
||||
{
|
||||
Wire *w = m->wire(conn.first);
|
||||
|
||||
if (w == nullptr || w->port_id == 0)
|
||||
continue;
|
||||
|
||||
if (GetSize(conn.second) == 0)
|
||||
continue;
|
||||
|
||||
SigSpec sig = conn.second;
|
||||
|
||||
if (!keep_portwidths && GetSize(w) != GetSize(conn.second))
|
||||
{
|
||||
if (GetSize(w) < GetSize(conn.second))
|
||||
{
|
||||
int n = GetSize(conn.second) - GetSize(w);
|
||||
if (!w->port_input && w->port_output)
|
||||
module->connect(sig.extract(GetSize(w), n), Const(0, n));
|
||||
sig.remove(GetSize(w), n);
|
||||
}
|
||||
else
|
||||
{
|
||||
int n = GetSize(w) - GetSize(conn.second);
|
||||
if (w->port_input && !w->port_output)
|
||||
sig.append(Const(0, n));
|
||||
else
|
||||
sig.append(module->addWire(NEW_ID, n));
|
||||
}
|
||||
|
||||
if (!conn.second.is_fully_const() || !w->port_input || w->port_output)
|
||||
log_warning("Resizing cell port %s.%s.%s from %d bits to %d bits.\n", log_id(module), log_id(cell),
|
||||
log_id(conn.first), GetSize(conn.second), GetSize(sig));
|
||||
cell->setPort(conn.first, sig);
|
||||
}
|
||||
|
||||
if (w->port_output && !w->port_input && sig.has_const())
|
||||
log_error("Output port %s.%s.%s (%s) is connected to constants: %s\n",
|
||||
log_id(module), log_id(cell), log_id(conn.first), log_id(cell->type), log_signal(sig));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -106,7 +106,7 @@ void rmunused_module_cells(Module *module, bool verbose)
|
|||
if (raw_bit.wire == nullptr)
|
||||
continue;
|
||||
auto bit = sigmap(raw_bit);
|
||||
if (bit.wire == nullptr)
|
||||
if (bit.wire == nullptr && ct_all.cell_known(cell->type))
|
||||
driver_driver_logs[raw_sigmap(raw_bit)].push_back(stringf("Driver-driver conflict "
|
||||
"for %s between cell %s.%s and constant %s in %s: Resolved using constant.",
|
||||
log_signal(raw_bit), log_id(cell), log_id(it2.first), log_signal(bit), log_id(module)));
|
||||
|
|
|
@ -299,8 +299,8 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
|
|||
sig_q = dff->getPort("\\Q");
|
||||
sig_c = dff->getPort("\\C");
|
||||
sig_e = dff->getPort("\\E");
|
||||
val_cp = RTLIL::Const(dff->type[6] == 'P', 1);
|
||||
val_ep = RTLIL::Const(dff->type[7] == 'P', 1);
|
||||
val_cp = RTLIL::Const(dff->type[7] == 'P', 1);
|
||||
val_ep = RTLIL::Const(dff->type[8] == 'P', 1);
|
||||
}
|
||||
else if (dff->type == "$ff") {
|
||||
sig_d = dff->getPort("\\D");
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
pattern shiftmul
|
||||
//
|
||||
// Optimize mul+shift pairs that result from expressions such as foo[s*W+:W]
|
||||
//
|
||||
|
||||
state <SigSpec> shamt
|
||||
|
||||
|
@ -49,12 +52,16 @@ code
|
|||
if (GetSize(port(shift, \Y)) > const_factor)
|
||||
reject;
|
||||
|
||||
int factor_bits = ceil_log2(const_factor);
|
||||
SigSpec mul_din = port(mul, const_factor_port == \A ? \B : \A);
|
||||
|
||||
if (GetSize(shamt) < factor_bits+GetSize(mul_din))
|
||||
reject;
|
||||
|
||||
did_something = true;
|
||||
log("shiftmul pattern in %s: shift=%s, mul=%s\n", log_id(module), log_id(shift), log_id(mul));
|
||||
|
||||
int new_const_factor_log2 = ceil_log2(const_factor);
|
||||
int new_const_factor = 1 << new_const_factor_log2;
|
||||
|
||||
int new_const_factor = 1 << factor_bits;
|
||||
SigSpec padding(State::Sx, new_const_factor-const_factor);
|
||||
SigSpec old_a = port(shift, \A), new_a;
|
||||
int trunc = 0;
|
||||
|
@ -73,7 +80,7 @@ code
|
|||
if (trunc > 0)
|
||||
new_a.remove(GetSize(new_a)-trunc, trunc);
|
||||
|
||||
SigSpec new_b = {port(mul, const_factor_port == \A ? \B : \A), SigSpec(State::S0, new_const_factor_log2)};
|
||||
SigSpec new_b = {mul_din, SigSpec(State::S0, factor_bits)};
|
||||
if (param(shift, \B_SIGNED).as_bool())
|
||||
new_b.append(State::S0);
|
||||
|
||||
|
|
|
@ -332,7 +332,7 @@ struct FmcombinePass : public Pass {
|
|||
|
||||
gate_cell = module->cell(gate_name);
|
||||
if (gate_cell == nullptr)
|
||||
log_cmd_error("Gold cell %s not found in module %s.\n", log_id(gate_name), log_id(module));
|
||||
log_cmd_error("Gate cell %s not found in module %s.\n", log_id(gate_name), log_id(module));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -351,7 +351,7 @@ struct FmcombinePass : public Pass {
|
|||
if (!gold_cell->parameters.empty())
|
||||
log_cmd_error("Gold cell has unresolved instance parameters.\n");
|
||||
if (!gate_cell->parameters.empty())
|
||||
log_cmd_error("Gold cell has unresolved instance parameters.\n");
|
||||
log_cmd_error("Gate cell has unresolved instance parameters.\n");
|
||||
|
||||
FmcombineWorker worker(design, gold_cell->type, opts);
|
||||
worker.generate();
|
||||
|
|
|
@ -88,6 +88,8 @@ struct SimInstance
|
|||
SimInstance(SimShared *shared, Module *module, Cell *instance = nullptr, SimInstance *parent = nullptr) :
|
||||
shared(shared), module(module), instance(instance), parent(parent), sigmap(module)
|
||||
{
|
||||
log_assert(module);
|
||||
|
||||
if (parent) {
|
||||
log_assert(parent->children.count(instance) == 0);
|
||||
parent->children[instance] = this;
|
||||
|
@ -848,6 +850,9 @@ struct SimPass : public Pass {
|
|||
|
||||
if (design->full_selection()) {
|
||||
top_mod = design->top_module();
|
||||
|
||||
if (!top_mod)
|
||||
log_cmd_error("Design has no top module, use the 'hierarchy' command to specify one.\n");
|
||||
} else {
|
||||
auto mods = design->selected_whole_modules();
|
||||
if (GetSize(mods) != 1)
|
||||
|
|
|
@ -58,12 +58,21 @@ struct MuxcoverWorker
|
|||
bool use_mux16;
|
||||
bool nodecode;
|
||||
|
||||
int cost_mux2;
|
||||
int cost_mux4;
|
||||
int cost_mux8;
|
||||
int cost_mux16;
|
||||
|
||||
MuxcoverWorker(Module *module) : module(module), sigmap(module)
|
||||
{
|
||||
use_mux4 = false;
|
||||
use_mux8 = false;
|
||||
use_mux16 = false;
|
||||
nodecode = false;
|
||||
cost_mux2 = COST_MUX2;
|
||||
cost_mux4 = COST_MUX4;
|
||||
cost_mux8 = COST_MUX8;
|
||||
cost_mux16 = COST_MUX16;
|
||||
decode_mux_counter = 0;
|
||||
}
|
||||
|
||||
|
@ -157,7 +166,7 @@ struct MuxcoverWorker
|
|||
if (std::get<2>(entry))
|
||||
return 0;
|
||||
|
||||
return COST_MUX2 / GetSize(std::get<1>(entry));
|
||||
return cost_mux2 / GetSize(std::get<1>(entry));
|
||||
}
|
||||
|
||||
void implement_decode_mux(SigBit ctrl_bit)
|
||||
|
@ -209,7 +218,7 @@ struct MuxcoverWorker
|
|||
mux.inputs.push_back(B);
|
||||
mux.selects.push_back(S1);
|
||||
|
||||
mux.cost += COST_MUX2;
|
||||
mux.cost += cost_mux2;
|
||||
mux.cost += find_best_cover(tree, A);
|
||||
mux.cost += find_best_cover(tree, B);
|
||||
|
||||
|
@ -247,7 +256,7 @@ struct MuxcoverWorker
|
|||
mux.selects.push_back(S1);
|
||||
mux.selects.push_back(T1);
|
||||
|
||||
mux.cost += COST_MUX4;
|
||||
mux.cost += cost_mux4;
|
||||
mux.cost += find_best_cover(tree, A);
|
||||
mux.cost += find_best_cover(tree, B);
|
||||
mux.cost += find_best_cover(tree, C);
|
||||
|
@ -310,7 +319,7 @@ struct MuxcoverWorker
|
|||
mux.selects.push_back(T1);
|
||||
mux.selects.push_back(U1);
|
||||
|
||||
mux.cost += COST_MUX8;
|
||||
mux.cost += cost_mux8;
|
||||
mux.cost += find_best_cover(tree, A);
|
||||
mux.cost += find_best_cover(tree, B);
|
||||
mux.cost += find_best_cover(tree, C);
|
||||
|
@ -414,7 +423,7 @@ struct MuxcoverWorker
|
|||
mux.selects.push_back(U1);
|
||||
mux.selects.push_back(V1);
|
||||
|
||||
mux.cost += COST_MUX16;
|
||||
mux.cost += cost_mux16;
|
||||
mux.cost += find_best_cover(tree, A);
|
||||
mux.cost += find_best_cover(tree, B);
|
||||
mux.cost += find_best_cover(tree, C);
|
||||
|
@ -569,9 +578,11 @@ struct MuxcoverPass : public Pass {
|
|||
log("\n");
|
||||
log("Cover trees of $_MUX_ cells with $_MUX{4,8,16}_ cells\n");
|
||||
log("\n");
|
||||
log(" -mux4, -mux8, -mux16\n");
|
||||
log(" Use the specified types of MUXes. If none of those options are used,\n");
|
||||
log(" the effect is the same as if all of them where used.\n");
|
||||
log(" -mux4[=cost], -mux8[=cost], -mux16[=cost]\n");
|
||||
log(" Use the specified types of MUXes (with optional integer costs). If none\n");
|
||||
log(" of these options are given, the effect is the same as if all of them are.\n");
|
||||
log(" Default costs: $_MUX_ = %d, $_MUX4_ = %d,\n", COST_MUX2, COST_MUX4);
|
||||
log(" $_MUX8_ = %d, $_MUX16_ = %d\n", COST_MUX8, COST_MUX16);
|
||||
log("\n");
|
||||
log(" -nodecode\n");
|
||||
log(" Do not insert decoder logic. This reduces the number of possible\n");
|
||||
|
@ -587,23 +598,39 @@ struct MuxcoverPass : public Pass {
|
|||
bool use_mux8 = false;
|
||||
bool use_mux16 = false;
|
||||
bool nodecode = false;
|
||||
int cost_mux4 = COST_MUX4;
|
||||
int cost_mux8 = COST_MUX8;
|
||||
int cost_mux16 = COST_MUX16;
|
||||
|
||||
size_t argidx;
|
||||
for (argidx = 1; argidx < args.size(); argidx++)
|
||||
{
|
||||
if (args[argidx] == "-mux4") {
|
||||
const auto &arg = args[argidx];
|
||||
if (arg.size() >= 5 && arg.substr(0,5) == "-mux4") {
|
||||
use_mux4 = true;
|
||||
if (arg.size() > 5) {
|
||||
if (arg[5] != '=') break;
|
||||
cost_mux4 = atoi(arg.substr(5).c_str());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-mux8") {
|
||||
if (arg.size() >= 5 && arg.substr(0,5) == "-mux8") {
|
||||
use_mux8 = true;
|
||||
if (arg.size() > 5) {
|
||||
if (arg[5] != '=') break;
|
||||
cost_mux8 = atoi(arg.substr(5).c_str());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-mux16") {
|
||||
if (arg.size() >= 6 && arg.substr(0,6) == "-mux16") {
|
||||
use_mux16 = true;
|
||||
if (arg.size() > 6) {
|
||||
if (arg[6] != '=') break;
|
||||
cost_mux16 = atoi(arg.substr(6).c_str());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-nodecode") {
|
||||
if (arg == "-nodecode") {
|
||||
nodecode = true;
|
||||
continue;
|
||||
}
|
||||
|
@ -623,6 +650,9 @@ struct MuxcoverPass : public Pass {
|
|||
worker.use_mux4 = use_mux4;
|
||||
worker.use_mux8 = use_mux8;
|
||||
worker.use_mux16 = use_mux16;
|
||||
worker.cost_mux4 = cost_mux4;
|
||||
worker.cost_mux8 = cost_mux8;
|
||||
worker.cost_mux16 = cost_mux16;
|
||||
worker.nodecode = nodecode;
|
||||
worker.run();
|
||||
}
|
||||
|
|
|
@ -606,6 +606,9 @@ struct ShregmapPass : public Pass {
|
|||
log(" -tech greenpak4\n");
|
||||
log(" map to greenpak4 shift registers.\n");
|
||||
log("\n");
|
||||
log(" -tech xilinx\n");
|
||||
log(" map to xilinx dynamic-length shift registers.\n");
|
||||
log("\n");
|
||||
}
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue