mirror of
https://github.com/YosysHQ/yosys
synced 2025-09-30 05:09:04 +00:00
kernel: Rewrite bufNormalize
This is a complete rewrite of the RTLIL-kernel-side bufnorm code. This is done to support inout ports and undirected connections as well as to allow removal of cells while in bufnorm mode. This doesn't yet update the (experimental) `bufnorm` pass, so to manually test the new kernel functionality, it is important to only use `bufnorm -update` and `bufnorm -reset` which rely entirely on the kernel functionality. Other modes of the `bufnorm` pass may still fail in the presence of inout ports or undirected connections.
This commit is contained in:
parent
1251e92e3a
commit
d88d6fce87
5 changed files with 716 additions and 184 deletions
211
kernel/rtlil.cc
211
kernel/rtlil.cc
|
@ -2844,7 +2844,13 @@ void RTLIL::Module::remove(RTLIL::Cell *cell)
|
|||
log_assert(cells_.count(cell->name) != 0);
|
||||
log_assert(refcount_cells_ == 0);
|
||||
cells_.erase(cell->name);
|
||||
delete cell;
|
||||
if (design && design->flagBufferedNormalized && buf_norm_cell_queue.count(cell)) {
|
||||
cell->type.clear();
|
||||
cell->name.clear();
|
||||
pending_deleted_cells.insert(cell);
|
||||
} else {
|
||||
delete cell;
|
||||
}
|
||||
}
|
||||
|
||||
void RTLIL::Module::remove(RTLIL::Process *process)
|
||||
|
@ -3019,6 +3025,14 @@ void RTLIL::Module::fixup_ports()
|
|||
|
||||
std::sort(all_ports.begin(), all_ports.end(), fixup_ports_compare);
|
||||
|
||||
if (design && design->flagBufferedNormalized) {
|
||||
for (auto &w : wires_)
|
||||
if (w.second->driverCell_ && w.second->driverCell_->type == ID($input_port))
|
||||
buf_norm_wire_queue.insert(w.second);
|
||||
|
||||
buf_norm_wire_queue.insert(all_ports.begin(), all_ports.end());
|
||||
}
|
||||
|
||||
ports.clear();
|
||||
for (size_t i = 0; i < all_ports.size(); i++) {
|
||||
ports.push_back(all_ports[i]->name);
|
||||
|
@ -4163,188 +4177,7 @@ bool RTLIL::Cell::hasPort(const RTLIL::IdString& portname) const
|
|||
return connections_.count(portname) != 0;
|
||||
}
|
||||
|
||||
void RTLIL::Cell::unsetPort(const RTLIL::IdString& portname)
|
||||
{
|
||||
RTLIL::SigSpec signal;
|
||||
auto conn_it = connections_.find(portname);
|
||||
|
||||
if (conn_it != connections_.end())
|
||||
{
|
||||
for (auto mon : module->monitors)
|
||||
mon->notify_connect(this, conn_it->first, conn_it->second, signal);
|
||||
|
||||
if (module->design)
|
||||
for (auto mon : module->design->monitors)
|
||||
mon->notify_connect(this, conn_it->first, conn_it->second, signal);
|
||||
|
||||
if (yosys_xtrace) {
|
||||
log("#X# Unconnect %s.%s.%s\n", log_id(this->module), log_id(this), log_id(portname));
|
||||
log_backtrace("-X- ", yosys_xtrace-1);
|
||||
}
|
||||
|
||||
connections_.erase(conn_it);
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
flagBufferedNormalized = false;
|
||||
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) || !connections_.empty())
|
||||
{
|
||||
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();
|
||||
if (wire->driverCell_) {
|
||||
log_error("Conflict between %s %s in module %s\n",
|
||||
log_id(cell), log_id(wire->driverCell_), log_id(this));
|
||||
}
|
||||
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);
|
||||
auto conn_it = r.first;
|
||||
if (!r.second && conn_it->second == signal)
|
||||
return;
|
||||
|
||||
for (auto mon : module->monitors)
|
||||
mon->notify_connect(this, conn_it->first, conn_it->second, signal);
|
||||
|
||||
if (module->design)
|
||||
for (auto mon : module->design->monitors)
|
||||
mon->notify_connect(this, conn_it->first, conn_it->second, signal);
|
||||
|
||||
if (yosys_xtrace) {
|
||||
log("#X# Connect %s.%s.%s = %s (%d)\n", log_id(this->module), log_id(this), log_id(portname), log_signal(signal), GetSize(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);
|
||||
}
|
||||
// bufnorm
|
||||
|
||||
const RTLIL::SigSpec &RTLIL::Cell::getPort(const RTLIL::IdString& portname) const
|
||||
{
|
||||
|
@ -5638,6 +5471,18 @@ bool RTLIL::SigSpec::has_const() const
|
|||
return false;
|
||||
}
|
||||
|
||||
bool RTLIL::SigSpec::has_const(State state) const
|
||||
{
|
||||
cover("kernel.rtlil.sigspec.has_const");
|
||||
|
||||
pack();
|
||||
for (auto it = chunks_.begin(); it != chunks_.end(); it++)
|
||||
if (it->width > 0 && it->wire == NULL && std::find(it->data.begin(), it->data.end(), state) != it->data.end())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool RTLIL::SigSpec::has_marked_bits() const
|
||||
{
|
||||
cover("kernel.rtlil.sigspec.has_marked_bits");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue