mirror of
https://github.com/YosysHQ/yosys
synced 2025-06-23 22:33:41 +00:00
Merge pull request #21 from alaindargelas/fix_const_connections
Fix top-connectivity and connections to constants
This commit is contained in:
commit
9edc21dd9a
3 changed files with 122 additions and 71 deletions
3
Makefile
3
Makefile
|
@ -241,7 +241,7 @@ LTOFLAGS := $(CLANG_LTO)
|
||||||
|
|
||||||
ifneq ($(SANITIZER),)
|
ifneq ($(SANITIZER),)
|
||||||
$(info [Clang Sanitizer] $(SANITIZER))
|
$(info [Clang Sanitizer] $(SANITIZER))
|
||||||
CXXFLAGS += -g -O1 -fno-omit-frame-pointer -fno-optimize-sibling-calls -fsanitize=$(SANITIZER)
|
CXXFLAGS += -g -fno-omit-frame-pointer -fno-optimize-sibling-calls -fsanitize=$(SANITIZER)
|
||||||
LINKFLAGS += -g -fsanitize=$(SANITIZER)
|
LINKFLAGS += -g -fsanitize=$(SANITIZER)
|
||||||
ifneq ($(findstring address,$(SANITIZER)),)
|
ifneq ($(findstring address,$(SANITIZER)),)
|
||||||
ENABLE_COVER := 0
|
ENABLE_COVER := 0
|
||||||
|
@ -749,6 +749,7 @@ OBJS += passes/cmds/activity.o
|
||||||
OBJS += passes/cmds/splitnetlist.o
|
OBJS += passes/cmds/splitnetlist.o
|
||||||
OBJS += passes/cmds/reconstructbusses.o
|
OBJS += passes/cmds/reconstructbusses.o
|
||||||
OBJS += passes/sat/sim.o
|
OBJS += passes/sat/sim.o
|
||||||
|
OBJS += passes/techmap/bufnorm.o
|
||||||
|
|
||||||
OBJS += passes/cmds/segv.o
|
OBJS += passes/cmds/segv.o
|
||||||
|
|
||||||
|
|
|
@ -14,17 +14,41 @@ struct ReconstructBusses : public ScriptPass {
|
||||||
|
|
||||||
bool is_digits(const std::string &str) { return std::all_of(str.begin(), str.end(), ::isdigit); }
|
bool is_digits(const std::string &str) { return std::all_of(str.begin(), str.end(), ::isdigit); }
|
||||||
|
|
||||||
|
// Get the index <index> from the signal name "prefix_<index>_"
|
||||||
|
int getIndex(std::string name, std::map<std::string, RTLIL::Wire *> &wirenames_to_remove)
|
||||||
|
{
|
||||||
|
std::map<std::string, RTLIL::Wire *>::iterator itr_lhs = wirenames_to_remove.find(name);
|
||||||
|
if (itr_lhs != wirenames_to_remove.end()) {
|
||||||
|
std::string::iterator conn_lhs_end = name.end() - 1;
|
||||||
|
if ((*conn_lhs_end) == '_') {
|
||||||
|
name = name.substr(0, name.size() - 1);
|
||||||
|
if (name.find("_") != std::string::npos) {
|
||||||
|
std::string ch_index_str = name.substr(name.find_last_of('_') + 1);
|
||||||
|
if (!ch_index_str.empty() && is_digits(ch_index_str)) {
|
||||||
|
int ch_index = std::stoi(ch_index_str);
|
||||||
|
return ch_index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
void execute(std::vector<std::string>, RTLIL::Design *design) override
|
void execute(std::vector<std::string>, RTLIL::Design *design) override
|
||||||
{
|
{
|
||||||
if (design == nullptr) {
|
if (design == nullptr) {
|
||||||
log_error("No design object");
|
log_error("No design object");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
bool debug = false;
|
||||||
|
if (std::getenv("DEBUG_RECONSTRUCT_BUSSES")) {
|
||||||
|
debug = true;
|
||||||
|
}
|
||||||
log("Running reconstructbusses pass\n");
|
log("Running reconstructbusses pass\n");
|
||||||
log_flush();
|
log_flush();
|
||||||
log("Creating bus groups\n");
|
|
||||||
log_flush();
|
|
||||||
for (auto module : design->modules()) {
|
for (auto module : design->modules()) {
|
||||||
|
log("Creating bus groups for module %s\n", module->name.str().c_str());
|
||||||
|
log_flush();
|
||||||
// Collect all wires with a common prefix
|
// Collect all wires with a common prefix
|
||||||
dict<std::string, std::vector<RTLIL::Wire *>> wire_groups;
|
dict<std::string, std::vector<RTLIL::Wire *>> wire_groups;
|
||||||
for (auto wire : module->wires()) {
|
for (auto wire : module->wires()) {
|
||||||
|
@ -83,6 +107,8 @@ struct ReconstructBusses : public ScriptPass {
|
||||||
// Reconstruct vectors
|
// Reconstruct vectors
|
||||||
for (auto &it : wire_groups) {
|
for (auto &it : wire_groups) {
|
||||||
std::string prefix = it.first;
|
std::string prefix = it.first;
|
||||||
|
if (debug)
|
||||||
|
std::cout << "Wire group:" << prefix << std::endl;
|
||||||
std::vector<RTLIL::Wire *> &wires = it.second;
|
std::vector<RTLIL::Wire *> &wires = it.second;
|
||||||
|
|
||||||
// Create a new vector wire
|
// Create a new vector wire
|
||||||
|
@ -107,39 +133,34 @@ struct ReconstructBusses : public ScriptPass {
|
||||||
log_flush();
|
log_flush();
|
||||||
// Reconnect cells
|
// Reconnect cells
|
||||||
for (auto cell : module->cells()) {
|
for (auto cell : module->cells()) {
|
||||||
|
if (debug)
|
||||||
|
std::cout << "Cell:" << cell->name.c_str() << std::endl;
|
||||||
for (auto &conn : cell->connections_) {
|
for (auto &conn : cell->connections_) {
|
||||||
RTLIL::SigSpec new_sig;
|
RTLIL::SigSpec new_sig;
|
||||||
bool modified = false;
|
bool modified = false;
|
||||||
for (auto chunk : conn.second.chunks()) {
|
for (auto chunk : conn.second.chunks()) {
|
||||||
// std::cout << "Port:" << conn.first.c_str() << std::endl;
|
if (debug) {
|
||||||
// std::cout << "Conn:" << chunk.wire->name.c_str() << std::endl;
|
std::cout << " Port:" << conn.first.c_str() << std::endl;
|
||||||
|
std::cout << " Conn:" << (chunk.wire ? chunk.wire->name.c_str() : "constant") << std::endl;
|
||||||
|
}
|
||||||
// Find the connections that match the wire group prefix
|
// Find the connections that match the wire group prefix
|
||||||
std::string lhs_name = chunk.wire->name.c_str();
|
if (chunk.wire == nullptr) {
|
||||||
std::map<std::string, RTLIL::Wire *>::iterator itr = wirenames_to_remove.find(lhs_name);
|
continue;
|
||||||
if (itr != wirenames_to_remove.end()) {
|
}
|
||||||
std::string ch_name = chunk.wire->name.c_str();
|
std::string lhs_name = chunk.wire ? chunk.wire->name.c_str() : "";
|
||||||
if (!ch_name.empty()) {
|
int lhsIndex = getIndex(lhs_name, wirenames_to_remove);
|
||||||
std::string::iterator ch_end = ch_name.end() - 1;
|
std::map<std::string, RTLIL::Wire *>::iterator itr_lhs = wirenames_to_remove.find(lhs_name);
|
||||||
if ((*ch_end) == '_') {
|
if (itr_lhs != wirenames_to_remove.end()) {
|
||||||
ch_name = ch_name.substr(0, ch_name.size() - 1);
|
if (lhsIndex >= 0) {
|
||||||
if (ch_name.find("_") != std::string::npos) {
|
// Create a new connection sigspec that matches the previous
|
||||||
std::string ch_index_str =
|
// bit index
|
||||||
ch_name.substr(ch_name.find_last_of('_') + 1);
|
RTLIL::SigSpec bit = RTLIL::SigSpec(itr_lhs->second, lhsIndex, 1);
|
||||||
// std::cout << "ch_name: " << ch_name << std::endl;
|
new_sig.append(bit);
|
||||||
if ((!ch_index_str.empty() && is_digits(ch_index_str))) {
|
modified = true;
|
||||||
// Create a new connection sigspec that matches the previous
|
} else {
|
||||||
// bit index
|
new_sig.append(chunk);
|
||||||
int ch_index = std::stoi(ch_index_str);
|
modified = true;
|
||||||
RTLIL::SigSpec bit = RTLIL::SigSpec(itr->second, ch_index, 1);
|
|
||||||
new_sig.append(bit);
|
|
||||||
modified = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
new_sig.append(chunk);
|
|
||||||
modified = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Replace the previous connection
|
// Replace the previous connection
|
||||||
|
@ -147,10 +168,17 @@ struct ReconstructBusses : public ScriptPass {
|
||||||
conn.second = new_sig;
|
conn.second = new_sig;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (debug)
|
||||||
|
run_pass("write_rtlil post_reconnect_cells.rtlil");
|
||||||
log("Reconnecting top connections\n");
|
log("Reconnecting top connections\n");
|
||||||
log_flush();
|
log_flush();
|
||||||
// Reconnect top connections before removing the old wires
|
// Reconnect top connections before removing the old wires
|
||||||
|
std::vector<RTLIL::SigSig> newConnections;
|
||||||
for (auto &conn : module->connections()) {
|
for (auto &conn : module->connections()) {
|
||||||
|
// Keep all the connections that won't get rewired
|
||||||
|
newConnections.push_back(conn);
|
||||||
|
}
|
||||||
|
for (auto &conn : newConnections) {
|
||||||
RTLIL::SigSpec lhs = conn.first;
|
RTLIL::SigSpec lhs = conn.first;
|
||||||
RTLIL::SigSpec rhs = conn.second;
|
RTLIL::SigSpec rhs = conn.second;
|
||||||
auto lit = lhs.chunks().rbegin();
|
auto lit = lhs.chunks().rbegin();
|
||||||
|
@ -162,40 +190,40 @@ struct ReconstructBusses : public ScriptPass {
|
||||||
RTLIL::SigChunk sub_rhs = *rit;
|
RTLIL::SigChunk sub_rhs = *rit;
|
||||||
while (lit != lhs.chunks().rend()) {
|
while (lit != lhs.chunks().rend()) {
|
||||||
RTLIL::SigChunk sub_lhs = *lit;
|
RTLIL::SigChunk sub_lhs = *lit;
|
||||||
std::string conn_lhs = sub_lhs.wire->name.c_str();
|
std::string conn_lhs_s = sub_lhs.wire ? sub_lhs.wire->name.c_str() : "";
|
||||||
if (!conn_lhs.empty()) {
|
std::string conn_rhs_s = sub_rhs.wire ? sub_rhs.wire->name.c_str() : "";
|
||||||
// std::cout << "Conn LHS: " << conn_lhs << std::endl;
|
if (!conn_lhs_s.empty()) {
|
||||||
// std::string conn_rhs = sub_rhs.wire->name.c_str();
|
if (debug) {
|
||||||
// std::cout << "Conn RHS: " << conn_rhs << std::endl;
|
std::cout << "Conn LHS: " << conn_lhs_s << std::endl;
|
||||||
|
std::cout << "Conn RHS: " << conn_rhs_s << std::endl;
|
||||||
std::map<std::string, RTLIL::Wire *>::iterator itr = wirenames_to_remove.find(conn_lhs);
|
}
|
||||||
if (itr != wirenames_to_remove.end()) {
|
int lhsIndex = getIndex(conn_lhs_s, wirenames_to_remove);
|
||||||
std::string::iterator conn_lhs_end = conn_lhs.end() - 1;
|
int rhsIndex = getIndex(conn_rhs_s, wirenames_to_remove);
|
||||||
if ((*conn_lhs_end) == '_') {
|
std::map<std::string, RTLIL::Wire *>::iterator itr_lhs = wirenames_to_remove.find(conn_lhs_s);
|
||||||
conn_lhs = conn_lhs.substr(0, conn_lhs.size() - 1);
|
std::map<std::string, RTLIL::Wire *>::iterator itr_rhs = wirenames_to_remove.find(conn_rhs_s);
|
||||||
if (conn_lhs.find("_") != std::string::npos) {
|
if (itr_lhs != wirenames_to_remove.end() || itr_rhs != wirenames_to_remove.end()) {
|
||||||
std::string ch_index_str = conn_lhs.substr(conn_lhs.find_last_of('_') + 1);
|
if (lhsIndex >= 0) {
|
||||||
if (!ch_index_str.empty() && is_digits(ch_index_str)) {
|
// Create the LHS sigspec of the desired bit
|
||||||
int ch_index = std::stoi(ch_index_str);
|
RTLIL::SigSpec lbit = RTLIL::SigSpec(itr_lhs->second, lhsIndex, 1);
|
||||||
// Create the LHS sigspec of the desired bit
|
if (sub_rhs.size() > 1) {
|
||||||
RTLIL::SigSpec bit = RTLIL::SigSpec(itr->second, ch_index, 1);
|
// If RHS has width > 1, replace with the bitblasted RHS
|
||||||
if (sub_rhs.size() > 1) {
|
// corresponding to the connected bit
|
||||||
// If RHS has width > 1, replace with the bitblasted RHS
|
RTLIL::SigSpec rhs_bit = RTLIL::SigSpec(sub_rhs.wire, lhsIndex, 1);
|
||||||
// corresponding to the connected bit
|
// And connect it
|
||||||
RTLIL::SigSpec rhs_bit =
|
module->connect(lbit, rhs_bit);
|
||||||
RTLIL::SigSpec(sub_rhs.wire, ch_index, 1);
|
} else {
|
||||||
// And connect it
|
// Else, directly connect
|
||||||
module->connect(bit, rhs_bit);
|
if (rhsIndex >= 0) {
|
||||||
} else {
|
RTLIL::SigSpec rbit = RTLIL::SigSpec(itr_rhs->second, rhsIndex, 1);
|
||||||
// Else, directly connect
|
module->connect(lbit, rbit);
|
||||||
module->connect(bit, sub_rhs);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// Else, directly connect
|
module->connect(lbit, sub_rhs);
|
||||||
RTLIL::SigSpec bit = RTLIL::SigSpec(itr->second, 0, 1);
|
|
||||||
module->connect(bit, sub_rhs);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// Else, directly connect
|
||||||
|
RTLIL::SigSpec bit = RTLIL::SigSpec(itr_lhs->second, 0, 1);
|
||||||
|
module->connect(bit, sub_rhs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -204,7 +232,10 @@ struct ReconstructBusses : public ScriptPass {
|
||||||
rit++;
|
rit++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (debug)
|
||||||
|
run_pass("write_rtlil post_reconnect_top.rtlil");
|
||||||
// Remove old wires
|
// Remove old wires
|
||||||
|
// Cleans the dangling connections too
|
||||||
log("Removing old wires\n");
|
log("Removing old wires\n");
|
||||||
log_flush();
|
log_flush();
|
||||||
module->remove(wires_to_remove);
|
module->remove(wires_to_remove);
|
||||||
|
@ -213,6 +244,8 @@ struct ReconstructBusses : public ScriptPass {
|
||||||
log_flush();
|
log_flush();
|
||||||
module->fixup_ports();
|
module->fixup_ports();
|
||||||
}
|
}
|
||||||
|
if (debug)
|
||||||
|
run_pass("write_rtlil post_reconstructbusses.rtlil");
|
||||||
log("End reconstructbusses pass\n");
|
log("End reconstructbusses pass\n");
|
||||||
log_flush();
|
log_flush();
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,7 +123,7 @@ void lhs2rhs(RTLIL::Design *design, dict<RTLIL::SigSpec, RTLIL::SigSpec> &lhsSig
|
||||||
}
|
}
|
||||||
for (uint32_t i = 0; i < lhsBits.size(); i++) {
|
for (uint32_t i = 0; i < lhsBits.size(); i++) {
|
||||||
if (i < rhsBits.size())
|
if (i < rhsBits.size())
|
||||||
lhsSig2rhsSig[lhsBits[i]] = rhsBits[i];
|
lhsSig2rhsSig[lhsBits[i]] = rhsBits[i];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
lhsSig2rhsSig[lhs] = rhs;
|
lhsSig2rhsSig[lhs] = rhs;
|
||||||
|
@ -153,8 +153,21 @@ struct SplitNetlist : public ScriptPass {
|
||||||
log_error("No design object");
|
log_error("No design object");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool debug = false;
|
||||||
|
if (std::getenv("DEBUG_SPLITNETLIST")) {
|
||||||
|
debug = true;
|
||||||
|
}
|
||||||
log("Running splitnetlist pass\n");
|
log("Running splitnetlist pass\n");
|
||||||
log_flush();
|
log_flush();
|
||||||
|
|
||||||
|
// Add buffers for pass-through and connections to constants
|
||||||
|
// so we can find cells that can be used by submod
|
||||||
|
Pass::call(design, "bufnorm -buf");
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
run_pass("write_rtlil post_buf.rtlil");
|
||||||
|
|
||||||
log("Mapping signals to cells\n");
|
log("Mapping signals to cells\n");
|
||||||
log_flush();
|
log_flush();
|
||||||
// Precompute cell output sigspec to cell map
|
// Precompute cell output sigspec to cell map
|
||||||
|
@ -183,17 +196,17 @@ struct SplitNetlist : public ScriptPass {
|
||||||
for (auto wire : design->top_module()->wires()) {
|
for (auto wire : design->top_module()->wires()) {
|
||||||
if (!wire->port_output)
|
if (!wire->port_output)
|
||||||
continue;
|
continue;
|
||||||
std::string output_port_name = wire->name.c_str();
|
std::string output_port_name = wire ? wire->name.c_str() : "";
|
||||||
if (output_port_name.empty())
|
if (output_port_name.empty())
|
||||||
continue;
|
continue;
|
||||||
// We want to truncate the final _<index>_ part of the string
|
// We want to truncate the final _<index>_ part of the string
|
||||||
// Example: "add_Y_0_"
|
// Example: "add_Y_0_"
|
||||||
// Result: "add_Y"
|
// Result: "add_Y"
|
||||||
std::string::iterator end = output_port_name.end()-1;
|
std::string::iterator end = output_port_name.end() - 1;
|
||||||
if ((*end) == '_') {
|
if ((*end) == '_') {
|
||||||
// Last character is an _, it is a bit blasted index
|
// Last character is an _, it is a bit blasted index
|
||||||
end--;
|
end--;
|
||||||
for (; end != output_port_name.begin(); end--) {
|
for (; end != output_port_name.begin(); end--) {
|
||||||
if ((*end) != '_') {
|
if ((*end) != '_') {
|
||||||
// Truncate until the next _
|
// Truncate until the next _
|
||||||
continue;
|
continue;
|
||||||
|
@ -242,19 +255,23 @@ struct SplitNetlist : public ScriptPass {
|
||||||
log("Creating submods\n");
|
log("Creating submods\n");
|
||||||
log_flush();
|
log_flush();
|
||||||
for (CellName_ObjectMap::iterator itr = cellName_ObjectMap.begin(); itr != cellName_ObjectMap.end(); itr++) {
|
for (CellName_ObjectMap::iterator itr = cellName_ObjectMap.begin(); itr != cellName_ObjectMap.end(); itr++) {
|
||||||
// std::cout << "Cluster name: " << itr->first << std::endl;
|
if (debug)
|
||||||
|
std::cout << "Cluster name: " << itr->first << std::endl;
|
||||||
CellsAndSigs &components = itr->second;
|
CellsAndSigs &components = itr->second;
|
||||||
for (auto cell : components.visitedCells) {
|
for (auto cell : components.visitedCells) {
|
||||||
cell->set_string_attribute(RTLIL::escape_id("submod"), itr->first);
|
cell->set_string_attribute(RTLIL::escape_id("submod"), itr->first);
|
||||||
// std::cout << " CELL: " << cell->name.c_str() << std::endl;
|
if (debug)
|
||||||
|
std::cout << " CELL: " << cell->name.c_str() << std::endl;
|
||||||
}
|
}
|
||||||
// for (auto sigspec : components.visitedSigSpec) {
|
|
||||||
// std::cout << " SIG: " << SigName(sigspec) << std::endl;
|
|
||||||
// }
|
|
||||||
// std::cout << std::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute the submod command
|
// Execute the submod command
|
||||||
Pass::call(design, "submod -copy");
|
Pass::call(design, "submod -copy");
|
||||||
|
|
||||||
|
// Remove buffers introduced by bufnorm
|
||||||
|
Pass::call(design, "techmap -D SIMLIB_NOCHECKS -map +/simlib.v t:$buf");
|
||||||
|
Pass::call(design, "clean");
|
||||||
|
|
||||||
log("End splitnetlist pass\n");
|
log("End splitnetlist pass\n");
|
||||||
log_flush();
|
log_flush();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue