@Override
  public void visit(Design des) {
    final GenericJob gj = EngineThread.getGenericJob();
    final boolean allowDPLutMem =
        gj.getUnscopedBooleanOptionValue(OptionRegistry.ALLOW_DUAL_PORT_LUT);

    memToAcc = new HashMap<LogicalMemory, Set<MemoryAccessBlock>>();
    super.visit(des);
    for (LogicalMemory mem : memToAcc.keySet()) {
      boolean readOnlyPort = false;
      if (!allowDPLutMem && mem.getImplementation().isLUT()) {
        continue;
      }
      if (allowDPLutMem && mem.getImplementation().isLUT()) {
        readOnlyPort = true;
      }

      // Find one task with more than one access. If the memory
      // implementation
      // has one port as read-only, then ensure that the found task has at
      // least
      // one read.
      boolean validForDualPorting = false;
      for (Set<MemoryAccessBlock> mabs : taskToAcc.get(mem).values()) {
        if (mabs.size() < 2) {
          continue;
        }

        if (readOnlyPort) {
          for (MemoryAccessBlock mab : mabs) {
            if (mab.getMemoryAccess().isReadAccess()) {
              validForDualPorting = true;
              break;
            }
          }
        } else {
          validForDualPorting = true;
          break;
        }
      }

      if (validForDualPorting) {
        if (mem.getLogicalMemoryPorts().size() < 2) {
          mem.createLogicalMemoryPort();
          String id = mem.getSourceName() == null ? mem.toString() : mem.getSourceName();
          gj.info("Created a second memory port for " + id);
        }
        gj.info("\tReallocating accesses to memory");

        // Do the re-allocation by task so that multiple accesses in a
        // task are split across the dual ports
        Map<Task, Set<MemoryAccessBlock>> accessMap = taskToAcc.get(mem);
        for (Set<MemoryAccessBlock> accesses : accessMap.values()) {
          for (MemoryAccessBlock mab : accesses) {
            mem.removeAccessor(mab);
          }
          Iterator<LogicalMemoryPort> portIter = mem.getLogicalMemoryPorts().iterator();
          LogicalMemoryPort port1 = portIter.next();
          LogicalMemoryPort port2 = portIter.next();

          boolean evenReadOnly = false;
          if (mem.getImplementation().isLUT()) {
            final boolean port1readOnly = port1.isReadOnly();
            final boolean port2readOnly = port2.isReadOnly();
            assert port1readOnly || port2readOnly
                : "LUT memories must have at least 1 read only port";

            evenReadOnly = true;
            if (!port1readOnly) {
              // Port 2 must be read only, thus switch them.
              LogicalMemoryPort p = port2;
              port2 = port1;
              port1 = p;
            }
          }

          boolean even = true;
          for (MemoryAccessBlock mab : accesses) {
            if (even) {
              if (evenReadOnly && !mab.getMemoryAccess().isReadAccess()) {
                port2.addAccess(mab);
                // dont switch 'even' since we've not yet added
                // to port 1
              } else {
                port1.addAccess(mab);
                even = !even;
              }
            } else {
              port2.addAccess(mab);
              even = !even;
            }
          }
        }
      }
    }
  }
 @Override
 public void visit(Task task) {
   currentTask = task;
   super.visit(task);
 }