mirror of
https://github.com/YosysHQ/yosys
synced 2025-04-23 09:05:32 +00:00
Add RTLIL "buffered-normalized mode" and improve "bufnorm" pass
Signed-off-by: Claire Xenia Wolf <claire@clairexen.net>
This commit is contained in:
parent
8bb70bac8d
commit
80119386c0
5 changed files with 238 additions and 13 deletions
133
kernel/rtlil.cc
133
kernel/rtlil.cc
|
@ -21,6 +21,7 @@
|
|||
#include "kernel/macc.h"
|
||||
#include "kernel/celltypes.h"
|
||||
#include "kernel/binding.h"
|
||||
#include "kernel/sigtools.h"
|
||||
#include "frontends/verilog/verilog_frontend.h"
|
||||
#include "frontends/verilog/preproc.h"
|
||||
#include "backends/rtlil/rtlil_backend.h"
|
||||
|
@ -3564,6 +3565,104 @@ void RTLIL::Cell::unsetPort(const RTLIL::IdString& portname)
|
|||
}
|
||||
}
|
||||
|
||||
void RTLIL::Design::bufNormalize(bool enable)
|
||||
{
|
||||
if (!enable)
|
||||
{
|
||||
if (!flagBufferedNormalized)
|
||||
return;
|
||||
|
||||
for (auto module : modules()) {
|
||||
module->bufNormQueue.clear();
|
||||
for (auto wire : module->wires()) {
|
||||
wire->driverCell = nullptr;
|
||||
wire->driverPort = IdString();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!flagBufferedNormalized)
|
||||
{
|
||||
for (auto module : modules())
|
||||
{
|
||||
for (auto cell : module->cells())
|
||||
for (auto &conn : cell->connections()) {
|
||||
if (!cell->output(conn.first) || GetSize(conn.second) == 0)
|
||||
continue;
|
||||
if (conn.second.is_wire()) {
|
||||
Wire *wire = conn.second.as_wire();
|
||||
log_assert(wire->driverCell == nullptr);
|
||||
wire->driverCell = cell;
|
||||
wire->driverPort = conn.first;
|
||||
} else {
|
||||
pair<RTLIL::Cell*, RTLIL::IdString> key(cell, conn.first);
|
||||
module->bufNormQueue.insert(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
flagBufferedNormalized = true;
|
||||
}
|
||||
|
||||
for (auto module : modules())
|
||||
module->bufNormalize();
|
||||
}
|
||||
|
||||
void RTLIL::Module::bufNormalize()
|
||||
{
|
||||
if (!design->flagBufferedNormalized)
|
||||
return;
|
||||
|
||||
while (GetSize(bufNormQueue))
|
||||
{
|
||||
pool<pair<RTLIL::Cell*, RTLIL::IdString>> queue;
|
||||
bufNormQueue.swap(queue);
|
||||
|
||||
pool<Wire*> outWires;
|
||||
for (auto &conn : connections())
|
||||
for (auto &chunk : conn.first.chunks())
|
||||
if (chunk.wire) outWires.insert(chunk.wire);
|
||||
|
||||
SigMap sigmap(this);
|
||||
new_connections({});
|
||||
|
||||
for (auto &key : queue)
|
||||
{
|
||||
Cell *cell = key.first;
|
||||
const IdString &portname = key.second;
|
||||
const SigSpec &sig = cell->getPort(portname);
|
||||
if (GetSize(sig) == 0) continue;
|
||||
|
||||
if (sig.is_wire()) {
|
||||
Wire *wire = sig.as_wire();
|
||||
log_assert(wire->driverCell == nullptr);
|
||||
wire->driverCell = cell;
|
||||
wire->driverPort = portname;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (auto &chunk : sig.chunks())
|
||||
if (chunk.wire) outWires.insert(chunk.wire);
|
||||
|
||||
Wire *wire = addWire(NEW_ID, GetSize(sig));
|
||||
sigmap.add(sig, wire);
|
||||
cell->setPort(portname, wire);
|
||||
|
||||
// FIXME: Move init attributes from old 'sig' to new 'wire'
|
||||
}
|
||||
|
||||
for (auto wire : outWires)
|
||||
{
|
||||
SigSpec outsig = wire, insig = sigmap(wire);
|
||||
for (int i = 0; i < GetSize(wire); i++)
|
||||
if (insig[i] == outsig[i])
|
||||
insig[i] = State::Sx;
|
||||
addBuf(NEW_ID, insig, outsig);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RTLIL::Cell::setPort(const RTLIL::IdString& portname, RTLIL::SigSpec signal)
|
||||
{
|
||||
auto r = connections_.insert(portname);
|
||||
|
@ -3583,6 +3682,40 @@ void RTLIL::Cell::setPort(const RTLIL::IdString& portname, RTLIL::SigSpec signal
|
|||
log_backtrace("-X- ", yosys_xtrace-1);
|
||||
}
|
||||
|
||||
while (module->design && module->design->flagBufferedNormalized && output(portname))
|
||||
{
|
||||
pair<RTLIL::Cell*, RTLIL::IdString> key(this, portname);
|
||||
|
||||
if (conn_it->second.is_wire()) {
|
||||
Wire *w = conn_it->second.as_wire();
|
||||
if (w->driverCell == this && w->driverPort == portname) {
|
||||
w->driverCell = nullptr;
|
||||
w->driverPort = IdString();
|
||||
}
|
||||
}
|
||||
|
||||
if (GetSize(signal) == 0) {
|
||||
module->bufNormQueue.erase(key);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!signal.is_wire()) {
|
||||
module->bufNormQueue.insert(key);
|
||||
break;
|
||||
}
|
||||
|
||||
Wire *w = signal.as_wire();
|
||||
if (w->driverCell != nullptr) {
|
||||
pair<RTLIL::Cell*, RTLIL::IdString> other_key(w->driverCell, w->driverPort);
|
||||
module->bufNormQueue.insert(other_key);
|
||||
}
|
||||
w->driverCell = this;
|
||||
w->driverPort = portname;
|
||||
|
||||
module->bufNormQueue.erase(key);
|
||||
break;
|
||||
}
|
||||
|
||||
conn_it->second = std::move(signal);
|
||||
}
|
||||
|
||||
|
|
|
@ -1066,6 +1066,9 @@ struct RTLIL::Design
|
|||
pool<RTLIL::Monitor*> monitors;
|
||||
dict<std::string, std::string> scratchpad;
|
||||
|
||||
bool flagBufferedNormalized = false;
|
||||
void bufNormalize(bool enable=true);
|
||||
|
||||
int refcount_modules_;
|
||||
dict<RTLIL::IdString, RTLIL::Module*> modules_;
|
||||
std::vector<RTLIL::Binding*> bindings_;
|
||||
|
@ -1210,6 +1213,9 @@ public:
|
|||
std::vector<RTLIL::IdString> ports;
|
||||
void fixup_ports();
|
||||
|
||||
pool<pair<RTLIL::Cell*, RTLIL::IdString>> bufNormQueue;
|
||||
void bufNormalize();
|
||||
|
||||
template<typename T> void rewrite_sigspecs(T &functor);
|
||||
template<typename T> void rewrite_sigspecs2(T &functor);
|
||||
void cloneInto(RTLIL::Module *new_mod) const;
|
||||
|
@ -1525,6 +1531,9 @@ public:
|
|||
int width, start_offset, port_id;
|
||||
bool port_input, port_output, upto, is_signed;
|
||||
|
||||
RTLIL::Cell *driverCell = nullptr;
|
||||
RTLIL::IdString driverPort;
|
||||
|
||||
#ifdef WITH_PYTHON
|
||||
static std::map<unsigned int, RTLIL::Wire*> *get_all_wires(void);
|
||||
#endif
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue