3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2026-07-15 03:35:40 +00:00

patch: instead of cell->cell, use port->sig rewrites

This commit is contained in:
Emil J. Tywoniak 2026-05-27 17:00:34 +02:00
parent b3a33aeeba
commit 1cd0d37511
4 changed files with 105 additions and 72 deletions

View file

@ -54,24 +54,50 @@ RTLIL::Wire *RTLIL::Patch::addWire(RTLIL::IdString name, const RTLIL::Wire *othe
return wire;
}
void Patch::collect_src(Cell* old_cell) {
src.insert(old_cell->get_src_attribute());
log("collect %s\n", old_cell->name);
std::vector<Cell*> inputs = {};
for (auto [port_name, sig] : old_cell->connections()) {
auto dir = old_cell->port_dir(port_name);
log_assert(dir != PD_UNKNOWN);
if (dir == PD_INPUT || dir == PD_INOUT) {
if (sig.size() && sig.is_wire()) {
Wire* in_wire = sig.as_wire();
if (!leaves.count(in_wire))
inputs.push_back(in_wire->driverCell());
struct SrcCollector {
pool<Cell*> to_do;
pool<Cell*> done;
pool<string> src;
void collect_src(Cell* old_cell) {
if (done.count(old_cell))
return;
done.insert(old_cell);
log("collect %s\n", old_cell->name);
src.insert(old_cell->get_src_attribute());
std::vector<Cell*> input_cells = {};
for (auto [port_name, sig] : old_cell->connections()) {
auto dir = old_cell->port_dir(port_name);
log_assert(dir != PD_UNKNOWN);
if (dir == PD_INPUT || dir == PD_INOUT) {
if (sig.size() && sig.is_wire()) {
Wire* in_wire = sig.as_wire();
if (!in_wire->module)
input_cells.push_back(in_wire->driverCell());
// if (!leaves.count(in_wire))
}
}
}
for (auto input : input_cells)
collect_src(input);
}
for (auto input : inputs)
collect_src(input);
}
void collect_src(SigSpec old_sig) {
log("collect %s\n", log_signal(old_sig));
for (auto bit : old_sig) {
if (bit.is_wire() && bit.wire->module) {
log_assert(bit.wire->driverCell_);
to_do.insert(bit.wire->driverCell_);
}
}
for (auto cell : to_do)
collect_src(cell);
}
};
void Patch::gc(Cell* old_cell) {
log("gc %s\n", old_cell->name);
@ -89,7 +115,9 @@ void Patch::gc(Cell* old_cell) {
}
if (dir == PD_INPUT || dir == PD_INOUT) {
Wire* in_wire = sig.as_wire();
if (!leaves.count(in_wire))
log_assert(in_wire);
log_debug("%s\n", in_wire->name);
if (in_wire->known_driver() && !leaves.count(in_wire))
inputs.push_back(in_wire->driverCell());
}
}
@ -99,42 +127,45 @@ void Patch::gc(Cell* old_cell) {
gc(input);
}
void Patch::patch(Cell* old_cell, Cell* new_cell) {
log_assert(!leaves.empty());
collect_src(old_cell);
std::string src_str = AttrObject::strpool_attribute_to_str(src);
for (auto& wire: wires_) {
wire->module = mod;
Wire* raw = wire.release();
mod->wires_[raw->name] = raw;
}
log("patching:\n");
log_cell(old_cell);
Wire* Patch::commit_wire(std::unique_ptr<Wire> wire) {
Wire* raw = wire.release();
mod->wires_[raw->name] = raw;
raw->module = mod;
return raw;
}
Cell* Patch::commit_cell(std::unique_ptr<Cell> cell) {
Cell* raw = cell.release();
mod->cells_[raw->name] = raw;
raw->module = mod;
raw->initIndex();
return raw;
}
void Patch::patch(Cell* old_cell, IdString old_port, SigSpec new_sig) {
SigSpec old_sig = old_cell->getPort(old_port);
log_assert(old_sig.size() == new_sig.size());
log_debug("patching %s %s which is %s with %s:\n", old_cell->name, old_port, log_signal(old_sig), log_signal(new_sig));
SrcCollector collector;
collector.collect_src(old_sig);
std::string src_str = AttrObject::strpool_attribute_to_str(collector.src);
old_cell->setPort(old_port, SigSpec());
mod->connect(old_sig, new_sig);
if (map)
map->add(old_sig, new_sig);
for (auto& cell: cells_) {
log_cell(cell.get());
cell->set_src_attribute(src_str);
Cell* raw = cell.release();
mod->cells_[raw->name] = raw;
for (auto [port_name, sig] : raw->connections()) {
auto dir = raw->port_dir(port_name);
log_assert(dir != PD_UNKNOWN);
if (dir == PD_OUTPUT || dir == PD_INOUT) {
if (raw == new_cell) {
// RAUW
auto yoink = old_cell->getPort(port_name);
log(">>>> RAUW %s to %s\n", port_name, log_signal(yoink));
new_cell->setPort(port_name, yoink);
old_cell->setPort(port_name, mod->addWire(NEW_ID, yoink.size()));
}
}
}
raw->module = mod;
raw->initIndex();
raw->fixup_parameters();
cell->fixup_parameters();
commit_cell(std::move(cell));
}
log_module(mod, "");
for (auto& wire: wires_)
commit_wire(std::move(wire));
gc(old_cell);
}
YOSYS_NAMESPACE_END

View file

@ -8,11 +8,7 @@ YOSYS_NAMESPACE_BEGIN
struct RTLIL::Patch final : public CellAdderMixin<RTLIL::Patch>
{
Hasher::hash_t hashidx_;
[[nodiscard]] Hasher hash_into(Hasher h) const { h.eat(hashidx_); return h; }
private:
void collect_src(Cell* old_cell);
void gc(Cell* old_cell);
protected:
@ -20,22 +16,21 @@ protected:
void add(RTLIL::Cell *cell);
void add(RTLIL::Process *process);
public:
Module *mod;
// SigMap map;
vector<std::unique_ptr<Wire>> wires_;
vector<std::unique_ptr<Cell>> cells_;
Cell* root;
pool<Wire*> leaves;
Cell* commit_cell(std::unique_ptr<Cell> cell);
Wire* commit_wire(std::unique_ptr<Wire> wire);
// vector<RTLIL::SigSig> connections_;
pool<string> src;
public:
Module* mod;
SigMap* map;
vector<std::unique_ptr<Wire>> wires_ = {};
vector<std::unique_ptr<Cell>> cells_ = {};
pool<Wire*> leaves = {};
void connect(const RTLIL::SigSig &conn);
void connect(const RTLIL::SigSpec &lhs, const RTLIL::SigSpec &rhs);
const std::vector<RTLIL::SigSig> &connections() const;
void patch(Cell* old_cell, Cell* new_cell);
void patch(Cell* old_cell, IdString old_port, SigSpec new_sig);
RTLIL::Wire *addWire(RTLIL::IdString name, int width = 1);
RTLIL::Wire *addWire(RTLIL::IdString name, const RTLIL::Wire *other);

View file

@ -15,6 +15,7 @@ struct TestPatchPass : public Pass {
(void) args;
design->sigNormalize();
for (auto module : design->selected_modules()) {
SigMap sigmap(module);
for (auto cell : module->selected_cells()) {
if (cell->type == ID($add)) {
Cell* add = cell;
@ -22,17 +23,18 @@ struct TestPatchPass : public Pass {
log_assert(add->getPort(ID::B).known_driver());
auto neg = add->getPort(ID::B)[0].wire->driverCell();
log_assert(neg->type == ID($not));
RTLIL::Patch patcher;
patcher.mod = module;
RTLIL::Patch patcher = {{}, module, nullptr};
int width = cell->getPort(ID::A).size();
auto sub = patcher.addSub(NEW_ID,
neg->getPort(ID::A),
add->getPort(ID::A),
patcher.addWire(NEW_ID, cell->getPort(ID::A).size()));
auto new_cell = patcher.addNeg(NEW_ID, sub->getPort(ID::Y), SigSpec());
patcher.addWire(NEW_ID, width));
auto new_out_wire = patcher.addWire(NEW_ID, width);
auto new_cell = patcher.addNeg(NEW_ID, sub->getPort(ID::Y), new_out_wire);
log_cell(new_cell);
patcher.leaves.insert(neg->getPort(ID::A).as_wire());
patcher.leaves.insert(add->getPort(ID::A).as_wire());
patcher.patch(add, new_cell);
patcher.patch(add, ID::Y, new_out_wire);
}
}
}

View file

@ -628,12 +628,17 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
if (sig_b == State::S0) {
replace_cell(assign_map, module, cell, "xor_buffer", ID::Y, sig_a);
} else {
RTLIL::Patch patcher;
patcher.mod = module;
Wire* y = patcher.addWire(NEW_ID, cell->type == ID($xor) ? cell->getParam(ID::Y_WIDTH).as_int() : 1);
RTLIL::Patch patcher = {{}, module, &assign_map};
Wire* y = patcher.addWire(NEW_ID, 1);
Cell* new_cell = cell->type == ID($xor) ? patcher.addNot(NEW_ID, sig_a, y) : patcher.addNotGate(NEW_ID, sig_a, y);
patcher.leaves = {cell->getPort(port_a).as_wire()};
patcher.patch(cell, new_cell);
SigSpec sig_y = y;
int width = cell->type == ID($xor) ? cell->getParam(ID::Y_WIDTH).as_int() : 1;
sig_y.append(RTLIL::Const(State::S0, width-1));
(void)new_cell;
for (auto chunk : cell->getPort(port_a).chunks())
if (chunk.wire)
patcher.leaves.insert(chunk.wire);
patcher.patch(cell, ID::Y, sig_y);
}
goto next_cell;
}