yosys/kernel/unstable/patch.cc

109 lines
2.6 KiB
C++
Raw Normal View History

2025-12-19 19:14:33 +01:00
#include "kernel/unstable/patch.h"
2025-12-31 17:46:27 +01:00
#include "kernel/celltypes.h"
2026-05-19 12:36:41 +02:00
#include "kernel/log.h"
2025-12-31 17:46:27 +01:00
#include "kernel/rtlil.h"
2025-12-19 19:14:33 +01:00
YOSYS_NAMESPACE_BEGIN
2025-12-31 17:59:24 +01:00
/**
* Notes
*
* If we want GC, we need more indices
* namely user count (and users?). This should be optional
*
*
2025-12-31 17:59:24 +01:00
*/
2025-12-19 19:14:33 +01:00
using namespace RTLIL;
template class CellAdderMixin<Patch>;
2025-12-19 19:14:33 +01:00
Cell* Patch::addCell(IdString name, IdString type) {
2026-05-19 12:36:41 +02:00
cells_.push_back(std::make_unique<Cell>(Cell::ConstructToken{}));
2026-05-14 17:43:46 +02:00
Cell* cell = cells_.back().get();
2026-05-19 12:36:41 +02:00
cell->name = name;
2026-05-14 17:43:46 +02:00
cell->type = type;
return cell;
}
Wire* Patch::addWire(IdString name, int width) {
2026-05-19 15:33:41 +02:00
wires_.push_back(std::make_unique<Wire>(Wire::ConstructToken{}));
Wire* wire = wires_.back().get();
wire->name = name;
wire->width = width;
return wire;
}
// TODO code golf
2026-05-19 15:57:10 +02:00
2026-05-19 15:33:41 +02:00
RTLIL::Wire *RTLIL::Patch::addWire(RTLIL::IdString name, const RTLIL::Wire *other)
{
RTLIL::Wire *wire = addWire(std::move(name));
wire->width = other->width;
wire->start_offset = other->start_offset;
wire->port_id = other->port_id;
wire->port_input = other->port_input;
wire->port_output = other->port_output;
wire->upto = other->upto;
wire->is_signed = other->is_signed;
wire->attributes = other->attributes;
return wire;
2025-12-19 19:14:33 +01:00
}
2026-05-19 12:36:41 +02:00
void Patch::patch(Cell* old_cell, Cell* new_cell) {
2026-05-19 15:33:41 +02:00
for (auto& wire: wires_) {
Wire* raw = wire.release();
mod->wires_[raw->name] = raw;
}
2026-05-19 12:36:41 +02:00
pool<Cell*> patch_cells;
for (auto& cell: cells_) {
2026-05-19 12:36:41 +02:00
patch_cells.insert(cell.get());
}
log("patching:\n");
log_cell(old_cell);
for (auto& cell: cells_) {
log("with:\n");
log_cell(cell.get());
log("ptr %p\n", cell.get());
Cell* raw = cell.release();
log("ptr2 %p\n", raw);
mod->cells_[raw->name] = raw;
raw->module = mod;
for (auto [port_name, sig] : raw->connections()) {
auto dir = raw->port_dir(port_name);
log_assert(dir != PD_UNKNOWN);
if (raw == new_cell)
if (dir == PD_OUTPUT || dir == PD_INOUT) {
// RAUW
2026-05-19 15:57:10 +02:00
// TODO optimized implementation for signorm fanout transfer?
2026-05-19 12:36:41 +02:00
old_cell->setPort(port_name, mod->addWire(NEW_ID, sig.size()));
new_cell->setPort(port_name, sig);
auto* wire = sig.as_wire();
wire->driverCell_ = new_cell;
wire->driverPort_ = port_name;
}
2026-05-19 12:36:41 +02:00
// } else {
// new_cell->setPort(port_name, sig); // map?
// for (auto chunk : map(sig).chunks()) {
// if (chunk.size() == 0)
// continue;
// log_assert(chunk.is_wire());
// auto* wire = chunk.wire;
// // TODO Use roots instead?
// if (patch_cells.count(wire->driverCell_)) {
// // How do we handle this?
// log_assert(false);
// } else {
// // mod->sig_norm_index
// }
// }
}
}
2026-05-19 12:36:41 +02:00
log_module(mod, "");
2025-12-31 17:46:27 +01:00
}
2025-12-19 19:14:33 +01:00
YOSYS_NAMESPACE_END