mirror of
https://github.com/YosysHQ/yosys
synced 2025-06-24 06:43:41 +00:00
obs_clean debug and fencing
This commit is contained in:
parent
ee67e3c901
commit
4089c1b358
1 changed files with 83 additions and 21 deletions
|
@ -106,16 +106,28 @@ void collectTransitiveFanin(RTLIL::SigSpec &sig, SigMap &sigmap, dict<RTLIL::Sig
|
||||||
|
|
||||||
// Only keep the cells and wires that are visited using the transitive fanin reached from output ports or keep signals
|
// Only keep the cells and wires that are visited using the transitive fanin reached from output ports or keep signals
|
||||||
void observabilityClean(RTLIL::Module *module, SigMap &sigmap, dict<RTLIL::SigSpec, std::set<Cell *>> &sig2CellsInFanin,
|
void observabilityClean(RTLIL::Module *module, SigMap &sigmap, dict<RTLIL::SigSpec, std::set<Cell *>> &sig2CellsInFanin,
|
||||||
dict<RTLIL::SigSpec, RTLIL::SigSpec> &lhsSig2RhsSig, bool unused_wires)
|
dict<RTLIL::SigSpec, RTLIL::SigSpec> &lhsSig2RhsSig, bool unused_wires, bool unused_assigns, bool debug)
|
||||||
{
|
{
|
||||||
if (module->get_bool_attribute(ID::keep))
|
if (module->get_bool_attribute(ID::keep))
|
||||||
return;
|
return;
|
||||||
std::set<Cell *> visitedCells;
|
std::set<Cell *> visitedCells;
|
||||||
std::set<RTLIL::SigSpec> visitedSigSpec;
|
std::set<RTLIL::SigSpec> visitedSigSpec;
|
||||||
|
if (debug) {
|
||||||
|
log("Collecting cell transitive fanin\n");
|
||||||
|
log_flush();
|
||||||
|
}
|
||||||
// Collect observable logic (connected to one output)
|
// Collect observable logic (connected to one output)
|
||||||
|
// By cells
|
||||||
for (auto elt : sig2CellsInFanin) {
|
for (auto elt : sig2CellsInFanin) {
|
||||||
RTLIL::SigSpec po = elt.first;
|
RTLIL::SigSpec po = elt.first;
|
||||||
|
if ((!po.size()) || (!po[0].is_wire())) {
|
||||||
|
// Can't perform the analysis correctly.
|
||||||
|
if (debug) {
|
||||||
|
log("Module contains some logic that prevents obs_clean analysis\n");
|
||||||
|
log_flush();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
RTLIL::Wire *w = po[0].wire;
|
RTLIL::Wire *w = po[0].wire;
|
||||||
if (w && (!w->port_output) && (!w->get_bool_attribute(ID::keep))) {
|
if (w && (!w->port_output) && (!w->get_bool_attribute(ID::keep))) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -129,8 +141,21 @@ void observabilityClean(RTLIL::Module *module, SigMap &sigmap, dict<RTLIL::SigSp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (debug) {
|
||||||
|
log("Collecting assign transitive fanin\n");
|
||||||
|
log_flush();
|
||||||
|
}
|
||||||
|
// By assigns
|
||||||
for (auto elt : lhsSig2RhsSig) {
|
for (auto elt : lhsSig2RhsSig) {
|
||||||
RTLIL::SigSpec po = elt.first;
|
RTLIL::SigSpec po = elt.first;
|
||||||
|
if ((!po.size()) || (!po[0].is_wire())) {
|
||||||
|
// Can't perform the analysis correctly.
|
||||||
|
if (debug) {
|
||||||
|
log("Module contains some logic that prevents obs_clean analysis\n");
|
||||||
|
log_flush();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
RTLIL::Wire *w = po[0].wire;
|
RTLIL::Wire *w = po[0].wire;
|
||||||
if (w && (!w->port_output) && (!w->get_bool_attribute(ID::keep))) {
|
if (w && (!w->port_output) && (!w->get_bool_attribute(ID::keep))) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -144,7 +169,12 @@ void observabilityClean(RTLIL::Module *module, SigMap &sigmap, dict<RTLIL::SigSp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (unused_assigns) {
|
||||||
// Remove unused assign stmts
|
// Remove unused assign stmts
|
||||||
|
if (debug) {
|
||||||
|
log("Removing unused assign\n");
|
||||||
|
log_flush();
|
||||||
|
}
|
||||||
std::vector<RTLIL::SigSig> newConnections;
|
std::vector<RTLIL::SigSig> newConnections;
|
||||||
for (auto it = module->connections().begin(); it != module->connections().end(); ++it) {
|
for (auto it = module->connections().begin(); it != module->connections().end(); ++it) {
|
||||||
RTLIL::SigSpec lhs = it->first;
|
RTLIL::SigSpec lhs = it->first;
|
||||||
|
@ -165,9 +195,14 @@ void observabilityClean(RTLIL::Module *module, SigMap &sigmap, dict<RTLIL::SigSp
|
||||||
for (auto conn : newConnections) {
|
for (auto conn : newConnections) {
|
||||||
module->connect(conn);
|
module->connect(conn);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (unused_wires) {
|
if (unused_wires) {
|
||||||
// Remove unused wires
|
// Remove unused wires
|
||||||
|
if (debug) {
|
||||||
|
log("Removing unused wires\n");
|
||||||
|
log_flush();
|
||||||
|
}
|
||||||
// TODO: This impacts equiv_opt ability to perform equivalence checking
|
// TODO: This impacts equiv_opt ability to perform equivalence checking
|
||||||
pool<RTLIL::Wire *> wiresToRemove;
|
pool<RTLIL::Wire *> wiresToRemove;
|
||||||
for (auto wire : module->wires()) {
|
for (auto wire : module->wires()) {
|
||||||
|
@ -197,6 +232,10 @@ void observabilityClean(RTLIL::Module *module, SigMap &sigmap, dict<RTLIL::SigSp
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove unused cells
|
// Remove unused cells
|
||||||
|
if (debug) {
|
||||||
|
log("Removing unused cells\n");
|
||||||
|
log_flush();
|
||||||
|
}
|
||||||
std::set<Cell *> cellsToRemove;
|
std::set<Cell *> cellsToRemove;
|
||||||
for (auto cell : module->cells()) {
|
for (auto cell : module->cells()) {
|
||||||
if (visitedCells.count(cell)) {
|
if (visitedCells.count(cell)) {
|
||||||
|
@ -229,13 +268,25 @@ struct ObsClean : public ScriptPass {
|
||||||
void execute(std::vector<std::string> args, RTLIL::Design *design) override
|
void execute(std::vector<std::string> args, RTLIL::Design *design) override
|
||||||
{
|
{
|
||||||
bool unused_wires = false;
|
bool unused_wires = false;
|
||||||
|
bool unused_assigns = false;
|
||||||
|
bool debug = false;
|
||||||
|
if (std::getenv("DEBUG_OBS_CLEAN")) {
|
||||||
|
debug = true;
|
||||||
|
}
|
||||||
size_t argidx;
|
size_t argidx;
|
||||||
for (argidx = 1; argidx < args.size(); argidx++) {
|
for (argidx = 1; argidx < args.size(); argidx++) {
|
||||||
if (args[argidx] == "-wires") {
|
if (args[argidx] == "-wires") {
|
||||||
unused_wires = true;
|
unused_wires = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (args[argidx] == "-assigns") {
|
||||||
|
unused_assigns = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (args[argidx] == "-debug") {
|
||||||
|
debug = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
extra_args(args, argidx, design);
|
extra_args(args, argidx, design);
|
||||||
|
@ -252,18 +303,29 @@ struct ObsClean : public ScriptPass {
|
||||||
continue;
|
continue;
|
||||||
if (module->has_memories_warn())
|
if (module->has_memories_warn())
|
||||||
continue;
|
continue;
|
||||||
|
if (debug) {
|
||||||
|
log("Processing module: %s\n", module->name.c_str());
|
||||||
|
log_flush();
|
||||||
|
}
|
||||||
SigMap sigmap(module);
|
SigMap sigmap(module);
|
||||||
// Precompute cell output sigspec to cell map
|
// Precompute cell output sigspec to cell map
|
||||||
|
if (debug) {
|
||||||
|
log("Collecting cell info\n");
|
||||||
|
log_flush();
|
||||||
|
}
|
||||||
dict<RTLIL::SigSpec, std::set<Cell *>> sig2CellsInFanin;
|
dict<RTLIL::SigSpec, std::set<Cell *>> sig2CellsInFanin;
|
||||||
dict<RTLIL::SigSpec, std::set<Cell *>> sig2CellsInFanout;
|
dict<RTLIL::SigSpec, std::set<Cell *>> sig2CellsInFanout;
|
||||||
sigCellDrivers(module, sigmap, sig2CellsInFanout, sig2CellsInFanin);
|
sigCellDrivers(module, sigmap, sig2CellsInFanout, sig2CellsInFanin);
|
||||||
// Precompute lhs2rhs and rhs2lhs sigspec map
|
// Precompute lhs2rhs and rhs2lhs sigspec map
|
||||||
|
if (debug) {
|
||||||
|
log("Collecting assign info\n");
|
||||||
|
log_flush();
|
||||||
|
}
|
||||||
dict<RTLIL::SigSpec, RTLIL::SigSpec> lhsSig2RhsSig;
|
dict<RTLIL::SigSpec, RTLIL::SigSpec> lhsSig2RhsSig;
|
||||||
dict<RTLIL::SigSpec, std::set<RTLIL::SigSpec>> rhsSig2LhsSig;
|
dict<RTLIL::SigSpec, std::set<RTLIL::SigSpec>> rhsSig2LhsSig;
|
||||||
lhs2rhs_rhs2lhs(module, sigmap, rhsSig2LhsSig, lhsSig2RhsSig);
|
lhs2rhs_rhs2lhs(module, sigmap, rhsSig2LhsSig, lhsSig2RhsSig);
|
||||||
// Actual cleanup
|
// Actual cleanup
|
||||||
observabilityClean(module, sigmap, sig2CellsInFanin, lhsSig2RhsSig, unused_wires);
|
observabilityClean(module, sigmap, sig2CellsInFanin, lhsSig2RhsSig, unused_wires, unused_assigns, debug);
|
||||||
}
|
}
|
||||||
log("End obs_clean pass\n");
|
log("End obs_clean pass\n");
|
||||||
log_flush();
|
log_flush();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue