Corrections to option -expose in setundef pass
authorAman Goel <amangoel@umich.edu>
Mon, 14 May 2018 00:13:54 +0000 (20:13 -0400)
committerAman Goel <amangoel@umich.edu>
Mon, 14 May 2018 00:13:54 +0000 (20:13 -0400)
passes/cmds/setundef.cc

index 172b1c3f8d7ef27e2d062b74ef48bcbca775880e..0825cf83ed02dadf6747679853231077a4f91e18 100644 (file)
 USING_YOSYS_NAMESPACE
 PRIVATE_NAMESPACE_BEGIN
 
+static RTLIL::Wire * add_wire(RTLIL::Design *design, RTLIL::Module *module, std::string name, int width, bool flag_input, bool flag_output, bool flag_global)
+{
+  RTLIL::Wire *wire = NULL;
+  name = RTLIL::escape_id(name);
+
+  if (module->count_id(name) != 0)
+  {
+    if (module->wires_.count(name) > 0)
+      wire = module->wires_.at(name);
+
+    if (wire != NULL && wire->width != width)
+      wire = NULL;
+
+    if (wire != NULL && wire->port_input != flag_input)
+      wire = NULL;
+
+    if (wire != NULL && wire->port_output != flag_output)
+      wire = NULL;
+
+    if (wire == NULL) {
+      return wire;
+      log_cmd_error("Found incompatible object %s with same name in module %s!\n", name.c_str(), module->name.c_str());
+    }
+
+    log("Module %s already has such an object %s.\n", module->name.c_str(), name.c_str());
+  }
+  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());
+  }
+
+  if (!flag_global)
+    return wire;
+
+  for (auto &it : module->cells_)
+  {
+    if (design->modules_.count(it.second->type) == 0)
+      continue;
+
+    RTLIL::Module *mod = design->modules_.at(it.second->type);
+    if (!design->selected_whole_module(mod->name))
+      continue;
+    if (mod->get_bool_attribute("\\blackbox"))
+      continue;
+    if (it.second->hasPort(name))
+      continue;
+
+    it.second->setPort(name, wire);
+    log("Added connection %s to cell %s.%s (%s).\n", name.c_str(), module->name.c_str(), it.first.c_str(), it.second->type.c_str());
+  }
+
+  return wire;
+}
+
+
 struct SetundefWorker
 {
        int next_bit_mode;
@@ -178,31 +242,92 @@ 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)
+              for (auto bit : sigmap(wire))
+                if (bit.wire) used_wires.insert(bit);
+          }
 
-                               for (auto &it : module->wires_)
-                                       undriven_signals.add(sigmap(it.second));
+          pool<RTLIL::Wire*> undriven_wires;
+          for (auto bit : used_wires) {
+            if (!wire_drivers.count(bit)) {
+              undriven_wires.insert(bit.wire);
+            }
+          }
 
-                               for (auto &it : module->wires_)
-                                       if (it.second->port_input)
-                                               undriven_signals.del(sigmap(it.second));
+          for (auto &it : undriven_wires)
+            undriven_signals.add(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));
+          for (auto &it : undriven_wires)
+            if (it->port_input)
+              undriven_signals.del(sigmap(it));
 
-                               RTLIL::SigSpec sig = undriven_signals.export_all();
-        if (expose_mode) {
+          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()) {
-            c.wire->port_input = true;
-            log("New module port: %s/%s\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(c.wire->name));
+            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(design, module, name, c.width, true, false, false);
+              module->connect(RTLIL::SigSig(c.wire, 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_)
+            undriven_signals.add(sigmap(it.second));
+
+          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;
             for (int i = 0; i < c.width; i++)