mirror of
https://github.com/YosysHQ/yosys
synced 2025-09-08 10:41:26 +00:00
WIP prototype bidir aware kernel bufnorm code
This commit is contained in:
parent
727dabba95
commit
4de384d776
1 changed files with 101 additions and 21 deletions
116
kernel/rtlil.cc
116
kernel/rtlil.cc
|
@ -4063,11 +4063,24 @@ void RTLIL::Design::bufNormalize(bool enable)
|
||||||
{
|
{
|
||||||
for (auto cell : module->cells())
|
for (auto cell : module->cells())
|
||||||
for (auto &conn : cell->connections()) {
|
for (auto &conn : cell->connections()) {
|
||||||
if (!cell->output(conn.first) || GetSize(conn.second) == 0)
|
|
||||||
|
PortDir port_dir = cell->port_dir(conn.first);
|
||||||
|
if (port_dir == PD_INPUT || GetSize(conn.second) == 0)
|
||||||
continue;
|
continue;
|
||||||
if (conn.second.is_wire()) {
|
if (conn.second.is_wire()) {
|
||||||
Wire *wire = conn.second.as_wire();
|
Wire *wire = conn.second.as_wire();
|
||||||
log_assert(wire->driverCell_ == nullptr);
|
if (wire->driverCell_ != nullptr) {
|
||||||
|
if (port_dir != PD_OUTPUT) {
|
||||||
|
continue;
|
||||||
|
} else if (wire->driverCell_->port_dir(wire->driverPort_) != PD_OUTPUT) {
|
||||||
|
// port_dir == PD_OUTPUT
|
||||||
|
} else {
|
||||||
|
log_error("Conflict between %s.%s and %s.%s driving %s in module %s\n",
|
||||||
|
log_id(cell), log_id(conn.first),
|
||||||
|
log_id(wire->driverCell_), log_id(wire->driverPort_),
|
||||||
|
log_id(wire), log_id(module));
|
||||||
|
}
|
||||||
|
}
|
||||||
wire->driverCell_ = cell;
|
wire->driverCell_ = cell;
|
||||||
wire->driverPort_ = conn.first;
|
wire->driverPort_ = conn.first;
|
||||||
} else {
|
} else {
|
||||||
|
@ -4094,11 +4107,6 @@ void RTLIL::Module::bufNormalize()
|
||||||
pool<pair<RTLIL::Cell*, RTLIL::IdString>> queue;
|
pool<pair<RTLIL::Cell*, RTLIL::IdString>> queue;
|
||||||
bufNormQueue.swap(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);
|
SigMap sigmap(this);
|
||||||
new_connections({});
|
new_connections({});
|
||||||
|
|
||||||
|
@ -4112,18 +4120,23 @@ void RTLIL::Module::bufNormalize()
|
||||||
if (sig.is_wire()) {
|
if (sig.is_wire()) {
|
||||||
Wire *wire = sig.as_wire();
|
Wire *wire = sig.as_wire();
|
||||||
if (wire->driverCell_) {
|
if (wire->driverCell_) {
|
||||||
log_error("Conflict between %s %s in module %s\n",
|
PortDir port_dir = cell->port_dir(portname);
|
||||||
log_id(cell), log_id(wire->driverCell_), log_id(this));
|
if (port_dir != PD_OUTPUT) {
|
||||||
|
continue;
|
||||||
|
} else if (wire->driverCell_->port_dir(wire->driverPort_) != PD_OUTPUT) {
|
||||||
|
// port_dir == PD_OUTPUT
|
||||||
|
} else {
|
||||||
|
log_error("Conflict between %s.%s and %s.%s driving %s in module %s\n",
|
||||||
|
log_id(cell), log_id(portname),
|
||||||
|
log_id(wire->driverCell_), log_id(wire->driverPort_),
|
||||||
|
log_id(wire), log_id(this));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
log_assert(wire->driverCell_ == nullptr);
|
|
||||||
wire->driverCell_ = cell;
|
wire->driverCell_ = cell;
|
||||||
wire->driverPort_ = portname;
|
wire->driverPort_ = portname;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto &chunk : sig.chunks())
|
|
||||||
if (chunk.wire) outWires.insert(chunk.wire);
|
|
||||||
|
|
||||||
Wire *wire = addWire(NEW_ID, GetSize(sig));
|
Wire *wire = addWire(NEW_ID, GetSize(sig));
|
||||||
sigmap.add(sig, wire);
|
sigmap.add(sig, wire);
|
||||||
cell->setPort(portname, wire);
|
cell->setPort(portname, wire);
|
||||||
|
@ -4131,13 +4144,75 @@ void RTLIL::Module::bufNormalize()
|
||||||
// FIXME: Move init attributes from old 'sig' to new 'wire'
|
// FIXME: Move init attributes from old 'sig' to new 'wire'
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto wire : outWires)
|
pool<Wire*> conn_wires;
|
||||||
|
pool<Wire*> inout_conn_wires;
|
||||||
|
pool<Wire*> driven_conn_wires;
|
||||||
|
|
||||||
|
for (auto const &bit : sigmap.database)
|
||||||
|
if (bit.wire != nullptr)
|
||||||
|
conn_wires.insert(bit.wire);
|
||||||
|
|
||||||
|
for (auto wire : conn_wires) {
|
||||||
|
if (wire->driverCell_ == nullptr) {
|
||||||
|
if (!wire->port_input)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (wire->port_output) {
|
||||||
|
inout_conn_wires.insert(wire);
|
||||||
|
} else {
|
||||||
|
driven_conn_wires.insert(wire);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wire->driverCell_->port_dir(wire->driverPort_) == PD_OUTPUT) {
|
||||||
|
if (wire->port_input && !wire->port_output) {
|
||||||
|
log_error("Conflict between %s.%s and input port %s in module %s\n",
|
||||||
|
log_id(wire->driverCell_), log_id(wire->driverPort_),
|
||||||
|
log_id(wire), log_id(this));
|
||||||
|
}
|
||||||
|
driven_conn_wires.insert(wire);
|
||||||
|
} else {
|
||||||
|
inout_conn_wires.insert(wire);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto wire : inout_conn_wires)
|
||||||
|
for (int i = 0; i < GetSize(wire); ++i)
|
||||||
|
sigmap.database.promote(SigBit(wire, i));
|
||||||
|
|
||||||
|
for (auto wire : driven_conn_wires)
|
||||||
|
for (int i = 0; i < GetSize(wire); ++i)
|
||||||
|
sigmap.database.promote(SigBit(wire, i));
|
||||||
|
|
||||||
|
for (auto wire : conn_wires)
|
||||||
{
|
{
|
||||||
SigSpec outsig = wire, insig = sigmap(wire);
|
SigSpec outsig = wire, insig = sigmap(wire);
|
||||||
for (int i = 0; i < GetSize(wire); i++)
|
if (insig == outsig)
|
||||||
if (insig[i] == outsig[i])
|
continue;
|
||||||
insig[i] = State::Sx;
|
|
||||||
|
bool ambiguous_directionality = false;
|
||||||
|
|
||||||
|
for (int i = 0; i < GetSize(wire) && !ambiguous_directionality; i++) {
|
||||||
|
SigBit inbit = insig[i];
|
||||||
|
SigBit outbit = outsig[i];
|
||||||
|
|
||||||
|
if (inbit == outbit)
|
||||||
|
ambiguous_directionality = true;
|
||||||
|
else
|
||||||
|
ambiguous_directionality = !driven_conn_wires.count(inbit.wire);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ambiguous_directionality) {
|
||||||
|
Cell *connect = addCell(NEW_ID, ID($connect));
|
||||||
|
connect->setParam(ID::WIDTH, GetSize(insig));
|
||||||
|
connect->setPort(ID::A, insig);
|
||||||
|
connect->setPort(ID::Y, outsig);
|
||||||
|
} else {
|
||||||
addBuf(NEW_ID, insig, outsig);
|
addBuf(NEW_ID, insig, outsig);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4161,7 +4236,9 @@ void RTLIL::Cell::setPort(const RTLIL::IdString& portname, RTLIL::SigSpec signal
|
||||||
log_backtrace("-X- ", yosys_xtrace-1);
|
log_backtrace("-X- ", yosys_xtrace-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (module->design && module->design->flagBufferedNormalized && output(portname))
|
PortDir pd;
|
||||||
|
|
||||||
|
while (module->design && module->design->flagBufferedNormalized && (pd = port_dir(portname)) != PD_INPUT)
|
||||||
{
|
{
|
||||||
pair<RTLIL::Cell*, RTLIL::IdString> key(this, portname);
|
pair<RTLIL::Cell*, RTLIL::IdString> key(this, portname);
|
||||||
|
|
||||||
|
@ -4185,9 +4262,12 @@ void RTLIL::Cell::setPort(const RTLIL::IdString& portname, RTLIL::SigSpec signal
|
||||||
|
|
||||||
Wire *w = signal.as_wire();
|
Wire *w = signal.as_wire();
|
||||||
if (w->driverCell_ != nullptr) {
|
if (w->driverCell_ != nullptr) {
|
||||||
|
if (pd == PD_OUTPUT) {
|
||||||
pair<RTLIL::Cell*, RTLIL::IdString> other_key(w->driverCell_, w->driverPort_);
|
pair<RTLIL::Cell*, RTLIL::IdString> other_key(w->driverCell_, w->driverPort_);
|
||||||
module->bufNormQueue.insert(other_key);
|
module->bufNormQueue.insert(other_key);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
w->driverCell_ = this;
|
w->driverCell_ = this;
|
||||||
w->driverPort_ = portname;
|
w->driverPort_ = portname;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue