mirror of
https://github.com/YosysHQ/yosys
synced 2025-04-23 09:05:32 +00:00
Merging with official repo
This commit is contained in:
commit
4d343fc1cd
28 changed files with 1350 additions and 191 deletions
|
@ -23,6 +23,13 @@
|
|||
#include "kernel/rtlil.h"
|
||||
#include "kernel/log.h"
|
||||
|
||||
#define MODE_ZERO 0
|
||||
#define MODE_ONE 1
|
||||
#define MODE_UNDEF 2
|
||||
#define MODE_RANDOM 3
|
||||
#define MODE_ANYSEQ 4
|
||||
#define MODE_ANYCONST 5
|
||||
|
||||
USING_YOSYS_NAMESPACE
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
||||
|
@ -97,30 +104,32 @@ struct SetundefWorker
|
|||
|
||||
RTLIL::State next_bit()
|
||||
{
|
||||
if (next_bit_mode == 0)
|
||||
if (next_bit_mode == MODE_ZERO)
|
||||
return RTLIL::State::S0;
|
||||
|
||||
if (next_bit_mode == 1)
|
||||
if (next_bit_mode == MODE_ONE)
|
||||
return RTLIL::State::S1;
|
||||
|
||||
if (next_bit_mode == 2)
|
||||
log_abort();
|
||||
|
||||
if (next_bit_mode == 4)
|
||||
if (next_bit_mode == MODE_UNDEF)
|
||||
return RTLIL::State::Sx;
|
||||
|
||||
// xorshift32
|
||||
next_bit_state ^= next_bit_state << 13;
|
||||
next_bit_state ^= next_bit_state >> 17;
|
||||
next_bit_state ^= next_bit_state << 5;
|
||||
log_assert(next_bit_state != 0);
|
||||
if (next_bit_mode == MODE_RANDOM)
|
||||
{
|
||||
// xorshift32
|
||||
next_bit_state ^= next_bit_state << 13;
|
||||
next_bit_state ^= next_bit_state >> 17;
|
||||
next_bit_state ^= next_bit_state << 5;
|
||||
log_assert(next_bit_state != 0);
|
||||
|
||||
return ((next_bit_state >> (next_bit_state & 15)) & 16) ? RTLIL::State::S0 : RTLIL::State::S1;
|
||||
return ((next_bit_state >> (next_bit_state & 15)) & 16) ? RTLIL::State::S0 : RTLIL::State::S1;
|
||||
}
|
||||
|
||||
log_abort();
|
||||
}
|
||||
|
||||
void operator()(RTLIL::SigSpec &sig)
|
||||
{
|
||||
if (next_bit_mode == 2) {
|
||||
if (next_bit_mode == MODE_ANYSEQ || next_bit_mode == MODE_ANYCONST) {
|
||||
siglist.push_back(&sig);
|
||||
return;
|
||||
}
|
||||
|
@ -145,7 +154,7 @@ struct SetundefPass : public Pass {
|
|||
log(" also set undriven nets to constant values\n");
|
||||
log("\n");
|
||||
log(" -expose\n");
|
||||
log(" also expose undriven nets as inputs\n");
|
||||
log(" also expose undriven nets as inputs (use with -undriven)\n");
|
||||
log("\n");
|
||||
log(" -zero\n");
|
||||
log(" replace with bits cleared (0)\n");
|
||||
|
@ -159,6 +168,9 @@ struct SetundefPass : public Pass {
|
|||
log(" -anyseq\n");
|
||||
log(" replace with $anyseq drivers (for formal)\n");
|
||||
log("\n");
|
||||
log(" -anyconst\n");
|
||||
log(" replace with $anyconst drivers (for formal)\n");
|
||||
log("\n");
|
||||
log(" -random <seed>\n");
|
||||
log(" replace with random bits using the specified integer als seed\n");
|
||||
log(" value for the random number generator.\n");
|
||||
|
@ -191,25 +203,31 @@ struct SetundefPass : public Pass {
|
|||
}
|
||||
if (args[argidx] == "-zero") {
|
||||
got_value = true;
|
||||
worker.next_bit_mode = 0;
|
||||
worker.next_bit_mode = MODE_ZERO;
|
||||
worker.next_bit_state = 0;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-one") {
|
||||
got_value = true;
|
||||
worker.next_bit_mode = 1;
|
||||
worker.next_bit_mode = MODE_ONE;
|
||||
worker.next_bit_state = 0;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-anyseq") {
|
||||
got_value = true;
|
||||
worker.next_bit_mode = 2;
|
||||
worker.next_bit_mode = MODE_ANYSEQ;
|
||||
worker.next_bit_state = 0;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-anyconst") {
|
||||
got_value = true;
|
||||
worker.next_bit_mode = MODE_ANYCONST;
|
||||
worker.next_bit_state = 0;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-undef") {
|
||||
got_value = true;
|
||||
worker.next_bit_mode = 4;
|
||||
worker.next_bit_mode = MODE_UNDEF;
|
||||
worker.next_bit_state = 0;
|
||||
continue;
|
||||
}
|
||||
|
@ -219,7 +237,7 @@ struct SetundefPass : public Pass {
|
|||
}
|
||||
if (args[argidx] == "-random" && !got_value && argidx+1 < args.size()) {
|
||||
got_value = true;
|
||||
worker.next_bit_mode = 3;
|
||||
worker.next_bit_mode = MODE_RANDOM;
|
||||
worker.next_bit_state = atoi(args[++argidx].c_str()) + 1;
|
||||
for (int i = 0; i < 10; i++)
|
||||
worker.next_bit();
|
||||
|
@ -232,7 +250,10 @@ struct SetundefPass : public Pass {
|
|||
if (expose_mode && !undriven_mode)
|
||||
log_cmd_error("Option -expose must be used with option -undriven.\n");
|
||||
if (!got_value)
|
||||
log_cmd_error("One of the options -zero, -one, -anyseq, or -random <seed> must be specified.\n");
|
||||
log_cmd_error("One of the options -zero, -one, -anyseq, -anyconst, or -random <seed> must be specified.\n");
|
||||
|
||||
if (init_mode && (worker.next_bit_mode == MODE_ANYSEQ || worker.next_bit_mode == MODE_ANYCONST))
|
||||
log_cmd_error("The options -init and -anyseq / -anyconst are exclusive.\n");
|
||||
|
||||
for (auto module : design->selected_modules())
|
||||
{
|
||||
|
@ -419,7 +440,7 @@ struct SetundefPass : public Pass {
|
|||
|
||||
module->rewrite_sigspecs(worker);
|
||||
|
||||
if (worker.next_bit_mode == 2)
|
||||
if (worker.next_bit_mode == MODE_ANYSEQ || worker.next_bit_mode == MODE_ANYCONST)
|
||||
{
|
||||
vector<SigSpec*> siglist;
|
||||
siglist.swap(worker.siglist);
|
||||
|
@ -436,7 +457,10 @@ struct SetundefPass : public Pass {
|
|||
width++;
|
||||
|
||||
if (width > 0) {
|
||||
sig.replace(cursor, module->Anyseq(NEW_ID, width));
|
||||
if (worker.next_bit_mode == MODE_ANYSEQ)
|
||||
sig.replace(cursor, module->Anyseq(NEW_ID, width));
|
||||
else
|
||||
sig.replace(cursor, module->Anyconst(NEW_ID, width));
|
||||
cursor += width;
|
||||
} else {
|
||||
cursor++;
|
||||
|
|
|
@ -142,7 +142,7 @@ struct statdata_t
|
|||
}
|
||||
}
|
||||
|
||||
void log_data()
|
||||
void log_data(RTLIL::IdString mod_name, bool top_mod)
|
||||
{
|
||||
log(" Number of wires: %6d\n", num_wires);
|
||||
log(" Number of wire bits: %6d\n", num_wire_bits);
|
||||
|
@ -163,7 +163,7 @@ struct statdata_t
|
|||
|
||||
if (area != 0) {
|
||||
log("\n");
|
||||
log(" Chip area for this module: %f\n", area);
|
||||
log(" Chip area for %smodule '%s': %f\n", (top_mod) ? "top " : "", mod_name.c_str(), area);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -275,7 +275,7 @@ struct StatPass : public Pass {
|
|||
log("\n");
|
||||
log("=== %s%s ===\n", RTLIL::id2cstr(mod->name), design->selected_whole_module(mod->name) ? "" : " (partially selected)");
|
||||
log("\n");
|
||||
data.log_data();
|
||||
data.log_data(mod->name, false);
|
||||
}
|
||||
|
||||
if (top_mod != NULL && GetSize(mod_stat) > 1)
|
||||
|
@ -288,7 +288,7 @@ struct StatPass : public Pass {
|
|||
statdata_t data = hierarchy_worker(mod_stat, top_mod->name, 0);
|
||||
|
||||
log("\n");
|
||||
data.log_data();
|
||||
data.log_data(top_mod->name, true);
|
||||
}
|
||||
|
||||
log("\n");
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
|
||||
#include "kernel/yosys.h"
|
||||
#include "frontends/verific/verific.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <set>
|
||||
|
@ -258,7 +259,7 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check
|
|||
if (mod->wires_.count(portname) == 0)
|
||||
log_error("Array cell `%s.%s' connects to unknown port `%s'.\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name), RTLIL::id2cstr(conn.first));
|
||||
int port_size = mod->wires_.at(portname)->width;
|
||||
if (conn_size == port_size)
|
||||
if (conn_size == port_size || conn_size == 0)
|
||||
continue;
|
||||
if (conn_size != port_size*num)
|
||||
log_error("Array cell `%s.%s' has invalid port vs. signal size for port `%s'.\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name), RTLIL::id2cstr(conn.first));
|
||||
|
@ -421,6 +422,7 @@ struct HierarchyPass : public Pass {
|
|||
bool flag_simcheck = false;
|
||||
bool purge_lib = false;
|
||||
RTLIL::Module *top_mod = NULL;
|
||||
std::string load_top_mod;
|
||||
std::vector<std::string> libdirs;
|
||||
|
||||
bool auto_top_mode = false;
|
||||
|
@ -511,7 +513,7 @@ struct HierarchyPass : public Pass {
|
|||
top_mod = design->modules_.count(RTLIL::escape_id(args[argidx])) ? design->modules_.at(RTLIL::escape_id(args[argidx])) : NULL;
|
||||
}
|
||||
if (top_mod == NULL)
|
||||
log_cmd_error("Module `%s' not found!\n", args[argidx].c_str());
|
||||
load_top_mod = args[argidx];
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-auto-top") {
|
||||
|
@ -522,6 +524,22 @@ struct HierarchyPass : public Pass {
|
|||
}
|
||||
extra_args(args, argidx, design, false);
|
||||
|
||||
if (!load_top_mod.empty()) {
|
||||
#ifdef YOSYS_ENABLE_VERIFIC
|
||||
if (verific_import_pending) {
|
||||
verific_import(design, load_top_mod);
|
||||
top_mod = design->module(RTLIL::escape_id(load_top_mod));
|
||||
}
|
||||
#endif
|
||||
if (top_mod == NULL)
|
||||
log_cmd_error("Module `%s' not found!\n", load_top_mod.c_str());
|
||||
} else {
|
||||
#ifdef YOSYS_ENABLE_VERIFIC
|
||||
if (verific_import_pending)
|
||||
verific_import(design);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (generate_mode) {
|
||||
generate(design, generate_cells, generate_ports);
|
||||
return;
|
||||
|
|
|
@ -33,8 +33,20 @@ struct MemoryDffWorker
|
|||
dict<SigBit, int> sigbit_users_count;
|
||||
dict<SigSpec, Cell*> mux_cells_a, mux_cells_b;
|
||||
pool<Cell*> forward_merged_dffs, candidate_dffs;
|
||||
pool<SigBit> init_bits;
|
||||
|
||||
MemoryDffWorker(Module *module) : module(module), sigmap(module) { }
|
||||
MemoryDffWorker(Module *module) : module(module), sigmap(module)
|
||||
{
|
||||
for (auto wire : module->wires()) {
|
||||
if (wire->attributes.count("\\init") == 0)
|
||||
continue;
|
||||
SigSpec sig = sigmap(wire);
|
||||
Const initval = wire->attributes.count("\\init");
|
||||
for (int i = 0; i < GetSize(sig) && i < GetSize(initval); i++)
|
||||
if (initval[i] == State::S0 || initval[i] == State::S1)
|
||||
init_bits.insert(sig[i]);
|
||||
}
|
||||
}
|
||||
|
||||
bool find_sig_before_dff(RTLIL::SigSpec &sig, RTLIL::SigSpec &clk, bool &clk_polarity, bool after = false)
|
||||
{
|
||||
|
@ -45,6 +57,9 @@ struct MemoryDffWorker
|
|||
if (bit.wire == NULL)
|
||||
continue;
|
||||
|
||||
if (!after && init_bits.count(sigmap(bit)))
|
||||
return false;
|
||||
|
||||
for (auto cell : dff_cells)
|
||||
{
|
||||
if (after && forward_merged_dffs.count(cell))
|
||||
|
@ -72,6 +87,9 @@ struct MemoryDffWorker
|
|||
if (d.size() != 1)
|
||||
continue;
|
||||
|
||||
if (after && init_bits.count(d))
|
||||
return false;
|
||||
|
||||
bit = d;
|
||||
clk = this_clk;
|
||||
clk_polarity = this_clk_polarity;
|
||||
|
|
|
@ -61,49 +61,59 @@ struct MemoryNordffPass : public Pass {
|
|||
|
||||
SigSpec rd_addr = cell->getPort("\\RD_ADDR");
|
||||
SigSpec rd_data = cell->getPort("\\RD_DATA");
|
||||
SigSpec rd_clk = cell->getPort("\\RD_CLK");
|
||||
SigSpec rd_en = cell->getPort("\\RD_EN");
|
||||
Const rd_clk_enable = cell->getParam("\\RD_CLK_ENABLE");
|
||||
Const rd_clk_polarity = cell->getParam("\\RD_CLK_POLARITY");
|
||||
|
||||
for (int i = 0; i < rd_ports; i++)
|
||||
{
|
||||
bool clk_enable = rd_clk_enable[i] == State::S1;
|
||||
|
||||
if (!clk_enable)
|
||||
continue;
|
||||
|
||||
bool clk_polarity = cell->getParam("\\RD_CLK_POLARITY")[i] == State::S1;
|
||||
bool transparent = cell->getParam("\\RD_TRANSPARENT")[i] == State::S1;
|
||||
|
||||
SigSpec clk = cell->getPort("\\RD_CLK")[i] ;
|
||||
SigSpec en = cell->getPort("\\RD_EN")[i];
|
||||
Cell *c;
|
||||
|
||||
if (transparent)
|
||||
if (clk_enable)
|
||||
{
|
||||
SigSpec sig_q = module->addWire(NEW_ID, abits);
|
||||
SigSpec sig_d = rd_addr.extract(abits * i, abits);
|
||||
rd_addr.replace(abits * i, sig_q);
|
||||
if (en != State::S1)
|
||||
sig_d = module->Mux(NEW_ID, sig_q, sig_d, en);
|
||||
c = module->addDff(NEW_ID, clk, sig_d, sig_q, clk_polarity);
|
||||
}
|
||||
else
|
||||
{
|
||||
SigSpec sig_d = module->addWire(NEW_ID, width);
|
||||
SigSpec sig_q = rd_data.extract(width * i, width);
|
||||
rd_data.replace(width *i, sig_d);
|
||||
if (en != State::S1)
|
||||
sig_d = module->Mux(NEW_ID, sig_q, sig_d, en);
|
||||
c = module->addDff(NEW_ID, clk, sig_d, sig_q, clk_polarity);
|
||||
bool clk_polarity = cell->getParam("\\RD_CLK_POLARITY")[i] == State::S1;
|
||||
bool transparent = cell->getParam("\\RD_TRANSPARENT")[i] == State::S1;
|
||||
|
||||
SigSpec clk = cell->getPort("\\RD_CLK")[i] ;
|
||||
SigSpec en = cell->getPort("\\RD_EN")[i];
|
||||
Cell *c;
|
||||
|
||||
if (transparent)
|
||||
{
|
||||
SigSpec sig_q = module->addWire(NEW_ID, abits);
|
||||
SigSpec sig_d = rd_addr.extract(abits * i, abits);
|
||||
rd_addr.replace(abits * i, sig_q);
|
||||
if (en != State::S1)
|
||||
sig_d = module->Mux(NEW_ID, sig_q, sig_d, en);
|
||||
c = module->addDff(NEW_ID, clk, sig_d, sig_q, clk_polarity);
|
||||
}
|
||||
else
|
||||
{
|
||||
SigSpec sig_d = module->addWire(NEW_ID, width);
|
||||
SigSpec sig_q = rd_data.extract(width * i, width);
|
||||
rd_data.replace(width *i, sig_d);
|
||||
if (en != State::S1)
|
||||
sig_d = module->Mux(NEW_ID, sig_q, sig_d, en);
|
||||
c = module->addDff(NEW_ID, clk, sig_d, sig_q, clk_polarity);
|
||||
}
|
||||
|
||||
log("Extracted %s FF from read port %d of %s.%s: %s\n", transparent ? "addr" : "data",
|
||||
i, log_id(module), log_id(cell), log_id(c));
|
||||
}
|
||||
|
||||
log("Extracted %s FF from read port %d of %s.%s: %s\n", transparent ? "addr" : "data",
|
||||
i, log_id(module), log_id(cell), log_id(c));
|
||||
rd_en[i] = State::S1;
|
||||
rd_clk[i] = State::S0;
|
||||
rd_clk_enable[i] = State::S0;
|
||||
rd_clk_polarity[i] = State::S1;
|
||||
}
|
||||
|
||||
cell->setPort("\\RD_ADDR", rd_addr);
|
||||
cell->setPort("\\RD_DATA", rd_data);
|
||||
cell->setPort("\\RD_CLK", rd_clk);
|
||||
cell->setPort("\\RD_EN", rd_en);
|
||||
cell->setParam("\\RD_CLK_ENABLE", rd_clk_enable);
|
||||
cell->setParam("\\RD_CLK_POLARITY", rd_clk_polarity);
|
||||
}
|
||||
}
|
||||
} MemoryNordffPass;
|
||||
|
|
|
@ -60,6 +60,10 @@
|
|||
|
||||
#include "frontends/blif/blifparse.h"
|
||||
|
||||
#ifdef YOSYS_LINK_ABC
|
||||
extern "C" int Abc_RealMain(int argc, char *argv[]);
|
||||
#endif
|
||||
|
||||
USING_YOSYS_NAMESPACE
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
||||
|
@ -546,11 +550,13 @@ std::string replace_tempdir(std::string text, std::string tempdir_name, bool sho
|
|||
}
|
||||
|
||||
std::string selfdir_name = proc_self_dirname();
|
||||
while (1) {
|
||||
size_t pos = text.find(selfdir_name);
|
||||
if (pos == std::string::npos)
|
||||
break;
|
||||
text = text.substr(0, pos) + "<yosys-exe-dir>/" + text.substr(pos + GetSize(selfdir_name));
|
||||
if (selfdir_name != "/") {
|
||||
while (1) {
|
||||
size_t pos = text.find(selfdir_name);
|
||||
if (pos == std::string::npos)
|
||||
break;
|
||||
text = text.substr(0, pos) + "<yosys-exe-dir>/" + text.substr(pos + GetSize(selfdir_name));
|
||||
}
|
||||
}
|
||||
|
||||
return text;
|
||||
|
@ -943,8 +949,24 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
|
|||
buffer = stringf("%s -s -f %s/abc.script 2>&1", exe_file.c_str(), tempdir_name.c_str());
|
||||
log("Running ABC command: %s\n", replace_tempdir(buffer, tempdir_name, show_tempdir).c_str());
|
||||
|
||||
#ifndef YOSYS_LINK_ABC
|
||||
abc_output_filter filt(tempdir_name, show_tempdir);
|
||||
int ret = run_command(buffer, std::bind(&abc_output_filter::next_line, filt, std::placeholders::_1));
|
||||
#else
|
||||
// These needs to be mutable, supposedly due to getopt
|
||||
char *abc_argv[5];
|
||||
string tmp_script_name = stringf("%s/abc.script", tempdir_name.c_str());
|
||||
abc_argv[0] = strdup(exe_file.c_str());
|
||||
abc_argv[1] = strdup("-s");
|
||||
abc_argv[2] = strdup("-f");
|
||||
abc_argv[3] = strdup(tmp_script_name.c_str());
|
||||
abc_argv[4] = 0;
|
||||
int ret = Abc_RealMain(4, abc_argv);
|
||||
free(abc_argv[0]);
|
||||
free(abc_argv[1]);
|
||||
free(abc_argv[2]);
|
||||
free(abc_argv[3]);
|
||||
#endif
|
||||
if (ret != 0)
|
||||
log_error("ABC: execution of command \"%s\" failed: return code %d.\n", buffer.c_str(), ret);
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ struct DeminoutPass : public Pass {
|
|||
for (auto module : design->selected_modules())
|
||||
{
|
||||
SigMap sigmap(module);
|
||||
pool<SigBit> bits_written, bits_used, bits_inout;
|
||||
pool<SigBit> bits_written, bits_used, bits_inout, bits_tribuf;
|
||||
dict<SigBit, int> bits_numports;
|
||||
|
||||
for (auto wire : module->wires())
|
||||
|
@ -82,6 +82,25 @@ struct DeminoutPass : public Pass {
|
|||
if (cellport_in)
|
||||
for (auto bit : sigmap(conn.second))
|
||||
bits_used.insert(bit);
|
||||
|
||||
if (conn.first == "\\Y" && cell->type.in("$mux", "$pmux", "$_MUX_", "$_TBUF_"))
|
||||
{
|
||||
bool tribuf = (cell->type == "$_TBUF_");
|
||||
|
||||
if (!tribuf) {
|
||||
for (auto &c : cell->connections()) {
|
||||
if (!c.first.in("\\A", "\\B"))
|
||||
continue;
|
||||
for (auto b : sigmap(c.second))
|
||||
if (b == State::Sz)
|
||||
tribuf = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (tribuf)
|
||||
for (auto bit : sigmap(conn.second))
|
||||
bits_tribuf.insert(bit);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto wire : module->selected_wires())
|
||||
|
@ -95,10 +114,15 @@ struct DeminoutPass : public Pass {
|
|||
if (bits_numports[bit] > 1 || bits_inout.count(bit))
|
||||
new_input = true, new_output = true;
|
||||
|
||||
if (bits_written.count(bit))
|
||||
if (bits_written.count(bit)) {
|
||||
new_output = true;
|
||||
else if (bits_used.count(bit))
|
||||
new_input = true;
|
||||
if (bits_tribuf.count(bit))
|
||||
goto tribuf_bit;
|
||||
} else {
|
||||
tribuf_bit:
|
||||
if (bits_used.count(bit))
|
||||
new_input = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (new_input != new_output) {
|
||||
|
|
|
@ -146,11 +146,37 @@ struct IopadmapPass : public Pass {
|
|||
for (auto module : design->selected_modules())
|
||||
{
|
||||
dict<IdString, pool<int>> skip_wires;
|
||||
pool<SigBit> skip_wire_bits;
|
||||
SigMap sigmap(module);
|
||||
|
||||
for (auto cell : module->cells())
|
||||
{
|
||||
if (cell->type == RTLIL::escape_id(inpad_celltype) && cell->hasPort(RTLIL::escape_id(inpad_portname2)))
|
||||
for (auto bit : sigmap(cell->getPort(RTLIL::escape_id(inpad_portname2))))
|
||||
skip_wire_bits.insert(bit);
|
||||
|
||||
if (cell->type == RTLIL::escape_id(outpad_celltype) && cell->hasPort(RTLIL::escape_id(outpad_portname2)))
|
||||
for (auto bit : sigmap(cell->getPort(RTLIL::escape_id(outpad_portname2))))
|
||||
skip_wire_bits.insert(bit);
|
||||
|
||||
if (cell->type == RTLIL::escape_id(inoutpad_celltype) && cell->hasPort(RTLIL::escape_id(inoutpad_portname2)))
|
||||
for (auto bit : sigmap(cell->getPort(RTLIL::escape_id(inoutpad_portname2))))
|
||||
skip_wire_bits.insert(bit);
|
||||
|
||||
if (cell->type == RTLIL::escape_id(toutpad_celltype) && cell->hasPort(RTLIL::escape_id(toutpad_portname3)))
|
||||
for (auto bit : sigmap(cell->getPort(RTLIL::escape_id(toutpad_portname3))))
|
||||
skip_wire_bits.insert(bit);
|
||||
|
||||
if (cell->type == RTLIL::escape_id(tinoutpad_celltype) && cell->hasPort(RTLIL::escape_id(tinoutpad_portname4)))
|
||||
for (auto bit : sigmap(cell->getPort(RTLIL::escape_id(tinoutpad_portname4))))
|
||||
skip_wire_bits.insert(bit);
|
||||
}
|
||||
|
||||
if (!toutpad_celltype.empty() || !tinoutpad_celltype.empty())
|
||||
{
|
||||
SigMap sigmap(module);
|
||||
dict<SigBit, pair<IdString, pool<IdString>>> tbuf_bits;
|
||||
pool<pair<IdString, IdString>> norewrites;
|
||||
SigMap rewrites;
|
||||
|
||||
for (auto cell : module->cells())
|
||||
if (cell->type == "$_TBUF_") {
|
||||
|
@ -177,6 +203,9 @@ struct IopadmapPass : public Pass {
|
|||
if (tbuf_bits.count(mapped_wire_bit) == 0)
|
||||
continue;
|
||||
|
||||
if (skip_wire_bits.count(mapped_wire_bit))
|
||||
continue;
|
||||
|
||||
auto &tbuf_cache = tbuf_bits.at(mapped_wire_bit);
|
||||
Cell *tbuf_cell = module->cell(tbuf_cache.first);
|
||||
|
||||
|
@ -219,6 +248,9 @@ struct IopadmapPass : public Pass {
|
|||
|
||||
module->remove(tbuf_cell);
|
||||
skip_wires[wire->name].insert(i);
|
||||
|
||||
norewrites.insert(make_pair(cell->name, RTLIL::escape_id(tinoutpad_portname4)));
|
||||
rewrites.add(sigmap(wire_bit), owire);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -256,6 +288,22 @@ struct IopadmapPass : public Pass {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (GetSize(norewrites))
|
||||
{
|
||||
for (auto cell : module->cells())
|
||||
for (auto port : cell->connections())
|
||||
{
|
||||
if (norewrites.count(make_pair(cell->name, port.first)))
|
||||
continue;
|
||||
|
||||
SigSpec orig_sig = sigmap(port.second);
|
||||
SigSpec new_sig = rewrites(orig_sig);
|
||||
|
||||
if (orig_sig != new_sig)
|
||||
cell->setPort(port.first, new_sig);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto wire : module->selected_wires())
|
||||
|
@ -272,6 +320,13 @@ struct IopadmapPass : public Pass {
|
|||
skip_bit_indices = skip_wires.at(wire->name);
|
||||
}
|
||||
|
||||
for (int i = 0; i < GetSize(wire); i++)
|
||||
if (skip_wire_bits.count(sigmap(SigBit(wire, i))))
|
||||
skip_bit_indices.insert(i);
|
||||
|
||||
if (GetSize(wire) == GetSize(skip_bit_indices))
|
||||
continue;
|
||||
|
||||
if (wire->port_input && !wire->port_output) {
|
||||
if (inpad_celltype.empty()) {
|
||||
log("Don't map input port %s.%s: Missing option -inpad.\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(wire->name));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue