mirror of
https://github.com/YosysHQ/yosys
synced 2026-04-20 19:03:31 +00:00
WIP half broken snapshot
This commit is contained in:
parent
ea0ee069fb
commit
eae87b3161
9 changed files with 1226 additions and 60 deletions
|
|
@ -1437,6 +1437,7 @@ RTLIL::Module::Module()
|
|||
|
||||
RTLIL::Module::~Module()
|
||||
{
|
||||
clear_sig_norm_index();
|
||||
for (auto &pr : wires_)
|
||||
delete pr.second;
|
||||
for (auto &pr : memories)
|
||||
|
|
@ -2842,24 +2843,6 @@ void RTLIL::Module::remove(const pool<RTLIL::Wire*> &wires)
|
|||
delete it;
|
||||
}
|
||||
}
|
||||
|
||||
void RTLIL::Module::remove(RTLIL::Cell *cell)
|
||||
{
|
||||
while (!cell->connections_.empty())
|
||||
cell->unsetPort(cell->connections_.begin()->first);
|
||||
|
||||
log_assert(cells_.count(cell->name) != 0);
|
||||
log_assert(refcount_cells_ == 0);
|
||||
cells_.erase(cell->name);
|
||||
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)
|
||||
{
|
||||
log_assert(processes.count(process->name) != 0);
|
||||
|
|
@ -2996,29 +2979,6 @@ void RTLIL::Module::connect(const RTLIL::SigSpec &lhs, const RTLIL::SigSpec &rhs
|
|||
connect(RTLIL::SigSig(lhs, rhs));
|
||||
}
|
||||
|
||||
void RTLIL::Module::new_connections(const std::vector<RTLIL::SigSig> &new_conn)
|
||||
{
|
||||
for (auto mon : monitors)
|
||||
mon->notify_connect(this, new_conn);
|
||||
|
||||
if (design)
|
||||
for (auto mon : design->monitors)
|
||||
mon->notify_connect(this, new_conn);
|
||||
|
||||
if (yosys_xtrace) {
|
||||
log("#X# New connections vector in %s:\n", log_id(this));
|
||||
for (auto &conn: new_conn)
|
||||
log("#X# %s = %s (%d bits)\n", log_signal(conn.first), log_signal(conn.second), GetSize(conn.first));
|
||||
log_backtrace("-X- ", yosys_xtrace-1);
|
||||
}
|
||||
|
||||
connections_ = new_conn;
|
||||
}
|
||||
|
||||
const std::vector<RTLIL::SigSig> &RTLIL::Module::connections() const
|
||||
{
|
||||
return connections_;
|
||||
}
|
||||
|
||||
void RTLIL::Module::fixup_ports()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -121,6 +121,7 @@ namespace RTLIL
|
|||
struct Binding;
|
||||
struct IdString;
|
||||
struct StaticIdString;
|
||||
struct SigNormIndex;
|
||||
|
||||
typedef std::pair<SigSpec, SigSpec> SigSig;
|
||||
|
||||
|
|
@ -133,6 +134,8 @@ namespace RTLIL
|
|||
const IdString &id_str;
|
||||
const StaticId id;
|
||||
};
|
||||
|
||||
struct PortBit;
|
||||
};
|
||||
|
||||
struct RTLIL::IdString
|
||||
|
|
@ -1527,7 +1530,9 @@ struct RTLIL::Design
|
|||
dict<std::string, std::string> scratchpad;
|
||||
|
||||
bool flagBufferedNormalized = false;
|
||||
bool flagSigNormalized = false;
|
||||
void bufNormalize(bool enable=true);
|
||||
void sigNormalize(bool enable=true);
|
||||
|
||||
int refcount_modules_;
|
||||
dict<RTLIL::IdString, RTLIL::Module*> modules_;
|
||||
|
|
@ -1687,6 +1692,10 @@ struct RTLIL::Design
|
|||
|
||||
struct RTLIL::Module : public RTLIL::NamedObject
|
||||
{
|
||||
friend struct RTLIL::SigNormIndex;
|
||||
friend struct RTLIL::Cell;
|
||||
friend struct RTLIL::Design;
|
||||
|
||||
Hasher::hash_t hashidx_;
|
||||
[[nodiscard]] Hasher hash_into(Hasher h) const { h.eat(hashidx_); return h; }
|
||||
|
||||
|
|
@ -1745,6 +1754,18 @@ public:
|
|||
dict<RTLIL::Wire *, pool<RTLIL::Cell *>> buf_norm_connect_index;
|
||||
void bufNormalize();
|
||||
|
||||
protected:
|
||||
SigNormIndex *sig_norm_index = nullptr;
|
||||
void clear_sig_norm_index();
|
||||
int timestamp_ = 0;
|
||||
public:
|
||||
void sigNormalize();
|
||||
|
||||
int timestamp() const { return timestamp_; }
|
||||
int next_timestamp();
|
||||
std::vector<Cell *> dirty_cells(int starting_from);
|
||||
const pool<PortBit> &fanout(SigBit bit);
|
||||
|
||||
template<typename T> void rewrite_sigspecs(T &functor);
|
||||
template<typename T> void rewrite_sigspecs2(T &functor);
|
||||
void cloneInto(RTLIL::Module *new_mod) const;
|
||||
|
|
@ -2057,6 +2078,7 @@ struct RTLIL::Wire : public RTLIL::NamedObject
|
|||
protected:
|
||||
// use module->addWire() and module->remove() to create or destroy wires
|
||||
friend struct RTLIL::Module;
|
||||
friend struct RTLIL::SigNormIndex;
|
||||
Wire();
|
||||
~Wire();
|
||||
|
||||
|
|
@ -2248,6 +2270,33 @@ public:
|
|||
RTLIL::Process *clone() const;
|
||||
};
|
||||
|
||||
struct RTLIL::PortBit
|
||||
{
|
||||
RTLIL::Cell *cell;
|
||||
RTLIL::IdString port;
|
||||
int offset;
|
||||
PortBit(Cell* c, IdString p, int o) : cell(c), port(p), offset(o) {}
|
||||
|
||||
bool operator<(const PortBit &other) const {
|
||||
if (cell != other.cell)
|
||||
return cell < other.cell;
|
||||
if (port != other.port)
|
||||
return port < other.port;
|
||||
return offset < other.offset;
|
||||
}
|
||||
|
||||
bool operator==(const PortBit &other) const {
|
||||
return cell == other.cell && port == other.port && offset == other.offset;
|
||||
}
|
||||
|
||||
[[nodiscard]] Hasher hash_into(Hasher h) const {
|
||||
h.eat(cell->name);
|
||||
h.eat(port);
|
||||
h.eat(offset);
|
||||
return h;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
inline RTLIL::SigBit::SigBit() : wire(NULL), data(RTLIL::State::S0) { }
|
||||
inline RTLIL::SigBit::SigBit(RTLIL::State bit) : wire(NULL), data(bit) { }
|
||||
|
|
|
|||
|
|
@ -28,6 +28,219 @@
|
|||
YOSYS_NAMESPACE_BEGIN
|
||||
|
||||
|
||||
typedef std::pair<Cell*, IdString> cell_port_t;
|
||||
|
||||
|
||||
|
||||
struct RTLIL::SigNormIndex
|
||||
{
|
||||
SigNormIndex(RTLIL::Module *module) : module(module) {}
|
||||
RTLIL::Module *module;
|
||||
|
||||
SigMap sigmap;
|
||||
size_t restored_connections = 0;
|
||||
|
||||
dict<SigBit, pool<PortBit>> fanout;
|
||||
|
||||
pool<SigBit> newly_driven;
|
||||
|
||||
dict<Cell *, int> cell_timestamps;
|
||||
dict<int, pool<Cell *>> timestamp_cells;
|
||||
pool<Cell *> dirty;
|
||||
|
||||
void setup() {
|
||||
module->fixup_ports();
|
||||
setup_module_inputs();
|
||||
setup_driven_wires();
|
||||
setup_fanout();
|
||||
}
|
||||
|
||||
void normalize() {
|
||||
flush_connections();
|
||||
flush_newly_driven();
|
||||
}
|
||||
|
||||
void setup_module_inputs() {
|
||||
std::vector<Cell *> cells_to_remove;
|
||||
dict<Wire *, Cell *> input_port_cells;
|
||||
|
||||
for (auto cell : module->cells()) {
|
||||
if (cell->type != ID($input_port))
|
||||
continue;
|
||||
|
||||
auto const &sig_y = cell->getPort(ID::Y);
|
||||
Wire *wire;
|
||||
if (sig_y.is_wire() && (wire = sig_y.as_wire())->port_input && !wire->port_output && !input_port_cells.count(wire))
|
||||
input_port_cells.emplace(wire, cell);
|
||||
else
|
||||
cells_to_remove.push_back(cell);
|
||||
|
||||
for (auto cell : cells_to_remove)
|
||||
module->remove(cell);
|
||||
}
|
||||
|
||||
for (auto portname : module->ports) {
|
||||
Wire *wire = module->wire(portname);
|
||||
if (wire->port_input && !wire->port_output && !input_port_cells.count(wire)) {
|
||||
Cell *cell = module->addCell(NEW_ID, ID($input_port));
|
||||
cell->setParam(ID::WIDTH, GetSize(wire));
|
||||
cell->setPort(ID::Y, wire);
|
||||
input_port_cells.emplace(wire, cell);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto [wire, cell] : input_port_cells) {
|
||||
wire->driverCell_ = cell;
|
||||
wire->driverPort_ = ID::Y;
|
||||
}
|
||||
}
|
||||
|
||||
void setup_driven_wires() {
|
||||
for (auto cell : module->cells()) {
|
||||
for (auto &[port, sig] : cell->connections_) {
|
||||
if (cell->port_dir(port) == RTLIL::PD_INPUT)
|
||||
continue;
|
||||
if (sig.is_wire()) {
|
||||
Wire * wire = sig.as_wire();
|
||||
|
||||
if (wire->driverCell_ == cell && wire->driverPort_ == port)
|
||||
continue;
|
||||
if (wire->driverCell_ == nullptr) {
|
||||
wire->driverCell_ = cell;
|
||||
wire->driverPort_ = port;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
Wire *wire = module->addWire(NEW_ID, GetSize(sig));
|
||||
wire->driverCell_ = cell;
|
||||
wire->driverPort_ = port;
|
||||
|
||||
module->connect(sig, wire);
|
||||
sig = wire;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void setup_fanout() {
|
||||
for (auto cell : module->cells()) {
|
||||
for (auto &[port, sig] : cell->connections_) {
|
||||
if (cell->port_dir(port) != RTLIL::PD_INPUT)
|
||||
continue;
|
||||
int i = 0;
|
||||
for (auto bit : sig)
|
||||
fanout[bit].insert(PortBit(cell, port, i++));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void flush_connections() {
|
||||
std::vector<SigBit> connect_lhs;
|
||||
std::vector<SigBit> connect_rhs;
|
||||
|
||||
auto begin = module->connections_.begin() + restored_connections;
|
||||
auto end = module->connections_.end();
|
||||
|
||||
for (auto it = begin; it != end; ++it) {
|
||||
auto &[lhs, rhs] = *it;
|
||||
sigmap.apply(lhs);
|
||||
sigmap.apply(rhs);
|
||||
auto rhs_bits = rhs.bits().begin();
|
||||
|
||||
connect_lhs.clear();
|
||||
connect_rhs.clear();
|
||||
|
||||
for (auto l : lhs.bits()) {
|
||||
auto r = *(rhs_bits++);
|
||||
if (l == r)
|
||||
continue;
|
||||
// TODO figure out what should happen with 'z
|
||||
bool l_driven = !l.is_wire() || l.wire->known_driver();
|
||||
bool r_driven = !r.is_wire() || r.wire->known_driver();
|
||||
if (l_driven && r_driven) {
|
||||
connect_lhs.push_back(l);
|
||||
connect_rhs.push_back(r);
|
||||
continue;
|
||||
}
|
||||
|
||||
sigmap.add(l, r);
|
||||
if (l_driven) {
|
||||
sigmap.database.promote(l);
|
||||
newly_driven.insert(r);
|
||||
} else {
|
||||
sigmap.database.promote(r);
|
||||
newly_driven.insert(l);
|
||||
}
|
||||
}
|
||||
|
||||
if (!connect_lhs.empty()) {
|
||||
Cell *cell = module->addCell(NEW_ID, ID($connect));
|
||||
cell->setParam(ID::WIDTH, GetSize(connect_lhs));
|
||||
cell->setPort(ID::A, std::move(connect_lhs));
|
||||
cell->setPort(ID::B, std::move(connect_rhs));
|
||||
}
|
||||
}
|
||||
|
||||
module->connections_.clear();
|
||||
restored_connections = 0;
|
||||
}
|
||||
|
||||
void flush_newly_driven() {
|
||||
pool<cell_port_t> ports_to_normalize;
|
||||
SigSpec tmp;
|
||||
|
||||
while (!newly_driven.empty()) {
|
||||
SigBit current = newly_driven.pop();
|
||||
|
||||
auto found = fanout.find(current);
|
||||
if (found == fanout.end())
|
||||
continue;
|
||||
|
||||
ports_to_normalize.clear();
|
||||
|
||||
for (auto const &portbit : found->second)
|
||||
ports_to_normalize.emplace(portbit.cell, portbit.port);
|
||||
|
||||
for (auto const &[cell, port] : ports_to_normalize) {
|
||||
tmp = cell->getPort(port);
|
||||
cell->setPort(port, tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void restore_connections() {
|
||||
flush_connections();
|
||||
pool<Wire *> wires;
|
||||
for (auto const &bit : sigmap.database)
|
||||
if (bit.is_wire())
|
||||
wires.insert(bit.wire);
|
||||
|
||||
|
||||
std::vector<SigBit> connect_lhs;
|
||||
std::vector<SigBit> connect_rhs;
|
||||
|
||||
for (auto wire : wires) {
|
||||
connect_lhs.clear();
|
||||
connect_rhs.clear();
|
||||
for (int i = 0; i < GetSize(wire); ++i) {
|
||||
SigBit l = SigBit(wire, i);
|
||||
SigBit r = sigmap(l);
|
||||
if (l == r)
|
||||
continue;
|
||||
connect_lhs.push_back(l);
|
||||
connect_rhs.push_back(r);
|
||||
}
|
||||
|
||||
if (!connect_lhs.empty())
|
||||
module->connections_.emplace_back(std::move(connect_lhs), std::move(connect_rhs));
|
||||
}
|
||||
|
||||
restored_connections = module->connections_.size();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void RTLIL::Design::bufNormalize(bool enable)
|
||||
{
|
||||
if (!enable)
|
||||
|
|
@ -50,6 +263,8 @@ void RTLIL::Design::bufNormalize(bool enable)
|
|||
return;
|
||||
}
|
||||
|
||||
log_assert(!flagSigNormalized);
|
||||
|
||||
if (!flagBufferedNormalized)
|
||||
{
|
||||
for (auto module : modules())
|
||||
|
|
@ -78,8 +293,190 @@ void RTLIL::Design::bufNormalize(bool enable)
|
|||
module->bufNormalize();
|
||||
}
|
||||
|
||||
void RTLIL::Design::sigNormalize(bool enable)
|
||||
{
|
||||
if (!enable)
|
||||
{
|
||||
if (!flagSigNormalized)
|
||||
return;
|
||||
|
||||
|
||||
for (auto module : modules()) {
|
||||
module->connections();
|
||||
if (module->sig_norm_index != nullptr) {
|
||||
delete module->sig_norm_index;
|
||||
module->sig_norm_index = nullptr;
|
||||
}
|
||||
|
||||
for (auto wire : module->wires()) {
|
||||
wire->driverCell_ = nullptr;
|
||||
wire->driverPort_ = IdString();
|
||||
}
|
||||
}
|
||||
|
||||
flagSigNormalized = false;
|
||||
return;
|
||||
}
|
||||
|
||||
log_assert(!flagBufferedNormalized);
|
||||
|
||||
if (!flagSigNormalized)
|
||||
{
|
||||
|
||||
|
||||
flagSigNormalized = true;
|
||||
}
|
||||
|
||||
for (auto module : modules())
|
||||
module->sigNormalize();
|
||||
}
|
||||
|
||||
void RTLIL::Module::sigNormalize()
|
||||
{
|
||||
log_assert(design->flagSigNormalized);
|
||||
|
||||
if (sig_norm_index == nullptr) {
|
||||
auto new_index = new RTLIL::SigNormIndex(this);
|
||||
new_index->setup();
|
||||
sig_norm_index = new_index;
|
||||
}
|
||||
|
||||
sig_norm_index->normalize();
|
||||
|
||||
}
|
||||
|
||||
void RTLIL::Module::clear_sig_norm_index()
|
||||
{
|
||||
if (sig_norm_index == nullptr)
|
||||
return;
|
||||
delete sig_norm_index;
|
||||
}
|
||||
|
||||
|
||||
const std::vector<RTLIL::SigSig> &RTLIL::Module::connections() const
|
||||
{
|
||||
if (sig_norm_index != nullptr)
|
||||
sig_norm_index->restore_connections();
|
||||
return connections_;
|
||||
}
|
||||
|
||||
void RTLIL::Module::new_connections(const std::vector<RTLIL::SigSig> &new_conn)
|
||||
{
|
||||
if (sig_norm_index != nullptr) {
|
||||
sig_norm_index->restore_connections();
|
||||
sig_norm_index->restored_connections = 0;
|
||||
// TODO clear the sigmap as well?
|
||||
}
|
||||
for (auto mon : monitors)
|
||||
mon->notify_connect(this, new_conn);
|
||||
|
||||
if (design)
|
||||
for (auto mon : design->monitors)
|
||||
mon->notify_connect(this, new_conn);
|
||||
|
||||
if (yosys_xtrace) {
|
||||
log("#X# New connections vector in %s:\n", log_id(this));
|
||||
for (auto &conn: new_conn)
|
||||
log("#X# %s = %s (%d bits)\n", log_signal(conn.first), log_signal(conn.second), GetSize(conn.first));
|
||||
log_backtrace("-X- ", yosys_xtrace-1);
|
||||
}
|
||||
|
||||
connections_ = new_conn;
|
||||
}
|
||||
|
||||
|
||||
int RTLIL::Module::next_timestamp()
|
||||
{
|
||||
int old = timestamp_;
|
||||
int current = timestamp_ = old + 1;
|
||||
|
||||
if (sig_norm_index != nullptr) {
|
||||
sigNormalize();
|
||||
for (auto cell : sig_norm_index->dirty) {
|
||||
auto [found, inserted] = sig_norm_index->cell_timestamps.emplace(cell, old);
|
||||
if (!inserted) {
|
||||
log_assert(found->second != old);
|
||||
auto found_cells = sig_norm_index->timestamp_cells.find(found->second);
|
||||
log_assert(found_cells != sig_norm_index->timestamp_cells.end());
|
||||
bool erased = found_cells->second.erase(cell);
|
||||
log_assert(erased);
|
||||
if (found_cells->second.empty())
|
||||
sig_norm_index->timestamp_cells.erase(found_cells);
|
||||
found->second = old;
|
||||
}
|
||||
}
|
||||
sig_norm_index->timestamp_cells[old] = std::move(sig_norm_index->dirty);
|
||||
sig_norm_index->dirty.clear();
|
||||
}
|
||||
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
|
||||
std::vector<Cell *> RTLIL::Module::dirty_cells(int starting_from)
|
||||
{
|
||||
sigNormalize();
|
||||
std::vector<Cell *> result;
|
||||
if (starting_from == INT_MIN) {
|
||||
result.reserve(cells_.size());
|
||||
for (auto cell : cells())
|
||||
result.push_back(cell);
|
||||
return result;
|
||||
}
|
||||
|
||||
for (int i = starting_from; i < timestamp_; ++i) {
|
||||
auto found = sig_norm_index->timestamp_cells.find(i);
|
||||
if (found != sig_norm_index->timestamp_cells.end())
|
||||
for (auto cell : found->second)
|
||||
result.push_back(cell);
|
||||
}
|
||||
if (starting_from <= timestamp_)
|
||||
for (auto cell : sig_norm_index->dirty)
|
||||
result.push_back(cell);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const pool<RTLIL::PortBit> &RTLIL::Module::fanout(SigBit bit) {
|
||||
log_assert(sig_norm_index != nullptr);
|
||||
auto found = sig_norm_index->fanout.find(bit);
|
||||
static pool<RTLIL::PortBit> empty;
|
||||
if (found == sig_norm_index->fanout.end())
|
||||
return empty;
|
||||
return found->second;
|
||||
}
|
||||
|
||||
void RTLIL::Module::remove(RTLIL::Cell *cell)
|
||||
{
|
||||
while (!cell->connections_.empty())
|
||||
cell->unsetPort(cell->connections_.begin()->first);
|
||||
|
||||
log_assert(cells_.count(cell->name) != 0);
|
||||
log_assert(refcount_cells_ == 0);
|
||||
cells_.erase(cell->name);
|
||||
if (design && design->flagBufferedNormalized && buf_norm_cell_queue.count(cell)) {
|
||||
cell->type.clear();
|
||||
cell->name.clear();
|
||||
pending_deleted_cells.insert(cell);
|
||||
} else {
|
||||
if (sig_norm_index != nullptr) {
|
||||
auto found = sig_norm_index->cell_timestamps.find(cell);
|
||||
if (found != sig_norm_index->cell_timestamps.end()) {
|
||||
auto found_cells = sig_norm_index->timestamp_cells.find(found->second);
|
||||
log_assert(found_cells != sig_norm_index->timestamp_cells.end());
|
||||
bool erased = found_cells->second.erase(cell);
|
||||
log_assert(erased);
|
||||
if (found_cells->second.empty())
|
||||
sig_norm_index->timestamp_cells.erase(found_cells);
|
||||
sig_norm_index->cell_timestamps.erase(found);
|
||||
}
|
||||
sig_norm_index->dirty.erase(cell);
|
||||
}
|
||||
delete cell;
|
||||
}
|
||||
}
|
||||
|
||||
typedef ModWalker::PortBit PortBit;
|
||||
|
||||
void RTLIL::Module::bufNormalize()
|
||||
{
|
||||
|
|
@ -540,6 +937,53 @@ void RTLIL::Cell::unsetPort(const RTLIL::IdString& portname)
|
|||
log_backtrace("-X- ", yosys_xtrace-1);
|
||||
}
|
||||
|
||||
if (module->sig_norm_index != nullptr) {
|
||||
module->sig_norm_index->dirty.insert(this);
|
||||
bool is_input_port = port_dir(portname) == RTLIL::PD_INPUT;
|
||||
if (is_input_port) {
|
||||
auto &fanout = module->sig_norm_index->fanout;
|
||||
int counter = 0;
|
||||
for (auto bit : conn_it->second) {
|
||||
int i = counter++;
|
||||
auto found = fanout.find(bit);
|
||||
log_assert(found != fanout.end());
|
||||
int erased = found->second.erase(PortBit(this, portname, i));
|
||||
log_assert(erased);
|
||||
if (found->second.empty())
|
||||
fanout.erase(found);
|
||||
}
|
||||
} else {
|
||||
Wire *w = conn_it->second.as_wire();
|
||||
log_assert(w->driverCell_ == this);
|
||||
log_assert(w->driverPort_ == portname);
|
||||
w->driverCell_ = nullptr;
|
||||
w->driverPort_ = IdString();
|
||||
}
|
||||
// bool clear_fanout = true;
|
||||
// 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();
|
||||
// clear_fanout = false;
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (clear_fanout) {
|
||||
// auto &fanout = module->sig_norm_index->fanout;
|
||||
// int counter = 0;
|
||||
// for (auto bit : conn_it->second) {
|
||||
// int i = counter++;
|
||||
// auto found = fanout.find(bit);
|
||||
// log_assert(found != fanout.end());
|
||||
// int erased = found->second.erase(PortBit(this, portname, i));
|
||||
// log_assert(erased);
|
||||
// if (found->second.empty())
|
||||
// fanout.erase(found);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
if (module->design && module->design->flagBufferedNormalized) {
|
||||
if (conn_it->second.is_wire()) {
|
||||
Wire *w = conn_it->second.as_wire();
|
||||
|
|
@ -583,6 +1027,25 @@ void RTLIL::Cell::unsetPort(const RTLIL::IdString& portname)
|
|||
|
||||
void RTLIL::Cell::setPort(const RTLIL::IdString& portname, RTLIL::SigSpec signal)
|
||||
{
|
||||
bool is_input_port = false;
|
||||
if (module->sig_norm_index != nullptr) {
|
||||
module->sig_norm_index->sigmap.apply(signal);
|
||||
auto dir = port_dir(portname);
|
||||
|
||||
if (dir == RTLIL::PD_INPUT) {
|
||||
is_input_port = true;
|
||||
} else {
|
||||
Wire *wire = nullptr;
|
||||
if (signal.is_wire() && (wire = signal.as_wire())->driverCell_ != nullptr)
|
||||
wire = nullptr;
|
||||
if (wire == nullptr) {
|
||||
wire = module->addWire(NEW_ID, GetSize(signal));
|
||||
module->connect(signal, wire);
|
||||
signal = wire;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto r = connections_.insert(portname);
|
||||
auto conn_it = r.first;
|
||||
if (!r.second && conn_it->second == signal)
|
||||
|
|
@ -600,6 +1063,45 @@ void RTLIL::Cell::setPort(const RTLIL::IdString& portname, RTLIL::SigSpec signal
|
|||
log_backtrace("-X- ", yosys_xtrace-1);
|
||||
}
|
||||
|
||||
|
||||
if (module->sig_norm_index != nullptr) {
|
||||
module->sig_norm_index->dirty.insert(this);
|
||||
if (!r.second) {
|
||||
if (is_input_port) {
|
||||
auto &fanout = module->sig_norm_index->fanout;
|
||||
int counter = 0;
|
||||
for (auto bit : conn_it->second) {
|
||||
int i = counter++;
|
||||
auto found = fanout.find(bit);
|
||||
log_assert(found != fanout.end());
|
||||
int erased = found->second.erase(PortBit(this, portname, i));
|
||||
log_assert(erased);
|
||||
if (found->second.empty())
|
||||
fanout.erase(found);
|
||||
}
|
||||
} else {
|
||||
Wire *w = conn_it->second.as_wire();
|
||||
log_assert(w->driverCell_ == this);
|
||||
log_assert(w->driverPort_ == portname);
|
||||
w->driverCell_ = nullptr;
|
||||
w->driverPort_ = IdString();
|
||||
}
|
||||
}
|
||||
|
||||
if (is_input_port) {
|
||||
auto &fanout = module->sig_norm_index->fanout;
|
||||
int i = 0;
|
||||
for (auto bit : signal)
|
||||
fanout[bit].insert(PortBit(this, portname, i++));
|
||||
} else {
|
||||
Wire *w = signal.as_wire();
|
||||
log_assert(w->driverCell_ == nullptr);
|
||||
log_assert(w->driverPort_.empty());
|
||||
w->driverCell_ = this;
|
||||
w->driverPort_ = portname;
|
||||
}
|
||||
}
|
||||
|
||||
if (module->design && module->design->flagBufferedNormalized)
|
||||
{
|
||||
// We eagerly clear a driver that got disconnected by changing this port connection
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue