mirror of https://github.com/YosysHQ/yosys.git
opt_clean: move unused_bits analysis to kernel/unused_bits.h
This commit is contained in:
parent
bf86dd7faf
commit
0253911ee2
|
|
@ -406,7 +406,6 @@ struct EdifBackend : public Backend {
|
||||||
auto count_nontrivial_attr = [](Wire *w) {
|
auto count_nontrivial_attr = [](Wire *w) {
|
||||||
int count = w->attributes.size();
|
int count = w->attributes.size();
|
||||||
count -= w->attributes.count(ID::src);
|
count -= w->attributes.count(ID::src);
|
||||||
count -= w->attributes.count(ID::unused_bits);
|
|
||||||
return count;
|
return count;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -108,9 +108,7 @@ FSM optimization
|
||||||
The `fsm_opt` pass performs basic optimizations on `$fsm` cells (not including
|
The `fsm_opt` pass performs basic optimizations on `$fsm` cells (not including
|
||||||
state recoding). The following optimizations are performed (in this order):
|
state recoding). The following optimizations are performed (in this order):
|
||||||
|
|
||||||
- Unused control outputs are removed from the `$fsm` cell. The attribute
|
- Unused control outputs are removed from the `$fsm` cell.
|
||||||
``unused_bits`` (that is usually set by the `opt_clean` pass) is used to
|
|
||||||
determine which control outputs are unused.
|
|
||||||
|
|
||||||
- Control inputs that are connected to the same driver are merged.
|
- Control inputs that are connected to the same driver are merged.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -203,8 +203,6 @@ Removing unused cells and wires - `opt_clean` pass
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
This pass identifies unused signals and cells and removes them from the design.
|
This pass identifies unused signals and cells and removes them from the design.
|
||||||
It also creates an ``unused_bits`` attribute on wires with unused bits. This
|
|
||||||
attribute can be used for debugging or by other optimization passes.
|
|
||||||
|
|
||||||
When to use `opt` or `clean`
|
When to use `opt` or `clean`
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,7 @@ yosys_core(kernel
|
||||||
threading.h
|
threading.h
|
||||||
timinginfo.h
|
timinginfo.h
|
||||||
topo_scc.h
|
topo_scc.h
|
||||||
|
unused_bits.h
|
||||||
utils.h
|
utils.h
|
||||||
version.cc
|
version.cc
|
||||||
yosys.cc
|
yosys.cc
|
||||||
|
|
@ -145,6 +146,7 @@ yosys_core(kernel
|
||||||
sigtools.h
|
sigtools.h
|
||||||
threading.h
|
threading.h
|
||||||
timinginfo.h
|
timinginfo.h
|
||||||
|
unused_bits.h
|
||||||
utils.h
|
utils.h
|
||||||
yosys.h
|
yosys.h
|
||||||
yosys_common.h
|
yosys_common.h
|
||||||
|
|
|
||||||
|
|
@ -1029,7 +1029,6 @@ X(unsigned_a_i)
|
||||||
X(unsigned_b)
|
X(unsigned_b)
|
||||||
X(unsigned_b_i)
|
X(unsigned_b_i)
|
||||||
X(unsupported_sva)
|
X(unsupported_sva)
|
||||||
X(unused_bits)
|
|
||||||
X(use_dsp)
|
X(use_dsp)
|
||||||
X(value)
|
X(value)
|
||||||
X(via_celltype)
|
X(via_celltype)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
#ifndef UNUSED_BITS_H
|
||||||
|
#define UNUSED_BITS_H
|
||||||
|
|
||||||
|
#include "kernel/yosys.h"
|
||||||
|
#include "kernel/sigtools.h"
|
||||||
|
#include "kernel/newcelltypes.h"
|
||||||
|
|
||||||
|
YOSYS_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
struct UnusedBits
|
||||||
|
{
|
||||||
|
SigMap sigmap;
|
||||||
|
pool<RTLIL::SigBit> used;
|
||||||
|
|
||||||
|
UnusedBits(RTLIL::Module *module) : sigmap(module)
|
||||||
|
{
|
||||||
|
NewCellTypes ct(module->design);
|
||||||
|
collect_used(module, ct);
|
||||||
|
}
|
||||||
|
|
||||||
|
UnusedBits(RTLIL::Module *module, const NewCellTypes &ct) : sigmap(module)
|
||||||
|
{
|
||||||
|
collect_used(module, ct);
|
||||||
|
}
|
||||||
|
|
||||||
|
void collect_used(RTLIL::Module *module, const NewCellTypes &ct)
|
||||||
|
{
|
||||||
|
for (auto cell : module->cells())
|
||||||
|
for (auto &conn : cell->connections())
|
||||||
|
if (!ct.cell_output(cell->type, conn.first))
|
||||||
|
add_used(conn.second);
|
||||||
|
|
||||||
|
for (auto wire : module->wires())
|
||||||
|
if (wire->port_output)
|
||||||
|
add_used(wire);
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_used(const RTLIL::SigSpec &sig)
|
||||||
|
{
|
||||||
|
for (auto bit : sigmap(sig))
|
||||||
|
if (bit.wire != nullptr)
|
||||||
|
used.insert(bit);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool check(RTLIL::SigBit bit) const
|
||||||
|
{
|
||||||
|
RTLIL::SigBit mapped = sigmap(bit);
|
||||||
|
return mapped.wire != nullptr && !used.count(mapped);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
YOSYS_NAMESPACE_END
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
#include "kernel/yosys.h"
|
#include "kernel/yosys.h"
|
||||||
#include "kernel/celltypes.h"
|
#include "kernel/celltypes.h"
|
||||||
#include "kernel/sigtools.h"
|
#include "kernel/sigtools.h"
|
||||||
|
#include "kernel/unused_bits.h"
|
||||||
#include "backends/rtlil/rtlil_backend.h"
|
#include "backends/rtlil/rtlil_backend.h"
|
||||||
|
|
||||||
USING_YOSYS_NAMESPACE
|
USING_YOSYS_NAMESPACE
|
||||||
|
|
@ -190,19 +191,10 @@ struct WrapcellPass : Pass {
|
||||||
|
|
||||||
bool tracking_unused = has_fmt_field(name_fmt, "%unused");
|
bool tracking_unused = has_fmt_field(name_fmt, "%unused");
|
||||||
|
|
||||||
for (auto module : d->selected_modules()) {
|
NewCellTypes ct_all(d);
|
||||||
SigPool unused;
|
|
||||||
|
|
||||||
for (auto wire : module->wires())
|
for (auto module : d->selected_modules()) {
|
||||||
if (wire->has_attribute(ID::unused_bits)) {
|
UnusedBits unused(module, ct_all);
|
||||||
std::string str = wire->get_string_attribute(ID::unused_bits);
|
|
||||||
for (auto it = str.begin(); it != str.end();) {
|
|
||||||
auto sep = it;
|
|
||||||
for (; sep != str.end() && *sep != ' '; sep++);
|
|
||||||
unused.add(SigBit(wire, std::stoi(std::string(it, sep))));
|
|
||||||
for (it = sep; it != str.end() && *it == ' '; it++);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto cell : module->selected_cells()) {
|
for (auto cell : module->selected_cells()) {
|
||||||
Module *subm;
|
Module *subm;
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
#include "kernel/sigtools.h"
|
#include "kernel/sigtools.h"
|
||||||
#include "kernel/consteval.h"
|
#include "kernel/consteval.h"
|
||||||
#include "kernel/celltypes.h"
|
#include "kernel/celltypes.h"
|
||||||
|
#include "kernel/unused_bits.h"
|
||||||
#include "fsmdata.h"
|
#include "fsmdata.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|
@ -32,6 +33,7 @@ struct FsmExpand
|
||||||
{
|
{
|
||||||
RTLIL::Module *module;
|
RTLIL::Module *module;
|
||||||
RTLIL::Cell *fsm_cell;
|
RTLIL::Cell *fsm_cell;
|
||||||
|
UnusedBits& unused_bits;
|
||||||
bool full_mode;
|
bool full_mode;
|
||||||
|
|
||||||
SigMap assign_map;
|
SigMap assign_map;
|
||||||
|
|
@ -127,7 +129,7 @@ struct FsmExpand
|
||||||
if (trans_num > limit_transitions)
|
if (trans_num > limit_transitions)
|
||||||
{
|
{
|
||||||
log(" grown transition table to %d entries -> optimize.\n", trans_num);
|
log(" grown transition table to %d entries -> optimize.\n", trans_num);
|
||||||
FsmData::optimize_fsm(fsm_cell, module);
|
FsmData::optimize_fsm(fsm_cell, module, unused_bits);
|
||||||
already_optimized = true;
|
already_optimized = true;
|
||||||
|
|
||||||
trans_num = fsm_cell->parameters[ID::TRANS_NUM].as_int();
|
trans_num = fsm_cell->parameters[ID::TRANS_NUM].as_int();
|
||||||
|
|
@ -218,7 +220,7 @@ struct FsmExpand
|
||||||
fsm_data.copy_to_cell(fsm_cell);
|
fsm_data.copy_to_cell(fsm_cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
FsmExpand(RTLIL::Cell *cell, RTLIL::Design *design, RTLIL::Module *mod, bool full)
|
FsmExpand(RTLIL::Cell *cell, RTLIL::Design *design, RTLIL::Module *mod, UnusedBits& unused_bits, bool full) : unused_bits(unused_bits)
|
||||||
{
|
{
|
||||||
module = mod;
|
module = mod;
|
||||||
fsm_cell = cell;
|
fsm_cell = cell;
|
||||||
|
|
@ -257,7 +259,7 @@ struct FsmExpand
|
||||||
module->remove(c);
|
module->remove(c);
|
||||||
|
|
||||||
if (merged_set.size() > 0 && !already_optimized)
|
if (merged_set.size() > 0 && !already_optimized)
|
||||||
FsmData::optimize_fsm(fsm_cell, module);
|
FsmData::optimize_fsm(fsm_cell, module, unused_bits);
|
||||||
|
|
||||||
log(" merged %d cells into FSM.\n", GetSize(merged_set));
|
log(" merged %d cells into FSM.\n", GetSize(merged_set));
|
||||||
}
|
}
|
||||||
|
|
@ -296,12 +298,13 @@ struct FsmExpandPass : public Pass {
|
||||||
extra_args(args, argidx, design);
|
extra_args(args, argidx, design);
|
||||||
|
|
||||||
for (auto mod : design->selected_modules()) {
|
for (auto mod : design->selected_modules()) {
|
||||||
|
UnusedBits unused_bits(mod);
|
||||||
std::vector<RTLIL::Cell*> fsm_cells;
|
std::vector<RTLIL::Cell*> fsm_cells;
|
||||||
for (auto cell : mod->selected_cells())
|
for (auto cell : mod->selected_cells())
|
||||||
if (cell->type == ID($fsm))
|
if (cell->type == ID($fsm))
|
||||||
fsm_cells.push_back(cell);
|
fsm_cells.push_back(cell);
|
||||||
for (auto c : fsm_cells) {
|
for (auto c : fsm_cells) {
|
||||||
FsmExpand fsm_expand(c, design, mod, full_mode);
|
FsmExpand fsm_expand(c, design, mod, unused_bits, full_mode);
|
||||||
fsm_expand.execute();
|
fsm_expand.execute();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,8 @@
|
||||||
#include "kernel/sigtools.h"
|
#include "kernel/sigtools.h"
|
||||||
#include "kernel/consteval.h"
|
#include "kernel/consteval.h"
|
||||||
#include "kernel/celltypes.h"
|
#include "kernel/celltypes.h"
|
||||||
|
#include "kernel/unused_bits.h"
|
||||||
#include "fsmdata.h"
|
#include "fsmdata.h"
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
USING_YOSYS_NAMESPACE
|
USING_YOSYS_NAMESPACE
|
||||||
PRIVATE_NAMESPACE_BEGIN
|
PRIVATE_NAMESPACE_BEGIN
|
||||||
|
|
@ -33,6 +33,7 @@ struct FsmOpt
|
||||||
FsmData fsm_data;
|
FsmData fsm_data;
|
||||||
RTLIL::Cell *cell;
|
RTLIL::Cell *cell;
|
||||||
RTLIL::Module *module;
|
RTLIL::Module *module;
|
||||||
|
UnusedBits& unused_bits;
|
||||||
|
|
||||||
void opt_unreachable_states()
|
void opt_unreachable_states()
|
||||||
{
|
{
|
||||||
|
|
@ -79,21 +80,7 @@ struct FsmOpt
|
||||||
|
|
||||||
bool signal_is_unused(RTLIL::SigSpec sig)
|
bool signal_is_unused(RTLIL::SigSpec sig)
|
||||||
{
|
{
|
||||||
RTLIL::SigBit bit = sig.as_bit();
|
return unused_bits.check(sig.as_bit());
|
||||||
|
|
||||||
if (bit.wire == NULL || bit.wire->attributes.count(ID::unused_bits) == 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
char *str = strdup(bit.wire->attributes[ID::unused_bits].decode_string().c_str());
|
|
||||||
for (char *tok = strtok(str, " "); tok != NULL; tok = strtok(NULL, " ")) {
|
|
||||||
if (tok[0] && bit.offset == atoi(tok)) {
|
|
||||||
free(str);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(str);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void opt_const_and_unused_inputs()
|
void opt_const_and_unused_inputs()
|
||||||
|
|
@ -294,7 +281,7 @@ struct FsmOpt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FsmOpt(RTLIL::Cell *cell, RTLIL::Module *module)
|
FsmOpt(RTLIL::Cell *cell, RTLIL::Module *module, UnusedBits& unused_bits) : unused_bits(unused_bits)
|
||||||
{
|
{
|
||||||
log("Optimizing FSM `%s' from module `%s'.\n", cell->name, module->name);
|
log("Optimizing FSM `%s' from module `%s'.\n", cell->name, module->name);
|
||||||
|
|
||||||
|
|
@ -318,9 +305,9 @@ struct FsmOpt
|
||||||
|
|
||||||
PRIVATE_NAMESPACE_END
|
PRIVATE_NAMESPACE_END
|
||||||
|
|
||||||
void YOSYS_NAMESPACE_PREFIX FsmData::optimize_fsm(RTLIL::Cell *cell, RTLIL::Module *module)
|
void YOSYS_NAMESPACE_PREFIX FsmData::optimize_fsm(RTLIL::Cell *cell, RTLIL::Module *module, UnusedBits& unused_bits)
|
||||||
{
|
{
|
||||||
FsmOpt fsmopt(cell, module);
|
FsmOpt fsmopt(cell, module, unused_bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
PRIVATE_NAMESPACE_BEGIN
|
PRIVATE_NAMESPACE_BEGIN
|
||||||
|
|
@ -343,10 +330,12 @@ struct FsmOptPass : public Pass {
|
||||||
log_header(design, "Executing FSM_OPT pass (simple optimizations of FSMs).\n");
|
log_header(design, "Executing FSM_OPT pass (simple optimizations of FSMs).\n");
|
||||||
extra_args(args, 1, design);
|
extra_args(args, 1, design);
|
||||||
|
|
||||||
for (auto mod : design->selected_modules())
|
for (auto mod : design->selected_modules()) {
|
||||||
|
UnusedBits unused_bits(mod);
|
||||||
for (auto cell : mod->selected_cells())
|
for (auto cell : mod->selected_cells())
|
||||||
if (cell->type == ID($fsm))
|
if (cell->type == ID($fsm))
|
||||||
FsmData::optimize_fsm(cell, mod);
|
FsmData::optimize_fsm(cell, mod, unused_bits);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} FsmOptPass;
|
} FsmOptPass;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
#define FSMDATA_H
|
#define FSMDATA_H
|
||||||
|
|
||||||
#include "kernel/yosys.h"
|
#include "kernel/yosys.h"
|
||||||
|
#include "kernel/unused_bits.h"
|
||||||
|
|
||||||
YOSYS_NAMESPACE_BEGIN
|
YOSYS_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
|
@ -155,7 +156,7 @@ struct FsmData
|
||||||
}
|
}
|
||||||
|
|
||||||
// implemented in fsm_opt.cc
|
// implemented in fsm_opt.cc
|
||||||
static void optimize_fsm(RTLIL::Cell *cell, RTLIL::Module *module);
|
static void optimize_fsm(RTLIL::Cell *cell, RTLIL::Module *module, UnusedBits& unused_bits);
|
||||||
};
|
};
|
||||||
|
|
||||||
YOSYS_NAMESPACE_END
|
YOSYS_NAMESPACE_END
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,6 @@ int count_nontrivial_wire_attrs(RTLIL::Wire *w)
|
||||||
count -= w->attributes.count(ID::src);
|
count -= w->attributes.count(ID::src);
|
||||||
count -= w->attributes.count(ID::hdlname);
|
count -= w->attributes.count(ID::hdlname);
|
||||||
count -= w->attributes.count(ID::scopename);
|
count -= w->attributes.count(ID::scopename);
|
||||||
count -= w->attributes.count(ID::unused_bits);
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -168,13 +167,6 @@ bool check_any(const ShardedSigPool &sigs, const RTLIL::SigSpec &spec) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool check_all(const ShardedSigPool &sigs, const RTLIL::SigSpec &spec) {
|
|
||||||
for (SigBit b : spec)
|
|
||||||
if (sigs.find({b, b.hash_top().yield()}) == nullptr)
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct UpdateConnection {
|
struct UpdateConnection {
|
||||||
RTLIL::Cell *cell;
|
RTLIL::Cell *cell;
|
||||||
RTLIL::IdString port;
|
RTLIL::IdString port;
|
||||||
|
|
@ -328,33 +320,28 @@ struct DeferredUpdates {
|
||||||
};
|
};
|
||||||
struct UsedSignals {
|
struct UsedSignals {
|
||||||
// here, "connected" means "driven or driving something"
|
// here, "connected" means "driven or driving something"
|
||||||
// meanwhile, "used" means "driving something"
|
|
||||||
// sigmapped
|
// sigmapped
|
||||||
ShardedSigPool connected;
|
ShardedSigPool connected;
|
||||||
// pre-sigmapped
|
// pre-sigmapped
|
||||||
ShardedSigPool raw_connected;
|
ShardedSigPool raw_connected;
|
||||||
// sigmapped
|
|
||||||
ShardedSigPool used;
|
|
||||||
|
|
||||||
void clear(ParallelDispatchThreadPool::Subpool &subpool) {
|
void clear(ParallelDispatchThreadPool::Subpool &subpool) {
|
||||||
subpool.run([this](const ParallelDispatchThreadPool::RunCtx &ctx) {
|
subpool.run([this](const ParallelDispatchThreadPool::RunCtx &ctx) {
|
||||||
connected.clear(ctx);
|
connected.clear(ctx);
|
||||||
raw_connected.clear(ctx);
|
raw_connected.clear(ctx);
|
||||||
used.clear(ctx);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
DeferredUpdates analyse_connectivity(UsedSignals& used, SigConnKinds& sig_analysis, const AnalysisContext& actx, CleanRunContext &clean_ctx) {
|
DeferredUpdates analyse_connectivity(UsedSignals& used, SigConnKinds& sig_analysis, const AnalysisContext& actx) {
|
||||||
DeferredUpdates deferred(actx.subpool);
|
DeferredUpdates deferred(actx.subpool);
|
||||||
ShardedSigPool::Builder conn_builder(actx.subpool);
|
ShardedSigPool::Builder conn_builder(actx.subpool);
|
||||||
ShardedSigPool::Builder raw_conn_builder(actx.subpool);
|
ShardedSigPool::Builder raw_conn_builder(actx.subpool);
|
||||||
ShardedSigPool::Builder used_builder(actx.subpool);
|
|
||||||
|
|
||||||
// gather the usage information for cells and update cell connections with the altered sigmap
|
// gather the usage information for cells and update cell connections with the altered sigmap
|
||||||
// also gather the usage information for ports, wires with `keep`
|
// also gather the usage information for ports, wires with `keep`
|
||||||
// also gather init bits
|
// also gather init bits
|
||||||
actx.subpool.run([&deferred, &conn_builder, &raw_conn_builder, &used_builder, &sig_analysis, &actx, &clean_ctx](const ParallelDispatchThreadPool::RunCtx &ctx) {
|
actx.subpool.run([&deferred, &conn_builder, &raw_conn_builder, &sig_analysis, &actx](const ParallelDispatchThreadPool::RunCtx &ctx) {
|
||||||
// Parallel destruction of these sharded structures
|
// Parallel destruction of these sharded structures
|
||||||
sig_analysis.clear(ctx);
|
sig_analysis.clear(ctx);
|
||||||
|
|
||||||
|
|
@ -366,8 +353,6 @@ DeferredUpdates analyse_connectivity(UsedSignals& used, SigConnKinds& sig_analys
|
||||||
deferred.update_connections.insert(ctx, {cell, port, spec});
|
deferred.update_connections.insert(ctx, {cell, port, spec});
|
||||||
add_spec(raw_conn_builder, ctx, spec);
|
add_spec(raw_conn_builder, ctx, spec);
|
||||||
add_spec(conn_builder, ctx, spec);
|
add_spec(conn_builder, ctx, spec);
|
||||||
if (!clean_ctx.ct_all.cell_output(cell->type, port))
|
|
||||||
add_spec(used_builder, ctx, spec);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i : ctx.item_range(actx.mod->wires_size())) {
|
for (int i : ctx.item_range(actx.mod->wires_size())) {
|
||||||
|
|
@ -377,8 +362,6 @@ DeferredUpdates analyse_connectivity(UsedSignals& used, SigConnKinds& sig_analys
|
||||||
add_spec(raw_conn_builder, ctx, sig);
|
add_spec(raw_conn_builder, ctx, sig);
|
||||||
actx.assign_map.apply(sig);
|
actx.assign_map.apply(sig);
|
||||||
add_spec(conn_builder, ctx, sig);
|
add_spec(conn_builder, ctx, sig);
|
||||||
if (!wire->port_input)
|
|
||||||
add_spec(used_builder, ctx, sig);
|
|
||||||
}
|
}
|
||||||
if (wire->get_bool_attribute(ID::keep)) {
|
if (wire->get_bool_attribute(ID::keep)) {
|
||||||
RTLIL::SigSpec sig = RTLIL::SigSpec(wire);
|
RTLIL::SigSpec sig = RTLIL::SigSpec(wire);
|
||||||
|
|
@ -390,12 +373,11 @@ DeferredUpdates analyse_connectivity(UsedSignals& used, SigConnKinds& sig_analys
|
||||||
deferred.initialized_wires.insert(ctx, wire);
|
deferred.initialized_wires.insert(ctx, wire);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
actx.subpool.run([&conn_builder, &raw_conn_builder, &used_builder](const ParallelDispatchThreadPool::RunCtx &ctx) {
|
actx.subpool.run([&conn_builder, &raw_conn_builder](const ParallelDispatchThreadPool::RunCtx &ctx) {
|
||||||
conn_builder.process(ctx);
|
conn_builder.process(ctx);
|
||||||
raw_conn_builder.process(ctx);
|
raw_conn_builder.process(ctx);
|
||||||
used_builder.process(ctx);
|
|
||||||
});
|
});
|
||||||
used = {conn_builder, raw_conn_builder, used_builder};
|
used = {conn_builder, raw_conn_builder};
|
||||||
return deferred;
|
return deferred;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -404,14 +386,10 @@ struct WireDeleter {
|
||||||
ShardedVector<RTLIL::Wire*> remove_init;
|
ShardedVector<RTLIL::Wire*> remove_init;
|
||||||
ShardedVector<std::pair<RTLIL::Wire*, RTLIL::Const>> set_init;
|
ShardedVector<std::pair<RTLIL::Wire*, RTLIL::Const>> set_init;
|
||||||
ShardedVector<RTLIL::SigSig> new_connections;
|
ShardedVector<RTLIL::SigSig> new_connections;
|
||||||
ShardedVector<RTLIL::Wire*> remove_unused_bits;
|
|
||||||
ShardedVector<std::pair<RTLIL::Wire*, RTLIL::Const>> set_unused_bits;
|
|
||||||
WireDeleter(UsedSignals& used_sig_analysis, bool purge_mode, const AnalysisContext& actx) :
|
WireDeleter(UsedSignals& used_sig_analysis, bool purge_mode, const AnalysisContext& actx) :
|
||||||
remove_init(actx.subpool),
|
remove_init(actx.subpool),
|
||||||
set_init(actx.subpool),
|
set_init(actx.subpool),
|
||||||
new_connections(actx.subpool),
|
new_connections(actx.subpool) {
|
||||||
remove_unused_bits(actx.subpool),
|
|
||||||
set_unused_bits(actx.subpool) {
|
|
||||||
ShardedVector<RTLIL::Wire*> del_wires(actx.subpool);
|
ShardedVector<RTLIL::Wire*> del_wires(actx.subpool);
|
||||||
actx.subpool.run([&actx, purge_mode, &del_wires, &used_sig_analysis, this](const ParallelDispatchThreadPool::RunCtx &ctx) {
|
actx.subpool.run([&actx, purge_mode, &del_wires, &used_sig_analysis, this](const ParallelDispatchThreadPool::RunCtx &ctx) {
|
||||||
for (int i : ctx.item_range(actx.mod->wires_size())) {
|
for (int i : ctx.item_range(actx.mod->wires_size())) {
|
||||||
|
|
@ -471,32 +449,6 @@ struct WireDeleter {
|
||||||
} else
|
} else
|
||||||
if (init_changed)
|
if (init_changed)
|
||||||
set_init.insert(ctx, {wire, std::move(initval)});
|
set_init.insert(ctx, {wire, std::move(initval)});
|
||||||
|
|
||||||
std::string unused_bits;
|
|
||||||
if (!check_all(used_sig_analysis.used, s2)) {
|
|
||||||
for (int i = 0; i < GetSize(s2); i++) {
|
|
||||||
if (s2[i].wire == NULL)
|
|
||||||
continue;
|
|
||||||
SigBit b = s2[i];
|
|
||||||
if (used_sig_analysis.used.find({b, b.hash_top().yield()}) == nullptr) {
|
|
||||||
if (!unused_bits.empty())
|
|
||||||
unused_bits += " ";
|
|
||||||
unused_bits += stringf("%d", i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (unused_bits.empty() || wire->port_id != 0) {
|
|
||||||
if (wire->attributes.count(ID::unused_bits))
|
|
||||||
remove_unused_bits.insert(ctx, wire);
|
|
||||||
} else {
|
|
||||||
RTLIL::Const unused_bits_const(std::move(unused_bits));
|
|
||||||
if (wire->attributes.count(ID::unused_bits)) {
|
|
||||||
RTLIL::Const &unused_bits_attr = wire->attributes.at(ID::unused_bits);
|
|
||||||
if (unused_bits_attr != unused_bits_const)
|
|
||||||
set_unused_bits.insert(ctx, {wire, std::move(unused_bits_const)});
|
|
||||||
} else
|
|
||||||
set_unused_bits.insert(ctx, {wire, std::move(unused_bits_const)});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -511,10 +463,6 @@ struct WireDeleter {
|
||||||
p.first->attributes[ID::init] = std::move(p.second);
|
p.first->attributes[ID::init] = std::move(p.second);
|
||||||
for (auto &conn : new_connections)
|
for (auto &conn : new_connections)
|
||||||
mod->connect(std::move(conn));
|
mod->connect(std::move(conn));
|
||||||
for (RTLIL::Wire *wire : remove_unused_bits)
|
|
||||||
wire->attributes.erase(ID::unused_bits);
|
|
||||||
for (auto &p : set_unused_bits)
|
|
||||||
p.first->attributes[ID::unused_bits] = std::move(p.second);
|
|
||||||
}
|
}
|
||||||
int delete_wires(RTLIL::Module* mod, bool verbose) {
|
int delete_wires(RTLIL::Module* mod, bool verbose) {
|
||||||
int deleted_and_unreported = 0;
|
int deleted_and_unreported = 0;
|
||||||
|
|
@ -557,7 +505,7 @@ bool rmunused_module_signals(RTLIL::Module *module, ParallelDispatchThreadPool::
|
||||||
module->connections_.clear();
|
module->connections_.clear();
|
||||||
|
|
||||||
UsedSignals used;
|
UsedSignals used;
|
||||||
DeferredUpdates deferred = analyse_connectivity(used, conn_kinds, actx, clean_ctx);
|
DeferredUpdates deferred = analyse_connectivity(used, conn_kinds, actx);
|
||||||
fixup_cell_ports(deferred.update_connections);
|
fixup_cell_ports(deferred.update_connections);
|
||||||
// Rip up and re-apply init attributes onto representative wires with x-bits
|
// Rip up and re-apply init attributes onto representative wires with x-bits
|
||||||
// in place of unset init bits
|
// in place of unset init bits
|
||||||
|
|
|
||||||
|
|
@ -453,7 +453,6 @@ struct WreduceWorker
|
||||||
{
|
{
|
||||||
int count = w->attributes.size();
|
int count = w->attributes.size();
|
||||||
count -= w->attributes.count(ID::src);
|
count -= w->attributes.count(ID::src);
|
||||||
count -= w->attributes.count(ID::unused_bits);
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue