diff options
Diffstat (limited to 'passes/cmds/setundef.cc')
-rw-r--r-- | passes/cmds/setundef.cc | 263 |
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; |