3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2026-03-02 03:36:56 +00:00
yosys/passes/opt/opt_clean/inits.cc
2026-02-24 12:28:41 +01:00

146 lines
4.5 KiB
C++

/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
#include "kernel/register.h"
#include "kernel/sigtools.h"
#include "kernel/log.h"
#include "kernel/celltypes.h"
#include "kernel/ffinit.h"
#include "kernel/threading.h"
#include "kernel/yosys_common.h"
#include "passes/opt/opt_clean/shared.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
ShardedVector<std::pair<SigBit, State>> build_inits(AnalysisContext& actx) {
ShardedVector<std::pair<SigBit, State>> results(actx.subpool);
CellTypes fftypes;
fftypes.setup_internals_mem();
actx.subpool.run([&results, &fftypes, &actx](const ParallelDispatchThreadPool::RunCtx &ctx) {
for (int i : ctx.item_range(actx.mod->cells_size())) {
RTLIL::Cell *cell = actx.mod->cell_at(i);
if (fftypes.cell_known(cell->type) && cell->hasPort(ID::Q))
{
SigSpec sig = cell->getPort(ID::Q);
for (int i = 0; i < GetSize(sig); i++)
{
SigBit bit = sig[i];
if (bit.wire == nullptr || bit.wire->attributes.count(ID::init) == 0)
continue;
Const init = bit.wire->attributes.at(ID::init);
if (i >= GetSize(init) || init[i] == State::Sx || init[i] == State::Sz)
continue;
results.insert(ctx, {bit, init[i]});
}
}
}
});
return results;
}
dict<SigBit, State> qbits_from_inits(ShardedVector<std::pair<SigBit, State>>& inits, AnalysisContext& actx) {
dict<SigBit, State> qbits;
for (std::pair<SigBit, State> &p : inits) {
actx.assign_map.add(p.first);
qbits[p.first] = p.second;
}
return qbits;
}
ShardedVector<RTLIL::Wire*> deferred_init_transfer(const dict<SigBit, State>& qbits, AnalysisContext& actx) {
ShardedVector<RTLIL::Wire*> wire_results(actx.subpool);
actx.subpool.run([&actx, &qbits, &wire_results](const ParallelDispatchThreadPool::RunCtx &ctx) {
for (int j : ctx.item_range(actx.mod->wires_size())) {
RTLIL::Wire *wire = actx.mod->wire_at(j);
if (wire->attributes.count(ID::init) == 0)
continue;
Const init = wire->attributes.at(ID::init);
for (int i = 0; i < GetSize(wire) && i < GetSize(init); i++)
{
if (init[i] == State::Sx || init[i] == State::Sz)
continue;
SigBit wire_bit = SigBit(wire, i);
SigBit mapped_wire_bit = actx.assign_map(wire_bit);
if (wire_bit == mapped_wire_bit)
goto next_wire;
if (mapped_wire_bit.wire) {
if (qbits.count(mapped_wire_bit) == 0)
goto next_wire;
if (qbits.at(mapped_wire_bit) != init[i])
goto next_wire;
}
else {
if (mapped_wire_bit == State::Sx || mapped_wire_bit == State::Sz)
goto next_wire;
if (mapped_wire_bit != init[i]) {
log_warning("Initial value conflict for %s resolving to %s but with init %s.\n", log_signal(wire_bit), log_signal(mapped_wire_bit), log_signal(init[i]));
goto next_wire;
}
}
}
wire_results.insert(ctx, wire);
next_wire:;
}
});
return wire_results;
}
bool remove_redundant_inits(ShardedVector<RTLIL::Wire*> wires, bool verbose) {
bool did_something = false;
for (RTLIL::Wire *wire : wires) {
if (verbose)
log_debug(" removing redundant init attribute on %s.\n", log_id(wire));
wire->attributes.erase(ID::init);
did_something = true;
}
return did_something;
}
PRIVATE_NAMESPACE_END
YOSYS_NAMESPACE_BEGIN
bool rmunused_module_init(RTLIL::Module *module, ParallelDispatchThreadPool::Subpool &subpool, bool verbose)
{
AnalysisContext actx(module, subpool);
ShardedVector<std::pair<SigBit, State>> inits = build_inits(actx);
dict<SigBit, State> qbits = qbits_from_inits(inits, actx);
ShardedVector<RTLIL::Wire*> inits_to_transfer = deferred_init_transfer(qbits, actx);
bool did_something = remove_redundant_inits(inits_to_transfer, verbose);
if (did_something)
module->design->scratchpad_set_bool("opt.did_something", true);
return did_something;
}
YOSYS_NAMESPACE_END