summaryrefslogtreecommitdiff
path: root/passes/cmds/setundef.cc
diff options
context:
space:
mode:
Diffstat (limited to 'passes/cmds/setundef.cc')
-rw-r--r--passes/cmds/setundef.cc263
1 files changed, 232 insertions, 31 deletions
diff --git a/passes/cmds/setundef.cc b/passes/cmds/setundef.cc
index 26b2eb87..62d940ce 100644
--- a/passes/cmds/setundef.cc
+++ b/passes/cmds/setundef.cc
@@ -23,33 +23,82 @@
#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
+static RTLIL::Wire * add_wire(RTLIL::Module *module, std::string name, int width, bool flag_input, bool flag_output)
+{
+ RTLIL::Wire *wire = NULL;
+ name = RTLIL::escape_id(name);
+
+ if (module->count_id(name) != 0)
+ {
+ log("Module %s already has such an object %s.\n", module->name.c_str(), name.c_str());
+ name += "$";
+ return add_wire(module, name, width, flag_input, flag_output);
+ }
+ else
+ {
+ wire = module->addWire(name, width);
+ wire->port_input = flag_input;
+ wire->port_output = flag_output;
+
+ if (flag_input || flag_output) {
+ wire->port_id = module->wires_.size();
+ module->fixup_ports();
+ }
+
+ log("Added wire %s to module %s.\n", name.c_str(), module->name.c_str());
+ }
+
+ return wire;
+}
+
struct SetundefWorker
{
int next_bit_mode;
uint32_t next_bit_state;
+ vector<SigSpec*> siglist;
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;
- // 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_UNDEF)
+ return RTLIL::State::Sx;
+
+ 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 == MODE_ANYSEQ || next_bit_mode == MODE_ANYCONST) {
+ siglist.push_back(&sig);
+ return;
+ }
+
for (auto &bit : sig)
if (bit.wire == NULL && bit.data > RTLIL::State::S1)
bit = next_bit();
@@ -58,23 +107,35 @@ struct SetundefWorker
struct SetundefPass : public Pass {
SetundefPass() : Pass("setundef", "replace undef values with defined constants") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" setundef [options] [selection]\n");
log("\n");
- log("This command replaced undef (x) constants with defined (0/1) constants.\n");
+ log("This command replaces undef (x) constants with defined (0/1) constants.\n");
log("\n");
log(" -undriven\n");
log(" also set undriven nets to constant values\n");
log("\n");
+ log(" -expose\n");
+ log(" also expose undriven nets as inputs (use with -undriven)\n");
+ log("\n");
log(" -zero\n");
log(" replace with bits cleared (0)\n");
log("\n");
log(" -one\n");
log(" replace with bits set (1)\n");
log("\n");
+ log(" -undef\n");
+ log(" replace with undef (x) bits, may be used with -undriven\n");
+ log("\n");
+ 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");
@@ -83,13 +144,16 @@ struct SetundefPass : public Pass {
log(" also create/update init values for flip-flops\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
bool got_value = false;
bool undriven_mode = false;
+ bool expose_mode = false;
bool init_mode = false;
SetundefWorker worker;
+ log_header(design, "Executing SETUNDEF pass (replace undef values with defined constants).\n");
+
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{
@@ -97,14 +161,39 @@ struct SetundefPass : public Pass {
undriven_mode = true;
continue;
}
+ if (args[argidx] == "-expose") {
+ got_value = true;
+ expose_mode = true;
+ continue;
+ }
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 = 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 = MODE_UNDEF;
+ worker.next_bit_state = 0;
continue;
}
if (args[argidx] == "-init") {
@@ -113,7 +202,7 @@ struct SetundefPass : public Pass {
}
if (args[argidx] == "-random" && !got_value && argidx+1 < args.size()) {
got_value = true;
- worker.next_bit_mode = 2;
+ 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();
@@ -123,8 +212,13 @@ struct SetundefPass : public Pass {
}
extra_args(args, argidx, design);
+ 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, 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())
{
@@ -133,25 +227,103 @@ struct SetundefPass : public Pass {
if (!module->processes.empty())
log_error("The 'setundef' command can't operate in -undriven mode on modules with processes. Run 'proc' first.\n");
- SigMap sigmap(module);
- SigPool undriven_signals;
+ if (expose_mode)
+ {
+ SigMap sigmap(module);
+ dict<SigBit, bool> wire_drivers;
+ pool<SigBit> used_wires;
+ SigPool undriven_signals;
+
+ for (auto cell : module->cells())
+ for (auto &conn : cell->connections()) {
+ SigSpec sig = sigmap(conn.second);
+ if (cell->input(conn.first))
+ for (auto bit : sig)
+ if (bit.wire)
+ used_wires.insert(bit);
+ if (cell->output(conn.first))
+ for (int i = 0; i < GetSize(sig); i++)
+ if (sig[i].wire)
+ wire_drivers[sig[i]] = true;
+ }
+
+ for (auto wire : module->wires()) {
+ if (wire->port_input) {
+ SigSpec sig = sigmap(wire);
+ for (int i = 0; i < GetSize(sig); i++)
+ wire_drivers[sig[i]] = true;
+ }
+ if (wire->port_output) {
+ SigSpec sig = sigmap(wire);
+ for (auto bit : sig)
+ if (bit.wire)
+ used_wires.insert(bit);
+ }
+ }
+
+ pool<RTLIL::Wire*> undriven_wires;
+ for (auto bit : used_wires)
+ if (!wire_drivers.count(bit))
+ undriven_wires.insert(bit.wire);
+
+ for (auto &it : undriven_wires)
+ undriven_signals.add(sigmap(it));
+
+ for (auto &it : undriven_wires)
+ if (it->port_input)
+ undriven_signals.del(sigmap(it));
+
+ CellTypes ct(design);
+ for (auto &it : module->cells_)
+ for (auto &conn : it.second->connections())
+ if (!ct.cell_known(it.second->type) || ct.cell_output(it.second->type, conn.first))
+ undriven_signals.del(sigmap(conn.second));
+
+ RTLIL::SigSpec sig = undriven_signals.export_all();
+ for (auto &c : sig.chunks()) {
+ RTLIL::Wire * wire;
+ if (c.wire->width == c.width) {
+ wire = c.wire;
+ wire->port_input = true;
+ } else {
+ string name = c.wire->name.str() + "$[" + std::to_string(c.width + c.offset) + ":" + std::to_string(c.offset) + "]";
+ wire = add_wire(module, name, c.width, true, false);
+ module->connect(RTLIL::SigSig(c, wire));
+ }
+ log("Exposing undriven wire %s as input.\n", wire->name.c_str());
+ }
+ module->fixup_ports();
+ }
+ else
+ {
+ SigMap sigmap(module);
+ SigPool undriven_signals;
- for (auto &it : module->wires_)
- if (!it.second->port_input)
+ for (auto &it : module->wires_)
undriven_signals.add(sigmap(it.second));
- CellTypes ct(design);
- for (auto &it : module->cells_)
- for (auto &conn : it.second->connections())
- if (!ct.cell_known(it.second->type) || ct.cell_output(it.second->type, conn.first))
- undriven_signals.del(sigmap(conn.second));
-
- RTLIL::SigSpec sig = undriven_signals.export_all();
- for (auto &c : sig.chunks()) {
- RTLIL::SigSpec bits;
- for (int i = 0; i < c.width; i++)
- bits.append(worker.next_bit());
- module->connect(RTLIL::SigSig(c, bits));
+ for (auto &it : module->wires_)
+ if (it.second->port_input)
+ undriven_signals.del(sigmap(it.second));
+
+ CellTypes ct(design);
+ for (auto &it : module->cells_)
+ for (auto &conn : it.second->connections())
+ if (!ct.cell_known(it.second->type) || ct.cell_output(it.second->type, conn.first))
+ undriven_signals.del(sigmap(conn.second));
+
+ RTLIL::SigSpec sig = undriven_signals.export_all();
+ for (auto &c : sig.chunks()) {
+ RTLIL::SigSpec bits;
+ if (worker.next_bit_mode == MODE_ANYSEQ)
+ bits = module->Anyseq(NEW_ID, c.width);
+ else if (worker.next_bit_mode == MODE_ANYCONST)
+ bits = module->Anyconst(NEW_ID, c.width);
+ else
+ for (int i = 0; i < c.width; i++)
+ bits.append(worker.next_bit());
+ module->connect(RTLIL::SigSig(c, bits));
+ }
}
}
@@ -236,6 +408,35 @@ struct SetundefPass : public Pass {
}
module->rewrite_sigspecs(worker);
+
+ if (worker.next_bit_mode == MODE_ANYSEQ || worker.next_bit_mode == MODE_ANYCONST)
+ {
+ vector<SigSpec*> siglist;
+ siglist.swap(worker.siglist);
+
+ for (auto sigptr : siglist)
+ {
+ SigSpec &sig = *sigptr;
+ int cursor = 0;
+
+ while (cursor < GetSize(sig))
+ {
+ int width = 0;
+ while (cursor+width < GetSize(sig) && sig[cursor+width] == State::Sx)
+ width++;
+
+ if (width > 0) {
+ 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++;
+ }
+ }
+ }
+ }
}
}
} SetundefPass;