mirror of
https://github.com/YosysHQ/yosys
synced 2026-07-19 21:55:48 +00:00
WIP
This commit is contained in:
parent
afdae7b87e
commit
c3ffbf6fae
229 changed files with 3902 additions and 3835 deletions
|
|
@ -37,7 +37,7 @@ struct ExclusiveDatabase
|
|||
SigBit y_port;
|
||||
pool<Cell*> reduce_or;
|
||||
for (auto cell : module->cells()) {
|
||||
if (cell->type == ID($eq)) {
|
||||
if (cell->type == TW($eq)) {
|
||||
SigSpec y_sig = sigmap(cell->getPort(TW::Y));
|
||||
if (GetSize(y_sig) == 0)
|
||||
continue;
|
||||
|
|
@ -50,7 +50,7 @@ struct ExclusiveDatabase
|
|||
}
|
||||
y_port = y_sig[0];
|
||||
}
|
||||
else if (cell->type == ID($logic_not)) {
|
||||
else if (cell->type == TW($logic_not)) {
|
||||
SigSpec y_sig = sigmap(cell->getPort(TW::Y));
|
||||
if (GetSize(y_sig) == 0)
|
||||
continue;
|
||||
|
|
@ -58,7 +58,7 @@ struct ExclusiveDatabase
|
|||
const_sig = Const(State::S0, GetSize(nonconst_sig));
|
||||
y_port = y_sig[0];
|
||||
}
|
||||
else if (cell->type == ID($reduce_or)) {
|
||||
else if (cell->type == TW($reduce_or)) {
|
||||
reduce_or.insert(cell);
|
||||
continue;
|
||||
}
|
||||
|
|
@ -152,11 +152,11 @@ struct MuxpackWorker
|
|||
|
||||
for (auto cell : module->cells())
|
||||
{
|
||||
if (cell->type.in(ID($mux), ID($pmux)) && !cell->get_bool_attribute(ID::keep))
|
||||
if (cell->type.in(TW($mux), TW($pmux)) && !cell->get_bool_attribute(ID::keep))
|
||||
{
|
||||
SigSpec a_sig = sigmap(cell->getPort(TW::A));
|
||||
SigSpec b_sig;
|
||||
if (cell->type == ID($mux))
|
||||
if (cell->type == TW($mux))
|
||||
b_sig = sigmap(cell->getPort(TW::B));
|
||||
SigSpec y_sig = sigmap(cell->getPort(TW::Y));
|
||||
|
||||
|
|
@ -193,10 +193,10 @@ struct MuxpackWorker
|
|||
{
|
||||
for (auto cell : candidate_cells)
|
||||
{
|
||||
log_debug("Considering %s (%s)\n", cell, cell->type.unescape());
|
||||
log_debug("Considering %s (%s)\n", cell, cell->type.unescaped());
|
||||
|
||||
SigSpec a_sig = sigmap(cell->getPort(TW::A));
|
||||
if (cell->type == ID($mux)) {
|
||||
if (cell->type == TW($mux)) {
|
||||
SigSpec b_sig = sigmap(cell->getPort(TW::B));
|
||||
if (sig_chain_prev.count(a_sig) + sig_chain_prev.count(b_sig) != 1)
|
||||
goto start_cell;
|
||||
|
|
@ -204,7 +204,7 @@ struct MuxpackWorker
|
|||
if (!sig_chain_prev.count(a_sig))
|
||||
a_sig = b_sig;
|
||||
}
|
||||
else if (cell->type == ID($pmux)) {
|
||||
else if (cell->type == TW($pmux)) {
|
||||
if (!sig_chain_prev.count(a_sig))
|
||||
goto start_cell;
|
||||
}
|
||||
|
|
@ -289,7 +289,7 @@ struct MuxpackWorker
|
|||
s_sig.append(cursor_cell->getPort(TW::S));
|
||||
}
|
||||
else {
|
||||
log_assert(cursor_cell->type == ID($mux));
|
||||
log_assert(cursor_cell->type == TW($mux));
|
||||
b_sig.append(cursor_cell->getPort(TW::A));
|
||||
s_sig.append(module->LogicNot(NEW_TWINE, cursor_cell->getPort(TW::S)));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,10 +48,10 @@ struct OptBalanceTreeWorker {
|
|||
|
||||
// Calculate the "natural" output width for this operation
|
||||
int natural_width;
|
||||
if (cell_type == ID($add)) {
|
||||
if (cell_type == TW($add)) {
|
||||
// Addition produces max(A_WIDTH, B_WIDTH) + 1 (for carry bit)
|
||||
natural_width = std::max(a_width, b_width) + 1;
|
||||
} else if (cell_type == ID($mul)) {
|
||||
} else if (cell_type == TW($mul)) {
|
||||
// Multiplication produces A_WIDTH + B_WIDTH
|
||||
natural_width = a_width + b_width;
|
||||
} else {
|
||||
|
|
@ -84,9 +84,9 @@ struct OptBalanceTreeWorker {
|
|||
|
||||
// Create output wire
|
||||
int out_width = cell->getParam(ID::Y_WIDTH).as_int();
|
||||
if (cell_type == ID($add))
|
||||
if (cell_type == TW($add))
|
||||
out_width = max(sources[0].size(), sources[1].size()) + 1;
|
||||
else if (cell_type == ID($mul))
|
||||
else if (cell_type == TW($mul))
|
||||
out_width = sources[0].size() + sources[1].size();
|
||||
Wire* out_wire = module->addWire(NEW_TWINE, out_width);
|
||||
|
||||
|
|
@ -119,9 +119,9 @@ struct OptBalanceTreeWorker {
|
|||
|
||||
// Create output wire
|
||||
int out_width = cell->getParam(ID::Y_WIDTH).as_int();
|
||||
if (cell_type == ID($add))
|
||||
if (cell_type == TW($add))
|
||||
out_width = max(left_tree.size(), right_tree.size()) + 1;
|
||||
else if (cell_type == ID($mul))
|
||||
else if (cell_type == TW($mul))
|
||||
out_width = left_tree.size() + right_tree.size();
|
||||
Wire* out_wire = module->addWire(NEW_TWINE, out_width);
|
||||
|
||||
|
|
@ -344,14 +344,14 @@ struct OptBalanceTreePass : public Pass {
|
|||
|
||||
// Handle arguments
|
||||
size_t argidx;
|
||||
vector<IdString> cell_types = {ID($and), ID($or), ID($xor), ID($add), ID($mul)};
|
||||
vector<IdString> cell_types = {TW($and), TW($or), TW($xor), TW($add), TW($mul)};
|
||||
for (argidx = 1; argidx < args.size(); argidx++) {
|
||||
if (args[argidx] == "-arith") {
|
||||
cell_types = {ID($add), ID($mul)};
|
||||
cell_types = {TW($add), TW($mul)};
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-logic") {
|
||||
cell_types = {ID($and), ID($or), ID($xor)};
|
||||
cell_types = {TW($and), TW($or), TW($xor)};
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
|
@ -369,7 +369,7 @@ struct OptBalanceTreePass : public Pass {
|
|||
|
||||
// Log stats
|
||||
for (auto cell_type : cell_types)
|
||||
log("Converted %d %s cells into trees.\n", cell_count[cell_type], cell_type.unescape());
|
||||
log("Converted %d %s cells into trees.\n", cell_count[cell_type], design->twines.unescaped_str(cell_type));
|
||||
|
||||
// Clean up
|
||||
Yosys::run_pass("clean -purge");
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ struct ConflictLogs {
|
|||
// We could do this in parallel but hopefully this is rare.
|
||||
for (auto [_, cell] : mod->cells_) {
|
||||
for (auto &[port, sig] : cell->connections()) {
|
||||
if (clean_ctx.ct_all.cell_known(cell->type) && !clean_ctx.ct_all.cell_input(cell->type, port))
|
||||
if (clean_ctx.ct_all.cell_known(cell->type_impl) && !clean_ctx.ct_all.cell_input(cell->type_impl, port))
|
||||
continue;
|
||||
for (auto raw_bit : wire_map(sig))
|
||||
used_raw_bits.insert(raw_bit);
|
||||
|
|
@ -189,17 +189,17 @@ ConflictLogs explore(CellAnalysis& analysis, CellTraversal& traversal, const Sig
|
|||
actx.subpool.run([&analysis, &traversal, &logs, &wire_map, &mem2cells_vector, &wire2driver_builder, &actx, &clean_ctx](const ParallelDispatchThreadPool::RunCtx &ctx) {
|
||||
for (int i : ctx.item_range(actx.mod->cells_size())) {
|
||||
Cell *cell = actx.mod->cell_at(i);
|
||||
if (cell->type.in(ID($memwr), ID($memwr_v2), ID($meminit), ID($meminit_v2)))
|
||||
if (cell->type.in(TW($memwr), TW($memwr_v2), TW($meminit), TW($meminit_v2)))
|
||||
mem2cells_vector.insert(ctx, {cell->getParam(ID::MEMID).decode_string(), i});
|
||||
|
||||
for (auto &it2 : cell->connections()) {
|
||||
if (clean_ctx.ct_all.cell_known(cell->type) && !clean_ctx.ct_all.cell_output(cell->type, it2.first))
|
||||
if (clean_ctx.ct_all.cell_known(cell->type_impl) && !clean_ctx.ct_all.cell_output(cell->type_impl, it2.first))
|
||||
continue;
|
||||
for (auto raw_bit : it2.second) {
|
||||
if (raw_bit.wire == nullptr)
|
||||
continue;
|
||||
auto bit = actx.assign_map(raw_bit);
|
||||
if (bit.wire == nullptr && clean_ctx.ct_all.cell_known(cell->type)) {
|
||||
if (bit.wire == nullptr && clean_ctx.ct_all.cell_known(cell->type_impl)) {
|
||||
auto twines = cell->module->design->twines;
|
||||
std::string msg = stringf("Driver-driver conflict "
|
||||
"for %s between cell %s.%s and constant %s in %s: Resolved using constant.",
|
||||
|
|
@ -257,11 +257,11 @@ void fixup_unused_cells_and_mems(CellAnalysis& analysis, MemAnalysis& mem_analys
|
|||
for (auto cell_index : cell_indices) {
|
||||
Cell *cell = actx.mod->cell_at(cell_index);
|
||||
for (auto &it : cell->connections())
|
||||
if (!clean_ctx.ct_all.cell_known(cell->type) || clean_ctx.ct_all.cell_input(cell->type, it.first))
|
||||
if (!clean_ctx.ct_all.cell_known(cell->type_impl) || clean_ctx.ct_all.cell_input(cell->type_impl, it.first))
|
||||
for (auto bit : actx.assign_map(it.second))
|
||||
bits.insert(bit);
|
||||
|
||||
if (cell->type.in(ID($memrd), ID($memrd_v2))) {
|
||||
if (cell->type.in(TW($memrd), TW($memrd_v2))) {
|
||||
std::string mem_id = cell->getParam(ID::MEMID).decode_string();
|
||||
if (mem_analysis.indices.count(mem_id)) {
|
||||
int mem_index = mem_analysis.indices[mem_id];
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ USING_YOSYS_NAMESPACE
|
|||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
||||
bool is_signed(RTLIL::Cell* cell) {
|
||||
return cell->type == ID($pos) && cell->getParam(ID::A_SIGNED).as_bool();
|
||||
return cell->type == TW($pos) && cell->getParam(ID::A_SIGNED).as_bool();
|
||||
}
|
||||
|
||||
bool trim_buf(RTLIL::Cell* cell, ShardedVector<RTLIL::SigSig>& new_connections, const ParallelDispatchThreadPool::RunCtx &ctx) {
|
||||
|
|
@ -56,16 +56,16 @@ bool remove(ShardedVector<RTLIL::Cell*>& cells, RTLIL::Module* mod, bool verbose
|
|||
bool did_something = false;
|
||||
for (RTLIL::Cell *cell : cells) {
|
||||
if (verbose) {
|
||||
if (cell->type == ID($connect)) {
|
||||
if (cell->type == TW($connect)) {
|
||||
log_debug(" removing connect cell `%s': %s <-> %s\n", cell->name,
|
||||
log_signal(cell->getPort(TW::A)), log_signal(cell->getPort(TW::B)));
|
||||
} else if (cell->type == ID($input_port)) {
|
||||
} else if (cell->type == TW($input_port)) {
|
||||
log_debug(" removing input port marker cell `%s': %s\n", cell->name,
|
||||
log_signal(cell->getPort(TW::Y)));
|
||||
} else if (cell->type == ID($output_port)) {
|
||||
} else if (cell->type == TW($output_port)) {
|
||||
log_debug(" removing output port marker cell `%s': %s\n", cell->name,
|
||||
log_signal(cell->getPort(TW::A)));
|
||||
} else if (cell->type == ID($public)) {
|
||||
} else if (cell->type == TW($public)) {
|
||||
log_debug(" removing public wire marker cell `%s': %s\n", cell->name,
|
||||
log_signal(cell->getPort(TW::A)));
|
||||
} else {
|
||||
|
|
@ -89,17 +89,17 @@ void remove_temporary_cells(RTLIL::Module *module, ParallelDispatchThreadPool::S
|
|||
subpool.run([const_module, &delcells, &new_connections](const ParallelDispatchThreadPool::RunCtx &ctx) {
|
||||
for (int i : ctx.item_range(const_module->cells_size())) {
|
||||
RTLIL::Cell *cell = const_module->cell_at(i);
|
||||
if (cell->type.in(ID($pos), ID($_BUF_), ID($buf)) && !cell->has_keep_attr()) {
|
||||
if (cell->type.in(TW($pos), TW($_BUF_), TW($buf)) && !cell->has_keep_attr()) {
|
||||
if (trim_buf(cell, new_connections, ctx))
|
||||
delcells.insert(ctx, cell);
|
||||
} else if (cell->type.in(ID($connect)) && !cell->has_keep_attr()) {
|
||||
} else if (cell->type.in(TW($connect)) && !cell->has_keep_attr()) {
|
||||
RTLIL::SigSpec a = cell->getPort(TW::A);
|
||||
RTLIL::SigSpec b = cell->getPort(TW::B);
|
||||
if (a.has_const() && !b.has_const())
|
||||
std::swap(a, b);
|
||||
new_connections.insert(ctx, {a, b});
|
||||
delcells.insert(ctx, cell);
|
||||
} else if (cell->type.in(ID($input_port), ID($output_port), ID($public)) && !cell->has_keep_attr()) {
|
||||
} else if (cell->type.in(TW($input_port), TW($output_port), TW($public)) && !cell->has_keep_attr()) {
|
||||
delcells.insert(ctx, cell);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ ShardedVector<std::pair<SigBit, State>> build_inits(AnalysisContext& actx) {
|
|||
actx.subpool.run([&results, &actx](const ParallelDispatchThreadPool::RunCtx &ctx) {
|
||||
for (int i : ctx.item_range(actx.mod->cells_size())) {
|
||||
RTLIL::Cell *cell = actx.mod->cell_at(i);
|
||||
if (StaticCellTypes::Compat::internals_mem_ff(cell->type) && cell->hasPort(TW::Q))
|
||||
if (StaticCellTypes::Compat::internals_mem_ff(cell->type_impl) && cell->hasPort(TW::Q))
|
||||
{
|
||||
SigSpec sig = cell->getPort(TW::Q);
|
||||
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ struct KeepCache
|
|||
{
|
||||
if (keep_cell(cell, purge_mode))
|
||||
return true;
|
||||
if (cell->type.in(ID($specify2), ID($specify3), ID($specrule)))
|
||||
if (cell->type.in(TW($specify2), TW($specify3), TW($specrule)))
|
||||
return true;
|
||||
if (cell->module && cell->module->design) {
|
||||
RTLIL::Module *cell_module = cell->module->design->module(cell->type);
|
||||
|
|
@ -145,19 +145,19 @@ private:
|
|||
|
||||
static bool keep_cell(Cell *cell, bool purge_mode)
|
||||
{
|
||||
if (cell->type.in(ID($assert), ID($assume), ID($live), ID($fair), ID($cover)))
|
||||
if (cell->type.in(TW($assert), TW($assume), TW($live), TW($fair), TW($cover)))
|
||||
return true;
|
||||
|
||||
if (cell->type.in(ID($overwrite_tag)))
|
||||
if (cell->type.in(TW($overwrite_tag)))
|
||||
return true;
|
||||
|
||||
if (cell->type == ID($print) || cell->type == ID($check))
|
||||
if (cell->type == TW($print) || cell->type == TW($check))
|
||||
return true;
|
||||
|
||||
if (cell->has_keep_attr())
|
||||
return true;
|
||||
|
||||
if (!purge_mode && cell->type == ID($scopeinfo))
|
||||
if (!purge_mode && cell->type == TW($scopeinfo))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -251,20 +251,20 @@ struct SigConnKinds {
|
|||
for (int i : ctx.item_range(actx.mod->cells_size())) {
|
||||
RTLIL::Cell *cell = actx.mod->cell_at(i);
|
||||
if (!purge_mode) {
|
||||
if (clean_ctx.ct_reg(cell->type)) {
|
||||
if (clean_ctx.ct_reg(cell->type_impl)) {
|
||||
// Improve witness signal naming when clk2fflogic used
|
||||
// see commit message e36c71b5
|
||||
bool clk2fflogic = cell->get_bool_attribute(ID::clk2fflogic);
|
||||
for (auto &[port, sig] : cell->connections())
|
||||
if (clk2fflogic ? port == TW::D : clean_ctx.ct_all.cell_output(cell->type, port))
|
||||
if (clk2fflogic ? port == TW::D : clean_ctx.ct_all.cell_output(cell->type_impl, port))
|
||||
add_spec(raw_register_builder, ctx, sig);
|
||||
}
|
||||
for (auto &[_, sig] : cell->connections())
|
||||
add_spec(raw_cell_connected_builder, ctx, sig);
|
||||
}
|
||||
if (clean_ctx.ct_all.cell_known(cell->type))
|
||||
if (clean_ctx.ct_all.cell_known(cell->type_impl))
|
||||
for (auto &[port, sig] : cell->connections())
|
||||
if (clean_ctx.ct_all.cell_output(cell->type, port)) {
|
||||
if (clean_ctx.ct_all.cell_output(cell->type_impl, port)) {
|
||||
RTLIL::SigSpec spec = actx.assign_map(sig);
|
||||
unsigned int hash = spec.hash_into(Hasher()).yield();
|
||||
exact_cell_output_builder.insert(ctx, {std::move(spec), hash});
|
||||
|
|
@ -367,7 +367,7 @@ DeferredUpdates analyse_connectivity(UsedSignals& used, SigConnKinds& sig_analys
|
|||
deferred.update_connections.insert(ctx, {cell, port, spec});
|
||||
add_spec(raw_conn_builder, ctx, spec);
|
||||
add_spec(conn_builder, ctx, spec);
|
||||
if (!clean_ctx.ct_all.cell_output(cell->type, port))
|
||||
if (!clean_ctx.ct_all.cell_output(cell->type_impl, port))
|
||||
add_spec(used_builder, ctx, spec);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ void demorgan_worker(
|
|||
//TODO: Add support for reduce_xor
|
||||
//DeMorgan of XOR is either XOR (if even number of inputs) or XNOR (if odd number)
|
||||
|
||||
if( (cell->type != ID($reduce_and)) && (cell->type != ID($reduce_or)) )
|
||||
if( (cell->type != TW($reduce_and)) && (cell->type != TW($reduce_or)) )
|
||||
return;
|
||||
|
||||
auto insig = sigmap(cell->getPort(TW::A));
|
||||
|
|
@ -43,7 +43,7 @@ void demorgan_worker(
|
|||
if (GetSize(insig) < 1)
|
||||
return;
|
||||
|
||||
log("Inspecting %s cell %s (%d inputs)\n", cell->type.unescape(), cell->module->design->twines.str(cell->meta_->name), GetSize(insig));
|
||||
log("Inspecting %s cell %s (%d inputs)\n", cell->type.unescaped(), cell->module->design->twines.str(cell->meta_->name), GetSize(insig));
|
||||
int num_inverted = 0;
|
||||
for(int i=0; i<GetSize(insig); i++)
|
||||
{
|
||||
|
|
@ -55,7 +55,7 @@ void demorgan_worker(
|
|||
bool inverted = false;
|
||||
for(auto x : ports)
|
||||
{
|
||||
if(x.port == TW::Y && x.cell->type == ID($_NOT_))
|
||||
if(x.port == TW::Y && x.cell->type == TW($_NOT_))
|
||||
{
|
||||
inverted = true;
|
||||
break;
|
||||
|
|
@ -89,7 +89,7 @@ void demorgan_worker(
|
|||
RTLIL::Cell* srcinv = NULL;
|
||||
for(auto x : ports)
|
||||
{
|
||||
if(x.port == TW::Y && x.cell->type == ID($_NOT_))
|
||||
if(x.port == TW::Y && x.cell->type == TW($_NOT_))
|
||||
{
|
||||
srcinv = x.cell;
|
||||
break;
|
||||
|
|
@ -158,9 +158,9 @@ void demorgan_worker(
|
|||
cell->setPort(TW::A, insig);
|
||||
|
||||
//Change the cell type
|
||||
if(cell->type == ID($reduce_and))
|
||||
if(cell->type == TW($reduce_and))
|
||||
cell->type_impl = TW::$reduce_or;
|
||||
else if(cell->type == ID($reduce_or))
|
||||
else if(cell->type == TW($reduce_or))
|
||||
cell->type_impl = TW::$reduce_and;
|
||||
//don't change XOR
|
||||
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ struct OptDffWorker
|
|||
bitusers[bit]++;
|
||||
|
||||
for (auto cell : module->cells()) {
|
||||
if (cell->type.in(ID($mux), ID($pmux), ID($_MUX_))) {
|
||||
if (cell->type.in(TW($mux), TW($pmux), TW($_MUX_))) {
|
||||
RTLIL::SigSpec sig_y = sigmap(cell->getPort(TW::Y));
|
||||
for (int i = 0; i < GetSize(sig_y); i++)
|
||||
bit2mux[sig_y[i]] = cell_int_t(cell, i);
|
||||
|
|
@ -302,7 +302,7 @@ struct OptDffWorker
|
|||
initvals.remove_init(ff.sig_q[i]);
|
||||
module->connect(ff.sig_q[i], State::S0);
|
||||
log("Handling always-active CLR at position %d on %s (%s) from module %s (changing to const driver).\n",
|
||||
i, cell, cell->type.unescape(), module);
|
||||
i, cell, cell->type.unescaped(), module);
|
||||
sr_removed = true;
|
||||
} else if (is_always_active(ff.sig_set[i], ff.pol_set)) {
|
||||
initvals.remove_init(ff.sig_q[i]);
|
||||
|
|
@ -313,7 +313,7 @@ struct OptDffWorker
|
|||
else
|
||||
module->addNot(NEW_TWINE, ff.sig_clr[i], ff.sig_q[i]);
|
||||
log("Handling always-active SET at position %d on %s (%s) from module %s (changing to combinatorial circuit).\n",
|
||||
i, cell, cell->type.unescape(), module);
|
||||
i, cell, cell->type.unescaped(), module);
|
||||
sr_removed = true;
|
||||
} else {
|
||||
keep_bits.push_back(i);
|
||||
|
|
@ -336,7 +336,7 @@ struct OptDffWorker
|
|||
|
||||
if (clr_inactive && signal_all_same(ff.sig_set)) {
|
||||
log("Removing never-active CLR on %s (%s) from module %s.\n",
|
||||
cell, cell->type.unescape(), module);
|
||||
cell, cell->type.unescaped(), module);
|
||||
ff.has_sr = false;
|
||||
ff.has_arst = true;
|
||||
ff.pol_arst = ff.pol_set;
|
||||
|
|
@ -345,7 +345,7 @@ struct OptDffWorker
|
|||
changed = true;
|
||||
} else if (set_inactive && signal_all_same(ff.sig_clr)) {
|
||||
log("Removing never-active SET on %s (%s) from module %s.\n",
|
||||
cell, cell->type.unescape(), module);
|
||||
cell, cell->type.unescaped(), module);
|
||||
ff.has_sr = false;
|
||||
ff.has_arst = true;
|
||||
ff.pol_arst = ff.pol_clr;
|
||||
|
|
@ -371,7 +371,7 @@ struct OptDffWorker
|
|||
|
||||
if (!failed) {
|
||||
log("Converting CLR/SET to ARST on %s (%s) from module %s.\n",
|
||||
cell, cell->type.unescape(), module);
|
||||
cell, cell->type.unescaped(), module);
|
||||
ff.has_sr = false;
|
||||
ff.has_arst = true;
|
||||
ff.val_arst = val_arst_builder.build();
|
||||
|
|
@ -390,7 +390,7 @@ struct OptDffWorker
|
|||
// Converts constant Async Load to ARST
|
||||
if (is_always_inactive(ff.sig_aload, ff.pol_aload)) {
|
||||
log("Removing never-active async load on %s (%s) from module %s.\n",
|
||||
cell, cell->type.unescape(), module);
|
||||
cell, cell->type.unescaped(), module);
|
||||
ff.has_aload = false;
|
||||
changed = true;
|
||||
return false;
|
||||
|
|
@ -399,7 +399,7 @@ struct OptDffWorker
|
|||
if (is_active(ff.sig_aload, ff.pol_aload)) {
|
||||
// ALOAD always active
|
||||
log("Handling always-active async load on %s (%s) from module %s (changing to combinatorial circuit).\n",
|
||||
cell, cell->type.unescape(), module);
|
||||
cell, cell->type.unescaped(), module);
|
||||
ff.remove();
|
||||
|
||||
if (ff.has_sr) {
|
||||
|
|
@ -434,7 +434,7 @@ struct OptDffWorker
|
|||
// AD is constant -> ARST
|
||||
if (ff.sig_ad.is_fully_const() && !ff.has_arst && !ff.has_sr) {
|
||||
log("Changing const-value async load to async reset on %s (%s) from module %s.\n",
|
||||
cell, cell->type.unescape(), module);
|
||||
cell, cell->type.unescaped(), module);
|
||||
ff.has_arst = true;
|
||||
ff.has_aload = false;
|
||||
ff.sig_arst = ff.sig_aload;
|
||||
|
|
@ -451,12 +451,12 @@ struct OptDffWorker
|
|||
// Removes ARST if never active or replaces FF if always active
|
||||
if (is_inactive(ff.sig_arst, ff.pol_arst)) {
|
||||
log("Removing never-active ARST on %s (%s) from module %s.\n",
|
||||
cell, cell->type.unescape(), module);
|
||||
cell, cell->type.unescaped(), module);
|
||||
ff.has_arst = false;
|
||||
changed = true;
|
||||
} else if (is_always_active(ff.sig_arst, ff.pol_arst)) {
|
||||
log("Handling always-active ARST on %s (%s) from module %s (changing to const driver).\n",
|
||||
cell, cell->type.unescape(), module);
|
||||
cell, cell->type.unescaped(), module);
|
||||
ff.remove();
|
||||
module->connect(ff.sig_q, ff.val_arst);
|
||||
return true;
|
||||
|
|
@ -470,12 +470,12 @@ struct OptDffWorker
|
|||
// Removes SRST if never active or forces D to reset value if always active
|
||||
if (is_inactive(ff.sig_srst, ff.pol_srst)) {
|
||||
log("Removing never-active SRST on %s (%s) from module %s.\n",
|
||||
cell, cell->type.unescape(), module);
|
||||
cell, cell->type.unescaped(), module);
|
||||
ff.has_srst = false;
|
||||
changed = true;
|
||||
} else if (is_always_active(ff.sig_srst, ff.pol_srst)) {
|
||||
log("Handling always-active SRST on %s (%s) from module %s (changing to const D).\n",
|
||||
cell, cell->type.unescape(), module);
|
||||
cell, cell->type.unescaped(), module);
|
||||
ff.has_srst = false;
|
||||
if (!ff.ce_over_srst)
|
||||
ff.has_ce = false;
|
||||
|
|
@ -490,7 +490,7 @@ struct OptDffWorker
|
|||
if (is_always_inactive(ff.sig_ce, ff.pol_ce)) {
|
||||
if (ff.has_srst && !ff.ce_over_srst) {
|
||||
log("Handling never-active EN on %s (%s) from module %s (connecting SRST instead).\n",
|
||||
cell, cell->type.unescape(), module);
|
||||
cell, cell->type.unescaped(), module);
|
||||
ff.pol_ce = ff.pol_srst;
|
||||
ff.sig_ce = ff.sig_srst;
|
||||
ff.has_srst = false;
|
||||
|
|
@ -498,7 +498,7 @@ struct OptDffWorker
|
|||
changed = true;
|
||||
} else if (!opt.keepdc || ff.val_init.is_fully_def()) {
|
||||
log("Handling never-active EN on %s (%s) from module %s (removing D path).\n",
|
||||
cell, cell->type.unescape(), module);
|
||||
cell, cell->type.unescaped(), module);
|
||||
ff.has_ce = ff.has_clk = ff.has_srst = false;
|
||||
changed = true;
|
||||
} else {
|
||||
|
|
@ -508,7 +508,7 @@ struct OptDffWorker
|
|||
}
|
||||
} else if (is_active(ff.sig_ce, ff.pol_ce)) {
|
||||
log("Removing always-active EN on %s (%s) from module %s.\n",
|
||||
cell, cell->type.unescape(), module);
|
||||
cell, cell->type.unescaped(), module);
|
||||
ff.has_ce = false;
|
||||
changed = true;
|
||||
}
|
||||
|
|
@ -518,7 +518,7 @@ struct OptDffWorker
|
|||
{
|
||||
if (!opt.keepdc || ff.val_init.is_fully_def()) {
|
||||
log("Handling const CLK on %s (%s) from module %s (removing D path).\n",
|
||||
cell, cell->type.unescape(), module);
|
||||
cell, cell->type.unescaped(), module);
|
||||
ff.has_ce = ff.has_clk = ff.has_srst = false;
|
||||
changed = true;
|
||||
} else if (ff.has_ce || ff.has_srst || ff.sig_d != ff.sig_q) {
|
||||
|
|
@ -533,7 +533,7 @@ struct OptDffWorker
|
|||
// Detect feedback loops where D is hardwired to Q
|
||||
if (ff.has_clk && ff.has_srst) {
|
||||
log("Handling D = Q on %s (%s) from module %s (conecting SRST instead).\n",
|
||||
cell, cell->type.unescape(), module);
|
||||
cell, cell->type.unescaped(), module);
|
||||
if (ff.has_ce && ff.ce_over_srst) {
|
||||
SigSpec ce = ff.pol_ce ? ff.sig_ce : create_not(ff.sig_ce, ff.is_fine);
|
||||
SigSpec srst = ff.pol_srst ? ff.sig_srst : create_not(ff.sig_srst, ff.is_fine);
|
||||
|
|
@ -550,7 +550,7 @@ struct OptDffWorker
|
|||
changed = true;
|
||||
} else if (!opt.keepdc || ff.val_init.is_fully_def()) {
|
||||
log("Handling D = Q on %s (%s) from module %s (removing D path).\n",
|
||||
cell, cell->type.unescape(), module);
|
||||
cell, cell->type.unescaped(), module);
|
||||
ff.has_gclk = ff.has_clk = ff.has_ce = false;
|
||||
changed = true;
|
||||
}
|
||||
|
|
@ -623,7 +623,7 @@ struct OptDffWorker
|
|||
dff_cells.push_back(new_cell);
|
||||
|
||||
log("Adding SRST signal on %s (%s) from module %s (D = %s, Q = %s, rval = %s).\n",
|
||||
cell, cell->type.unescape(), module,
|
||||
cell, cell->type.unescaped(), module,
|
||||
log_signal(new_ff.sig_d), log_signal(new_ff.sig_q), log_signal(new_ff.val_srst));
|
||||
}
|
||||
|
||||
|
|
@ -693,7 +693,7 @@ struct OptDffWorker
|
|||
dff_cells.push_back(new_cell);
|
||||
|
||||
log("Adding EN signal on %s (%s) from module %s (D = %s, Q = %s).\n",
|
||||
cell, cell->type.unescape(), module,
|
||||
cell, cell->type.unescaped(), module,
|
||||
log_signal(new_ff.sig_d), log_signal(new_ff.sig_q));
|
||||
}
|
||||
|
||||
|
|
@ -760,7 +760,7 @@ struct OptDffWorker
|
|||
|
||||
if (ff.has_aload && !ff.has_clk && ff.sig_ad == ff.sig_q) {
|
||||
log("Handling AD = Q on %s (%s) from module %s (removing async load path).\n",
|
||||
cell, cell->type.unescape(), module);
|
||||
cell, cell->type.unescaped(), module);
|
||||
ff.has_aload = false;
|
||||
changed = true;
|
||||
}
|
||||
|
|
@ -878,7 +878,7 @@ struct OptDffWorker
|
|||
}
|
||||
|
||||
log("Setting constant %d-bit at position %d on %s (%s) from module %s.\n",
|
||||
val ? 1 : 0, i, cell, cell->type.unescape(), module);
|
||||
val ? 1 : 0, i, cell, cell->type.unescaped(), module);
|
||||
|
||||
// Replace the Q output with the constant value
|
||||
initvals.remove_init(ff.sig_q[i]);
|
||||
|
|
|
|||
|
|
@ -46,9 +46,9 @@ void replace_undriven(RTLIL::Module *module, const NewCellTypes &ct)
|
|||
|
||||
for (auto cell : module->cells())
|
||||
for (auto &conn : cell->connections()) {
|
||||
if (!ct.cell_known(cell->type) || ct.cell_output(cell->type, conn.first))
|
||||
if (!ct.cell_known(cell->type_impl) || ct.cell_output(cell->type_impl, conn.first))
|
||||
driven_signals.add(sigmap(conn.second));
|
||||
if (!ct.cell_known(cell->type) || ct.cell_input(cell->type, conn.first))
|
||||
if (!ct.cell_known(cell->type_impl) || ct.cell_input(cell->type_impl, conn.first))
|
||||
used_signals.add(sigmap(conn.second));
|
||||
}
|
||||
|
||||
|
|
@ -180,20 +180,20 @@ bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutativ
|
|||
int group_idx = GRP_DYN;
|
||||
RTLIL::SigBit bit_a = bits_a[i], bit_b = bits_b[i];
|
||||
|
||||
if (cell->type == ID($or)) {
|
||||
if (cell->type == TW($or)) {
|
||||
if (bit_a == RTLIL::State::S1 || bit_b == RTLIL::State::S1)
|
||||
bit_a = bit_b = RTLIL::State::S1;
|
||||
}
|
||||
else if (cell->type == ID($and)) {
|
||||
else if (cell->type == TW($and)) {
|
||||
if (bit_a == RTLIL::State::S0 || bit_b == RTLIL::State::S0)
|
||||
bit_a = bit_b = RTLIL::State::S0;
|
||||
}
|
||||
else if (!keepdc) {
|
||||
if (cell->type == ID($xor)) {
|
||||
if (cell->type == TW($xor)) {
|
||||
if (bit_a == bit_b)
|
||||
bit_a = bit_b = RTLIL::State::S0;
|
||||
}
|
||||
else if (cell->type == ID($xnor)) {
|
||||
else if (cell->type == TW($xnor)) {
|
||||
if (bit_a == bit_b)
|
||||
bit_a = bit_b = RTLIL::State::S1; // For consistency with gate-level which does $xnor -> $_XOR_ + $_NOT_
|
||||
}
|
||||
|
|
@ -257,15 +257,15 @@ bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutativ
|
|||
slot++;
|
||||
}
|
||||
|
||||
if (cell->type.in(ID($and), ID($or)) && kind == GRP_CONST_A) {
|
||||
if (cell->type.in(TW($and), TW($or)) && kind == GRP_CONST_A) {
|
||||
if (!keepdc) {
|
||||
if (cell->type == ID($and))
|
||||
if (cell->type == TW($and))
|
||||
new_a.replace(dict<SigBit,SigBit>{{State::Sx, State::S0}, {State::Sz, State::S0}}, &new_b);
|
||||
else if (cell->type == ID($or))
|
||||
else if (cell->type == TW($or))
|
||||
new_a.replace(dict<SigBit,SigBit>{{State::Sx, State::S1}, {State::Sz, State::S1}}, &new_b);
|
||||
else log_abort();
|
||||
}
|
||||
log_debug(" Direct Connection: %s (%s with %s)\n", log_signal(new_b), cell->type.unescape(), log_signal(new_a));
|
||||
log_debug(" Direct Connection: %s (%s with %s)\n", log_signal(new_b), cell->type.unescaped(), log_signal(new_a));
|
||||
// new_y becomes new_b directly: rewrite any bit_map entries pointing at new_y bits.
|
||||
dict<SigBit, SigBit> remap;
|
||||
for (int j = 0; j < group_size; j++)
|
||||
|
|
@ -277,26 +277,26 @@ bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutativ
|
|||
continue;
|
||||
}
|
||||
|
||||
if (cell->type.in(ID($xor), ID($xnor)) && kind == GRP_CONST_A) {
|
||||
if (cell->type.in(TW($xor), TW($xnor)) && kind == GRP_CONST_A) {
|
||||
SigSpec undef_a, undef_y, undef_b;
|
||||
SigSpec def_y, def_a, def_b;
|
||||
for (int j = 0; j < GetSize(new_y); j++) {
|
||||
bool undef = new_a[j] == State::Sx || new_a[j] == State::Sz;
|
||||
if (!keepdc && (undef || new_a[j] == new_b[j])) {
|
||||
undef_a.append(new_a[j]);
|
||||
if (cell->type == ID($xor))
|
||||
if (cell->type == TW($xor))
|
||||
undef_b.append(State::S0);
|
||||
// For consistency since simplemap does $xnor -> $_XOR_ + $_NOT_
|
||||
else if (cell->type == ID($xnor))
|
||||
else if (cell->type == TW($xnor))
|
||||
undef_b.append(State::S1);
|
||||
else log_abort();
|
||||
undef_y.append(new_y[j]);
|
||||
}
|
||||
else if (new_a[j] == State::S0 || new_a[j] == State::S1) {
|
||||
undef_a.append(new_a[j]);
|
||||
if (cell->type == ID($xor))
|
||||
if (cell->type == TW($xor))
|
||||
undef_b.append(new_a[j] == State::S1 ? patcher.Not(NEW_TWINE, new_b[j]).as_bit() : new_b[j]);
|
||||
else if (cell->type == ID($xnor))
|
||||
else if (cell->type == TW($xnor))
|
||||
undef_b.append(new_a[j] == State::S1 ? new_b[j] : patcher.Not(NEW_TWINE, new_b[j]).as_bit());
|
||||
else log_abort();
|
||||
undef_y.append(new_y[j]);
|
||||
|
|
@ -308,7 +308,7 @@ bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutativ
|
|||
}
|
||||
}
|
||||
if (!undef_y.empty()) {
|
||||
log_debug(" Direct Connection: %s (%s with %s)\n", log_signal(undef_b), cell->type.unescape(), log_signal(undef_a));
|
||||
log_debug(" Direct Connection: %s (%s with %s)\n", log_signal(undef_b), cell->type.unescaped(), log_signal(undef_a));
|
||||
dict<SigBit, SigBit> remap;
|
||||
for (int j = 0; j < GetSize(undef_y); j++)
|
||||
remap[undef_y[j]] = undef_b[j];
|
||||
|
|
@ -324,7 +324,7 @@ bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutativ
|
|||
new_y = std::move(def_y);
|
||||
}
|
||||
|
||||
RTLIL::Cell *c = patcher.addCell(NEW_TWINE, cell->type);
|
||||
RTLIL::Cell *c = patcher.addCell(NEW_TWINE, cell->type_impl);
|
||||
|
||||
c->setPort(TW::A, new_a);
|
||||
c->parameters[ID::A_WIDTH] = new_a.size();
|
||||
|
|
@ -362,7 +362,7 @@ std::optional<SigBit> get_inverted_raw(SigBit s)
|
|||
if (!s.is_wire() || !s.wire->known_driver())
|
||||
return std::nullopt;
|
||||
Cell* cell = s.wire->driverCell();
|
||||
if (!cell->type.in(ID($_NOT_), ID($not), ID($logic_not)))
|
||||
if (!cell->type.in(TW($_NOT_), TW($not), TW($logic_not)))
|
||||
return std::nullopt;
|
||||
if (GetSize(cell->getPort(TW::A)) != 1 || GetSize(cell->getPort(TW::Y)) != 1)
|
||||
return std::nullopt;
|
||||
|
|
@ -385,8 +385,9 @@ void handle_polarity_inv(Cell *cell, TwineRef port, IdString param, const SigMap
|
|||
SigBit sig = assign_map(raw);
|
||||
if (auto inv_a = get_inverted_raw(sig)) {
|
||||
SigBit new_sig = assign_map(*inv_a);
|
||||
auto twines = cell->module->design->twines;
|
||||
log_debug("Inverting %s of %s cell `%s' in module `%s': %s -> %s\n",
|
||||
IdString(RTLIL::StaticId(port)).unescape(), cell->type.unescape(), cell, cell->module,
|
||||
twines.unescaped_str(port), cell->type.unescaped(), cell, cell->module,
|
||||
log_signal(sig), log_signal(new_sig));
|
||||
cell->setPort(port, new_sig);
|
||||
cell->setParam(param, !cell->getParam(param).as_bool());
|
||||
|
|
@ -413,10 +414,11 @@ void handle_clkpol_celltype_swap(Cell *cell, string type1, string type2, TwineRe
|
|||
|
||||
if (cell->type.in(type1, type2)) {
|
||||
SigSpec sig = assign_map(cell->getPort(port));
|
||||
auto twines = cell->module->design->twines;
|
||||
if (auto inv_a = get_inverted_raw(sig)) {
|
||||
SigSpec new_sig = assign_map(*inv_a);
|
||||
log_debug("Inverting %s of %s cell `%s' in module `%s': %s -> %s\n",
|
||||
IdString(RTLIL::StaticId(port)).unescape(), cell->type.unescape(), cell, cell->module,
|
||||
twines.unescaped_str(port), cell->type.unescaped(), cell, cell->module,
|
||||
log_signal(sig), log_signal(new_sig));
|
||||
cell->setPort(port, new_sig);
|
||||
cell->type_impl = cell->module->design->twines.add(Twine{cell->type == type1 ? type2 : type1});
|
||||
|
|
@ -480,27 +482,27 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
if (!noclkinv)
|
||||
for (auto cell : dirty_cells)
|
||||
if (design->selected(module, cell)) {
|
||||
if (cell->type.in(ID($dff), ID($dffe), ID($dffsr), ID($dffsre), ID($adff), ID($adffe), ID($aldff), ID($aldffe), ID($sdff), ID($sdffe), ID($sdffce), ID($fsm), ID($memrd), ID($memrd_v2), ID($memwr), ID($memwr_v2)))
|
||||
if (cell->type.in(TW($dff), TW($dffe), TW($dffsr), TW($dffsre), TW($adff), TW($adffe), TW($aldff), TW($aldffe), TW($sdff), TW($sdffe), TW($sdffce), TW($fsm), TW($memrd), TW($memrd_v2), TW($memwr), TW($memwr_v2)))
|
||||
handle_polarity_inv(cell, TW::CLK, ID::CLK_POLARITY, assign_map);
|
||||
|
||||
if (cell->type.in(ID($sr), ID($dffsr), ID($dffsre), ID($dlatchsr))) {
|
||||
if (cell->type.in(TW($sr), TW($dffsr), TW($dffsre), TW($dlatchsr))) {
|
||||
handle_polarity_inv(cell, TW::SET, ID::SET_POLARITY, assign_map);
|
||||
handle_polarity_inv(cell, TW::CLR, ID::CLR_POLARITY, assign_map);
|
||||
}
|
||||
|
||||
if (cell->type.in(ID($adff), ID($adffe), ID($adlatch)))
|
||||
if (cell->type.in(TW($adff), TW($adffe), TW($adlatch)))
|
||||
handle_polarity_inv(cell, TW::ARST, ID::ARST_POLARITY, assign_map);
|
||||
|
||||
if (cell->type.in(ID($aldff), ID($aldffe)))
|
||||
if (cell->type.in(TW($aldff), TW($aldffe)))
|
||||
handle_polarity_inv(cell, TW::ALOAD, ID::ALOAD_POLARITY, assign_map);
|
||||
|
||||
if (cell->type.in(ID($sdff), ID($sdffe), ID($sdffce)))
|
||||
if (cell->type.in(TW($sdff), TW($sdffe), TW($sdffce)))
|
||||
handle_polarity_inv(cell, TW::SRST, ID::SRST_POLARITY, assign_map);
|
||||
|
||||
if (cell->type.in(ID($dffe), ID($adffe), ID($aldffe), ID($sdffe), ID($sdffce), ID($dffsre), ID($dlatch), ID($adlatch), ID($dlatchsr)))
|
||||
if (cell->type.in(TW($dffe), TW($adffe), TW($aldffe), TW($sdffe), TW($sdffce), TW($dffsre), TW($dlatch), TW($adlatch), TW($dlatchsr)))
|
||||
handle_polarity_inv(cell, TW::EN, ID::EN_POLARITY, assign_map);
|
||||
|
||||
if (!StaticCellTypes::Compat::stdcells_mem(cell->type))
|
||||
if (!StaticCellTypes::Compat::stdcells_mem(cell->type_impl))
|
||||
continue;
|
||||
|
||||
handle_clkpol_celltype_swap(cell, "$_SR_N?_", "$_SR_P?_", TW::S, assign_map);
|
||||
|
|
@ -560,19 +562,19 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
dict<RTLIL::SigBit, Cell*> outbit_to_cell;
|
||||
|
||||
for (auto cell : dirty_cells)
|
||||
if (design->selected(module, cell) && yosys_celltypes.cell_evaluable(cell->type)) {
|
||||
if (design->selected(module, cell) && yosys_celltypes.cell_evaluable(cell->type_impl)) {
|
||||
for (auto &conn : cell->connections())
|
||||
if (yosys_celltypes.cell_output(cell->type, conn.first))
|
||||
if (yosys_celltypes.cell_output(cell->type_impl, conn.first))
|
||||
for (auto bit : assign_map(conn.second))
|
||||
outbit_to_cell[bit] = cell;
|
||||
cells.node(cell);
|
||||
}
|
||||
|
||||
for (auto cell : dirty_cells)
|
||||
if (design->selected(module, cell) && yosys_celltypes.cell_evaluable(cell->type)) {
|
||||
if (design->selected(module, cell) && yosys_celltypes.cell_evaluable(cell->type_impl)) {
|
||||
const int r_index = cells.node(cell);
|
||||
for (auto &conn : cell->connections())
|
||||
if (yosys_celltypes.cell_input(cell->type, conn.first))
|
||||
if (yosys_celltypes.cell_input(cell->type_impl, conn.first))
|
||||
for (auto bit : assign_map(conn.second))
|
||||
if (outbit_to_cell.count(bit))
|
||||
cells.edge(cells.node(outbit_to_cell.at(bit)), r_index);
|
||||
|
|
@ -594,16 +596,16 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
bool detect_const_and = false;
|
||||
bool detect_const_or = false;
|
||||
|
||||
if (cell->type.in(ID($reduce_and), ID($_AND_)))
|
||||
if (cell->type.in(TW($reduce_and), TW($_AND_)))
|
||||
detect_const_and = true;
|
||||
|
||||
if (cell->type.in(ID($and), ID($logic_and)) && GetSize(cell->getPort(TW::A)) == 1 && GetSize(cell->getPort(TW::B)) == 1 && !cell->getParam(ID::A_SIGNED).as_bool())
|
||||
if (cell->type.in(TW($and), TW($logic_and)) && GetSize(cell->getPort(TW::A)) == 1 && GetSize(cell->getPort(TW::B)) == 1 && !cell->getParam(ID::A_SIGNED).as_bool())
|
||||
detect_const_and = true;
|
||||
|
||||
if (cell->type.in(ID($reduce_or), ID($reduce_bool), ID($_OR_)))
|
||||
if (cell->type.in(TW($reduce_or), TW($reduce_bool), TW($_OR_)))
|
||||
detect_const_or = true;
|
||||
|
||||
if (cell->type.in(ID($or), ID($logic_or)) && GetSize(cell->getPort(TW::A)) == 1 && GetSize(cell->getPort(TW::B)) == 1 && !cell->getParam(ID::A_SIGNED).as_bool())
|
||||
if (cell->type.in(TW($or), TW($logic_or)) && GetSize(cell->getPort(TW::A)) == 1 && GetSize(cell->getPort(TW::B)) == 1 && !cell->getParam(ID::A_SIGNED).as_bool())
|
||||
detect_const_or = true;
|
||||
|
||||
if (detect_const_and || detect_const_or)
|
||||
|
|
@ -656,17 +658,17 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
}
|
||||
}
|
||||
|
||||
if (cell->type.in(ID($_XOR_), ID($_XNOR_)) || (cell->type.in(ID($xor), ID($xnor)) && GetSize(cell->getPort(TW::A)) == 1 && GetSize(cell->getPort(TW::B)) == 1 && !cell->getParam(ID::A_SIGNED).as_bool()))
|
||||
if (cell->type.in(TW($_XOR_), TW($_XNOR_)) || (cell->type.in(TW($xor), TW($xnor)) && GetSize(cell->getPort(TW::A)) == 1 && GetSize(cell->getPort(TW::B)) == 1 && !cell->getParam(ID::A_SIGNED).as_bool()))
|
||||
{
|
||||
SigBit sig_a = assign_map(cell->getPort(TW::A));
|
||||
SigBit sig_b = assign_map(cell->getPort(TW::B));
|
||||
if (!keepdc && (sig_a == sig_b || sig_a == State::Sx || sig_a == State::Sz || sig_b == State::Sx || sig_b == State::Sz)) {
|
||||
OptExprPatcher patcher(module, &assign_map);
|
||||
if (cell->type.in(ID($xor), ID($_XOR_))) {
|
||||
if (cell->type.in(TW($xor), TW($_XOR_))) {
|
||||
patcher.patch(cell, TW::Y, RTLIL::State::S0, "const_xor");
|
||||
goto next_cell;
|
||||
}
|
||||
if (cell->type.in(ID($xnor), ID($_XNOR_))) {
|
||||
if (cell->type.in(TW($xnor), TW($_XNOR_))) {
|
||||
// For consistency since simplemap does $xnor -> $_XOR_ + $_NOT_
|
||||
int width = GetSize(cell->getPort(TW::Y));
|
||||
patcher.patch(cell, TW::Y, SigSpec(RTLIL::State::S1, width), "const_xnor");
|
||||
|
|
@ -679,9 +681,9 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
std::swap(sig_a, sig_b);
|
||||
if (sig_b == State::S0 || sig_b == State::S1) {
|
||||
OptExprPatcher patcher(module, &assign_map);
|
||||
bool is_gate = cell->type.in(ID($_XOR_), ID($_XNOR_));
|
||||
bool is_gate = cell->type.in(TW($_XOR_), TW($_XNOR_));
|
||||
int width = is_gate ? 1 : cell->getParam(ID::Y_WIDTH).as_int();
|
||||
if (cell->type.in(ID($xor), ID($_XOR_))) {
|
||||
if (cell->type.in(TW($xor), TW($_XOR_))) {
|
||||
if (sig_b == State::S0) {
|
||||
SigSpec sig_y = sig_a;
|
||||
sig_y.append(RTLIL::Const(State::S0, width-1));
|
||||
|
|
@ -693,7 +695,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
}
|
||||
goto next_cell;
|
||||
}
|
||||
if (cell->type.in(ID($xnor), ID($_XNOR_))) {
|
||||
if (cell->type.in(TW($xnor), TW($_XNOR_))) {
|
||||
if (sig_b == State::S1) {
|
||||
SigSpec sig_y = sig_a;
|
||||
sig_y.append(RTLIL::Const(State::S1, width-1));
|
||||
|
|
@ -709,10 +711,10 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
}
|
||||
}
|
||||
|
||||
if (cell->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_bool), ID($reduce_xor), ID($reduce_xnor), ID($neg)) &&
|
||||
if (cell->type.in(TW($reduce_and), TW($reduce_or), TW($reduce_bool), TW($reduce_xor), TW($reduce_xnor), TW($neg)) &&
|
||||
GetSize(cell->getPort(TW::A)) == 1 && GetSize(cell->getPort(TW::Y)) == 1)
|
||||
{
|
||||
if (cell->type == ID($reduce_xnor)) {
|
||||
if (cell->type == TW($reduce_xnor)) {
|
||||
log_debug("Replacing %s cell `%s' in module `%s' with $not cell.\n",
|
||||
cell->type.unescape(), cell->module->design->twines.str(cell->meta_->name), module);
|
||||
cell->type_impl = TW::$not;
|
||||
|
|
@ -724,7 +726,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
goto next_cell;
|
||||
}
|
||||
|
||||
if (cell->type.in(ID($and), ID($or), ID($xor), ID($xnor)))
|
||||
if (cell->type.in(TW($and), TW($or), TW($xor), TW($xnor)))
|
||||
{
|
||||
RTLIL::SigSpec sig_a = assign_map(cell->getPort(TW::A));
|
||||
RTLIL::SigSpec sig_b = assign_map(cell->getPort(TW::B));
|
||||
|
|
@ -750,8 +752,8 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
// Per-i (group, position_in_group); group = -1 means leave as Sx
|
||||
std::vector<std::pair<int, int>> origin(width, {-1, 0});
|
||||
|
||||
auto group_0 = cell->type == ID($xnor) ? 1 : 0;
|
||||
auto group_1 = cell->type == ID($xnor) ? 0 : 1;
|
||||
auto group_0 = cell->type == TW($xnor) ? 1 : 0;
|
||||
auto group_1 = cell->type == TW($xnor) ? 0 : 1;
|
||||
|
||||
for (int i = 0; i < width; i++) {
|
||||
auto bit_a = sig_a[i].data;
|
||||
|
|
@ -760,13 +762,13 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
else if (bit_a == State::Sx) origin[i] = {2, b_group_x.size()}, b_group_x.append(sig_b[i]);
|
||||
}
|
||||
|
||||
if (cell->type == ID($xnor))
|
||||
if (cell->type == TW($xnor))
|
||||
std::swap(b_group_0, b_group_1);
|
||||
|
||||
OptExprPatcher patcher(module, &assign_map);
|
||||
RTLIL::SigSpec y_new_0, y_new_1, y_new_x;
|
||||
|
||||
if (cell->type == ID($and)) {
|
||||
if (cell->type == TW($and)) {
|
||||
if (!b_group_0.empty()) y_new_0 = Const(State::S0, GetSize(b_group_0));
|
||||
if (!b_group_1.empty()) y_new_1 = b_group_1;
|
||||
if (!b_group_x.empty()) {
|
||||
|
|
@ -775,7 +777,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
else
|
||||
y_new_x = Const(State::S0, GetSize(b_group_x));
|
||||
}
|
||||
} else if (cell->type == ID($or)) {
|
||||
} else if (cell->type == TW($or)) {
|
||||
if (!b_group_0.empty()) y_new_0 = b_group_0;
|
||||
if (!b_group_1.empty()) y_new_1 = Const(State::S1, GetSize(b_group_1));
|
||||
if (!b_group_x.empty()) {
|
||||
|
|
@ -784,7 +786,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
else
|
||||
y_new_x = Const(State::S1, GetSize(b_group_x));
|
||||
}
|
||||
} else if (cell->type.in(ID($xor), ID($xnor))) {
|
||||
} else if (cell->type.in(TW($xor), TW($xnor))) {
|
||||
if (!b_group_0.empty()) y_new_0 = b_group_0;
|
||||
if (!b_group_1.empty()) y_new_1 = patcher.Not(NEW_TWINE, b_group_1);
|
||||
if (!b_group_x.empty()) {
|
||||
|
|
@ -809,7 +811,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
}
|
||||
}
|
||||
|
||||
if (cell->type == ID($bwmux))
|
||||
if (cell->type == TW($bwmux))
|
||||
{
|
||||
RTLIL::SigSpec sig_a = assign_map(cell->getPort(TW::A));
|
||||
RTLIL::SigSpec sig_b = assign_map(cell->getPort(TW::B));
|
||||
|
|
@ -866,13 +868,13 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
|
||||
if (do_fine)
|
||||
{
|
||||
if (cell->type.in(ID($not), ID($pos), ID($and), ID($or), ID($xor), ID($xnor)))
|
||||
if (cell->type.in(TW($not), TW($pos), TW($and), TW($or), TW($xor), TW($xnor)))
|
||||
if (group_cell_inputs(module, cell, true, assign_map, keepdc))
|
||||
goto next_cell;
|
||||
|
||||
if (cell->type.in(ID($logic_not), ID($logic_and), ID($logic_or), ID($reduce_or), ID($reduce_and), ID($reduce_bool)))
|
||||
if (cell->type.in(TW($logic_not), TW($logic_and), TW($logic_or), TW($reduce_or), TW($reduce_and), TW($reduce_bool)))
|
||||
{
|
||||
SigBit neutral_bit = cell->type == ID($reduce_and) ? State::S1 : State::S0;
|
||||
SigBit neutral_bit = cell->type == TW($reduce_and) ? State::S1 : State::S0;
|
||||
|
||||
RTLIL::SigSpec sig_a = assign_map(cell->getPort(TW::A));
|
||||
RTLIL::SigSpec new_sig_a;
|
||||
|
|
@ -892,7 +894,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
}
|
||||
}
|
||||
|
||||
if (cell->type.in(ID($logic_and), ID($logic_or)))
|
||||
if (cell->type.in(TW($logic_and), TW($logic_or)))
|
||||
{
|
||||
SigBit neutral_bit = State::S0;
|
||||
|
||||
|
|
@ -914,7 +916,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
}
|
||||
}
|
||||
|
||||
if (cell->type == ID($reduce_and))
|
||||
if (cell->type == TW($reduce_and))
|
||||
{
|
||||
RTLIL::SigSpec sig_a = assign_map(cell->getPort(TW::A));
|
||||
|
||||
|
|
@ -939,7 +941,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
}
|
||||
}
|
||||
|
||||
if (cell->type.in(ID($logic_not), ID($logic_and), ID($logic_or), ID($reduce_or), ID($reduce_bool)))
|
||||
if (cell->type.in(TW($logic_not), TW($logic_and), TW($logic_or), TW($reduce_or), TW($reduce_bool)))
|
||||
{
|
||||
RTLIL::SigSpec sig_a = assign_map(cell->getPort(TW::A));
|
||||
|
||||
|
|
@ -964,7 +966,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
}
|
||||
}
|
||||
|
||||
if (cell->type.in(ID($logic_and), ID($logic_or)))
|
||||
if (cell->type.in(TW($logic_and), TW($logic_or)))
|
||||
{
|
||||
RTLIL::SigSpec sig_b = assign_map(cell->getPort(TW::B));
|
||||
|
||||
|
|
@ -989,13 +991,13 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
}
|
||||
}
|
||||
|
||||
if (cell->type.in(ID($add), ID($sub)))
|
||||
if (cell->type.in(TW($add), TW($sub)))
|
||||
{
|
||||
RTLIL::SigSpec sig_a = assign_map(cell->getPort(TW::A));
|
||||
RTLIL::SigSpec sig_b = assign_map(cell->getPort(TW::B));
|
||||
RTLIL::SigSpec sig_y = cell->getPort(TW::Y);
|
||||
bool is_signed = cell->getParam(ID::A_SIGNED).as_bool();
|
||||
bool sub = cell->type == ID($sub);
|
||||
bool sub = cell->type == TW($sub);
|
||||
|
||||
int minsz = GetSize(sig_y);
|
||||
minsz = std::min(minsz, GetSize(sig_a));
|
||||
|
|
@ -1015,7 +1017,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
break;
|
||||
}
|
||||
if (i > 0) {
|
||||
log_debug("Stripping %d LSB bits of %s cell %s in module %s.\n", i, cell->type.unescape(), cell, module);
|
||||
log_debug("Stripping %d LSB bits of %s cell %s in module %s.\n", i, cell->type.unescaped(), cell, module);
|
||||
SigSpec new_a = sig_a.extract_end(i);
|
||||
SigSpec new_b = sig_b.extract_end(i);
|
||||
if (new_a.empty() && is_signed)
|
||||
|
|
@ -1030,7 +1032,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
}
|
||||
}
|
||||
|
||||
if (cell->type == ID($alu))
|
||||
if (cell->type == TW($alu))
|
||||
{
|
||||
RTLIL::SigSpec sig_a = assign_map(cell->getPort(TW::A));
|
||||
RTLIL::SigSpec sig_b = assign_map(cell->getPort(TW::B));
|
||||
|
|
@ -1071,7 +1073,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
break;
|
||||
}
|
||||
if (i > 0) {
|
||||
log_debug("Stripping %d LSB bits of %s cell %s in module %s.\n", i, cell->type.unescape(), cell, module);
|
||||
log_debug("Stripping %d LSB bits of %s cell %s in module %s.\n", i, cell->type.unescaped(), cell, module);
|
||||
SigSpec new_a = sig_a.extract_end(i);
|
||||
SigSpec new_b = sig_b.extract_end(i);
|
||||
if (new_a.empty() && is_signed)
|
||||
|
|
@ -1090,13 +1092,13 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
}
|
||||
skip_fine_alu:
|
||||
|
||||
if (cell->type.in(ID($reduce_xor), ID($reduce_xnor), ID($shift), ID($shiftx), ID($shl), ID($shr), ID($sshl), ID($sshr),
|
||||
ID($lt), ID($le), ID($ge), ID($gt), ID($neg), ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($divfloor), ID($modfloor), ID($pow)))
|
||||
if (cell->type.in(TW($reduce_xor), TW($reduce_xnor), TW($shift), TW($shiftx), TW($shl), TW($shr), TW($sshl), TW($sshr),
|
||||
TW($lt), TW($le), TW($ge), TW($gt), TW($neg), TW($add), TW($sub), TW($mul), TW($div), TW($mod), TW($divfloor), TW($modfloor), TW($pow)))
|
||||
{
|
||||
RTLIL::SigSpec sig_a = assign_map(cell->getPort(TW::A));
|
||||
RTLIL::SigSpec sig_b = cell->hasPort(TW::B) ? assign_map(cell->getPort(TW::B)) : RTLIL::SigSpec();
|
||||
|
||||
if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx)))
|
||||
if (cell->type.in(TW($shl), TW($shr), TW($sshl), TW($sshr), TW($shift), TW($shiftx)))
|
||||
sig_a = RTLIL::SigSpec();
|
||||
|
||||
for (auto &bit : sig_a.to_sigbit_vector())
|
||||
|
|
@ -1110,7 +1112,7 @@ skip_fine_alu:
|
|||
if (0) {
|
||||
found_the_x_bit:
|
||||
OptExprPatcher patcher(module, &assign_map);
|
||||
if (cell->type.in(ID($reduce_xor), ID($reduce_xnor), ID($lt), ID($le), ID($ge), ID($gt)))
|
||||
if (cell->type.in(TW($reduce_xor), TW($reduce_xnor), TW($lt), TW($le), TW($ge), TW($gt)))
|
||||
patcher.patch(cell, TW::Y, RTLIL::State::Sx, "x-bit in input");
|
||||
else
|
||||
patcher.patch(cell, TW::Y, RTLIL::SigSpec(RTLIL::State::Sx, GetSize(cell->getPort(TW::Y))), "x-bit in input");
|
||||
|
|
@ -1118,11 +1120,11 @@ skip_fine_alu:
|
|||
}
|
||||
}
|
||||
|
||||
if (cell->type.in(ID($shiftx), ID($shift)) && (cell->type == ID($shiftx) || !cell->getParam(ID::A_SIGNED).as_bool())) {
|
||||
if (cell->type.in(TW($shiftx), TW($shift)) && (cell->type == TW($shiftx) || !cell->getParam(ID::A_SIGNED).as_bool())) {
|
||||
SigSpec sig_a = assign_map(cell->getPort(TW::A));
|
||||
int width;
|
||||
bool trim_x = cell->type == ID($shiftx) || !keepdc;
|
||||
bool trim_0 = cell->type == ID($shift);
|
||||
bool trim_x = cell->type == TW($shiftx) || !keepdc;
|
||||
bool trim_0 = cell->type == TW($shift);
|
||||
for (width = GetSize(sig_a); width > 1; width--) {
|
||||
if ((trim_x && sig_a[width-1] == State::Sx) ||
|
||||
(trim_0 && sig_a[width-1] == State::S0))
|
||||
|
|
@ -1139,7 +1141,7 @@ skip_fine_alu:
|
|||
}
|
||||
}
|
||||
|
||||
if (cell->type.in(ID($_NOT_), ID($not), ID($logic_not)) && GetSize(cell->getPort(TW::Y)) == 1 && GetSize(cell->getPort(TW::A)) == 1) {
|
||||
if (cell->type.in(TW($_NOT_), TW($not), TW($logic_not)) && GetSize(cell->getPort(TW::Y)) == 1 && GetSize(cell->getPort(TW::A)) == 1) {
|
||||
if (auto inv_a = get_inverted(cell->getPort(TW::A), assign_map)) {
|
||||
OptExprPatcher patcher(module, &assign_map);
|
||||
patcher.patch(cell, TW::Y, *inv_a, "double_invert");
|
||||
|
|
@ -1147,9 +1149,9 @@ skip_fine_alu:
|
|||
}
|
||||
}
|
||||
|
||||
if (cell->type.in(ID($_MUX_), ID($mux))) {
|
||||
if (cell->type.in(TW($_MUX_), TW($mux))) {
|
||||
if (auto inv_a = get_inverted(cell->getPort(TW::S), assign_map)) {
|
||||
log_debug("Optimizing away select inverter for %s cell `%s' in module `%s'.\n", cell->type.unescape(), cell, module);
|
||||
log_debug("Optimizing away select inverter for %s cell `%s' in module `%s'.\n", cell->type.unescaped(), cell, module);
|
||||
RTLIL::SigSpec tmp = cell->getPort(TW::A);
|
||||
cell->setPort(TW::A, cell->getPort(TW::B));
|
||||
cell->setPort(TW::B, tmp);
|
||||
|
|
@ -1159,7 +1161,7 @@ skip_fine_alu:
|
|||
}
|
||||
}
|
||||
|
||||
if (cell->type == ID($_NOT_)) {
|
||||
if (cell->type == TW($_NOT_)) {
|
||||
RTLIL::SigSpec input = cell->getPort(TW::A);
|
||||
assign_map.apply(input);
|
||||
if (input.match("1")) ACTION_DO_Y(0);
|
||||
|
|
@ -1167,7 +1169,7 @@ skip_fine_alu:
|
|||
if (input.match("*")) ACTION_DO_Y(x);
|
||||
}
|
||||
|
||||
if (cell->type == ID($_AND_)) {
|
||||
if (cell->type == TW($_AND_)) {
|
||||
RTLIL::SigSpec input;
|
||||
input.append(cell->getPort(TW::B));
|
||||
input.append(cell->getPort(TW::A));
|
||||
|
|
@ -1186,7 +1188,7 @@ skip_fine_alu:
|
|||
if (input.match("1 ")) ACTION_DO(TW::Y, input.extract(0, 1));
|
||||
}
|
||||
|
||||
if (cell->type == ID($_OR_)) {
|
||||
if (cell->type == TW($_OR_)) {
|
||||
RTLIL::SigSpec input;
|
||||
input.append(cell->getPort(TW::B));
|
||||
input.append(cell->getPort(TW::A));
|
||||
|
|
@ -1205,7 +1207,7 @@ skip_fine_alu:
|
|||
if (input.match("0 ")) ACTION_DO(TW::Y, input.extract(0, 1));
|
||||
}
|
||||
|
||||
if (cell->type == ID($_XOR_)) {
|
||||
if (cell->type == TW($_XOR_)) {
|
||||
RTLIL::SigSpec input;
|
||||
input.append(cell->getPort(TW::B));
|
||||
input.append(cell->getPort(TW::A));
|
||||
|
|
@ -1220,7 +1222,7 @@ skip_fine_alu:
|
|||
}
|
||||
}
|
||||
|
||||
if (cell->type == ID($_MUX_)) {
|
||||
if (cell->type == TW($_MUX_)) {
|
||||
RTLIL::SigSpec input;
|
||||
input.append(cell->getPort(TW::S));
|
||||
input.append(cell->getPort(TW::B));
|
||||
|
|
@ -1250,8 +1252,8 @@ skip_fine_alu:
|
|||
}
|
||||
}
|
||||
|
||||
if (cell->type.in(ID($_TBUF_), ID($tribuf))) {
|
||||
RTLIL::SigSpec input = cell->getPort(cell->type == ID($_TBUF_) ? TW::E : TW::EN);
|
||||
if (cell->type.in(TW($_TBUF_), TW($tribuf))) {
|
||||
RTLIL::SigSpec input = cell->getPort(cell->type == TW($_TBUF_) ? TW::E : TW::EN);
|
||||
RTLIL::SigSpec a = cell->getPort(TW::A);
|
||||
assign_map.apply(input);
|
||||
assign_map.apply(a);
|
||||
|
|
@ -1266,7 +1268,7 @@ skip_fine_alu:
|
|||
}
|
||||
}
|
||||
|
||||
if (cell->type.in(ID($eq), ID($ne), ID($eqx), ID($nex)))
|
||||
if (cell->type.in(TW($eq), TW($ne), TW($eqx), TW($nex)))
|
||||
{
|
||||
RTLIL::SigSpec a = cell->getPort(TW::A);
|
||||
RTLIL::SigSpec b = cell->getPort(TW::B);
|
||||
|
|
@ -1282,7 +1284,7 @@ skip_fine_alu:
|
|||
log_assert(GetSize(a) == GetSize(b));
|
||||
for (int i = 0; i < GetSize(a); i++) {
|
||||
if (a[i].wire == NULL && b[i].wire == NULL && a[i] != b[i] && a[i].data <= RTLIL::State::S1 && b[i].data <= RTLIL::State::S1) {
|
||||
RTLIL::SigSpec new_y = RTLIL::SigSpec(cell->type.in(ID($eq), ID($eqx)) ? RTLIL::State::S0 : RTLIL::State::S1);
|
||||
RTLIL::SigSpec new_y = RTLIL::SigSpec(cell->type.in(TW($eq), TW($eqx)) ? RTLIL::State::S0 : RTLIL::State::S1);
|
||||
new_y.extend_u0(cell->parameters[ID::Y_WIDTH].as_int(), false);
|
||||
OptExprPatcher patcher(module, &assign_map);
|
||||
patcher.patch(cell, TW::Y, new_y, "isneq");
|
||||
|
|
@ -1300,7 +1302,7 @@ skip_fine_alu:
|
|||
}
|
||||
|
||||
if (new_a.size() == 0) {
|
||||
RTLIL::SigSpec new_y = RTLIL::SigSpec(cell->type.in(ID($eq), ID($eqx)) ? RTLIL::State::S1 : RTLIL::State::S0);
|
||||
RTLIL::SigSpec new_y = RTLIL::SigSpec(cell->type.in(TW($eq), TW($eqx)) ? RTLIL::State::S1 : RTLIL::State::S0);
|
||||
new_y.extend_u0(cell->parameters[ID::Y_WIDTH].as_int(), false);
|
||||
OptExprPatcher patcher(module, &assign_map);
|
||||
patcher.patch(cell, TW::Y, new_y, "empty");
|
||||
|
|
@ -1315,7 +1317,7 @@ skip_fine_alu:
|
|||
}
|
||||
}
|
||||
|
||||
if (cell->type.in(ID($eq), ID($ne)) && cell->parameters[ID::Y_WIDTH].as_int() == 1 &&
|
||||
if (cell->type.in(TW($eq), TW($ne)) && cell->parameters[ID::Y_WIDTH].as_int() == 1 &&
|
||||
cell->parameters[ID::A_WIDTH].as_int() == 1 && cell->parameters[ID::B_WIDTH].as_int() == 1)
|
||||
{
|
||||
RTLIL::SigSpec a = assign_map(cell->getPort(TW::A));
|
||||
|
|
@ -1332,11 +1334,11 @@ skip_fine_alu:
|
|||
RTLIL::SigSpec input = b;
|
||||
ACTION_DO(TW::Y, Const(State::Sx, GetSize(cell->getPort(TW::Y))));
|
||||
} else
|
||||
if (b.as_bool() == (cell->type == ID($eq))) {
|
||||
if (b.as_bool() == (cell->type == TW($eq))) {
|
||||
RTLIL::SigSpec input = b;
|
||||
ACTION_DO(TW::Y, cell->getPort(TW::A));
|
||||
} else {
|
||||
log_debug("Replacing %s cell `%s' in module `%s' with inverter.\n", cell->type.unescape(), cell, module);
|
||||
log_debug("Replacing %s cell `%s' in module `%s' with inverter.\n", cell->type.unescaped(), cell, module);
|
||||
cell->parameters.erase(ID::B_WIDTH);
|
||||
cell->parameters.erase(ID::B_SIGNED);
|
||||
cell->unsetPort(TW::B);
|
||||
|
|
@ -1347,11 +1349,11 @@ skip_fine_alu:
|
|||
}
|
||||
}
|
||||
|
||||
if (cell->type.in(ID($eq), ID($ne)) &&
|
||||
if (cell->type.in(TW($eq), TW($ne)) &&
|
||||
(assign_map(cell->getPort(TW::A)).is_fully_zero() || assign_map(cell->getPort(TW::B)).is_fully_zero()))
|
||||
{
|
||||
log_debug("Replacing %s cell `%s' in module `%s' with %s.\n", cell->type.unescape(), cell,
|
||||
module, cell->type == ID($eq) ? "$logic_not" : "$reduce_bool");
|
||||
log_debug("Replacing %s cell `%s' in module `%s' with %s.\n", cell->type.unescaped(), cell,
|
||||
module, cell->type == TW($eq) ? "$logic_not" : "$reduce_bool");
|
||||
if (assign_map(cell->getPort(TW::A)).is_fully_zero()) {
|
||||
cell->setPort(TW::A, cell->getPort(TW::B));
|
||||
cell->setParam(ID::A_SIGNED, cell->getParam(ID::B_SIGNED));
|
||||
|
|
@ -1360,28 +1362,28 @@ skip_fine_alu:
|
|||
cell->unsetPort(TW::B);
|
||||
cell->unsetParam(ID::B_SIGNED);
|
||||
cell->unsetParam(ID::B_WIDTH);
|
||||
cell->type_impl = (cell->type == ID($eq)) ? TW::$logic_not : TW::$reduce_bool;
|
||||
cell->type_impl = (cell->type == TW($eq)) ? TW::$logic_not : TW::$reduce_bool;
|
||||
did_something = true;
|
||||
goto next_cell;
|
||||
}
|
||||
|
||||
if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx)) && (keepdc ? assign_map(cell->getPort(TW::B)).is_fully_def() : assign_map(cell->getPort(TW::B)).is_fully_const()))
|
||||
if (cell->type.in(TW($shl), TW($shr), TW($sshl), TW($sshr), TW($shift), TW($shiftx)) && (keepdc ? assign_map(cell->getPort(TW::B)).is_fully_def() : assign_map(cell->getPort(TW::B)).is_fully_const()))
|
||||
{
|
||||
bool sign_ext = cell->type == ID($sshr) && cell->getParam(ID::A_SIGNED).as_bool();
|
||||
bool sign_ext = cell->type == TW($sshr) && cell->getParam(ID::A_SIGNED).as_bool();
|
||||
RTLIL::SigSpec sig_b = assign_map(cell->getPort(TW::B));
|
||||
const bool b_sign_ext = cell->type.in(ID($shift), ID($shiftx)) && cell->getParam(ID::B_SIGNED).as_bool();
|
||||
const bool b_sign_ext = cell->type.in(TW($shift), TW($shiftx)) && cell->getParam(ID::B_SIGNED).as_bool();
|
||||
// We saturate the value to prevent overflow, but note that this could
|
||||
// cause incorrect opimization in the impractical case that A is 2^32 bits
|
||||
// wide
|
||||
int shift_bits = sig_b.as_int_saturating(b_sign_ext);
|
||||
|
||||
if (cell->type.in(ID($shl), ID($sshl)))
|
||||
if (cell->type.in(TW($shl), TW($sshl)))
|
||||
shift_bits *= -1;
|
||||
|
||||
RTLIL::SigSpec sig_a = assign_map(cell->getPort(TW::A));
|
||||
RTLIL::SigSpec sig_y(cell->type == ID($shiftx) ? RTLIL::State::Sx : RTLIL::State::S0, cell->getParam(ID::Y_WIDTH).as_int());
|
||||
RTLIL::SigSpec sig_y(cell->type == TW($shiftx) ? RTLIL::State::Sx : RTLIL::State::S0, cell->getParam(ID::Y_WIDTH).as_int());
|
||||
|
||||
if (cell->type != ID($shiftx) && GetSize(sig_a) < GetSize(sig_y))
|
||||
if (cell->type != TW($shiftx) && GetSize(sig_a) < GetSize(sig_y))
|
||||
sig_a.extend_u0(GetSize(sig_y), cell->getParam(ID::A_SIGNED).as_bool());
|
||||
|
||||
// Limit indexing to the size of a, which is behaviourally identical (result is all 0)
|
||||
|
|
@ -1411,14 +1413,14 @@ skip_fine_alu:
|
|||
bool identity_wrt_b = false;
|
||||
bool arith_inverse = false;
|
||||
|
||||
if (cell->type.in(ID($add), ID($sub), ID($alu), ID($or), ID($xor)))
|
||||
if (cell->type.in(TW($add), TW($sub), TW($alu), TW($or), TW($xor)))
|
||||
{
|
||||
RTLIL::SigSpec a = assign_map(cell->getPort(TW::A));
|
||||
RTLIL::SigSpec b = assign_map(cell->getPort(TW::B));
|
||||
|
||||
bool sub = cell->type == ID($sub);
|
||||
bool sub = cell->type == TW($sub);
|
||||
|
||||
if (cell->type == ID($alu)) {
|
||||
if (cell->type == TW($alu)) {
|
||||
RTLIL::SigBit sig_ci = assign_map(cell->getPort(TW::CI));
|
||||
RTLIL::SigBit sig_bi = assign_map(cell->getPort(TW::BI));
|
||||
|
||||
|
|
@ -1437,7 +1439,7 @@ skip_fine_alu:
|
|||
identity_wrt_a = true;
|
||||
}
|
||||
|
||||
if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx)))
|
||||
if (cell->type.in(TW($shl), TW($shr), TW($sshl), TW($sshr), TW($shift), TW($shiftx)))
|
||||
{
|
||||
RTLIL::SigSpec b = assign_map(cell->getPort(TW::B));
|
||||
|
||||
|
|
@ -1445,7 +1447,7 @@ skip_fine_alu:
|
|||
identity_wrt_a = true;
|
||||
}
|
||||
|
||||
if (cell->type == ID($mul))
|
||||
if (cell->type == TW($mul))
|
||||
{
|
||||
RTLIL::SigSpec a = assign_map(cell->getPort(TW::A));
|
||||
RTLIL::SigSpec b = assign_map(cell->getPort(TW::B));
|
||||
|
|
@ -1457,7 +1459,7 @@ skip_fine_alu:
|
|||
identity_wrt_a = true;
|
||||
}
|
||||
|
||||
if (cell->type == ID($div))
|
||||
if (cell->type == TW($div))
|
||||
{
|
||||
RTLIL::SigSpec b = assign_map(cell->getPort(TW::B));
|
||||
|
||||
|
|
@ -1470,7 +1472,7 @@ skip_fine_alu:
|
|||
log_debug("Replacing %s cell `%s' in module `%s' with identity for port %c.\n",
|
||||
cell->type.c_str(), cell->name.c_str(), module->design->twines.str(module->meta_->name).c_str(), identity_wrt_a ? 'A' : 'B');
|
||||
|
||||
if (cell->type == ID($alu)) {
|
||||
if (cell->type == TW($alu)) {
|
||||
bool a_signed = cell->parameters[ID::A_SIGNED].as_bool();
|
||||
bool b_signed = cell->parameters[ID::B_SIGNED].as_bool();
|
||||
bool is_signed = a_signed && b_signed;
|
||||
|
|
@ -1502,7 +1504,7 @@ skip_fine_alu:
|
|||
a_port_width = cell->getParam(identity_wrt_a ? ID::A_WIDTH : ID::B_WIDTH).as_int();
|
||||
}
|
||||
|
||||
IdString new_type = arith_inverse ? ID($neg) : ID($pos);
|
||||
TwineRef new_type = arith_inverse ? TW($neg) : TW($pos);
|
||||
SigSpec new_y = patcher.addWire(NEW_TWINE, y_width);
|
||||
Cell *new_cell = patcher.addCell(NEW_TWINE, new_type);
|
||||
new_cell->setPort(TW::A, a_port);
|
||||
|
|
@ -1533,20 +1535,20 @@ skip_fine_alu:
|
|||
}
|
||||
skip_identity:
|
||||
|
||||
if (mux_bool && cell->type.in(ID($mux), ID($_MUX_)) &&
|
||||
if (mux_bool && cell->type.in(TW($mux), TW($_MUX_)) &&
|
||||
cell->getPort(TW::A) == State::S0 && cell->getPort(TW::B) == State::S1) {
|
||||
OptExprPatcher patcher(module, &assign_map);
|
||||
patcher.patch(cell, TW::Y, cell->getPort(TW::S), "mux_bool");
|
||||
goto next_cell;
|
||||
}
|
||||
|
||||
if (mux_bool && cell->type.in(ID($mux), ID($_MUX_)) &&
|
||||
if (mux_bool && cell->type.in(TW($mux), TW($_MUX_)) &&
|
||||
cell->getPort(TW::A) == State::S1 && cell->getPort(TW::B) == State::S0) {
|
||||
log_debug("Replacing %s cell `%s' in module `%s' with inverter.\n", cell->type.unescape(), cell, module);
|
||||
log_debug("Replacing %s cell `%s' in module `%s' with inverter.\n", cell->type.unescaped(), cell, module);
|
||||
cell->setPort(TW::A, cell->getPort(TW::S));
|
||||
cell->unsetPort(TW::B);
|
||||
cell->unsetPort(TW::S);
|
||||
if (cell->type == ID($mux)) {
|
||||
if (cell->type == TW($mux)) {
|
||||
Const width = cell->parameters[ID::WIDTH];
|
||||
cell->parameters[ID::A_WIDTH] = width;
|
||||
cell->parameters[ID::Y_WIDTH] = width;
|
||||
|
|
@ -1559,11 +1561,11 @@ skip_identity:
|
|||
goto next_cell;
|
||||
}
|
||||
|
||||
if (consume_x && mux_bool && cell->type.in(ID($mux), ID($_MUX_)) && cell->getPort(TW::A) == State::S0) {
|
||||
log_debug("Replacing %s cell `%s' in module `%s' with and-gate.\n", cell->type.unescape(), cell, module);
|
||||
if (consume_x && mux_bool && cell->type.in(TW($mux), TW($_MUX_)) && cell->getPort(TW::A) == State::S0) {
|
||||
log_debug("Replacing %s cell `%s' in module `%s' with and-gate.\n", cell->type.unescaped(), cell, module);
|
||||
cell->setPort(TW::A, cell->getPort(TW::S));
|
||||
cell->unsetPort(TW::S);
|
||||
if (cell->type == ID($mux)) {
|
||||
if (cell->type == TW($mux)) {
|
||||
Const width = cell->parameters[ID::WIDTH];
|
||||
cell->parameters[ID::A_WIDTH] = width;
|
||||
cell->parameters[ID::B_WIDTH] = width;
|
||||
|
|
@ -1578,11 +1580,11 @@ skip_identity:
|
|||
goto next_cell;
|
||||
}
|
||||
|
||||
if (consume_x && mux_bool && cell->type.in(ID($mux), ID($_MUX_)) && cell->getPort(TW::B) == State::S1) {
|
||||
log_debug("Replacing %s cell `%s' in module `%s' with or-gate.\n", cell->type.unescape(), cell, module);
|
||||
if (consume_x && mux_bool && cell->type.in(TW($mux), TW($_MUX_)) && cell->getPort(TW::B) == State::S1) {
|
||||
log_debug("Replacing %s cell `%s' in module `%s' with or-gate.\n", cell->type.unescaped(), cell, module);
|
||||
cell->setPort(TW::B, cell->getPort(TW::S));
|
||||
cell->unsetPort(TW::S);
|
||||
if (cell->type == ID($mux)) {
|
||||
if (cell->type == TW($mux)) {
|
||||
Const width = cell->parameters[ID::WIDTH];
|
||||
cell->parameters[ID::A_WIDTH] = width;
|
||||
cell->parameters[ID::B_WIDTH] = width;
|
||||
|
|
@ -1597,7 +1599,7 @@ skip_identity:
|
|||
goto next_cell;
|
||||
}
|
||||
|
||||
if (mux_undef && cell->type.in(ID($mux), ID($pmux))) {
|
||||
if (mux_undef && cell->type.in(TW($mux), TW($pmux))) {
|
||||
RTLIL::SigSpec new_a, new_b, new_s;
|
||||
int width = GetSize(cell->getPort(TW::A));
|
||||
if ((cell->getPort(TW::A).is_fully_undef() && cell->getPort(TW::B).is_fully_undef()) ||
|
||||
|
|
@ -1632,7 +1634,7 @@ skip_identity:
|
|||
}
|
||||
if (cell->getPort(TW::S).size() != new_s.size()) {
|
||||
log_debug("Optimized away %d select inputs of %s cell `%s' in module `%s'.\n",
|
||||
GetSize(cell->getPort(TW::S)) - GetSize(new_s), cell->type.unescape(), cell, module);
|
||||
GetSize(cell->getPort(TW::S)) - GetSize(new_s), cell->type.unescaped(), cell, module);
|
||||
cell->setPort(TW::A, new_a);
|
||||
cell->setPort(TW::B, new_b);
|
||||
cell->setPort(TW::S, new_s);
|
||||
|
|
@ -1647,10 +1649,10 @@ skip_identity:
|
|||
}
|
||||
}
|
||||
|
||||
if (mux_undef && cell->type.in(ID($_MUX4_), ID($_MUX8_), ID($_MUX16_))) {
|
||||
if (mux_undef && cell->type.in(TW($_MUX4_), TW($_MUX8_), TW($_MUX16_))) {
|
||||
int num_inputs = 4;
|
||||
if (cell->type == ID($_MUX8_)) num_inputs = 8;
|
||||
if (cell->type == ID($_MUX16_)) num_inputs = 16;
|
||||
if (cell->type == TW($_MUX8_)) num_inputs = 8;
|
||||
if (cell->type == TW($_MUX16_)) num_inputs = 16;
|
||||
int undef_inputs = 0;
|
||||
for (auto &conn : cell->connections())
|
||||
if (conn.first != TW::S && conn.first != TW::T && conn.first != TW::U && conn.first != TW::V && conn.first != TW::Y)
|
||||
|
|
@ -1663,7 +1665,7 @@ skip_identity:
|
|||
}
|
||||
|
||||
#define FOLD_1ARG_CELL(_t) \
|
||||
if (cell->type == ID($##_t)) { \
|
||||
if (cell->type == TW($##_t)) { \
|
||||
RTLIL::SigSpec a = cell->getPort(TW::A); \
|
||||
assign_map.apply(a); \
|
||||
if (a.is_fully_const()) { \
|
||||
|
|
@ -1677,7 +1679,7 @@ skip_identity:
|
|||
} \
|
||||
}
|
||||
#define FOLD_2ARG_CELL(_t) \
|
||||
if (cell->type == ID($##_t)) { \
|
||||
if (cell->type == TW($##_t)) { \
|
||||
RTLIL::SigSpec a = cell->getPort(TW::A); \
|
||||
RTLIL::SigSpec b = cell->getPort(TW::B); \
|
||||
assign_map.apply(a), assign_map.apply(b); \
|
||||
|
|
@ -1692,7 +1694,7 @@ skip_identity:
|
|||
} \
|
||||
}
|
||||
#define FOLD_2ARG_SIMPLE_CELL(_t, B_ID) \
|
||||
if (cell->type == ID($##_t)) { \
|
||||
if (cell->type == TW($##_t)) { \
|
||||
RTLIL::SigSpec a = cell->getPort(TW::A); \
|
||||
RTLIL::SigSpec b = cell->getPort(B_ID); \
|
||||
assign_map.apply(a), assign_map.apply(b); \
|
||||
|
|
@ -1704,7 +1706,7 @@ skip_identity:
|
|||
} \
|
||||
}
|
||||
#define FOLD_MUX_CELL(_t) \
|
||||
if (cell->type == ID($##_t)) { \
|
||||
if (cell->type == TW($##_t)) { \
|
||||
RTLIL::SigSpec a = cell->getPort(TW::A); \
|
||||
RTLIL::SigSpec b = cell->getPort(TW::B); \
|
||||
RTLIL::SigSpec s = cell->getPort(TW::S); \
|
||||
|
|
@ -1770,7 +1772,7 @@ skip_identity:
|
|||
FOLD_MUX_CELL(bwmux);
|
||||
|
||||
// be very conservative with optimizing $mux cells as we do not want to break mux trees
|
||||
if (cell->type == ID($mux)) {
|
||||
if (cell->type == TW($mux)) {
|
||||
RTLIL::SigSpec input = assign_map(cell->getPort(TW::S));
|
||||
RTLIL::SigSpec inA = assign_map(cell->getPort(TW::A));
|
||||
RTLIL::SigSpec inB = assign_map(cell->getPort(TW::B));
|
||||
|
|
@ -1779,7 +1781,7 @@ skip_identity:
|
|||
else if (inA == inB)
|
||||
ACTION_DO(TW::Y, cell->getPort(TW::A));
|
||||
}
|
||||
if (cell->type == ID($pow) && cell->getPort(TW::A).is_fully_const() && !cell->parameters[ID::B_SIGNED].as_bool()) {
|
||||
if (cell->type == TW($pow) && cell->getPort(TW::A).is_fully_const() && !cell->parameters[ID::B_SIGNED].as_bool()) {
|
||||
SigSpec sig_a = assign_map(cell->getPort(TW::A));
|
||||
SigSpec sig_y = assign_map(cell->getPort(TW::Y));
|
||||
int y_size = GetSize(sig_y);
|
||||
|
|
@ -1806,7 +1808,7 @@ skip_identity:
|
|||
int a_width = cell->parameters[ID::A_WIDTH].as_int();
|
||||
|
||||
SigSpec y_wire = patcher.addWire(NEW_TWINE, y_size);
|
||||
Cell *mul = patcher.addCell(NEW_TWINE, ID($mul));
|
||||
Cell *mul = patcher.addCell(NEW_TWINE, TW($mul));
|
||||
mul->setPort(TW::A, Const(bit_idx, a_width));
|
||||
mul->setPort(TW::B, cell->getPort(TW::B));
|
||||
mul->setPort(TW::Y, y_wire);
|
||||
|
|
@ -1826,7 +1828,7 @@ skip_identity:
|
|||
goto next_cell;
|
||||
}
|
||||
}
|
||||
if (!keepdc && cell->type == ID($mul))
|
||||
if (!keepdc && cell->type == TW($mul))
|
||||
{
|
||||
bool a_signed = cell->parameters[ID::A_SIGNED].as_bool();
|
||||
bool b_signed = cell->parameters[ID::B_SIGNED].as_bool();
|
||||
|
|
@ -1914,7 +1916,7 @@ skip_identity:
|
|||
}
|
||||
}
|
||||
|
||||
if (cell->type.in(ID($div), ID($mod), ID($divfloor), ID($modfloor)))
|
||||
if (cell->type.in(TW($div), TW($mod), TW($divfloor), TW($modfloor)))
|
||||
{
|
||||
bool a_signed = cell->parameters[ID::A_SIGNED].as_bool();
|
||||
bool b_signed = cell->parameters[ID::B_SIGNED].as_bool();
|
||||
|
|
@ -1937,9 +1939,9 @@ skip_identity:
|
|||
int exp;
|
||||
if (!keepdc && sig_b.is_onehot(&exp) && !(b_signed && exp == GetSize(sig_b) - 1))
|
||||
{
|
||||
if (cell->type.in(ID($div), ID($divfloor)))
|
||||
if (cell->type.in(TW($div), TW($divfloor)))
|
||||
{
|
||||
bool is_truncating = cell->type == ID($div);
|
||||
bool is_truncating = cell->type == TW($div);
|
||||
log_debug("Replacing %s-divide-by-%s cell `%s' in module `%s' with shift-by-%d.\n",
|
||||
is_truncating ? "truncating" : "flooring",
|
||||
log_signal(sig_b), cell->name.c_str(), module->design->twines.str(module->meta_->name).c_str(), exp);
|
||||
|
|
@ -1965,9 +1967,9 @@ skip_identity:
|
|||
|
||||
cell->check();
|
||||
}
|
||||
else if (cell->type.in(ID($mod), ID($modfloor)))
|
||||
else if (cell->type.in(TW($mod), TW($modfloor)))
|
||||
{
|
||||
bool is_truncating = cell->type == ID($mod);
|
||||
bool is_truncating = cell->type == TW($mod);
|
||||
log_debug("Replacing %s-modulo-by-%s cell `%s' in module `%s' with bitmask.\n",
|
||||
is_truncating ? "truncating" : "flooring",
|
||||
log_signal(sig_b), cell->name.c_str(), module->design->twines.str(module->meta_->name).c_str());
|
||||
|
|
@ -2010,7 +2012,7 @@ skip_identity:
|
|||
}
|
||||
|
||||
// Find places in $alu cell where the carry is constant, and split it at these points.
|
||||
if (do_fine && !keepdc && cell->type == ID($alu))
|
||||
if (do_fine && !keepdc && cell->type == TW($alu))
|
||||
{
|
||||
bool a_signed = cell->parameters[ID::A_SIGNED].as_bool();
|
||||
bool b_signed = cell->parameters[ID::B_SIGNED].as_bool();
|
||||
|
|
@ -2075,7 +2077,7 @@ skip_identity:
|
|||
SigSpec slice_x = patcher.addWire(NEW_TWINE, sz);
|
||||
SigSpec slice_co = patcher.addWire(NEW_TWINE, sz);
|
||||
|
||||
RTLIL::Cell *c = patcher.addCell(NEW_TWINE, cell->type);
|
||||
RTLIL::Cell *c = patcher.addCell(NEW_TWINE, cell->type_impl);
|
||||
c->setPort(TW::A, sig_a.extract(prev, sz));
|
||||
c->setPort(TW::B, sig_b.extract(prev, sz));
|
||||
c->setPort(TW::BI, sig_bi);
|
||||
|
|
@ -2107,7 +2109,7 @@ skip_alu_split:
|
|||
|
||||
// remove redundant pairs of bits in ==, ===, !=, and !==
|
||||
// replace cell with const driver if inputs can't be equal
|
||||
if (do_fine && cell->type.in(ID($eq), ID($ne), ID($eqx), ID($nex)))
|
||||
if (do_fine && cell->type.in(TW($eq), TW($ne), TW($eqx), TW($nex)))
|
||||
{
|
||||
pool<pair<SigBit, SigBit>> redundant_cache;
|
||||
mfp<SigBit> contradiction_cache;
|
||||
|
|
@ -2153,7 +2155,7 @@ skip_alu_split:
|
|||
if (contradiction_cache.find(State::S0) == contradiction_cache.find(State::S1))
|
||||
{
|
||||
SigSpec y_sig = cell->getPort(TW::Y);
|
||||
Const y_value(cell->type.in(ID($eq), ID($eqx)) ? 0 : 1, GetSize(y_sig));
|
||||
Const y_value(cell->type.in(TW($eq), TW($eqx)) ? 0 : 1, GetSize(y_sig));
|
||||
|
||||
log_debug("Replacing cell `%s' in module `%s' with constant driver %s.\n",
|
||||
cell, module, log_signal(y_value));
|
||||
|
|
@ -2166,7 +2168,7 @@ skip_alu_split:
|
|||
if (redundant_bits)
|
||||
{
|
||||
log_debug("Removed %d redundant input bits from %s cell `%s' in module `%s'.\n",
|
||||
redundant_bits, cell->type.unescape(), cell, module);
|
||||
redundant_bits, cell->type.unescaped(), cell, module);
|
||||
|
||||
cell->setPort(TW::A, sig_a);
|
||||
cell->setPort(TW::B, sig_b);
|
||||
|
|
@ -2179,7 +2181,7 @@ skip_alu_split:
|
|||
}
|
||||
|
||||
// simplify comparisons
|
||||
if (do_fine && cell->type.in(ID($lt), ID($ge), ID($gt), ID($le)))
|
||||
if (do_fine && cell->type.in(TW($lt), TW($ge), TW($gt), TW($le)))
|
||||
{
|
||||
IdString cmp_type = cell->type;
|
||||
SigSpec var_sig = cell->getPort(TW::A);
|
||||
|
|
@ -2192,14 +2194,14 @@ skip_alu_split:
|
|||
{
|
||||
std::swap(var_sig, const_sig);
|
||||
std::swap(var_width, const_width);
|
||||
if (cmp_type == ID($gt))
|
||||
cmp_type = ID($lt);
|
||||
else if (cmp_type == ID($lt))
|
||||
cmp_type = ID($gt);
|
||||
else if (cmp_type == ID($ge))
|
||||
cmp_type = ID($le);
|
||||
else if (cmp_type == ID($le))
|
||||
cmp_type = ID($ge);
|
||||
if (cmp_type == TW($gt))
|
||||
cmp_type = TW($lt);
|
||||
else if (cmp_type == TW($lt))
|
||||
cmp_type = TW($gt);
|
||||
else if (cmp_type == TW($ge))
|
||||
cmp_type = TW($le);
|
||||
else if (cmp_type == TW($le))
|
||||
cmp_type = TW($ge);
|
||||
}
|
||||
|
||||
if (const_sig.is_fully_def() && const_sig.is_fully_const())
|
||||
|
|
@ -2211,25 +2213,25 @@ skip_alu_split:
|
|||
|
||||
if (!is_signed)
|
||||
{ /* unsigned */
|
||||
if (const_sig.is_fully_zero() && cmp_type == ID($lt)) {
|
||||
if (const_sig.is_fully_zero() && cmp_type == TW($lt)) {
|
||||
condition = "unsigned X<0";
|
||||
replacement = "constant 0";
|
||||
replace_sig[0] = State::S0;
|
||||
replace = true;
|
||||
}
|
||||
if (const_sig.is_fully_zero() && cmp_type == ID($ge)) {
|
||||
if (const_sig.is_fully_zero() && cmp_type == TW($ge)) {
|
||||
condition = "unsigned X>=0";
|
||||
replacement = "constant 1";
|
||||
replace_sig[0] = State::S1;
|
||||
replace = true;
|
||||
}
|
||||
if (const_width == var_width && const_sig.is_fully_ones() && cmp_type == ID($gt)) {
|
||||
if (const_width == var_width && const_sig.is_fully_ones() && cmp_type == TW($gt)) {
|
||||
condition = "unsigned X>~0";
|
||||
replacement = "constant 0";
|
||||
replace_sig[0] = State::S0;
|
||||
replace = true;
|
||||
}
|
||||
if (const_width == var_width && const_sig.is_fully_ones() && cmp_type == ID($le)) {
|
||||
if (const_width == var_width && const_sig.is_fully_ones() && cmp_type == TW($le)) {
|
||||
condition = "unsigned X<=~0";
|
||||
replacement = "constant 1";
|
||||
replace_sig[0] = State::S1;
|
||||
|
|
@ -2244,14 +2246,14 @@ skip_alu_split:
|
|||
var_high_sig[i - const_bit_hot] = var_sig[i];
|
||||
}
|
||||
|
||||
if (cmp_type == ID($lt))
|
||||
if (cmp_type == TW($lt))
|
||||
{
|
||||
condition = stringf("unsigned X<%s", log_signal(const_sig));
|
||||
replacement = stringf("!X[%d:%d]", var_width - 1, const_bit_hot);
|
||||
replace_sig[0] = patcher.LogicNot(NEW_TWINE, var_high_sig).as_bit();
|
||||
replace = true;
|
||||
}
|
||||
if (cmp_type == ID($ge))
|
||||
if (cmp_type == TW($ge))
|
||||
{
|
||||
condition = stringf("unsigned X>=%s", log_signal(const_sig));
|
||||
replacement = stringf("|X[%d:%d]", var_width - 1, const_bit_hot);
|
||||
|
|
@ -2264,19 +2266,19 @@ skip_alu_split:
|
|||
if (const_bit_set >= var_width)
|
||||
{
|
||||
string cmp_name;
|
||||
if (cmp_type == ID($lt) || cmp_type == ID($le))
|
||||
if (cmp_type == TW($lt) || cmp_type == TW($le))
|
||||
{
|
||||
if (cmp_type == ID($lt)) cmp_name = "<";
|
||||
if (cmp_type == ID($le)) cmp_name = "<=";
|
||||
if (cmp_type == TW($lt)) cmp_name = "<";
|
||||
if (cmp_type == TW($le)) cmp_name = "<=";
|
||||
condition = stringf("unsigned X[%d:0]%s%s", var_width - 1, cmp_name, log_signal(const_sig));
|
||||
replacement = "constant 1";
|
||||
replace_sig[0] = State::S1;
|
||||
replace = true;
|
||||
}
|
||||
if (cmp_type == ID($gt) || cmp_type == ID($ge))
|
||||
if (cmp_type == TW($gt) || cmp_type == TW($ge))
|
||||
{
|
||||
if (cmp_type == ID($gt)) cmp_name = ">";
|
||||
if (cmp_type == ID($ge)) cmp_name = ">=";
|
||||
if (cmp_type == TW($gt)) cmp_name = ">";
|
||||
if (cmp_type == TW($ge)) cmp_name = ">=";
|
||||
condition = stringf("unsigned X[%d:0]%s%s", var_width - 1, cmp_name, log_signal(const_sig));
|
||||
replacement = "constant 0";
|
||||
replace_sig[0] = State::S0;
|
||||
|
|
@ -2286,14 +2288,14 @@ skip_alu_split:
|
|||
}
|
||||
else
|
||||
{ /* signed */
|
||||
if (const_sig.is_fully_zero() && cmp_type == ID($lt))
|
||||
if (const_sig.is_fully_zero() && cmp_type == TW($lt))
|
||||
{
|
||||
condition = "signed X<0";
|
||||
replacement = stringf("X[%d]", var_width - 1);
|
||||
replace_sig[0] = var_sig[var_width - 1];
|
||||
replace = true;
|
||||
}
|
||||
if (const_sig.is_fully_zero() && cmp_type == ID($ge))
|
||||
if (const_sig.is_fully_zero() && cmp_type == TW($ge))
|
||||
{
|
||||
condition = "signed X>=0";
|
||||
replacement = stringf("X[%d]", var_width - 1);
|
||||
|
|
|
|||
|
|
@ -52,9 +52,9 @@ struct OptFfInvWorker
|
|||
continue;
|
||||
if (port.port != TW::Y)
|
||||
return false;
|
||||
if (port.cell->type.in(ID($not), ID($_NOT_))) {
|
||||
if (port.cell->type.in(TW($not), TW($_NOT_))) {
|
||||
// OK
|
||||
} else if (port.cell->type.in(ID($lut))) {
|
||||
} else if (port.cell->type.in(TW($lut))) {
|
||||
if (port.cell->getParam(ID::WIDTH) != 1)
|
||||
return false;
|
||||
if (port.cell->getParam(ID::LUT).as_int() != 1)
|
||||
|
|
@ -78,7 +78,7 @@ struct OptFfInvWorker
|
|||
return false;
|
||||
if (port.port != TW::A)
|
||||
return false;
|
||||
if (!port.cell->type.in(ID($not), ID($_NOT_), ID($lut)))
|
||||
if (!port.cell->type.in(TW($not), TW($_NOT_), TW($lut)))
|
||||
return false;
|
||||
q_luts.insert(port.cell);
|
||||
}
|
||||
|
|
@ -87,7 +87,7 @@ struct OptFfInvWorker
|
|||
ff.sig_d = d_inv->getPort(TW::A);
|
||||
|
||||
for (Cell *lut: q_luts) {
|
||||
if (lut->type == ID($lut)) {
|
||||
if (lut->type == TW($lut)) {
|
||||
int flip_mask = 0;
|
||||
SigSpec sig_a = lut->getPort(TW::A);
|
||||
for (int i = 0; i < GetSize(sig_a); i++) {
|
||||
|
|
@ -137,7 +137,7 @@ struct OptFfInvWorker
|
|||
continue;
|
||||
if (port.port != TW::Y)
|
||||
return false;
|
||||
if (!port.cell->type.in(ID($not), ID($_NOT_), ID($lut)))
|
||||
if (!port.cell->type.in(TW($not), TW($_NOT_), TW($lut)))
|
||||
return false;
|
||||
log_assert(d_lut == nullptr);
|
||||
d_lut = port.cell;
|
||||
|
|
@ -157,9 +157,9 @@ struct OptFfInvWorker
|
|||
return false;
|
||||
if (port.port != TW::A)
|
||||
return false;
|
||||
if (port.cell->type.in(ID($not), ID($_NOT_))) {
|
||||
if (port.cell->type.in(TW($not), TW($_NOT_))) {
|
||||
// OK
|
||||
} else if (port.cell->type.in(ID($lut))) {
|
||||
} else if (port.cell->type.in(TW($lut))) {
|
||||
if (port.cell->getParam(ID::WIDTH) != 1)
|
||||
return false;
|
||||
if (port.cell->getParam(ID::LUT).as_int() != 1)
|
||||
|
|
@ -176,7 +176,7 @@ struct OptFfInvWorker
|
|||
ff.sig_q = q_inv->getPort(TW::Y);
|
||||
module->remove(q_inv);
|
||||
|
||||
if (d_lut->type == ID($lut)) {
|
||||
if (d_lut->type == TW($lut)) {
|
||||
Const mask = d_lut->getParam(ID::LUT);
|
||||
Const::Builder new_mask_builder(GetSize(mask));
|
||||
for (int i = 0; i < GetSize(mask); i++) {
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ struct ModuleIndex {
|
|||
if (!port || (!port->port_input && !port->port_output) || port->width != value.size()) {
|
||||
log_error("Port %s connected on instance %s not found in module %s"
|
||||
" or width is not matching\n",
|
||||
port_name.unescape(), instantiation, module);
|
||||
design->twines.unescaped_str(port_name), instantiation, module);
|
||||
}
|
||||
|
||||
if (port->port_input && port->port_output) {
|
||||
|
|
@ -145,12 +145,12 @@ struct ModuleIndex {
|
|||
|
||||
if (nunused > 0) {
|
||||
log("Disconnected %d input bits of instance '%s' (type '%s') in '%s'\n",
|
||||
nunused, instantiation, instantiation->type.unescape(), parent.module);
|
||||
nunused, instantiation, design->twines.unescaped_str(instantiation->type), parent.module);
|
||||
changed = true;
|
||||
}
|
||||
if (nconstants > 0) {
|
||||
log("Substituting constant for %d output bits of instance '%s' (type '%s') in '%s'\n",
|
||||
nconstants, instantiation, instantiation->type.unescape(), parent.module);
|
||||
nconstants, instantiation, design->twines.unescaped_str(instantiation->type), parent.module);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -163,8 +163,8 @@ struct ModuleIndex {
|
|||
SigSpec new_tie;
|
||||
|
||||
for (auto port_bit : class_) {
|
||||
if (instantiation->connections_.count(port_bit.wire->name)) {
|
||||
SigBit bit = instantiation->connections_.at(port_bit.wire->name)[port_bit.offset];
|
||||
if (instantiation->connections_.count(port_bit.wire->meta_->name)) {
|
||||
SigBit bit = instantiation->connections_.at(port_bit.wire->meta_->name)[port_bit.offset];
|
||||
if (parent.used.check(bit)) {
|
||||
if (!new_tie.empty()) {
|
||||
severed_port_bits.append(port_bit);
|
||||
|
|
@ -181,7 +181,7 @@ struct ModuleIndex {
|
|||
|
||||
severed_port_bits.sort_and_unify();
|
||||
for (auto chunk : severed_port_bits.chunks()) {
|
||||
SigSpec &value = instantiation->connections_.at(chunk.wire->name);
|
||||
SigSpec &value = instantiation->connections_.at(chunk.wire->meta_->name);
|
||||
SigSpec dummy = parent.module->addWire(NEW_TWINE_SUFFIX("tie_together"), chunk.width);
|
||||
for (int i = 0; i < chunk.width; i++)
|
||||
value[chunk.offset + i] = dummy[i];
|
||||
|
|
@ -189,7 +189,7 @@ struct ModuleIndex {
|
|||
|
||||
if (ntie_togethers > 0) {
|
||||
log("Replacing %d output bits with tie-togethers on instance '%s' of '%s' in '%s'\n",
|
||||
ntie_togethers, instantiation, instantiation->type.unescape(), parent.module);
|
||||
ntie_togethers, instantiation, design->twines.unescaped_str(instantiation->type), parent.module);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
|
|
@ -290,7 +290,7 @@ struct UsageData {
|
|||
if (!port || (!port->port_input && !port->port_output) || port->width != value.size()) {
|
||||
log_error("Port %s connected on instance %s not found in module %s"
|
||||
" or width is not matching\n",
|
||||
port_name.unescape(), instance, module);
|
||||
module->design->twines.unescaped_str(port_name), instance, module);
|
||||
}
|
||||
|
||||
if (port->port_input && port->port_output) {
|
||||
|
|
@ -338,7 +338,7 @@ struct UsageData {
|
|||
|
||||
dict<SigBit, SigBit> replacement_map;
|
||||
for (auto chunk : disconnect_outputs.chunks()) {
|
||||
Wire *repl_wire = module->addWire(module->uniquify(std::string("$") + chunk.wire->name.str()), chunk.size());
|
||||
Wire *repl_wire = module->addWire(module->uniquify(Twine{std::string("$") + chunk.wire->name.str()}), chunk.size());
|
||||
for (int i = 0; i < repl_wire->width; i++)
|
||||
replacement_map[SigSpec(chunk)[i]] = SigBit(repl_wire, i);
|
||||
}
|
||||
|
|
@ -454,7 +454,7 @@ struct OptHierPass : Pass {
|
|||
for (auto module : d->modules()) {
|
||||
for (auto cell : module->cells()) {
|
||||
if (usage_datas.count(cell->type)) {
|
||||
log_debug("Account for instance %s of %s in %s\n", cell, cell->type.unescape(), module);
|
||||
log_debug("Account for instance %s of %s in %s\n", cell, cell->type.unescaped(), module);
|
||||
usage_datas.at(cell->type).refine(cell, indices.at(module->name));
|
||||
}
|
||||
}
|
||||
|
|
@ -471,7 +471,7 @@ struct OptHierPass : Pass {
|
|||
|
||||
for (auto cell : module->cells()) {
|
||||
if (indices.count(cell->type)) {
|
||||
log_debug("Applying changes to instance %s of %s in %s\n", cell, cell->type.unescape(), module);
|
||||
log_debug("Applying changes to instance %s of %s in %s\n", cell, cell->type.unescaped(), module);
|
||||
did_something |= indices.at(cell->type).apply_changes(parent_index, cell);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ struct OptLutWorker
|
|||
log("Discovering LUTs.\n");
|
||||
for (auto cell : module->selected_cells())
|
||||
{
|
||||
if (cell->type == ID($lut))
|
||||
if (cell->type == TW($lut))
|
||||
{
|
||||
if (cell->has_keep_attr())
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ struct OptLutInsPass : public Pass {
|
|||
std::vector<SigBit> output;
|
||||
bool ignore_const = false;
|
||||
if (techname == "") {
|
||||
if (cell->type != ID($lut))
|
||||
if (cell->type != TW($lut))
|
||||
continue;
|
||||
inputs = cell->getPort(TW::A);
|
||||
output = cell->getPort(TW::Y);
|
||||
|
|
|
|||
|
|
@ -108,13 +108,13 @@ struct OptMemPass : public Pass {
|
|||
}
|
||||
State bit;
|
||||
if (!always_0[i]) {
|
||||
log("%s.%s: removing const-1 lane %d\n", module->name.unescape(), mem.memid.unescape(), i);
|
||||
log("%s.%s: removing const-1 lane %d\n", design->twines.unescaped_str(module->name), design->twines.unescaped_str(mem.memid), i);
|
||||
bit = State::S1;
|
||||
} else if (!always_1[i]) {
|
||||
log("%s.%s: removing const-0 lane %d\n", module->name.unescape(), mem.memid.unescape(), i);
|
||||
log("%s.%s: removing const-0 lane %d\n", design->twines.unescaped_str(module->name), design->twines.unescaped_str(mem.memid), i);
|
||||
bit = State::S0;
|
||||
} else {
|
||||
log("%s.%s: removing const-x lane %d\n", module->name.unescape(), mem.memid.unescape(), i);
|
||||
log("%s.%s: removing const-x lane %d\n", design->twines.unescaped_str(module->name), design->twines.unescaped_str(mem.memid), i);
|
||||
bit = State::Sx;
|
||||
}
|
||||
// Reconnect read port data.
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ struct OptMemFeedbackWorker
|
|||
{
|
||||
auto &port = mem.wr_ports[i];
|
||||
|
||||
log(" Analyzing %s.%s write port %d.\n", module, mem.memid.unescape(), i);
|
||||
log(" Analyzing %s.%s write port %d.\n", module, design->twines.unescaped_str(mem.memid), i);
|
||||
|
||||
for (int sub = 0; sub < (1 << port.wide_log2); sub++)
|
||||
{
|
||||
|
|
@ -232,7 +232,7 @@ struct OptMemFeedbackWorker
|
|||
|
||||
// Okay, let's do it.
|
||||
|
||||
log("Populating enable bits on write ports of memory %s.%s with async read feedback:\n", module, mem.memid.unescape());
|
||||
log("Populating enable bits on write ports of memory %s.%s with async read feedback:\n", module, design->twines.unescaped_str(mem.memid));
|
||||
|
||||
// If a write port has a feedback path that we're about to bypass,
|
||||
// but also has priority over some other write port, the feedback
|
||||
|
|
@ -293,7 +293,7 @@ struct OptMemFeedbackWorker
|
|||
|
||||
for (auto cell : module->cells())
|
||||
{
|
||||
if (cell->type == ID($mux))
|
||||
if (cell->type == TW($mux))
|
||||
{
|
||||
RTLIL::SigSpec sig_a = sigmap_xmux(cell->getPort(TW::A));
|
||||
RTLIL::SigSpec sig_b = sigmap_xmux(cell->getPort(TW::B));
|
||||
|
|
@ -304,7 +304,7 @@ struct OptMemFeedbackWorker
|
|||
sigmap_xmux.add(cell->getPort(TW::Y), sig_a);
|
||||
}
|
||||
|
||||
if (cell->type.in(ID($mux), ID($pmux)))
|
||||
if (cell->type.in(TW($mux), TW($pmux)))
|
||||
{
|
||||
std::vector<RTLIL::SigBit> sig_y = sigmap(cell->getPort(TW::Y));
|
||||
for (int i = 0; i < int(sig_y.size()); i++)
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ struct OptMemWidenPass : public Pass {
|
|||
factor_log2 = port.wide_log2;
|
||||
if (factor_log2 == 0)
|
||||
continue;
|
||||
log("Widening base width of memory %s in module %s by factor %d.\n", mem.memid.unescape(), design->twines.str(module->meta_->name).c_str(), 1 << factor_log2);
|
||||
log("Widening base width of memory %s in module %s by factor %d.\n", design->twines.unescaped_str(mem.memid), design->twines.str(module->meta_->name).c_str(), 1 << factor_log2);
|
||||
total_count++;
|
||||
// The inits are too messy to expand one-by-one, for they may
|
||||
// collide with one another after expansion. Just hit it with
|
||||
|
|
|
|||
|
|
@ -121,18 +121,18 @@ struct OptMergeThreadWorker : public CellHasher
|
|||
const RTLIL::Cell *cell = module->cell_at(cell_index);
|
||||
if (!module->selected(cell))
|
||||
continue;
|
||||
if (cell->type.in(ID($meminit), ID($meminit_v2), ID($mem), ID($mem_v2))) {
|
||||
if (cell->type.in(TW($meminit), TW($meminit_v2), TW($mem), TW($mem_v2))) {
|
||||
// Ignore those for performance: meminit can have an excessively large port,
|
||||
// mem can have an excessively large parameter holding the init data
|
||||
continue;
|
||||
}
|
||||
if (cell->type == ID($scopeinfo))
|
||||
if (cell->type == TW($scopeinfo))
|
||||
continue;
|
||||
if (mode_keepdc && has_dont_care_initval(cell))
|
||||
continue;
|
||||
if (!cell->known())
|
||||
continue;
|
||||
if (!mode_share_all && !ct.cell_known(cell->type))
|
||||
if (!mode_share_all && !ct.cell_known(cell->type_impl))
|
||||
continue;
|
||||
|
||||
Hasher::hash_t h = hash_cell_function(cell, Hasher()).yield();
|
||||
|
|
@ -397,20 +397,20 @@ struct OptMergePass : public Pass {
|
|||
ct.setup_stdcells();
|
||||
ct.setup_stdcells_mem();
|
||||
if (mode_nomux) {
|
||||
ct.cell_types.erase(ID($mux));
|
||||
ct.cell_types.erase(ID($pmux));
|
||||
ct.cell_types.erase(TW($mux));
|
||||
ct.cell_types.erase(TW($pmux));
|
||||
}
|
||||
ct.cell_types.erase(ID($tribuf));
|
||||
ct.cell_types.erase(ID($_TBUF_));
|
||||
ct.cell_types.erase(ID($anyseq));
|
||||
ct.cell_types.erase(ID($anyconst));
|
||||
ct.cell_types.erase(ID($allseq));
|
||||
ct.cell_types.erase(ID($allconst));
|
||||
ct.cell_types.erase(TW($tribuf));
|
||||
ct.cell_types.erase(TW($_TBUF_));
|
||||
ct.cell_types.erase(TW($anyseq));
|
||||
ct.cell_types.erase(TW($anyconst));
|
||||
ct.cell_types.erase(TW($allseq));
|
||||
ct.cell_types.erase(TW($allconst));
|
||||
// Synthetic driver cells signorm creates for module ports — must
|
||||
// never be folded into one another, otherwise distinct ports collapse.
|
||||
ct.cell_types.erase(ID($input_port));
|
||||
ct.cell_types.erase(ID($output_port));
|
||||
ct.cell_types.erase(ID($public));
|
||||
ct.cell_types.erase(TW($input_port));
|
||||
ct.cell_types.erase(TW($output_port));
|
||||
ct.cell_types.erase(TW($public));
|
||||
|
||||
// patcher.patch uses connect_incremental + fanout queries.
|
||||
design->sigNormalize(true);
|
||||
|
|
|
|||
|
|
@ -91,21 +91,21 @@ struct CellHasher
|
|||
{
|
||||
// TODO: when implemented, use celltypes to match:
|
||||
// (builtin || stdcell) && (unary || binary) && symmetrical
|
||||
if (cell->type.in(ID($and), ID($or), ID($xor), ID($xnor), ID($add), ID($mul),
|
||||
ID($logic_and), ID($logic_or), ID($_AND_), ID($_OR_), ID($_XOR_))) {
|
||||
if (cell->type.in(TW($and), TW($or), TW($xor), TW($xnor), TW($add), TW($mul),
|
||||
TW($logic_and), TW($logic_or), TW($_AND_), TW($_OR_), TW($_XOR_))) {
|
||||
hashlib::commutative_hash comm;
|
||||
comm.eat(map_sig(cell->getPort(TW::A)));
|
||||
comm.eat(map_sig(cell->getPort(TW::B)));
|
||||
h = comm.hash_into(h);
|
||||
} else if (cell->type.in(ID($reduce_xor), ID($reduce_xnor))) {
|
||||
} else if (cell->type.in(TW($reduce_xor), TW($reduce_xnor))) {
|
||||
SigSpec a = map_sig(cell->getPort(TW::A));
|
||||
a.sort();
|
||||
h = a.hash_into(h);
|
||||
} else if (cell->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_bool))) {
|
||||
} else if (cell->type.in(TW($reduce_and), TW($reduce_or), TW($reduce_bool))) {
|
||||
SigSpec a = map_sig(cell->getPort(TW::A));
|
||||
a.sort_and_unify();
|
||||
h = a.hash_into(h);
|
||||
} else if (cell->type == ID($pmux)) {
|
||||
} else if (cell->type == TW($pmux)) {
|
||||
SigSpec sig_s = map_sig(cell->getPort(TW::S));
|
||||
SigSpec sig_b = map_sig(cell->getPort(TW::B));
|
||||
h = hash_pmux_in(sig_s, sig_b, h);
|
||||
|
|
@ -177,8 +177,8 @@ struct CellHasher
|
|||
}
|
||||
}
|
||||
|
||||
if (cell1->type.in(ID($and), ID($or), ID($xor), ID($xnor), ID($add), ID($mul),
|
||||
ID($logic_and), ID($logic_or), ID($_AND_), ID($_OR_), ID($_XOR_))) {
|
||||
if (cell1->type.in(TW($and), TW($or), TW($xor), TW($xnor), TW($add), TW($mul),
|
||||
TW($logic_and), TW($logic_or), TW($_AND_), TW($_OR_), TW($_XOR_))) {
|
||||
if (conn1.at(TW::A) < conn1.at(TW::B)) {
|
||||
std::swap(conn1[TW::A], conn1[TW::B]);
|
||||
}
|
||||
|
|
@ -186,15 +186,15 @@ struct CellHasher
|
|||
std::swap(conn2[TW::A], conn2[TW::B]);
|
||||
}
|
||||
} else
|
||||
if (cell1->type.in(ID($reduce_xor), ID($reduce_xnor))) {
|
||||
if (cell1->type.in(TW($reduce_xor), TW($reduce_xnor))) {
|
||||
conn1[TW::A].sort();
|
||||
conn2[TW::A].sort();
|
||||
} else
|
||||
if (cell1->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_bool))) {
|
||||
if (cell1->type.in(TW($reduce_and), TW($reduce_or), TW($reduce_bool))) {
|
||||
conn1[TW::A].sort_and_unify();
|
||||
conn2[TW::A].sort_and_unify();
|
||||
} else
|
||||
if (cell1->type == ID($pmux)) {
|
||||
if (cell1->type == TW($pmux)) {
|
||||
sort_pmux_conn(conn1);
|
||||
sort_pmux_conn(conn2);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,20 +44,20 @@ using MergeableTypes = StaticCellTypes::Categories::Category;
|
|||
// is intentionally not included, so $anyinit stays excluded
|
||||
static constexpr MergeableTypes build_mergeable_types(bool nomux) {
|
||||
auto c = StaticCellTypes::categories.is_known;
|
||||
c.set_id(ID($anyinit), false);
|
||||
c.set_id(ID($tribuf), false);
|
||||
c.set_id(ID($_TBUF_), false);
|
||||
c.set_id(ID($anyseq), false);
|
||||
c.set_id(ID($anyconst), false);
|
||||
c.set_id(ID($allseq), false);
|
||||
c.set_id(ID($allconst), false);
|
||||
c.set_id(ID($connect), false);
|
||||
c.set_id(ID($input_port), false);
|
||||
c.set_id(ID($output_port), false);
|
||||
c.set_id(ID($public), false);
|
||||
c.set_id(TW($anyinit), false);
|
||||
c.set_id(TW($tribuf), false);
|
||||
c.set_id(TW($_TBUF_), false);
|
||||
c.set_id(TW($anyseq), false);
|
||||
c.set_id(TW($anyconst), false);
|
||||
c.set_id(TW($allseq), false);
|
||||
c.set_id(TW($allconst), false);
|
||||
c.set_id(TW($connect), false);
|
||||
c.set_id(TW($input_port), false);
|
||||
c.set_id(TW($output_port), false);
|
||||
c.set_id(TW($public), false);
|
||||
if (nomux) {
|
||||
c.set_id(ID($mux), false);
|
||||
c.set_id(ID($pmux), false);
|
||||
c.set_id(TW($mux), false);
|
||||
c.set_id(TW($pmux), false);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
|
@ -161,18 +161,18 @@ struct OptMergeIncWorker
|
|||
for (auto cell : module->cells()) {
|
||||
if (!design->selected(module, cell))
|
||||
continue;
|
||||
if (cell->type.in(ID($meminit), ID($meminit_v2), ID($mem), ID($mem_v2))) {
|
||||
if (cell->type.in(TW($meminit), TW($meminit_v2), TW($mem), TW($mem_v2))) {
|
||||
// Ignore those for performance: meminit can have an excessively large port,
|
||||
// mem can have an excessively large parameter holding the init data
|
||||
continue;
|
||||
}
|
||||
if (cell->type == ID($scopeinfo))
|
||||
if (cell->type == TW($scopeinfo))
|
||||
continue;
|
||||
if (mode_keepdc && hasher.has_dont_care_initval(cell))
|
||||
continue;
|
||||
if (!cell->known())
|
||||
continue;
|
||||
if (!mode_share_all && !ct(cell->type))
|
||||
if (!mode_share_all && !ct(cell->type_impl))
|
||||
continue;
|
||||
|
||||
cells.push_back(cell);
|
||||
|
|
@ -190,18 +190,18 @@ struct OptMergeIncWorker
|
|||
for (auto cell : module->dirty_cells(timestamp)) {
|
||||
if (!design->selected(module, cell))
|
||||
continue;
|
||||
if (cell->type.in(ID($meminit), ID($meminit_v2), ID($mem), ID($mem_v2))) {
|
||||
if (cell->type.in(TW($meminit), TW($meminit_v2), TW($mem), TW($mem_v2))) {
|
||||
// Ignore those for performance: meminit can have an excessively large port,
|
||||
// mem can have an excessively large parameter holding the init data
|
||||
continue;
|
||||
}
|
||||
if (cell->type == ID($scopeinfo))
|
||||
if (cell->type == TW($scopeinfo))
|
||||
continue;
|
||||
if (mode_keepdc && hasher.has_dont_care_initval(cell))
|
||||
continue;
|
||||
if (!cell->known())
|
||||
continue;
|
||||
if (!mode_share_all && !ct(cell->type))
|
||||
if (!mode_share_all && !ct(cell->type_impl))
|
||||
continue;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -232,7 +232,7 @@ struct OptMuxtreeWorker
|
|||
|
||||
for (auto cell : module->cells())
|
||||
{
|
||||
if (cell->type.in(ID($mux), ID($pmux)))
|
||||
if (cell->type.in(TW($mux), TW($pmux)))
|
||||
track_mux(cell);
|
||||
else
|
||||
see_non_mux_cell(cell);
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ struct OptReduceWorker
|
|||
for (auto &bit : sig_a)
|
||||
{
|
||||
if (bit == RTLIL::State::S0) {
|
||||
if (cell->type == ID($reduce_and)) {
|
||||
if (cell->type == TW($reduce_and)) {
|
||||
new_sig_a_bits.clear();
|
||||
new_sig_a_bits.insert(RTLIL::State::S0);
|
||||
break;
|
||||
|
|
@ -58,7 +58,7 @@ struct OptReduceWorker
|
|||
continue;
|
||||
}
|
||||
if (bit == RTLIL::State::S1) {
|
||||
if (cell->type == ID($reduce_or)) {
|
||||
if (cell->type == TW($reduce_or)) {
|
||||
new_sig_a_bits.clear();
|
||||
new_sig_a_bits.insert(RTLIL::State::S1);
|
||||
break;
|
||||
|
|
@ -90,7 +90,7 @@ struct OptReduceWorker
|
|||
new_sig_a.sort_and_unify();
|
||||
|
||||
if (GetSize(new_sig_a) == 0)
|
||||
new_sig_a = (cell->type == ID($reduce_or)) ? State::S0 : State::S1;
|
||||
new_sig_a = (cell->type == TW($reduce_or)) ? State::S0 : State::S1;
|
||||
|
||||
if (new_sig_a != sig_a || sig_a.size() != cell->getPort(TW::A).size()) {
|
||||
log(" New input vector for %s cell %s: %s\n", cell->type, cell->name, log_signal(new_sig_a));
|
||||
|
|
@ -126,7 +126,7 @@ struct OptReduceWorker
|
|||
RTLIL::SigSpec this_s{this_s_bit};
|
||||
if (this_s.size() > 1)
|
||||
{
|
||||
RTLIL::Cell *reduce_or_cell = module->addCell(NEW_TWINE, ID($reduce_or));
|
||||
RTLIL::Cell *reduce_or_cell = module->addCell(NEW_TWINE, TW($reduce_or));
|
||||
reduce_or_cell->setPort(TW::A, this_s);
|
||||
reduce_or_cell->parameters[ID::A_SIGNED] = RTLIL::Const(0);
|
||||
reduce_or_cell->parameters[ID::A_WIDTH] = RTLIL::Const(this_s.size());
|
||||
|
|
@ -151,7 +151,7 @@ struct OptReduceWorker
|
|||
return;
|
||||
}
|
||||
|
||||
if (new_sig_s.size() != sig_s.size() || (new_sig_s.size() == 1 && cell->type == ID($pmux))) {
|
||||
if (new_sig_s.size() != sig_s.size() || (new_sig_s.size() == 1 && cell->type == TW($pmux))) {
|
||||
log(" New ctrl vector for %s cell %s: %s\n", cell->type, cell->name, log_signal(new_sig_s));
|
||||
did_something = true;
|
||||
total_count++;
|
||||
|
|
@ -338,7 +338,7 @@ struct OptReduceWorker
|
|||
SigSpec sig_y = assign_map(cell->getPort(TW::Y));
|
||||
int width = GetSize(sig_y);
|
||||
|
||||
if (cell->type != ID($bmux))
|
||||
if (cell->type != TW($bmux))
|
||||
sig_b = assign_map(cell->getPort(TW::B));
|
||||
|
||||
RTLIL::SigSig old_sig_conn;
|
||||
|
|
@ -386,7 +386,7 @@ struct OptReduceWorker
|
|||
if (GetSize(swizzle) != width)
|
||||
{
|
||||
log(" Consolidated identical input bits for %s cell %s:\n", cell->type, cell->name);
|
||||
if (cell->type != ID($bmux)) {
|
||||
if (cell->type != TW($bmux)) {
|
||||
log(" Old ports: A=%s, B=%s, Y=%s\n", log_signal(cell->getPort(TW::A)),
|
||||
log_signal(cell->getPort(TW::B)), log_signal(cell->getPort(TW::Y)));
|
||||
} else {
|
||||
|
|
@ -403,7 +403,7 @@ struct OptReduceWorker
|
|||
new_sig_a.append(sig_a[i+j]);
|
||||
cell->setPort(TW::A, new_sig_a);
|
||||
|
||||
if (cell->type != ID($bmux)) {
|
||||
if (cell->type != TW($bmux)) {
|
||||
SigSpec new_sig_b;
|
||||
for (int i = 0; i < GetSize(sig_b); i += width)
|
||||
for (int j: swizzle)
|
||||
|
|
@ -418,7 +418,7 @@ struct OptReduceWorker
|
|||
|
||||
cell->parameters[ID::WIDTH] = RTLIL::Const(GetSize(swizzle));
|
||||
|
||||
if (cell->type != ID($bmux)) {
|
||||
if (cell->type != TW($bmux)) {
|
||||
log(" New ports: A=%s, B=%s, Y=%s\n", log_signal(cell->getPort(TW::A)),
|
||||
log_signal(cell->getPort(TW::B)), log_signal(cell->getPort(TW::Y)));
|
||||
} else {
|
||||
|
|
@ -520,14 +520,14 @@ struct OptReduceWorker
|
|||
SigPool mem_wren_sigs;
|
||||
for (auto &cell_it : module->cells_) {
|
||||
RTLIL::Cell *cell = cell_it.second;
|
||||
if (cell->type.in(ID($mem), ID($mem_v2)))
|
||||
if (cell->type.in(TW($mem), TW($mem_v2)))
|
||||
mem_wren_sigs.add(assign_map(cell->getPort(TW::WR_EN)));
|
||||
if (cell->type.in(ID($memwr), ID($memwr_v2)))
|
||||
if (cell->type.in(TW($memwr), TW($memwr_v2)))
|
||||
mem_wren_sigs.add(assign_map(cell->getPort(TW::EN)));
|
||||
}
|
||||
for (auto &cell_it : module->cells_) {
|
||||
RTLIL::Cell *cell = cell_it.second;
|
||||
if (cell->type == ID($dff) && mem_wren_sigs.check_any(assign_map(cell->getPort(TW::Q))))
|
||||
if (cell->type == TW($dff) && mem_wren_sigs.check_any(assign_map(cell->getPort(TW::Q))))
|
||||
mem_wren_sigs.add(assign_map(cell->getPort(TW::D)));
|
||||
}
|
||||
|
||||
|
|
@ -536,7 +536,7 @@ struct OptReduceWorker
|
|||
keep_expanding_mem_wren_sigs = false;
|
||||
for (auto &cell_it : module->cells_) {
|
||||
RTLIL::Cell *cell = cell_it.second;
|
||||
if (cell->type == ID($mux) && mem_wren_sigs.check_any(assign_map(cell->getPort(TW::Y)))) {
|
||||
if (cell->type == TW($mux) && mem_wren_sigs.check_any(assign_map(cell->getPort(TW::Y)))) {
|
||||
if (!mem_wren_sigs.check_all(assign_map(cell->getPort(TW::A))) ||
|
||||
!mem_wren_sigs.check_all(assign_map(cell->getPort(TW::B))))
|
||||
keep_expanding_mem_wren_sigs = true;
|
||||
|
|
@ -553,7 +553,7 @@ struct OptReduceWorker
|
|||
// merge trees of reduce_* cells to one single cell and unify input vectors
|
||||
// (only handle reduce_and and reduce_or for various reasons)
|
||||
|
||||
const IdString type_list[] = { ID($reduce_or), ID($reduce_and) };
|
||||
const IdString type_list[] = { TW($reduce_or), TW($reduce_and) };
|
||||
for (auto type : type_list)
|
||||
{
|
||||
SigSet<RTLIL::Cell*> drivers;
|
||||
|
|
@ -577,13 +577,13 @@ struct OptReduceWorker
|
|||
|
||||
for (auto cell : module->selected_cells())
|
||||
{
|
||||
if (!cell->type.in(ID($mux), ID($pmux), ID($bmux), ID($demux)))
|
||||
if (!cell->type.in(TW($mux), TW($pmux), TW($bmux), TW($demux)))
|
||||
continue;
|
||||
|
||||
// this optimization is to aggressive for most coarse-grain applications.
|
||||
// but we always want it for multiplexers driving write enable ports.
|
||||
if (do_fine || mem_wren_sigs.check_any(assign_map(cell->getPort(TW::Y)))) {
|
||||
if (cell->type == ID($demux)) {
|
||||
if (cell->type == TW($demux)) {
|
||||
if (opt_demux_bits(cell))
|
||||
continue;
|
||||
} else {
|
||||
|
|
@ -592,11 +592,11 @@ struct OptReduceWorker
|
|||
}
|
||||
}
|
||||
|
||||
if (cell->type.in(ID($mux), ID($pmux)))
|
||||
if (cell->type.in(TW($mux), TW($pmux)))
|
||||
opt_pmux(cell);
|
||||
else if (cell->type == ID($bmux))
|
||||
else if (cell->type == TW($bmux))
|
||||
opt_bmux(cell);
|
||||
else if (cell->type == ID($demux))
|
||||
else if (cell->type == TW($demux))
|
||||
opt_demux(cell);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,27 +81,27 @@ struct ExtSigSpec {
|
|||
bool operator==(const ExtSigSpec &other) const { return is_signed == other.is_signed && sign == other.sign && sig == other.sig && semantics == other.semantics; }
|
||||
};
|
||||
|
||||
#define FINE_BITWISE_OPS ID($_AND_), ID($_NAND_), ID($_OR_), ID($_NOR_), ID($_XOR_), ID($_XNOR_), ID($_ANDNOT_), ID($_ORNOT_)
|
||||
#define FINE_BITWISE_OPS TW($_AND_), TW($_NAND_), TW($_OR_), TW($_NOR_), TW($_XOR_), TW($_XNOR_), TW($_ANDNOT_), TW($_ORNOT_)
|
||||
|
||||
#define BITWISE_OPS FINE_BITWISE_OPS, ID($and), ID($or), ID($xor), ID($xnor)
|
||||
#define BITWISE_OPS FINE_BITWISE_OPS, TW($and), TW($or), TW($xor), TW($xnor)
|
||||
|
||||
#define REDUCTION_OPS ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool), ID($reduce_nand)
|
||||
#define REDUCTION_OPS TW($reduce_and), TW($reduce_or), TW($reduce_xor), TW($reduce_xnor), TW($reduce_bool), TW($reduce_nand)
|
||||
|
||||
#define LOGICAL_OPS ID($logic_and), ID($logic_or)
|
||||
#define LOGICAL_OPS TW($logic_and), TW($logic_or)
|
||||
|
||||
#define SHIFT_OPS ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx)
|
||||
#define SHIFT_OPS TW($shl), TW($shr), TW($sshl), TW($sshr), TW($shift), TW($shiftx)
|
||||
|
||||
#define RELATIONAL_OPS ID($lt), ID($le), ID($eq), ID($ne), ID($eqx), ID($nex), ID($ge), ID($gt)
|
||||
#define RELATIONAL_OPS TW($lt), TW($le), TW($eq), TW($ne), TW($eqx), TW($nex), TW($ge), TW($gt)
|
||||
|
||||
bool cell_supported(RTLIL::Cell *cell)
|
||||
{
|
||||
if (cell->type.in(ID($alu))) {
|
||||
if (cell->type.in(TW($alu))) {
|
||||
RTLIL::SigSpec sig_bi = cell->getPort(TW::BI);
|
||||
RTLIL::SigSpec sig_ci = cell->getPort(TW::CI);
|
||||
|
||||
if (sig_bi.is_fully_const() && sig_ci.is_fully_const() && sig_bi == sig_ci)
|
||||
return true;
|
||||
} else if (cell->type.in(LOGICAL_OPS, SHIFT_OPS, BITWISE_OPS, RELATIONAL_OPS, ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($divfloor), ID($modfloor), ID($concat))) {
|
||||
} else if (cell->type.in(LOGICAL_OPS, SHIFT_OPS, BITWISE_OPS, RELATIONAL_OPS, TW($add), TW($sub), TW($mul), TW($div), TW($mod), TW($divfloor), TW($modfloor), TW($concat))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -113,7 +113,7 @@ std::map<IdString, IdString> mergeable_type_map;
|
|||
bool mergeable(RTLIL::Cell *a, RTLIL::Cell *b)
|
||||
{
|
||||
if (mergeable_type_map.empty()) {
|
||||
mergeable_type_map.insert({ID($sub), ID($add)});
|
||||
mergeable_type_map.insert({TW($sub), TW($add)});
|
||||
}
|
||||
auto a_type = a->type;
|
||||
if (mergeable_type_map.count(a_type))
|
||||
|
|
@ -128,10 +128,10 @@ bool mergeable(RTLIL::Cell *a, RTLIL::Cell *b)
|
|||
|
||||
TwineRef decode_port_semantics(RTLIL::Cell *cell, TwineRef port_name)
|
||||
{
|
||||
if (cell->type.in(ID($lt), ID($le), ID($ge), ID($gt), ID($div), ID($mod), ID($divfloor), ID($modfloor), ID($concat), SHIFT_OPS) && port_name == TW::B)
|
||||
if (cell->type.in(TW($lt), TW($le), TW($ge), TW($gt), TW($div), TW($mod), TW($divfloor), TW($modfloor), TW($concat), SHIFT_OPS) && port_name == TW::B)
|
||||
return port_name;
|
||||
|
||||
if (cell->type.in(ID($_ANDNOT_), ID($_ORNOT_)))
|
||||
if (cell->type.in(TW($_ANDNOT_), TW($_ORNOT_)))
|
||||
return port_name;
|
||||
|
||||
return Twine::Null;
|
||||
|
|
@ -139,9 +139,9 @@ TwineRef decode_port_semantics(RTLIL::Cell *cell, TwineRef port_name)
|
|||
|
||||
RTLIL::SigSpec decode_port_sign(RTLIL::Cell *cell, TwineRef port_name) {
|
||||
|
||||
if (cell->type == ID($alu) && port_name == TW::B)
|
||||
if (cell->type == TW($alu) && port_name == TW::B)
|
||||
return cell->getPort(TW::BI);
|
||||
else if (cell->type == ID($sub) && port_name == TW::B)
|
||||
else if (cell->type == TW($sub) && port_name == TW::B)
|
||||
return RTLIL::Const(1, 1);
|
||||
|
||||
return RTLIL::Const(0, 1);
|
||||
|
|
@ -247,7 +247,7 @@ void merge_operators(RTLIL::Module *module, RTLIL::Cell *mux, const std::vector<
|
|||
mux_to_oper = module->Pmux(NEW_TWINE, shared_pmux_a, shared_pmux_b, shared_pmux_s);
|
||||
}
|
||||
|
||||
if (shared_op->type.in(ID($alu))) {
|
||||
if (shared_op->type.in(TW($alu))) {
|
||||
shared_op->setPort(TW::X, module->addWire(NEW_TWINE, GetSize(new_out)));
|
||||
shared_op->setPort(TW::CO, module->addWire(NEW_TWINE, GetSize(new_out)));
|
||||
}
|
||||
|
|
@ -365,7 +365,7 @@ struct OptSharePass : public Pass {
|
|||
dict<RTLIL::SigBit, int> bit_users;
|
||||
|
||||
for (auto cell : module->cells()) {
|
||||
if (cell->type.in(ID($input_port), ID($output_port), ID($public)))
|
||||
if (cell->type.in(TW($input_port), TW($output_port), TW($public)))
|
||||
continue;
|
||||
for (auto conn : cell->connections())
|
||||
for (auto bit : conn.second)
|
||||
|
|
@ -386,7 +386,7 @@ struct OptSharePass : public Pass {
|
|||
continue;
|
||||
|
||||
bool skip = false;
|
||||
if (cell->type == ID($alu)) {
|
||||
if (cell->type == TW($alu)) {
|
||||
for (TwineRef port_name : {TW::X, TW::CO}) {
|
||||
for (auto outbit : sigmap(cell->getPort(port_name)))
|
||||
if (bit_users[outbit] > 1)
|
||||
|
|
@ -417,7 +417,7 @@ struct OptSharePass : public Pass {
|
|||
std::vector<merged_op_t> merged_ops;
|
||||
|
||||
for (auto mux : module->selected_cells()) {
|
||||
if (!mux->type.in(ID($mux), ID($_MUX_), ID($pmux)))
|
||||
if (!mux->type.in(TW($mux), TW($_MUX_), TW($pmux)))
|
||||
continue;
|
||||
|
||||
int mux_port_size = GetSize(mux->getPort(TW::A));
|
||||
|
|
@ -564,7 +564,7 @@ struct OptSharePass : public Pass {
|
|||
log(" Found cells that share an operand and can be merged by moving the %s %s in front "
|
||||
"of "
|
||||
"them:\n",
|
||||
shared.mux->type.unescape(), shared.mux);
|
||||
design->twines.unescaped_str(shared.mux->type), shared.mux);
|
||||
for (const auto& op : shared.ports)
|
||||
log(" %s\n", op.op);
|
||||
log("\n");
|
||||
|
|
|
|||
|
|
@ -54,17 +54,17 @@ struct OnehotDatabase
|
|||
vector<SigSpec> inputs;
|
||||
SigSpec output;
|
||||
|
||||
if (cell->type.in(ID($adff), ID($adffe), ID($dff), ID($dffe), ID($sdff), ID($sdffe), ID($sdffce), ID($dlatch), ID($adlatch), ID($ff)))
|
||||
if (cell->type.in(TW($adff), TW($adffe), TW($dff), TW($dffe), TW($sdff), TW($sdffe), TW($sdffce), TW($dlatch), TW($adlatch), TW($ff)))
|
||||
{
|
||||
output = cell->getPort(TW::Q);
|
||||
if (cell->type.in(ID($adff), ID($adffe), ID($adlatch)))
|
||||
if (cell->type.in(TW($adff), TW($adffe), TW($adlatch)))
|
||||
inputs.push_back(cell->getParam(ID::ARST_VALUE));
|
||||
if (cell->type.in(ID($sdff), ID($sdffe), ID($sdffce)))
|
||||
if (cell->type.in(TW($sdff), TW($sdffe), TW($sdffce)))
|
||||
inputs.push_back(cell->getParam(ID::SRST_VALUE));
|
||||
inputs.push_back(cell->getPort(TW::D));
|
||||
}
|
||||
|
||||
if (cell->type.in(ID($mux), ID($pmux)))
|
||||
if (cell->type.in(TW($mux), TW($pmux)))
|
||||
{
|
||||
output = cell->getPort(TW::Y);
|
||||
inputs.push_back(cell->getPort(TW::A));
|
||||
|
|
@ -285,7 +285,7 @@ struct Pmux2ShiftxPass : public Pass {
|
|||
|
||||
for (auto cell : module->cells())
|
||||
{
|
||||
if (cell->type == ID($eq))
|
||||
if (cell->type == TW($eq))
|
||||
{
|
||||
dict<SigBit, State> bits;
|
||||
|
||||
|
|
@ -333,7 +333,7 @@ struct Pmux2ShiftxPass : public Pass {
|
|||
goto next_cell;
|
||||
}
|
||||
|
||||
if (cell->type == ID($logic_not))
|
||||
if (cell->type == TW($logic_not))
|
||||
{
|
||||
dict<SigBit, State> bits;
|
||||
|
||||
|
|
@ -359,10 +359,10 @@ struct Pmux2ShiftxPass : public Pass {
|
|||
|
||||
for (auto cell : module->selected_cells())
|
||||
{
|
||||
if (cell->type != ID($pmux))
|
||||
if (cell->type != TW($pmux))
|
||||
continue;
|
||||
|
||||
string src = cell->get_src_attribute();
|
||||
TwineRef src = cell->meta_->src;
|
||||
int width = cell->getParam(ID::WIDTH).as_int();
|
||||
int width_bits = ceil_log2(width);
|
||||
int extwidth = width;
|
||||
|
|
@ -777,7 +777,7 @@ struct OnehotPass : public Pass {
|
|||
|
||||
for (auto cell : module->selected_cells())
|
||||
{
|
||||
if (cell->type != ID($eq))
|
||||
if (cell->type != TW($eq))
|
||||
continue;
|
||||
|
||||
SigSpec A = sigmap(cell->getPort(TW::A));
|
||||
|
|
@ -851,7 +851,7 @@ struct OnehotPass : public Pass {
|
|||
}
|
||||
|
||||
RTLIL::Patch patcher(module, &sigmap);
|
||||
patcher.patch(cell, ID::Y, replacement);
|
||||
patcher.patch(cell, TW::Y, replacement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ struct ShareWorker
|
|||
queue_bits.insert(modwalker.signal_outputs.begin(), modwalker.signal_outputs.end());
|
||||
|
||||
for (auto &it : module->cells_)
|
||||
if (!StaticCellTypes::Compat::internals_nomem_noff(it.second->type)) {
|
||||
if (!StaticCellTypes::Compat::internals_nomem_noff(it.second->type_impl)) {
|
||||
pool<RTLIL::SigBit> &bits = modwalker.cell_inputs[it.second];
|
||||
queue_bits.insert(bits.begin(), bits.end());
|
||||
}
|
||||
|
|
@ -88,13 +88,13 @@ struct ShareWorker
|
|||
queue_bits.clear();
|
||||
|
||||
for (auto &pbit : portbits) {
|
||||
if ((pbit.cell->type == ID($mux) || pbit.cell->type == ID($pmux)) && visited_cells.count(pbit.cell) == 0) {
|
||||
if ((pbit.cell->type == TW($mux) || pbit.cell->type == TW($pmux)) && visited_cells.count(pbit.cell) == 0) {
|
||||
pool<RTLIL::SigBit> bits = modwalker.sigmap(pbit.cell->getPort(TW::S)).to_sigbit_pool();
|
||||
terminal_bits.insert(bits.begin(), bits.end());
|
||||
queue_bits.insert(bits.begin(), bits.end());
|
||||
visited_cells.insert(pbit.cell);
|
||||
}
|
||||
if (StaticCellTypes::Compat::internals_nomem_noff(pbit.cell->type) && visited_cells.count(pbit.cell) == 0) {
|
||||
if (StaticCellTypes::Compat::internals_nomem_noff(pbit.cell->type_impl) && visited_cells.count(pbit.cell) == 0) {
|
||||
pool<RTLIL::SigBit> &bits = modwalker.cell_inputs[pbit.cell];
|
||||
terminal_bits.insert(bits.begin(), bits.end());
|
||||
queue_bits.insert(bits.begin(), bits.end());
|
||||
|
|
@ -351,7 +351,7 @@ struct ShareWorker
|
|||
{
|
||||
for (auto cell : module->cells())
|
||||
{
|
||||
if (!design->selected(module, cell) || !modwalker.ct.cell_known(cell->type))
|
||||
if (!design->selected(module, cell) || !modwalker.ct.cell_known(cell->type_impl))
|
||||
continue;
|
||||
|
||||
for (auto &bit : modwalker.cell_outputs[cell])
|
||||
|
|
@ -362,7 +362,7 @@ struct ShareWorker
|
|||
not_a_muxed_cell:
|
||||
continue;
|
||||
|
||||
if (cell->type.in(ID($memrd), ID($memrd_v2))) {
|
||||
if (cell->type.in(TW($memrd), TW($memrd_v2))) {
|
||||
if (cell->parameters.at(ID::CLK_ENABLE).as_bool())
|
||||
continue;
|
||||
if (config.opt_aggressive || !modwalker.sigmap(cell->getPort(TW::ADDR)).is_fully_const())
|
||||
|
|
@ -370,19 +370,19 @@ struct ShareWorker
|
|||
continue;
|
||||
}
|
||||
|
||||
if (cell->type.in(ID($mul), ID($div), ID($mod), ID($divfloor), ID($modfloor))) {
|
||||
if (cell->type.in(TW($mul), TW($div), TW($mod), TW($divfloor), TW($modfloor))) {
|
||||
if (config.opt_aggressive || cell->parameters.at(ID::Y_WIDTH).as_int() >= 4)
|
||||
shareable_cells.insert(cell);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr))) {
|
||||
if (cell->type.in(TW($shl), TW($shr), TW($sshl), TW($sshr))) {
|
||||
if (config.opt_aggressive || cell->parameters.at(ID::Y_WIDTH).as_int() >= 8)
|
||||
shareable_cells.insert(cell);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (generic_ops(cell->type)) {
|
||||
if (generic_ops(cell->type_impl)) {
|
||||
if (config.opt_aggressive)
|
||||
shareable_cells.insert(cell);
|
||||
continue;
|
||||
|
|
@ -395,7 +395,7 @@ struct ShareWorker
|
|||
if (c1->type != c2->type)
|
||||
return false;
|
||||
|
||||
if (c1->type.in(ID($memrd), ID($memrd_v2)))
|
||||
if (c1->type.in(TW($memrd), TW($memrd_v2)))
|
||||
{
|
||||
if (c1->parameters.at(ID::MEMID).decode_string() != c2->parameters.at(ID::MEMID).decode_string())
|
||||
return false;
|
||||
|
|
@ -406,7 +406,7 @@ struct ShareWorker
|
|||
return true;
|
||||
}
|
||||
|
||||
if (config.generic_uni_ops(c1->type))
|
||||
if (config.generic_uni_ops(c1->type_impl))
|
||||
{
|
||||
if (!config.opt_aggressive)
|
||||
{
|
||||
|
|
@ -423,7 +423,7 @@ struct ShareWorker
|
|||
return true;
|
||||
}
|
||||
|
||||
if (config.generic_bin_ops(c1->type) || c1->type == ID($alu))
|
||||
if (config.generic_bin_ops(c1->type_impl) || c1->type == TW($alu))
|
||||
{
|
||||
if (!config.opt_aggressive)
|
||||
{
|
||||
|
|
@ -443,7 +443,7 @@ struct ShareWorker
|
|||
return true;
|
||||
}
|
||||
|
||||
if (config.generic_cbin_ops(c1->type))
|
||||
if (config.generic_cbin_ops(c1->type_impl))
|
||||
{
|
||||
if (!config.opt_aggressive)
|
||||
{
|
||||
|
|
@ -469,7 +469,7 @@ struct ShareWorker
|
|||
return true;
|
||||
}
|
||||
|
||||
if (c1->type == ID($macc))
|
||||
if (c1->type == TW($macc))
|
||||
{
|
||||
if (!config.opt_aggressive)
|
||||
if (share_macc(c1, c2) > 2 * min(bits_macc(c1), bits_macc(c2))) return false;
|
||||
|
|
@ -505,7 +505,7 @@ struct ShareWorker
|
|||
{
|
||||
log_assert(c1->type == c2->type);
|
||||
|
||||
if (config.generic_uni_ops(c1->type))
|
||||
if (config.generic_uni_ops(c1->type_impl))
|
||||
{
|
||||
if (c1->parameters.at(ID::A_SIGNED).as_bool() != c2->parameters.at(ID::A_SIGNED).as_bool())
|
||||
{
|
||||
|
|
@ -540,7 +540,7 @@ struct ShareWorker
|
|||
|
||||
RTLIL::Wire *y = module->addWire(NEW_TWINE, y_width);
|
||||
|
||||
RTLIL::Cell *supercell = module->addCell(NEW_TWINE, c1->type);
|
||||
RTLIL::Cell *supercell = module->addCell(NEW_TWINE, c1->type_impl);
|
||||
supercell->parameters[ID::A_SIGNED] = a_signed;
|
||||
supercell->parameters[ID::A_WIDTH] = a_width;
|
||||
supercell->parameters[ID::Y_WIDTH] = y_width;
|
||||
|
|
@ -554,11 +554,11 @@ struct ShareWorker
|
|||
return supercell;
|
||||
}
|
||||
|
||||
if (config.generic_bin_ops(c1->type) || config.generic_cbin_ops(c1->type) || c1->type == ID($alu))
|
||||
if (config.generic_bin_ops(c1->type_impl) || config.generic_cbin_ops(c1->type_impl) || c1->type_impl == TW($alu))
|
||||
{
|
||||
bool modified_src_cells = false;
|
||||
|
||||
if (config.generic_cbin_ops(c1->type))
|
||||
if (config.generic_cbin_ops(c1->type_impl))
|
||||
{
|
||||
int score_unflipped = max(c1->parameters.at(ID::A_WIDTH).as_int(), c2->parameters.at(ID::A_WIDTH).as_int()) +
|
||||
max(c1->parameters.at(ID::B_WIDTH).as_int(), c2->parameters.at(ID::B_WIDTH).as_int());
|
||||
|
|
@ -616,7 +616,7 @@ struct ShareWorker
|
|||
log_assert(a_signed == c2->parameters.at(ID::A_SIGNED).as_bool());
|
||||
log_assert(b_signed == c2->parameters.at(ID::B_SIGNED).as_bool());
|
||||
|
||||
if (c1->type == ID($shl) || c1->type == ID($shr) || c1->type == ID($sshl) || c1->type == ID($sshr))
|
||||
if (c1->type == TW($shl) || c1->type == TW($shr) || c1->type == TW($sshl) || c1->type == TW($sshr))
|
||||
b_signed = false;
|
||||
|
||||
RTLIL::SigSpec a1 = c1->getPort(TW::A);
|
||||
|
|
@ -631,7 +631,7 @@ struct ShareWorker
|
|||
int b_width = max(b1.size(), b2.size());
|
||||
int y_width = max(y1.size(), y2.size());
|
||||
|
||||
if (c1->type == ID($shr) && a_signed)
|
||||
if (c1->type == TW($shr) && a_signed)
|
||||
{
|
||||
a_width = max(y_width, a_width);
|
||||
|
||||
|
|
@ -657,10 +657,10 @@ struct ShareWorker
|
|||
supercell_aux.insert(module->addMux(NEW_TWINE, b2, b1, act, b));
|
||||
|
||||
RTLIL::Wire *y = module->addWire(NEW_TWINE, y_width);
|
||||
RTLIL::Wire *x = c1->type == ID($alu) ? module->addWire(NEW_TWINE, y_width) : nullptr;
|
||||
RTLIL::Wire *co = c1->type == ID($alu) ? module->addWire(NEW_TWINE, y_width) : nullptr;
|
||||
RTLIL::Wire *x = c1->type == TW($alu) ? module->addWire(NEW_TWINE, y_width) : nullptr;
|
||||
RTLIL::Wire *co = c1->type == TW($alu) ? module->addWire(NEW_TWINE, y_width) : nullptr;
|
||||
|
||||
RTLIL::Cell *supercell = module->addCell(NEW_TWINE, c1->type);
|
||||
RTLIL::Cell *supercell = module->addCell(NEW_TWINE, c1->type_impl);
|
||||
supercell->parameters[ID::A_SIGNED] = a_signed;
|
||||
supercell->parameters[ID::B_SIGNED] = b_signed;
|
||||
supercell->parameters[ID::A_WIDTH] = a_width;
|
||||
|
|
@ -669,7 +669,7 @@ struct ShareWorker
|
|||
supercell->setPort(TW::A, a);
|
||||
supercell->setPort(TW::B, b);
|
||||
supercell->setPort(TW::Y, y);
|
||||
if (c1->type == ID($alu)) {
|
||||
if (c1->type == TW($alu)) {
|
||||
RTLIL::Wire *ci = module->addWire(NEW_TWINE), *bi = module->addWire(NEW_TWINE);
|
||||
supercell_aux.insert(module->addMux(NEW_TWINE, c2->getPort(TW::CI), c1->getPort(TW::CI), act, ci));
|
||||
supercell_aux.insert(module->addMux(NEW_TWINE, c2->getPort(TW::BI), c1->getPort(TW::BI), act, bi));
|
||||
|
|
@ -682,7 +682,7 @@ struct ShareWorker
|
|||
|
||||
supercell_aux.insert(module->addPos(NEW_TWINE, y, y1));
|
||||
supercell_aux.insert(module->addPos(NEW_TWINE, y, y2));
|
||||
if (c1->type == ID($alu)) {
|
||||
if (c1->type == TW($alu)) {
|
||||
supercell_aux.insert(module->addPos(NEW_TWINE, co, c1->getPort(TW::CO)));
|
||||
supercell_aux.insert(module->addPos(NEW_TWINE, co, c2->getPort(TW::CO)));
|
||||
supercell_aux.insert(module->addPos(NEW_TWINE, x, c1->getPort(TW::X)));
|
||||
|
|
@ -693,16 +693,16 @@ struct ShareWorker
|
|||
return supercell;
|
||||
}
|
||||
|
||||
if (c1->type == ID($macc))
|
||||
if (c1->type == TW($macc))
|
||||
{
|
||||
RTLIL::Cell *supercell = module->addCell(NEW_TWINE, c1->type);
|
||||
RTLIL::Cell *supercell = module->addCell(NEW_TWINE, c1->type_impl);
|
||||
supercell_aux.insert(supercell);
|
||||
share_macc(c1, c2, act, supercell, &supercell_aux);
|
||||
supercell->check();
|
||||
return supercell;
|
||||
}
|
||||
|
||||
if (c1->type.in(ID($memrd), ID($memrd_v2)))
|
||||
if (c1->type.in(TW($memrd), TW($memrd_v2)))
|
||||
{
|
||||
RTLIL::Cell *supercell = module->addCell(NEW_TWINE, c1);
|
||||
RTLIL::SigSpec addr1 = c1->getPort(TW::ADDR);
|
||||
|
|
@ -744,7 +744,7 @@ struct ShareWorker
|
|||
modwalker.get_consumers(pbits, modwalker.cell_outputs[cell]);
|
||||
|
||||
for (auto &bit : pbits) {
|
||||
if ((bit.cell->type == ID($mux) || bit.cell->type == ID($pmux)) && bit.port == TW::S)
|
||||
if ((bit.cell->type == TW($mux) || bit.cell->type == TW($pmux)) && bit.port == TW::S)
|
||||
forbidden_controls_cache[cell].insert(bit.cell->getPort(TW::S).extract(bit.offset, 1));
|
||||
consumer_cells.insert(bit.cell);
|
||||
}
|
||||
|
|
@ -752,7 +752,7 @@ struct ShareWorker
|
|||
recursion_state.insert(cell);
|
||||
|
||||
for (auto c : consumer_cells)
|
||||
if (StaticCellTypes::Compat::internals_nomem_noff(c->type)) {
|
||||
if (StaticCellTypes::Compat::internals_nomem_noff(c->type_impl)) {
|
||||
const pool<RTLIL::SigBit> &bits = find_forbidden_controls(c);
|
||||
forbidden_controls_cache[cell].insert(bits.begin(), bits.end());
|
||||
}
|
||||
|
|
@ -891,8 +891,8 @@ struct ShareWorker
|
|||
return activation_patterns_cache.at(cell);
|
||||
}
|
||||
for (auto &pbit : modwalker.signal_consumers[bit]) {
|
||||
log_assert(StaticCellTypes::Compat::internals_nomem_noff(pbit.cell->type));
|
||||
if ((pbit.cell->type == ID($mux) || pbit.cell->type == ID($pmux)) && (pbit.port == TW::A || pbit.port == TW::B))
|
||||
log_assert(StaticCellTypes::Compat::internals_nomem_noff(pbit.cell->type_impl));
|
||||
if ((pbit.cell->type == TW($mux) || pbit.cell->type == TW($pmux)) && (pbit.port == TW::A || pbit.port == TW::B))
|
||||
driven_data_muxes.insert(pbit.cell);
|
||||
else
|
||||
driven_cells.insert(pbit.cell);
|
||||
|
|
@ -1095,9 +1095,9 @@ struct ShareWorker
|
|||
dict<RTLIL::SigBit, pool<RTLIL::Cell*>> bit_to_cells;
|
||||
|
||||
for (auto cell : module->cells())
|
||||
if (ct.cell_known(cell->type))
|
||||
if (ct.cell_known(cell->type_impl))
|
||||
for (auto &conn : cell->connections()) {
|
||||
if (ct.cell_output(cell->type, conn.first))
|
||||
if (ct.cell_output(cell->type_impl, conn.first))
|
||||
for (auto bit : topo_sigmap(conn.second)) {
|
||||
cell_to_bits[cell].insert(bit);
|
||||
topo_bit_drivers[bit].insert(cell);
|
||||
|
|
@ -1123,7 +1123,7 @@ struct ShareWorker
|
|||
for (auto &loop : toposort.loops) {
|
||||
log("### loop ###\n");
|
||||
for (auto &c : loop)
|
||||
log("%s (%s)\n", c, c->type.unescape());
|
||||
log("%s (%s)\n", c, design->twines.unescaped_str(c->type));
|
||||
}
|
||||
|
||||
return found_scc;
|
||||
|
|
@ -1167,13 +1167,13 @@ struct ShareWorker
|
|||
pool<RTLIL::Cell*> new_queue;
|
||||
|
||||
for (auto c : queue) {
|
||||
if (!ct.cell_known(c->type))
|
||||
if (!ct.cell_known(c->type_impl))
|
||||
continue;
|
||||
for (auto &conn : c->connections())
|
||||
if (ct.cell_input(c->type, conn.first))
|
||||
if (ct.cell_input(c->type_impl, conn.first))
|
||||
for (auto bit : conn.second)
|
||||
for (auto &pi : mi.query_ports(bit))
|
||||
if (ct.cell_known(pi.cell->type) && ct.cell_output(pi.cell->type, pi.port))
|
||||
if (ct.cell_known(pi.cell->type_impl) && ct.cell_output(pi.cell->type_impl, pi.port))
|
||||
new_queue.insert(pi.cell);
|
||||
covered.insert(c);
|
||||
}
|
||||
|
|
@ -1247,7 +1247,7 @@ struct ShareWorker
|
|||
RTLIL::Cell *cell = *shareable_cells.begin();
|
||||
shareable_cells.erase(cell);
|
||||
|
||||
log(" Analyzing resource sharing options for %s (%s):\n", cell, cell->type.unescape());
|
||||
log(" Analyzing resource sharing options for %s (%s):\n", cell, cell->type.unescaped());
|
||||
|
||||
const pool<ssc_pair_t> &cell_activation_patterns = find_cell_activation_patterns(cell, " ");
|
||||
RTLIL::SigSpec cell_activation_signals = bits_from_activation_patterns(cell_activation_patterns);
|
||||
|
|
@ -1280,7 +1280,7 @@ struct ShareWorker
|
|||
|
||||
for (auto other_cell : candidates)
|
||||
{
|
||||
log(" Analyzing resource sharing with %s (%s):\n", other_cell, other_cell->type.unescape());
|
||||
log(" Analyzing resource sharing with %s (%s):\n", other_cell, design->twines.unescaped_str(other_cell->type));
|
||||
|
||||
const pool<ssc_pair_t> &other_cell_activation_patterns = find_cell_activation_patterns(other_cell, " ");
|
||||
RTLIL::SigSpec other_cell_activation_signals = bits_from_activation_patterns(other_cell_activation_patterns);
|
||||
|
|
@ -1431,7 +1431,7 @@ struct ShareWorker
|
|||
log(" Activation signal for %s: %s\n", other_cell, log_signal(act));
|
||||
}
|
||||
|
||||
log(" New cell: %s (%s)\n", supercell, supercell->type.unescape());
|
||||
log(" New cell: %s (%s)\n", supercell, design->twines.unescaped_str(supercell->type));
|
||||
|
||||
cells_to_remove.insert(cell);
|
||||
cells_to_remove.insert(other_cell);
|
||||
|
|
@ -1478,7 +1478,7 @@ struct ShareWorker
|
|||
if (!cells_to_remove.empty()) {
|
||||
log("Removing %d cells in module %s:\n", GetSize(cells_to_remove), module);
|
||||
for (auto c : cells_to_remove) {
|
||||
log(" Removing cell %s (%s).\n", c, c->type.unescape());
|
||||
log(" Removing cell %s (%s).\n", c, design->twines.unescaped_str(c->type));
|
||||
remove_cell(c);
|
||||
}
|
||||
}
|
||||
|
|
@ -1532,45 +1532,45 @@ struct SharePass : public Pass {
|
|||
config.opt_aggressive = false;
|
||||
config.opt_fast = false;
|
||||
|
||||
config.generic_uni_ops.set_id(ID($not));
|
||||
// config.generic_uni_ops.set_id(ID($pos));
|
||||
config.generic_uni_ops.set_id(ID($neg));
|
||||
config.generic_uni_ops.set_id(TW($not));
|
||||
// config.generic_uni_ops.set_id(TW($pos));
|
||||
config.generic_uni_ops.set_id(TW($neg));
|
||||
|
||||
config.generic_cbin_ops.set_id(ID($and));
|
||||
config.generic_cbin_ops.set_id(ID($or));
|
||||
config.generic_cbin_ops.set_id(ID($xor));
|
||||
config.generic_cbin_ops.set_id(ID($xnor));
|
||||
config.generic_cbin_ops.set_id(TW($and));
|
||||
config.generic_cbin_ops.set_id(TW($or));
|
||||
config.generic_cbin_ops.set_id(TW($xor));
|
||||
config.generic_cbin_ops.set_id(TW($xnor));
|
||||
|
||||
config.generic_bin_ops.set_id(ID($shl));
|
||||
config.generic_bin_ops.set_id(ID($shr));
|
||||
config.generic_bin_ops.set_id(ID($sshl));
|
||||
config.generic_bin_ops.set_id(ID($sshr));
|
||||
config.generic_bin_ops.set_id(TW($shl));
|
||||
config.generic_bin_ops.set_id(TW($shr));
|
||||
config.generic_bin_ops.set_id(TW($sshl));
|
||||
config.generic_bin_ops.set_id(TW($sshr));
|
||||
|
||||
config.generic_bin_ops.set_id(ID($lt));
|
||||
config.generic_bin_ops.set_id(ID($le));
|
||||
config.generic_bin_ops.set_id(ID($eq));
|
||||
config.generic_bin_ops.set_id(ID($ne));
|
||||
config.generic_bin_ops.set_id(ID($eqx));
|
||||
config.generic_bin_ops.set_id(ID($nex));
|
||||
config.generic_bin_ops.set_id(ID($ge));
|
||||
config.generic_bin_ops.set_id(ID($gt));
|
||||
config.generic_bin_ops.set_id(TW($lt));
|
||||
config.generic_bin_ops.set_id(TW($le));
|
||||
config.generic_bin_ops.set_id(TW($eq));
|
||||
config.generic_bin_ops.set_id(TW($ne));
|
||||
config.generic_bin_ops.set_id(TW($eqx));
|
||||
config.generic_bin_ops.set_id(TW($nex));
|
||||
config.generic_bin_ops.set_id(TW($ge));
|
||||
config.generic_bin_ops.set_id(TW($gt));
|
||||
|
||||
config.generic_cbin_ops.set_id(ID($add));
|
||||
config.generic_cbin_ops.set_id(ID($mul));
|
||||
config.generic_cbin_ops.set_id(TW($add));
|
||||
config.generic_cbin_ops.set_id(TW($mul));
|
||||
|
||||
config.generic_bin_ops.set_id(ID($sub));
|
||||
config.generic_bin_ops.set_id(ID($div));
|
||||
config.generic_bin_ops.set_id(ID($mod));
|
||||
config.generic_bin_ops.set_id(ID($divfloor));
|
||||
config.generic_bin_ops.set_id(ID($modfloor));
|
||||
// config.generic_bin_ops.set_id(ID($pow));
|
||||
config.generic_bin_ops.set_id(TW($sub));
|
||||
config.generic_bin_ops.set_id(TW($div));
|
||||
config.generic_bin_ops.set_id(TW($mod));
|
||||
config.generic_bin_ops.set_id(TW($divfloor));
|
||||
config.generic_bin_ops.set_id(TW($modfloor));
|
||||
// config.generic_bin_ops.set_id(TW($pow));
|
||||
|
||||
config.generic_uni_ops.set_id(ID($logic_not));
|
||||
config.generic_cbin_ops.set_id(ID($logic_and));
|
||||
config.generic_cbin_ops.set_id(ID($logic_or));
|
||||
config.generic_uni_ops.set_id(TW($logic_not));
|
||||
config.generic_cbin_ops.set_id(TW($logic_and));
|
||||
config.generic_cbin_ops.set_id(TW($logic_or));
|
||||
|
||||
config.generic_other_ops.set_id(ID($alu));
|
||||
config.generic_other_ops.set_id(ID($macc));
|
||||
config.generic_other_ops.set_id(TW($alu));
|
||||
config.generic_other_ops.set_id(TW($macc));
|
||||
|
||||
log_header(design, "Executing SHARE pass (SAT-based resource sharing).\n");
|
||||
|
||||
|
|
|
|||
|
|
@ -29,21 +29,21 @@ PRIVATE_NAMESPACE_BEGIN
|
|||
|
||||
struct WreduceConfig
|
||||
{
|
||||
pool<IdString> supported_cell_types;
|
||||
pool<TwineRef> supported_cell_types;
|
||||
bool keepdc = false;
|
||||
bool mux_undef = false;
|
||||
|
||||
WreduceConfig()
|
||||
{
|
||||
supported_cell_types = pool<IdString>({
|
||||
ID($not), ID($pos), ID($neg),
|
||||
ID($and), ID($or), ID($xor), ID($xnor),
|
||||
ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx),
|
||||
ID($lt), ID($le), ID($eq), ID($ne), ID($eqx), ID($nex), ID($ge), ID($gt),
|
||||
ID($add), ID($sub), ID($mul), // ID($div), ID($mod), ID($divfloor), ID($modfloor), ID($pow),
|
||||
ID($mux), ID($pmux),
|
||||
ID($dff), ID($dffe), ID($adff), ID($adffe), ID($sdff), ID($sdffe), ID($sdffce),
|
||||
ID($dlatch), ID($adlatch),
|
||||
supported_cell_types = pool<TwineRef>({
|
||||
TW($not), TW($pos), TW($neg),
|
||||
TW($and), TW($or), TW($xor), TW($xnor),
|
||||
TW($shl), TW($shr), TW($sshl), TW($sshr), TW($shift), TW($shiftx),
|
||||
TW($lt), TW($le), TW($eq), TW($ne), TW($eqx), TW($nex), TW($ge), TW($gt),
|
||||
TW($add), TW($sub), TW($mul), // TW($div), TW($mod), TW($divfloor), TW($modfloor), TW($pow),
|
||||
TW($mux), TW($pmux),
|
||||
TW($dff), TW($dffe), TW($adff), TW($adffe), TW($sdff), TW($sdffe), TW($sdffce),
|
||||
TW($dlatch), TW($adlatch),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -104,14 +104,14 @@ struct WreduceWorker
|
|||
sig_removed.append(bits_removed[i]);
|
||||
|
||||
if (GetSize(bits_removed) == GetSize(sig_y)) {
|
||||
log("Removed cell %s.%s (%s).\n", module, cell, cell->type.unescape());
|
||||
log("Removed cell %s.%s (%s).\n", module, cell, cell->type.unescaped());
|
||||
module->connect(sig_y, sig_removed);
|
||||
module->remove(cell);
|
||||
return;
|
||||
}
|
||||
|
||||
log("Removed top %d bits (of %d) from mux cell %s.%s (%s).\n",
|
||||
GetSize(sig_removed), GetSize(sig_y), module, cell, cell->type.unescape());
|
||||
GetSize(sig_removed), GetSize(sig_y), module, cell, cell->type.unescaped());
|
||||
|
||||
int n_removed = GetSize(sig_removed);
|
||||
int n_kept = GetSize(sig_y) - GetSize(sig_removed);
|
||||
|
|
@ -211,13 +211,13 @@ struct WreduceWorker
|
|||
return;
|
||||
|
||||
if (GetSize(sig_q) == 0) {
|
||||
log("Removed cell %s.%s (%s).\n", module, cell, cell->type.unescape());
|
||||
log("Removed cell %s.%s (%s).\n", module, cell, cell->type.unescaped());
|
||||
module->remove(cell);
|
||||
return;
|
||||
}
|
||||
|
||||
log("Removed top %d bits (of %d) from FF cell %s.%s (%s).\n", width_before - GetSize(sig_q), width_before,
|
||||
module, cell, cell->type.unescape());
|
||||
module, cell, cell->type.unescaped());
|
||||
|
||||
for (auto bit : sig_d)
|
||||
work_queue_bits.insert(bit);
|
||||
|
|
@ -246,7 +246,7 @@ struct WreduceWorker
|
|||
auto &twines = cell->module->design->twines;
|
||||
SigSpec sig = mi.sigmap(cell->getPort(twines.add(Twine{stringf("\\%c", port)})));
|
||||
|
||||
if (port == 'B' && cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr)))
|
||||
if (port == 'B' && cell->type.in(TW($shl), TW($shr), TW($sshl), TW($sshr)))
|
||||
port_signed = false;
|
||||
|
||||
int bits_removed = 0;
|
||||
|
|
@ -267,7 +267,7 @@ struct WreduceWorker
|
|||
|
||||
if (bits_removed) {
|
||||
log("Removed top %d bits (of %d) from port %c of cell %s.%s (%s).\n",
|
||||
bits_removed, GetSize(sig) + bits_removed, port, module, cell, cell->type.unescape());
|
||||
bits_removed, GetSize(sig) + bits_removed, port, module, cell, cell->type.unescaped());
|
||||
// SigSpec sig = mi.sigmap(cell->getPort(twines.add(Twine{stringf("\\%c", port)})));
|
||||
cell->setPort(twines.add(Twine{stringf("\\%c", port)}), sig);
|
||||
did_something = true;
|
||||
|
|
@ -291,13 +291,13 @@ struct WreduceWorker
|
|||
{
|
||||
bool did_something = false;
|
||||
|
||||
if (!config->supported_cell_types.count(cell->type))
|
||||
if (!config->supported_cell_types.count(cell->type_impl))
|
||||
return;
|
||||
|
||||
if (cell->type.in(ID($mux), ID($pmux)))
|
||||
if (cell->type.in(TW($mux), TW($pmux)))
|
||||
return run_cell_mux(cell);
|
||||
|
||||
if (cell->type.in(ID($dff), ID($dffe), ID($adff), ID($adffe), ID($sdff), ID($sdffe), ID($sdffce), ID($dlatch), ID($adlatch)))
|
||||
if (cell->type.in(TW($dff), TW($dffe), TW($adff), TW($adffe), TW($sdff), TW($sdffe), TW($sdffce), TW($dlatch), TW($adlatch)))
|
||||
return run_cell_dff(cell);
|
||||
|
||||
SigSpec sig = mi.sigmap(cell->getPort(TW::Y));
|
||||
|
|
@ -311,7 +311,7 @@ struct WreduceWorker
|
|||
int max_port_a_size = cell->hasPort(TW::A) ? GetSize(cell->getPort(TW::A)) : -1;
|
||||
int max_port_b_size = cell->hasPort(TW::B) ? GetSize(cell->getPort(TW::B)) : -1;
|
||||
|
||||
if (cell->type.in(ID($not), ID($pos), ID($neg), ID($and), ID($or), ID($xor), ID($add), ID($sub))) {
|
||||
if (cell->type.in(TW($not), TW($pos), TW($neg), TW($and), TW($or), TW($xor), TW($add), TW($sub))) {
|
||||
max_port_a_size = min(max_port_a_size, GetSize(sig));
|
||||
max_port_b_size = min(max_port_b_size, GetSize(sig));
|
||||
}
|
||||
|
|
@ -321,7 +321,7 @@ struct WreduceWorker
|
|||
|
||||
// For some operations if the output is no wider than either of the inputs
|
||||
// we are free to choose the signedness of the operands
|
||||
if (cell->type.in(ID($mul), ID($add), ID($sub)) &&
|
||||
if (cell->type.in(TW($mul), TW($add), TW($sub)) &&
|
||||
max_port_a_size == GetSize(sig) &&
|
||||
max_port_b_size == GetSize(sig)) {
|
||||
SigSpec sig_a = mi.sigmap(cell->getPort(TW::A)), sig_b = mi.sigmap(cell->getPort(TW::B));
|
||||
|
|
@ -331,7 +331,7 @@ struct WreduceWorker
|
|||
sig_b.extend_u0(max_port_b_size);
|
||||
|
||||
int signed_cost, unsigned_cost;
|
||||
if (cell->type == ID($mul)) {
|
||||
if (cell->type == TW($mul)) {
|
||||
signed_cost = reduced_opsize(sig_a, true) * reduced_opsize(sig_b, true);
|
||||
unsigned_cost = reduced_opsize(sig_a, false) * reduced_opsize(sig_b, false);
|
||||
} else {
|
||||
|
|
@ -341,7 +341,7 @@ struct WreduceWorker
|
|||
|
||||
if (!port_a_signed && !port_b_signed && signed_cost < unsigned_cost) {
|
||||
log("Converting cell %s.%s (%s) from unsigned to signed.\n",
|
||||
module, cell, cell->type.unescape());
|
||||
module, cell, cell->type.unescaped());
|
||||
cell->setParam(ID::A_SIGNED, 1);
|
||||
cell->setParam(ID::B_SIGNED, 1);
|
||||
port_a_signed = true;
|
||||
|
|
@ -349,7 +349,7 @@ struct WreduceWorker
|
|||
did_something = true;
|
||||
} else if (port_a_signed && port_b_signed && unsigned_cost < signed_cost) {
|
||||
log("Converting cell %s.%s (%s) from signed to unsigned.\n",
|
||||
module, cell, cell->type.unescape());
|
||||
module, cell, cell->type.unescaped());
|
||||
cell->setParam(ID::A_SIGNED, 0);
|
||||
cell->setParam(ID::B_SIGNED, 0);
|
||||
port_a_signed = false;
|
||||
|
|
@ -358,7 +358,7 @@ struct WreduceWorker
|
|||
}
|
||||
}
|
||||
|
||||
if (max_port_a_size >= 0 && cell->type != ID($shiftx))
|
||||
if (max_port_a_size >= 0 && cell->type != TW($shiftx))
|
||||
run_reduce_inport(cell, 'A', max_port_a_size, port_a_signed, did_something);
|
||||
|
||||
if (max_port_b_size >= 0)
|
||||
|
|
@ -369,7 +369,7 @@ struct WreduceWorker
|
|||
if (GetSize(sig_a) > 0 && sig_a[GetSize(sig_a)-1] == State::S0 &&
|
||||
GetSize(sig_b) > 0 && sig_b[GetSize(sig_b)-1] == State::S0) {
|
||||
log("Converting cell %s.%s (%s) from signed to unsigned.\n",
|
||||
module, cell, cell->type.unescape());
|
||||
module, cell, cell->type.unescaped());
|
||||
cell->setParam(ID::A_SIGNED, 0);
|
||||
cell->setParam(ID::B_SIGNED, 0);
|
||||
port_a_signed = false;
|
||||
|
|
@ -382,7 +382,7 @@ struct WreduceWorker
|
|||
SigSpec sig_a = mi.sigmap(cell->getPort(TW::A));
|
||||
if (GetSize(sig_a) > 0 && sig_a[GetSize(sig_a)-1] == State::S0) {
|
||||
log("Converting cell %s.%s (%s) from signed to unsigned.\n",
|
||||
module, cell, cell->type.unescape());
|
||||
module, cell, cell->type.unescaped());
|
||||
cell->setParam(ID::A_SIGNED, 0);
|
||||
port_a_signed = false;
|
||||
did_something = true;
|
||||
|
|
@ -393,7 +393,7 @@ struct WreduceWorker
|
|||
// Reduce size of port Y based on sizes for A and B and unused bits in Y
|
||||
|
||||
int bits_removed = 0;
|
||||
if (port_a_signed && cell->type == ID($shr)) {
|
||||
if (port_a_signed && cell->type == TW($shr)) {
|
||||
// do not reduce size of output on $shr cells with signed A inputs
|
||||
} else {
|
||||
while (GetSize(sig) > 0)
|
||||
|
|
@ -411,9 +411,9 @@ struct WreduceWorker
|
|||
}
|
||||
}
|
||||
|
||||
if (cell->type.in(ID($pos), ID($add), ID($mul), ID($and), ID($or), ID($xor), ID($sub)))
|
||||
if (cell->type.in(TW($pos), TW($add), TW($mul), TW($and), TW($or), TW($xor), TW($sub)))
|
||||
{
|
||||
bool is_signed = cell->getParam(ID::A_SIGNED).as_bool() || cell->type == ID($sub);
|
||||
bool is_signed = cell->getParam(ID::A_SIGNED).as_bool() || cell->type == TW($sub);
|
||||
|
||||
int a_size = 0, b_size = 0;
|
||||
if (cell->hasPort(TW::A)) a_size = GetSize(cell->getPort(TW::A));
|
||||
|
|
@ -421,10 +421,10 @@ struct WreduceWorker
|
|||
|
||||
int max_y_size = max(a_size, b_size);
|
||||
|
||||
if (cell->type.in(ID($add), ID($sub)))
|
||||
if (cell->type.in(TW($add), TW($sub)))
|
||||
max_y_size++;
|
||||
|
||||
if (cell->type == ID($mul))
|
||||
if (cell->type == TW($mul))
|
||||
max_y_size = a_size + b_size;
|
||||
|
||||
max_y_size = std::max(max_y_size, 1);
|
||||
|
|
@ -441,14 +441,14 @@ struct WreduceWorker
|
|||
}
|
||||
|
||||
if (GetSize(sig) == 0) {
|
||||
log("Removed cell %s.%s (%s).\n", module, cell, cell->type.unescape());
|
||||
log("Removed cell %s.%s (%s).\n", module, cell, cell->type.unescaped());
|
||||
module->remove(cell);
|
||||
return;
|
||||
}
|
||||
|
||||
if (bits_removed) {
|
||||
log("Removed top %d bits (of %d) from port Y of cell %s.%s (%s).\n",
|
||||
bits_removed, GetSize(sig) + bits_removed, module, cell, cell->type.unescape());
|
||||
bits_removed, GetSize(sig) + bits_removed, module, cell, cell->type.unescaped());
|
||||
cell->setPort(TW::Y, sig);
|
||||
did_something = true;
|
||||
}
|
||||
|
|
@ -591,9 +591,9 @@ struct WreducePass : public Pass {
|
|||
|
||||
for (auto c : module->selected_cells())
|
||||
{
|
||||
if (c->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool),
|
||||
ID($lt), ID($le), ID($eq), ID($ne), ID($eqx), ID($nex), ID($ge), ID($gt),
|
||||
ID($logic_not), ID($logic_and), ID($logic_or)) && GetSize(c->getPort(TW::Y)) > 1) {
|
||||
if (c->type.in(TW($reduce_and), TW($reduce_or), TW($reduce_xor), TW($reduce_xnor), TW($reduce_bool),
|
||||
TW($lt), TW($le), TW($eq), TW($ne), TW($eqx), TW($nex), TW($ge), TW($gt),
|
||||
TW($logic_not), TW($logic_and), TW($logic_or)) && GetSize(c->getPort(TW::Y)) > 1) {
|
||||
SigSpec sig = c->getPort(TW::Y);
|
||||
if (!sig.has_const()) {
|
||||
c->setPort(TW::Y, sig[0]);
|
||||
|
|
@ -603,7 +603,7 @@ struct WreducePass : public Pass {
|
|||
}
|
||||
}
|
||||
|
||||
if (c->type.in(ID($div), ID($mod), ID($divfloor), ID($modfloor), ID($pow)))
|
||||
if (c->type.in(TW($div), TW($mod), TW($divfloor), TW($modfloor), TW($pow)))
|
||||
{
|
||||
SigSpec A = c->getPort(TW::A);
|
||||
int original_a_width = GetSize(A);
|
||||
|
|
@ -616,7 +616,7 @@ struct WreducePass : public Pass {
|
|||
}
|
||||
if (original_a_width != GetSize(A)) {
|
||||
log("Removed top %d bits (of %d) from port A of cell %s.%s (%s).\n",
|
||||
original_a_width-GetSize(A), original_a_width, module, c, c->type.unescape());
|
||||
original_a_width-GetSize(A), original_a_width, module, c, design->twines.unescaped_str(c->type));
|
||||
c->setPort(TW::A, A);
|
||||
c->setParam(ID::A_WIDTH, GetSize(A));
|
||||
}
|
||||
|
|
@ -632,13 +632,13 @@ struct WreducePass : public Pass {
|
|||
}
|
||||
if (original_b_width != GetSize(B)) {
|
||||
log("Removed top %d bits (of %d) from port B of cell %s.%s (%s).\n",
|
||||
original_b_width-GetSize(B), original_b_width, module, c, c->type.unescape());
|
||||
original_b_width-GetSize(B), original_b_width, module, c, design->twines.unescaped_str(c->type));
|
||||
c->setPort(TW::B, B);
|
||||
c->setParam(ID::B_WIDTH, GetSize(B));
|
||||
}
|
||||
}
|
||||
|
||||
if (!opt_memx && c->type.in(ID($memrd), ID($memrd_v2), ID($memwr), ID($memwr_v2), ID($meminit), ID($meminit_v2))) {
|
||||
if (!opt_memx && c->type.in(TW($memrd), TW($memrd_v2), TW($memwr), TW($memwr_v2), TW($meminit), TW($meminit_v2))) {
|
||||
std::string memid_s = c->getParam(ID::MEMID).decode_string();
|
||||
TwineRef memid = design->twines.add(Twine{memid_s});
|
||||
RTLIL::Memory *mem = module->memories.at(memid);
|
||||
|
|
@ -648,7 +648,7 @@ struct WreducePass : public Pass {
|
|||
if (cur_addrbits > max_addrbits) {
|
||||
log("Removed top %d address bits (of %d) from memory %s port %s.%s (%s).\n",
|
||||
cur_addrbits-max_addrbits, cur_addrbits,
|
||||
c->type == ID($memrd) ? "read" : c->type == ID($memwr) ? "write" : "init",
|
||||
c->type == TW($memrd) ? "read" : c->type == TW($memwr) ? "write" : "init",
|
||||
module, c, memid_s);
|
||||
c->setParam(ID::ABITS, max_addrbits);
|
||||
c->setPort(TW::ADDR, c->getPort(TW::ADDR).extract(0, max_addrbits));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue