aboutsummaryrefslogtreecommitdiffstats
path: root/passes/cmds
diff options
context:
space:
mode:
Diffstat (limited to 'passes/cmds')
-rw-r--r--passes/cmds/rename.cc137
-rw-r--r--passes/cmds/setundef.cc24
-rw-r--r--passes/cmds/show.cc1
-rw-r--r--passes/cmds/stat.cc147
4 files changed, 271 insertions, 38 deletions
diff --git a/passes/cmds/rename.cc b/passes/cmds/rename.cc
index 81da35ffe..45576c91c 100644
--- a/passes/cmds/rename.cc
+++ b/passes/cmds/rename.cc
@@ -20,6 +20,7 @@
#include "kernel/register.h"
#include "kernel/rtlil.h"
#include "kernel/log.h"
+#include "kernel/hashlib.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
@@ -105,6 +106,60 @@ static IdString derive_name_from_cell_output_wire(const RTLIL::Cell *cell, strin
return name + suffix;
}
+static bool rename_witness(RTLIL::Design *design, dict<RTLIL::Module *, int> &cache, RTLIL::Module *module)
+{
+ auto cached = cache.find(module);
+ if (cached != cache.end()) {
+ if (cached->second == -1)
+ log_error("Cannot rename witness signals in a design containing recursive instantiations.\n");
+ return cached->second;
+ }
+ cache.emplace(module, -1);
+
+ bool has_witness_signals = false;
+ for (auto cell : module->cells())
+ {
+ RTLIL::Module *impl = design->module(cell->type);
+ if (impl != nullptr) {
+ bool witness_in_cell = rename_witness(design, cache, impl);
+ has_witness_signals |= witness_in_cell;
+ if (witness_in_cell && !cell->name.isPublic()) {
+ std::string name = cell->name.c_str() + 1;
+ for (auto &c : name)
+ if ((c < 'a' || c > 'z') && (c < 'A' || c > 'Z') && (c < '0' || c > '9') && c != '_')
+ c = '_';
+ auto new_id = module->uniquify("\\_witness_." + name);
+ cell->set_hdlname_attribute({ "_witness_", strstr(new_id.c_str(), ".") + 1 });
+ module->rename(cell, new_id);
+ }
+ }
+
+ if (cell->type.in(ID($anyconst), ID($anyseq), ID($anyinit), ID($allconst), ID($allseq))) {
+ has_witness_signals = true;
+ auto QY = cell->type == ID($anyinit) ? ID::Q : ID::Y;
+ auto sig_out = cell->getPort(QY);
+
+ for (auto chunk : sig_out.chunks()) {
+ if (chunk.is_wire() && !chunk.wire->name.isPublic()) {
+ std::string name = stringf("%s_%s", cell->type.c_str() + 1, cell->name.c_str() + 1);
+ for (auto &c : name)
+ if ((c < 'a' || c > 'z') && (c < 'A' || c > 'Z') && (c < '0' || c > '9') && c != '_')
+ c = '_';
+ auto new_id = module->uniquify("\\_witness_." + name);
+ auto new_wire = module->addWire(new_id, GetSize(sig_out));
+ new_wire->set_hdlname_attribute({ "_witness_", strstr(new_id.c_str(), ".") + 1 });
+ module->connect({sig_out, new_wire});
+ cell->setPort(QY, new_wire);
+ break;
+ }
+ }
+ }
+ }
+
+ cache[module] = has_witness_signals;
+ return has_witness_signals;
+}
+
struct RenamePass : public Pass {
RenamePass() : Pass("rename", "rename object in the design") { }
void help() override
@@ -146,6 +201,14 @@ struct RenamePass : public Pass {
log("pattern is '_%%_'.\n");
log("\n");
log("\n");
+ log(" rename -witness\n");
+ log("\n");
+ log("Assigns auto-generated names to all $any*/$all* output wires and containing\n");
+ log("cells that do not have a public name. This ensures that, during formal\n");
+ log("verification, a solver-found trace can be fully specified using a public\n");
+ log("hierarchical names.\n");
+ log("\n");
+ log("\n");
log(" rename -hide [selection]\n");
log("\n");
log("Assign private names (the ones with $-prefix) to all selected wires and cells\n");
@@ -156,6 +219,13 @@ struct RenamePass : public Pass {
log("\n");
log("Rename top module.\n");
log("\n");
+ log("\n");
+ log(" rename -scramble-name [-seed <seed>] [selection]\n");
+ log("\n");
+ log("Assign randomly-generated names to all selected wires and cells. The seed option\n");
+ log("can be used to change the random number generator seed from the default, but it\n");
+ log("must be non-zero.\n");
+ log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
@@ -164,10 +234,13 @@ struct RenamePass : public Pass {
bool flag_src = false;
bool flag_wire = false;
bool flag_enumerate = false;
+ bool flag_witness = false;
bool flag_hide = false;
bool flag_top = false;
bool flag_output = false;
+ bool flag_scramble_name = false;
bool got_mode = false;
+ unsigned int seed = 1;
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
@@ -193,6 +266,11 @@ struct RenamePass : public Pass {
got_mode = true;
continue;
}
+ if (arg == "-witness" && !got_mode) {
+ flag_witness = true;
+ got_mode = true;
+ continue;
+ }
if (arg == "-hide" && !got_mode) {
flag_hide = true;
got_mode = true;
@@ -203,6 +281,11 @@ struct RenamePass : public Pass {
got_mode = true;
continue;
}
+ if (arg == "-scramble-name" && !got_mode) {
+ flag_scramble_name = true;
+ got_mode = true;
+ continue;
+ }
if (arg == "-pattern" && argidx+1 < args.size() && args[argidx+1].find('%') != std::string::npos) {
int pos = args[++argidx].find('%');
pattern_prefix = args[argidx].substr(0, pos);
@@ -211,6 +294,11 @@ struct RenamePass : public Pass {
}
if (arg == "-suffix" && argidx + 1 < args.size()) {
cell_suffix = args[++argidx];
+ continue;
+ }
+ if (arg == "-seed" && argidx+1 < args.size()) {
+ seed = std::stoi(args[++argidx]);
+ continue;
}
break;
}
@@ -289,6 +377,19 @@ struct RenamePass : public Pass {
}
}
else
+ if (flag_witness)
+ {
+ extra_args(args, argidx, design, false);
+
+ RTLIL::Module *module = design->top_module();
+
+ if (module == nullptr)
+ log_cmd_error("No top module found!\n");
+
+ dict<RTLIL::Module *, int> cache;
+ rename_witness(design, cache, module);
+ }
+ else
if (flag_hide)
{
extra_args(args, argidx, design);
@@ -329,6 +430,42 @@ struct RenamePass : public Pass {
design->rename(module, new_name);
}
else
+ if (flag_scramble_name)
+ {
+ extra_args(args, argidx, design);
+
+ if (seed == 0)
+ log_error("Seed for -scramble-name cannot be zero.\n");
+
+ for (auto module : design->selected_modules())
+ {
+ if (module->memories.size() != 0 || module->processes.size() != 0) {
+ log_warning("Skipping module %s with unprocessed memories or processes\n", log_id(module));
+ continue;
+ }
+
+ dict<RTLIL::Wire *, IdString> new_wire_names;
+ dict<RTLIL::Cell *, IdString> new_cell_names;
+
+ for (auto wire : module->selected_wires())
+ if (wire->port_id == 0) {
+ seed = mkhash_xorshift(seed);
+ new_wire_names[wire] = stringf("$_%u_", seed);
+ }
+
+ for (auto cell : module->selected_cells()) {
+ seed = mkhash_xorshift(seed);
+ new_cell_names[cell] = stringf("$_%u_", seed);
+ }
+
+ for (auto &it : new_wire_names)
+ module->rename(it.first, it.second);
+
+ for (auto &it : new_cell_names)
+ module->rename(it.first, it.second);
+ }
+ }
+ else
{
if (argidx+2 != args.size())
log_cmd_error("Invalid number of arguments!\n");
diff --git a/passes/cmds/setundef.cc b/passes/cmds/setundef.cc
index a078b0b1c..590a7eb1d 100644
--- a/passes/cmds/setundef.cc
+++ b/passes/cmds/setundef.cc
@@ -20,6 +20,7 @@
#include "kernel/register.h"
#include "kernel/celltypes.h"
#include "kernel/sigtools.h"
+#include "kernel/mem.h"
#include "kernel/rtlil.h"
#include "kernel/log.h"
@@ -478,6 +479,29 @@ struct SetundefPass : public Pass {
log_assert(ffbits.empty());
}
+ if (worker.next_bit_mode == MODE_ANYSEQ || worker.next_bit_mode == MODE_ANYCONST)
+ {
+ // Do not add anyseq / anyconst to unused memory port clocks
+ std::vector<Mem> memories = Mem::get_selected_memories(module);
+ for (auto &mem : memories) {
+ bool changed = false;
+ for (auto &rd_port : mem.rd_ports) {
+ if (!rd_port.clk_enable && rd_port.clk.is_fully_undef()) {
+ changed = true;
+ rd_port.clk = State::S0;
+ }
+ }
+ for (auto &wr_port : mem.rd_ports) {
+ if (!wr_port.clk_enable && wr_port.clk.is_fully_undef()) {
+ changed = true;
+ wr_port.clk = State::S0;
+ }
+ }
+ if (changed)
+ mem.emit();
+ }
+ }
+
module->rewrite_sigspecs(worker);
if (worker.next_bit_mode == MODE_ANYSEQ || worker.next_bit_mode == MODE_ANYCONST)
diff --git a/passes/cmds/show.cc b/passes/cmds/show.cc
index 43deba47b..4d5605932 100644
--- a/passes/cmds/show.cc
+++ b/passes/cmds/show.cc
@@ -574,6 +574,7 @@ struct ShowWorker
{
ct.setup_internals();
ct.setup_internals_mem();
+ ct.setup_internals_anyinit();
ct.setup_stdcells();
ct.setup_stdcells_mem();
ct.setup_design(design);
diff --git a/passes/cmds/stat.cc b/passes/cmds/stat.cc
index c858c8631..a4984597d 100644
--- a/passes/cmds/stat.cc
+++ b/passes/cmds/stat.cc
@@ -17,10 +17,13 @@
*
*/
+#include <iterator>
+
#include "kernel/yosys.h"
#include "kernel/celltypes.h"
#include "passes/techmap/libparse.h"
#include "kernel/cost.h"
+#include "libs/json11/json11.hpp"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
@@ -32,14 +35,14 @@ struct statdata_t
#define STAT_NUMERIC_MEMBERS STAT_INT_MEMBERS X(area)
- #define X(_name) int _name;
+ #define X(_name) unsigned int _name;
STAT_INT_MEMBERS
#undef X
double area;
string tech;
std::map<RTLIL::IdString, int> techinfo;
- std::map<RTLIL::IdString, int, RTLIL::sort_by_id_str> num_cells_by_type;
+ std::map<RTLIL::IdString, unsigned int, RTLIL::sort_by_id_str> num_cells_by_type;
std::set<RTLIL::IdString> unknown_cell_area;
statdata_t operator+(const statdata_t &other) const
@@ -53,7 +56,7 @@ struct statdata_t
return sum;
}
- statdata_t operator*(int other) const
+ statdata_t operator*(unsigned int other) const
{
statdata_t sum = *this;
#define X(_name) sum._name *= other;
@@ -148,17 +151,17 @@ struct statdata_t
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);
- log(" Number of public wires: %6d\n", num_pub_wires);
- log(" Number of public wire bits: %6d\n", num_pub_wire_bits);
- log(" Number of memories: %6d\n", num_memories);
- log(" Number of memory bits: %6d\n", num_memory_bits);
- log(" Number of processes: %6d\n", num_processes);
- log(" Number of cells: %6d\n", num_cells);
+ log(" Number of wires: %6u\n", num_wires);
+ log(" Number of wire bits: %6u\n", num_wire_bits);
+ log(" Number of public wires: %6u\n", num_pub_wires);
+ log(" Number of public wire bits: %6u\n", num_pub_wire_bits);
+ log(" Number of memories: %6u\n", num_memories);
+ log(" Number of memory bits: %6u\n", num_memory_bits);
+ log(" Number of processes: %6u\n", num_processes);
+ log(" Number of cells: %6u\n", num_cells);
for (auto &it : num_cells_by_type)
if (it.second)
- log(" %-26s %6d\n", log_id(it.first), it.second);
+ log(" %-26s %6u\n", log_id(it.first), it.second);
if (!unknown_cell_area.empty()) {
log("\n");
@@ -173,13 +176,13 @@ struct statdata_t
if (tech == "xilinx")
{
- int lut6_cnt = num_cells_by_type[ID(LUT6)];
- int lut5_cnt = num_cells_by_type[ID(LUT5)];
- int lut4_cnt = num_cells_by_type[ID(LUT4)];
- int lut3_cnt = num_cells_by_type[ID(LUT3)];
- int lut2_cnt = num_cells_by_type[ID(LUT2)];
- int lut1_cnt = num_cells_by_type[ID(LUT1)];
- int lc_cnt = 0;
+ unsigned int lut6_cnt = num_cells_by_type[ID(LUT6)];
+ unsigned int lut5_cnt = num_cells_by_type[ID(LUT5)];
+ unsigned int lut4_cnt = num_cells_by_type[ID(LUT4)];
+ unsigned int lut3_cnt = num_cells_by_type[ID(LUT3)];
+ unsigned int lut2_cnt = num_cells_by_type[ID(LUT2)];
+ unsigned int lut1_cnt = num_cells_by_type[ID(LUT1)];
+ unsigned int lc_cnt = 0;
lc_cnt += lut6_cnt;
@@ -221,12 +224,12 @@ struct statdata_t
lc_cnt += (lut2_cnt + lut1_cnt + 1) / 2;
log("\n");
- log(" Estimated number of LCs: %10d\n", lc_cnt);
+ log(" Estimated number of LCs: %10u\n", lc_cnt);
}
if (tech == "cmos")
{
- int tran_cnt = 0;
+ unsigned int tran_cnt = 0;
bool tran_cnt_exact = true;
auto &gate_costs = CellCosts::cmos_gate_cost();
@@ -243,20 +246,48 @@ struct statdata_t
}
log("\n");
- log(" Estimated number of transistors: %10d%s\n", tran_cnt, tran_cnt_exact ? "" : "+");
+ log(" Estimated number of transistors: %10u%s\n", tran_cnt, tran_cnt_exact ? "" : "+");
}
}
+
+ void log_data_json(const char *mod_name, bool first_module)
+ {
+ if (!first_module)
+ log(",\n");
+ log(" %s: {\n", json11::Json(mod_name).dump().c_str());
+ log(" \"num_wires\": %u,\n", num_wires);
+ log(" \"num_wire_bits\": %u,\n", num_wire_bits);
+ log(" \"num_pub_wires\": %u,\n", num_pub_wires);
+ log(" \"num_pub_wire_bits\": %u,\n", num_pub_wire_bits);
+ log(" \"num_memories\": %u,\n", num_memories);
+ log(" \"num_memory_bits\": %u,\n", num_memory_bits);
+ log(" \"num_processes\": %u,\n", num_processes);
+ log(" \"num_cells\": %u,\n", num_cells);
+ log(" \"num_cells_by_type\": {\n");
+ bool first_line = true;
+ for (auto &it : num_cells_by_type)
+ if (it.second) {
+ if (!first_line)
+ log(",\n");
+ log(" %s: %u", json11::Json(log_id(it.first)).dump().c_str(), it.second);
+ first_line = false;
+ }
+ log("\n");
+ log(" }\n");
+ log(" }");
+ }
};
-statdata_t hierarchy_worker(std::map<RTLIL::IdString, statdata_t> &mod_stat, RTLIL::IdString mod, int level)
+statdata_t hierarchy_worker(std::map<RTLIL::IdString, statdata_t> &mod_stat, RTLIL::IdString mod, int level, bool quiet = false)
{
statdata_t mod_data = mod_stat.at(mod);
- std::map<RTLIL::IdString, int, RTLIL::sort_by_id_str> num_cells_by_type;
+ std::map<RTLIL::IdString, unsigned int, RTLIL::sort_by_id_str> num_cells_by_type;
num_cells_by_type.swap(mod_data.num_cells_by_type);
for (auto &it : num_cells_by_type)
if (mod_stat.count(it.first) > 0) {
- log(" %*s%-*s %6d\n", 2*level, "", 26-2*level, log_id(it.first), it.second);
+ if (!quiet)
+ log(" %*s%-*s %6u\n", 2*level, "", 26-2*level, log_id(it.first), it.second);
mod_data = mod_data + hierarchy_worker(mod_stat, it.first, level+1) * it.second;
mod_data.num_cells -= it.second;
} else {
@@ -314,12 +345,16 @@ struct StatPass : public Pass {
log(" annotate internal cell types with their word width.\n");
log(" e.g. $add_8 for an 8 bit wide $add cell.\n");
log("\n");
+ log(" -json\n");
+ log(" output the statistics in a machine-readable JSON format.\n");
+ log(" this is output to the console; use \"tee\" to output to a file.\n");
+ log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
log_header(design, "Printing statistics.\n");
- bool width_mode = false;
+ bool width_mode = false, json_mode = false;
RTLIL::Module *top_mod = nullptr;
std::map<RTLIL::IdString, statdata_t> mod_stat;
dict<IdString, double> cell_area;
@@ -348,13 +383,27 @@ struct StatPass : public Pass {
top_mod = design->module(RTLIL::escape_id(args[++argidx]));
continue;
}
+ if (args[argidx] == "-json") {
+ json_mode = true;
+ continue;
+ }
break;
}
extra_args(args, argidx, design);
- if (techname != "" && techname != "xilinx" && techname != "cmos")
+ if (techname != "" && techname != "xilinx" && techname != "cmos" && !json_mode)
log_cmd_error("Unsupported technology: '%s'\n", techname.c_str());
+ if (json_mode) {
+ log("{\n");
+ log(" \"creator\": %s,\n", json11::Json(yosys_version_str).dump().c_str());
+ std::stringstream invocation;
+ std::copy(args.begin(), args.end(), std::ostream_iterator<std::string>(invocation, " "));
+ log(" \"invocation\": %s,\n", json11::Json(invocation.str()).dump().c_str());
+ log(" \"modules\": {\n");
+ }
+
+ bool first_module = true;
for (auto mod : design->selected_modules())
{
if (!top_mod && design->full_selection())
@@ -364,23 +413,40 @@ struct StatPass : public Pass {
statdata_t data(design, mod, width_mode, cell_area, techname);
mod_stat[mod->name] = data;
+ if (json_mode) {
+ data.log_data_json(mod->name.c_str(), first_module);
+ first_module = false;
+ } else {
+ log("\n");
+ log("=== %s%s ===\n", log_id(mod->name), design->selected_whole_module(mod->name) ? "" : " (partially selected)");
+ log("\n");
+ data.log_data(mod->name, false);
+ }
+ }
+
+ if (json_mode) {
log("\n");
- log("=== %s%s ===\n", log_id(mod->name), design->selected_whole_module(mod->name) ? "" : " (partially selected)");
- log("\n");
- data.log_data(mod->name, false);
+ log(" },\n");
}
- if (top_mod != nullptr && GetSize(mod_stat) > 1)
+ if (top_mod != nullptr)
{
- log("\n");
- log("=== design hierarchy ===\n");
- log("\n");
+ if (!json_mode && GetSize(mod_stat) > 1) {
+ log("\n");
+ log("=== design hierarchy ===\n");
+ log("\n");
+ log(" %-28s %6d\n", log_id(top_mod->name), 1);
+ }
- log(" %-28s %6d\n", log_id(top_mod->name), 1);
- statdata_t data = hierarchy_worker(mod_stat, top_mod->name, 0);
+ statdata_t data = hierarchy_worker(mod_stat, top_mod->name, 0, /*quiet=*/json_mode);
+
+ if (json_mode)
+ data.log_data_json("design", true);
+ else if (GetSize(mod_stat) > 1) {
+ log("\n");
+ data.log_data(top_mod->name, true);
+ }
- log("\n");
- data.log_data(top_mod->name, true);
design->scratchpad_set_int("stat.num_wires", data.num_wires);
design->scratchpad_set_int("stat.num_wire_bits", data.num_wire_bits);
design->scratchpad_set_int("stat.num_pub_wires", data.num_pub_wires);
@@ -392,6 +458,11 @@ struct StatPass : public Pass {
design->scratchpad_set_int("stat.area", data.area);
}
+ if (json_mode) {
+ log("\n");
+ log("}\n");
+ }
+
log("\n");
}
} StatPass;