mirror of https://github.com/YosysHQ/yosys.git
opt_expr: WIP use patcher more
This commit is contained in:
parent
b594196a48
commit
dab9a386cc
|
|
@ -1117,6 +1117,7 @@ void RTLIL::Cell::signorm_index_add(IdString portname, const SigSpec &new_signal
|
|||
{
|
||||
auto &index = *module->sig_norm_index;
|
||||
index.dirty.insert(this);
|
||||
xlog("signorm_index_add cell %s port %s input %d signal %s\n", name, portname, is_input, log_signal(new_signal));
|
||||
if (is_input) {
|
||||
int i = 0;
|
||||
for (auto bit : new_signal) {
|
||||
|
|
|
|||
|
|
@ -94,23 +94,29 @@ void Patch::gc(Cell* old_cell) {
|
|||
for (auto [port_name, sig] : old_cell->connections()) {
|
||||
auto dir = old_cell->port_dir(port_name);
|
||||
log_assert(dir != PD_UNKNOWN);
|
||||
// TODO only running GC through whole connections?
|
||||
log_debug("\tport %s\n", port_name);
|
||||
if (sig.size() && sig.is_wire()) {
|
||||
if (dir == PD_OUTPUT || dir == PD_INOUT) {
|
||||
for (auto bit : sig) {
|
||||
// Reject GC if used
|
||||
if (!mod->fanout(bit).empty())
|
||||
if (!mod->fanout(bit).empty()) {
|
||||
log_debug("\treject fanout\n");
|
||||
return;
|
||||
} else
|
||||
log_debug("\tok\n");
|
||||
}
|
||||
}
|
||||
if (dir == PD_INPUT || dir == PD_INOUT) {
|
||||
Wire* in_wire = sig.as_wire();
|
||||
log_assert(in_wire);
|
||||
log_debug("%s\n", in_wire->name);
|
||||
log_debug("\twire %s\n", in_wire->name);
|
||||
if (in_wire->known_driver() && !leaves.count(in_wire))
|
||||
inputs.push_back(in_wire->driverCell());
|
||||
}
|
||||
}
|
||||
}
|
||||
log_debug("\tremove %s\n", old_cell->name);
|
||||
old_cell->module->remove(old_cell);
|
||||
for (auto input : inputs)
|
||||
gc(input);
|
||||
|
|
@ -134,7 +140,7 @@ Cell* Patch::commit_cell(std::unique_ptr<Cell> cell) {
|
|||
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));
|
||||
log("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);
|
||||
|
|
@ -147,12 +153,18 @@ void Patch::patch(Cell* old_cell, IdString old_port, SigSpec new_sig) {
|
|||
|
||||
// Inefficient
|
||||
for (auto& cell : cells_) {
|
||||
log_debug("cell %s\n", cell->name);
|
||||
for (auto& [port_name, sig] : cell->connections()) {
|
||||
log_debug("port %s\n", port_name);
|
||||
auto dir = cell->port_dir(port_name);
|
||||
if (dir == PD_INPUT || dir == PD_INOUT) {
|
||||
for (auto bit : sig)
|
||||
if (bit.is_wire() && bit.wire->module)
|
||||
for (auto bit : sig) {
|
||||
log("bit %s\n", log_signal(bit));
|
||||
if (bit.is_wire() && bit.wire->module) {
|
||||
leaves.insert(bit.wire);
|
||||
log_debug("leaf %s\n", bit.wire->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -167,6 +179,9 @@ void Patch::patch(Cell* old_cell, IdString old_port, SigSpec new_sig) {
|
|||
commit_wire(std::move(wire));
|
||||
|
||||
gc(old_cell);
|
||||
cells_.clear();
|
||||
wires_.clear();
|
||||
leaves.clear();
|
||||
}
|
||||
|
||||
YOSYS_NAMESPACE_END
|
||||
|
|
@ -6,7 +6,8 @@
|
|||
|
||||
YOSYS_NAMESPACE_BEGIN
|
||||
|
||||
struct RTLIL::Patch final : public CellAdderMixin<RTLIL::Patch>
|
||||
// No virtual methods — subclasses cannot be dispatched through a Patch pointer.
|
||||
struct RTLIL::Patch : public CellAdderMixin<RTLIL::Patch>
|
||||
{
|
||||
private:
|
||||
void gc(Cell* old_cell);
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
|
||||
#include "kernel/register.h"
|
||||
#include "kernel/rtlil.h"
|
||||
#include "kernel/sigtools.h"
|
||||
#include "kernel/celltypes.h"
|
||||
#include "kernel/newcelltypes.h"
|
||||
|
|
@ -118,15 +119,27 @@ void replace_undriven(RTLIL::Module *module, const NewCellTypes &ct)
|
|||
}
|
||||
}
|
||||
|
||||
void log_replace_sig(RTLIL::Module *module, RTLIL::Cell *cell,
|
||||
const std::string &info, RTLIL::SigSpec old_sig, RTLIL::SigSpec new_sig)
|
||||
{
|
||||
log_debug("Replacing %s cell `%s' (%s) in module `%s' with constant driver `%s = %s'.\n",
|
||||
cell->type.c_str(), cell->name.c_str(), info.c_str(),
|
||||
module->name.c_str(), log_signal(old_sig), log_signal(new_sig));
|
||||
}
|
||||
|
||||
void log_replace_port(RTLIL::Module *module, RTLIL::Cell *cell,
|
||||
const std::string &info, RTLIL::IdString port, RTLIL::SigSpec new_sig)
|
||||
{
|
||||
log_replace_sig(module, cell, info, cell->getPort(port), new_sig);
|
||||
}
|
||||
|
||||
void replace_cell(SigMap &assign_map, RTLIL::Module *module, RTLIL::Cell *cell,
|
||||
const std::string &info, IdString out_port, RTLIL::SigSpec out_val)
|
||||
{
|
||||
RTLIL::SigSpec Y = cell->getPort(out_port);
|
||||
out_val.extend_u0(Y.size(), false);
|
||||
|
||||
log_debug("Replacing %s cell `%s' (%s) in module `%s' with constant driver `%s = %s'.\n",
|
||||
cell->type.c_str(), cell->name.c_str(), info.c_str(),
|
||||
module->name.c_str(), log_signal(Y), log_signal(out_val));
|
||||
log_replace_sig(module, cell, info, Y, out_val);
|
||||
// log_cell(cell);
|
||||
assign_map.add(Y, out_val);
|
||||
module->connect(Y, out_val);
|
||||
|
|
@ -134,6 +147,14 @@ void replace_cell(SigMap &assign_map, RTLIL::Module *module, RTLIL::Cell *cell,
|
|||
did_something = true;
|
||||
}
|
||||
|
||||
struct OptExprPatcher : public RTLIL::Patch {
|
||||
using RTLIL::Patch::Patch;
|
||||
void patch(Cell *old_cell, IdString old_port, SigSpec new_sig, const std::string &info) {
|
||||
log_replace_port(mod, old_cell, info, old_port, new_sig);
|
||||
RTLIL::Patch::patch(old_cell, old_port, new_sig);
|
||||
}
|
||||
};
|
||||
|
||||
bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutative, SigMap &sigmap, bool keepdc)
|
||||
{
|
||||
IdString b_name = cell->hasPort(ID::B) ? ID::B : ID::A;
|
||||
|
|
@ -621,18 +642,34 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
if (!sig_a.wire)
|
||||
std::swap(sig_a, sig_b);
|
||||
if (sig_b == State::S0 || sig_b == State::S1) {
|
||||
OptExprPatcher patcher(module, &assign_map);
|
||||
bool is_gate = cell->type.in(ID($_XOR_), ID($_XNOR_));
|
||||
int width = is_gate ? 1 : cell->getParam(ID::Y_WIDTH).as_int();
|
||||
if (cell->type.in(ID($xor), ID($_XOR_))) {
|
||||
if (sig_b == State::S0) {
|
||||
replace_cell(assign_map, module, cell, "xor_buffer", ID::Y, sig_a);
|
||||
} else {
|
||||
RTLIL::Patch patcher(module, &assign_map);
|
||||
SigSpec sig_y = cell->type == ID($xor) ? patcher.Not(NEW_ID, sig_a) : (SigSpec)patcher.NotGate(NEW_ID, sig_a);
|
||||
int width = cell->type == ID($xor) ? cell->getParam(ID::Y_WIDTH).as_int() : 1;
|
||||
SigSpec sig_y = sig_a;
|
||||
sig_y.append(RTLIL::Const(State::S0, width-1));
|
||||
patcher.patch(cell, ID::Y, sig_y);
|
||||
// replace_cell(assign_map, module, cell, "xor_buffer", ID::Y, sig_y);
|
||||
patcher.patch(cell, ID::Y, sig_y, "xor_buffer");
|
||||
} else {
|
||||
SigSpec sig_y = is_gate ? (SigSpec)patcher.NotGate(NEW_ID, sig_a) : patcher.Not(NEW_ID, sig_a);
|
||||
sig_y.append(RTLIL::Const(State::S0, width-1));
|
||||
patcher.patch(cell, ID::Y, sig_y, "xor_buffer");
|
||||
}
|
||||
goto next_cell;
|
||||
}
|
||||
// if (cell->type.in(ID($xnor), ID($_XNOR_))) {
|
||||
// if (sig_b == State::S1) {
|
||||
// SigSpec sig_y = sig_a;
|
||||
// sig_y.append(RTLIL::Const(State::S1, width-1));
|
||||
// patcher.patch(cell, ID::Y, sig_y, "xnor_buffer");
|
||||
// } else {
|
||||
// SigSpec sig_y = is_gate ? (SigSpec)patcher.NotGate(NEW_ID, sig_a) : patcher.Not(NEW_ID, sig_a);
|
||||
// sig_y.append(RTLIL::Const(State::S1, width-1));
|
||||
// patcher.patch(cell, ID::Y, sig_y, "xnor_buffer");
|
||||
// }
|
||||
// goto next_cell;
|
||||
// }
|
||||
if (cell->type.in(ID($xnor), ID($_XNOR_))) {
|
||||
SigSpec sig_y;
|
||||
if (cell->type == ID($xnor)) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue