mirror of
https://github.com/YosysHQ/yosys
synced 2026-05-29 21:36:33 +00:00
Accumulate connect cells.
This commit is contained in:
parent
4e4fd1a26e
commit
d9faee0153
5 changed files with 99 additions and 75 deletions
|
|
@ -240,11 +240,11 @@ struct HierarchyPass : public Pass {
|
||||||
if ((flag_simcheck || flag_smtcheck) && top_mod == nullptr)
|
if ((flag_simcheck || flag_smtcheck) && top_mod == nullptr)
|
||||||
log_error("Design has no top module.\n");
|
log_error("Design has no top module.\n");
|
||||||
|
|
||||||
expand_all_interfaces(design, top_mod, flag_check, flag_simcheck, flag_smtcheck, libdirs);
|
Hierarchy::ConnectAccumulator connect_acc;
|
||||||
|
expand_all_interfaces(design, top_mod, flag_check, flag_simcheck, flag_smtcheck, libdirs, &connect_acc);
|
||||||
|
|
||||||
log_header(design, "Resolving $connect directionality..\n");
|
log_header(design, "Resolving $connect directionality..\n");
|
||||||
for (auto module : design->modules())
|
Hierarchy::resolve_acc_connects(design, connect_acc);
|
||||||
resolve_connect_directionality(module);
|
|
||||||
|
|
||||||
if (top_mod != NULL) {
|
if (top_mod != NULL) {
|
||||||
log_header(design, "Analyzing design hierarchy..\n");
|
log_header(design, "Analyzing design hierarchy..\n");
|
||||||
|
|
|
||||||
|
|
@ -172,14 +172,14 @@ void delete_marked_modules(Design* design) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void expand_all_interfaces(Design* design, Module*& top_mod, bool flag_check, bool flag_simcheck, bool flag_smtcheck, const std::vector<std::string> &libdirs) {
|
void expand_all_interfaces(Design* design, Module*& top_mod, bool flag_check, bool flag_simcheck, bool flag_smtcheck, const std::vector<std::string> &libdirs, ConnectAccumulator* connect_acc) {
|
||||||
bool did_something = true;
|
bool did_something = true;
|
||||||
while (did_something)
|
while (did_something)
|
||||||
{
|
{
|
||||||
did_something = false;
|
did_something = false;
|
||||||
|
|
||||||
for (auto module : used_modules(design, top_mod)) {
|
for (auto module : used_modules(design, top_mod)) {
|
||||||
if (expand_module(design, module, flag_check, flag_simcheck, flag_smtcheck, libdirs))
|
if (expand_module(design, module, flag_check, flag_simcheck, flag_smtcheck, libdirs, connect_acc))
|
||||||
did_something = true;
|
did_something = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -246,7 +246,7 @@ struct CellArrays {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check, bool flag_simcheck, bool flag_smtcheck, const std::vector<std::string> &libdirs)
|
bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check, bool flag_simcheck, bool flag_smtcheck, const std::vector<std::string> &libdirs, ConnectAccumulator* connect_acc)
|
||||||
{
|
{
|
||||||
bool did_something = false;
|
bool did_something = false;
|
||||||
CellArrays cell_arrays;
|
CellArrays cell_arrays;
|
||||||
|
|
@ -264,6 +264,8 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check
|
||||||
}
|
}
|
||||||
IFModExpander if_mod_expander(*design, *module);
|
IFModExpander if_mod_expander(*design, *module);
|
||||||
for (auto cell : module->cells()) {
|
for (auto cell : module->cells()) {
|
||||||
|
if (connect_acc)
|
||||||
|
connect_acc->collect(module, cell);
|
||||||
if (auto unarrayed_type = cell_arrays.trim_and_register(cell))
|
if (auto unarrayed_type = cell_arrays.trim_and_register(cell))
|
||||||
cell->type = *unarrayed_type;
|
cell->type = *unarrayed_type;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,23 @@
|
||||||
YOSYS_NAMESPACE_BEGIN
|
YOSYS_NAMESPACE_BEGIN
|
||||||
namespace Hierarchy {
|
namespace Hierarchy {
|
||||||
|
|
||||||
void expand_all_interfaces(Design* design, Module*& top_mod, bool flag_check, bool flag_simcheck, bool flag_smtcheck, const std::vector<std::string> &libdirs);
|
struct ConnectAccumulator {
|
||||||
bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check, bool flag_simcheck, bool flag_smtcheck, const std::vector<std::string> &libdirs);
|
dict<IdString, pool<IdString>> module_connect_cells;
|
||||||
|
|
||||||
|
// Collect a $connect cell during hierarchy traversal
|
||||||
|
void collect(Module* module, Cell* cell) {
|
||||||
|
if (cell->type == ID($connect) && !cell->has_keep_attr()) {
|
||||||
|
SigSpec sig_a = cell->getPort(ID::A);
|
||||||
|
SigSpec sig_b = cell->getPort(ID::B);
|
||||||
|
if (sig_a.size() > 0 && sig_b.size() > 0) {
|
||||||
|
module_connect_cells[module->name].insert(cell->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void expand_all_interfaces(Design* design, Module*& top_mod, bool flag_check, bool flag_simcheck, bool flag_smtcheck, const std::vector<std::string> &libdirs, ConnectAccumulator* connect_acc);
|
||||||
|
bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check, bool flag_simcheck, bool flag_smtcheck, const std::vector<std::string> &libdirs, ConnectAccumulator* connect_acc);
|
||||||
|
|
||||||
// For expanding a module's interface connections
|
// For expanding a module's interface connections
|
||||||
struct IFModExpander
|
struct IFModExpander
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
#include "kernel/yosys_common.h"
|
#include "kernel/yosys_common.h"
|
||||||
#include "passes/hierarchy/util/ports.h"
|
#include "passes/hierarchy/util/ports.h"
|
||||||
|
#include "passes/hierarchy/util/interfaces.h"
|
||||||
#include "kernel/sigtools.h"
|
#include "kernel/sigtools.h"
|
||||||
|
|
||||||
YOSYS_NAMESPACE_BEGIN
|
YOSYS_NAMESPACE_BEGIN
|
||||||
|
|
@ -190,87 +191,92 @@ namespace Hierarchy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool resolve_connect_directionality(Module* module) {
|
void resolve_acc_connects(Design* design, const ConnectAccumulator& connect_acc) {
|
||||||
bool did_something = false;
|
std::vector<IdString> sorted_module_names;
|
||||||
int iteration = 0;
|
for (const auto& [mod_name, cell_names] : connect_acc.module_connect_cells)
|
||||||
|
sorted_module_names.push_back(mod_name);
|
||||||
|
std::sort(sorted_module_names.begin(), sorted_module_names.end());
|
||||||
|
|
||||||
while (true) {
|
for (auto mod_name : sorted_module_names) {
|
||||||
iteration++;
|
Module* module = design->module(mod_name);
|
||||||
pool<Cell*> cells_to_remove;
|
if (!module)
|
||||||
vector<SigSig> new_connections;
|
continue;
|
||||||
SigMap sigmap(module);
|
|
||||||
SigPool driven_signals;
|
|
||||||
|
|
||||||
build_driven_signals_index(module, sigmap, driven_signals);
|
const pool<IdString>& cell_names = connect_acc.module_connect_cells.at(mod_name);
|
||||||
|
pool<IdString> remaining_cell_names = cell_names;
|
||||||
|
int iteration = 0;
|
||||||
|
|
||||||
for (auto cell : module->cells())
|
while (true) {
|
||||||
{
|
iteration++;
|
||||||
if (cell->type != ID($connect))
|
pool<Cell*> cells_to_remove;
|
||||||
continue;
|
vector<SigSig> new_connections;
|
||||||
|
SigMap sigmap(module);
|
||||||
|
SigPool driven_signals;
|
||||||
|
|
||||||
if (cell->has_keep_attr())
|
build_driven_signals_index(module, sigmap, driven_signals);
|
||||||
continue;
|
|
||||||
|
|
||||||
SigSpec sig_a = cell->getPort(ID::A);
|
for (auto cell_name : remaining_cell_names) {
|
||||||
SigSpec sig_b = cell->getPort(ID::B);
|
Cell* cell = module->cell(cell_name);
|
||||||
|
if (!cell || cell->type != ID($connect) || cell->has_keep_attr())
|
||||||
|
continue;
|
||||||
|
|
||||||
if (sig_a.size() == 0 || sig_b.size() == 0)
|
SigSpec sig_a = cell->getPort(ID::A);
|
||||||
continue;
|
SigSpec sig_b = cell->getPort(ID::B);
|
||||||
|
|
||||||
SigDirection dir_a = get_signal_direction(sig_a, sigmap, driven_signals);
|
if (sig_a.size() == 0 || sig_b.size() == 0)
|
||||||
SigDirection dir_b = get_signal_direction(sig_b, sigmap, driven_signals);
|
continue;
|
||||||
|
|
||||||
if (dir_a == SigDirection::CONFLICT || dir_b == SigDirection::CONFLICT)
|
SigDirection dir_a = get_signal_direction(sig_a, sigmap, driven_signals);
|
||||||
continue;
|
SigDirection dir_b = get_signal_direction(sig_b, sigmap, driven_signals);
|
||||||
|
|
||||||
SigSpec driver, driven;
|
if (dir_a == SigDirection::CONFLICT || dir_b == SigDirection::CONFLICT)
|
||||||
bool can_resolve = false;
|
continue;
|
||||||
|
|
||||||
if ((dir_a == SigDirection::OUTPUT || dir_a == SigDirection::DRIVEN) && dir_b == SigDirection::INPUT) {
|
SigSpec driver, driven;
|
||||||
driver = sig_a;
|
bool can_resolve = false;
|
||||||
driven = sig_b;
|
|
||||||
can_resolve = true;
|
if ((dir_a == SigDirection::OUTPUT || dir_a == SigDirection::DRIVEN) && dir_b == SigDirection::INPUT) {
|
||||||
}
|
driver = sig_a;
|
||||||
else if (dir_a == SigDirection::INPUT && (dir_b == SigDirection::OUTPUT || dir_b == SigDirection::DRIVEN)) {
|
driven = sig_b;
|
||||||
driver = sig_b;
|
can_resolve = true;
|
||||||
driven = sig_a;
|
}
|
||||||
can_resolve = true;
|
else if (dir_a == SigDirection::INPUT && (dir_b == SigDirection::OUTPUT || dir_b == SigDirection::DRIVEN)) {
|
||||||
}
|
driver = sig_b;
|
||||||
else if (dir_a == SigDirection::DRIVEN && dir_b == SigDirection::UNKNOWN) {
|
driven = sig_a;
|
||||||
driver = sig_a;
|
can_resolve = true;
|
||||||
driven = sig_b;
|
}
|
||||||
can_resolve = true;
|
else if (dir_a == SigDirection::DRIVEN && dir_b == SigDirection::UNKNOWN) {
|
||||||
}
|
driver = sig_a;
|
||||||
else if (dir_a == SigDirection::UNKNOWN && dir_b == SigDirection::DRIVEN) {
|
driven = sig_b;
|
||||||
driver = sig_b;
|
can_resolve = true;
|
||||||
driven = sig_a;
|
}
|
||||||
can_resolve = true;
|
else if (dir_a == SigDirection::UNKNOWN && dir_b == SigDirection::DRIVEN) {
|
||||||
}
|
driver = sig_b;
|
||||||
else {
|
driven = sig_a;
|
||||||
continue;
|
can_resolve = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (can_resolve) {
|
||||||
|
log_debug("Resolving $connect %s: %s <- %s\n", log_id(cell), log_signal(driven), log_signal(driver));
|
||||||
|
new_connections.push_back({driven, driver});
|
||||||
|
cells_to_remove.insert(cell);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (can_resolve) {
|
for (auto &conn : new_connections)
|
||||||
log_debug("Resolving $connect %s: %s <- %s\n", log_id(cell), log_signal(driven), log_signal(driver));
|
module->connect(conn);
|
||||||
new_connections.push_back({driven, driver});
|
|
||||||
cells_to_remove.insert(cell);
|
for (auto cell : cells_to_remove) {
|
||||||
|
remaining_cell_names.erase(cell->name);
|
||||||
|
module->remove(cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cells_to_remove.empty())
|
||||||
|
break;
|
||||||
|
|
||||||
|
log_debug("$connect res iteration %d: resolved %d cells\n", iteration, GetSize(cells_to_remove));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto &conn : new_connections)
|
|
||||||
module->connect(conn);
|
|
||||||
|
|
||||||
for (auto cell : cells_to_remove)
|
|
||||||
module->remove(cell);
|
|
||||||
|
|
||||||
if (cells_to_remove.empty())
|
|
||||||
break;
|
|
||||||
|
|
||||||
did_something = true;
|
|
||||||
log_debug("$connect res iteration %d: resolved %d cells\n", iteration, GetSize(cells_to_remove));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return did_something;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,13 +22,14 @@
|
||||||
#define HIERARCHY_PORTS_H
|
#define HIERARCHY_PORTS_H
|
||||||
|
|
||||||
#include "kernel/yosys.h"
|
#include "kernel/yosys.h"
|
||||||
|
#include "passes/hierarchy/util/interfaces.h"
|
||||||
|
|
||||||
YOSYS_NAMESPACE_BEGIN
|
YOSYS_NAMESPACE_BEGIN
|
||||||
|
|
||||||
namespace Hierarchy {
|
namespace Hierarchy {
|
||||||
std::pair<Module*, bool> derive_blackbox_dynports(Module* module, Cell* cell, Design* design, std::set<Module*>& blackbox_derivatives);
|
std::pair<Module*, bool> derive_blackbox_dynports(Module* module, Cell* cell, Design* design, std::set<Module*>& blackbox_derivatives);
|
||||||
void check_and_adjust_ports(Module* module, std::set<Module*>& blackbox_derivatives, bool keep_portwidths, bool top_is_from_verific);
|
void check_and_adjust_ports(Module* module, std::set<Module*>& blackbox_derivatives, bool keep_portwidths, bool top_is_from_verific);
|
||||||
bool resolve_connect_directionality(Module* module);
|
void resolve_acc_connects(Design* design, const ConnectAccumulator& connect_acc);
|
||||||
};
|
};
|
||||||
|
|
||||||
YOSYS_NAMESPACE_END
|
YOSYS_NAMESPACE_END
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue