/** Responsible for traversing within a Call */
 @Override
 protected void traverse(Call node) {
   if (_schedule.db) _schedule.ln(_schedule.GDA, "Traversing Call " + node);
   if (node.getProcedure() != null) {
     node.getProcedure().accept(this);
   }
 }
Beispiel #2
0
  /**
   * DOCUMENT ME!
   *
   * @param call DOCUMENT ME!
   */
  @Override
  public void visit(Call call) {
    if (_schedule.db) {
      _schedule.ln(_schedule.GVISIT, "visiting call " + call);
    }

    beginFrame();
    call.getProcedure().accept(this);
    ConnectionFrame procedureFrame = endFrame();

    // record duplicates of the procedure's connections
    // Some connections contain the same buses (done & address)
    // which we only want 1 new port for not multiples...
    Map<ID, ID> duplicatedMap = new HashMap<ID, ID>();
    // for (Iterator resources =
    // procedureFrame.getConnectedResources().iterator();
    // resources.hasNext();)
    // {
    // Resource resource = (Resource)resources.next();
    for (Resource resource : procedureFrame.getConnectedResources()) {
      Collection<Connection> readConnections = procedureFrame.getReadConnections(resource);
      for (Connection read : readConnections) {
        Connection duplicate = read.duplicate(call, duplicatedMap);
        mapPortsAndBuses(call, duplicate, read);
        recordRead(duplicate, call);
      }

      Collection<Connection> writeConnections = procedureFrame.getWriteConnections(resource);
      for (Connection write : writeConnections) {
        Connection duplicate = write.duplicate(call, duplicatedMap);
        mapPortsAndBuses(call, duplicate, write);
        recordWrite(duplicate, call);
      }
    }
  }
Beispiel #3
0
 private InputPin connectInputPin(Design design, Call call, Port port, String name) {
   Port procedurePort = call.getProcedurePort(port);
   InputPin pin = new InputPin(procedurePort);
   port.setBus(pin.getBus());
   IDSourceInfo info =
       (name != null)
           ? call.getProcedure().getIDSourceInfo().deriveField(name, -1, -1)
           : procedurePort.getIDSourceInfo();
   pin.setIDSourceInfo(info);
   Bus pinBus = pin.getBus();
   pinBus.setUsed(true);
   port.setBus(pinBus);
   design.addInputPin(pin, port);
   return pin;
 }
Beispiel #4
0
  private void generateKickers() {
    final GenericJob job = EngineThread.getGenericJob();
    final boolean blockIO = !job.getUnscopedBooleanOptionValue(OptionRegistry.NO_BLOCK_IO); // If
    // Do
    // BlockIO
    final boolean doBlockSched =
        !job.getUnscopedBooleanOptionValue(OptionRegistry.SCHEDULE_NO_BLOCK_SCHEDULING);
    final boolean moduleBuilder =
        EngineThread.getGenericJob().getUnscopedBooleanOptionValue(OptionRegistry.MODULE_BUILDER);

    final Map<String, Kicker> kickers = new HashMap<String, Kicker>();
    for (Task task : design.getTasks()) {
      final Call call = task.getCall();
      final String domainSpec =
          (String)
              ((OptionString) EngineThread.getGenericJob().getOption(OptionRegistry.CLOCK_DOMAIN))
                  .getValue(call.getSearchLabel());

      if (!task.isKickerRequired()) {
        // Ensure that the Go port is validly connected
        if (!call.getGoPort().isConnected()) {
          job.warn("Task " + call.showIDLogical() + " is not autostart and has no enabling signal");
          Constant constant = new SimpleConstant(0, 1, false);
          constant.pushValuesForward();
          call.getGoPort().setBus(constant.getValueBus());
          call.getGoPort().pushValueForward();
        }
        continue;
      }

      Kicker kicker;
      final String kickerKey;
      if (doBlockSched && !moduleBuilder) {
        // Connect up a KickerContinuous that will keep us running at
        // max rate indefinately. We expect only one task in block
        // io, but if we have more than one, we need individual
        // kickers so that we use the right clock/reset for each.
        kicker = new Kicker.KickerContinuous();
        // Use the kickers string b/c there will be a (unique)
        // feedback from the task done
        kickerKey = kicker.toString();
      } else if (blockIO) {
        boolean fbRequired = checkFeedback(call.getProcedure().getBody());
        // System.out.println("Generated perpetual kicker withT/withoutF "
        // + fbRequired + " feedback flop required");
        // Connect up a KickerPerpetual that will keep us running
        // indefinately. We expect only one task in block io, but
        // if we have more than one, each needs its own kicker
        // anyway (since we OR back in the done). We could use
        // just one kicker for all and put the OR external but
        // there is no Design level module to put this stuff in.
        // Argh!
        kicker = new Kicker.KickerPerpetual(fbRequired);
        // Use the kickers string b/c there will be a (unique)
        // feedback from the task done
        kickerKey = kicker.toString();
      } else {
        if (moduleBuilder) {
          continue;
        }

        // find a kicker that matches this calls clk and reset
        // kickerKey = call.getClockName() + call.getResetName();
        kickerKey = domainSpec;
        kicker = kickers.get(kickerKey);
        // if we didn't find it, construct a new one
        if (kicker == null) {
          kicker = new Kicker();
        }
      }
      if (!kickers.containsKey(kickerKey)) {
        kickers.put(kickerKey, kicker);
        design.addComponentToDesign(kicker);
        design.getClockDomain(domainSpec).connectComponentToDomain(kicker);
      }

      if (call.getGoPort().isUsed()) {
        call.getGoPort().setBus(kicker.getDoneBus());
      }

      if (kicker.getRepeatPort() != null) {
        Bus callDone = call.getExit(Exit.DONE).getDoneBus();
        if (!callDone.isUsed()) {
          // there is the off-chance that it has fixed timing
          // and thus needs no done. Create a sequence of flops
          // to bypass.
          if (!call.getLatency().isFixed()) {
            EngineThread.getEngine()
                .fatalError(
                    "Unexpected internal state.  Design does not have a control structure and has variable timing");
          }
          Bus done = kicker.getDoneBus();
          for (int i = 0; i < call.getLatency().getMinClocks(); i++) {
            // Needs RESET b/c it is in the control path
            Reg flop = Reg.getConfigurableReg(Reg.REGR, ID.showLogical(call) + "_go_done_" + i);
            design.getClockDomain(domainSpec).connectComponentToDomain(flop);
            flop.getInternalResetPort().setBus(flop.getResetPort().getBus());
            flop.getDataPort().setBus(done);
            // Ensure that we've constant propagated the flop
            flop.propagateValuesForward();
            done = flop.getResultBus();
            design.addComponentToDesign(flop);
          }
          callDone = done;
        }
        kicker.getRepeatPort().setBus(callDone);
      }
    }
  }
Beispiel #5
0
  /**
   * Creates Pins on the design to connect each task's I/O.
   *
   * @param design the Design to be connected
   */
  @SuppressWarnings("deprecation")
  private void connectTasks(Design design) {
    // Map kickers = new HashMap();

    for (Task task : design.getTasks()) {
      Call call = task.getCall();

      // Note: when creating the InputPins, they are based on the related
      // procedure port instead of the call port, because the InputPin
      // needs
      // the Port's peer bus to get sizing information

      // might have a this port
      if (task.getCall().getThisPort() != null) {
        int width = task.getCall().getThisPort().getValue().getSize();

        /*
         * The base address of the top level object reference is always
         * 0, since it isn't actually stored in memory.
         */
        Constant constant = new SimpleConstant(0, width, false);
        task.setHiddenConstant(constant);
      }

      // If module_builder, then publish the ports, and don't use a kicker
      if (EngineThread.getGenericJob()
          .getUnscopedBooleanOptionValue(OptionRegistry.MODULE_BUILDER)) {
        // get the entry method
        EntryMethod em = call.getProcedure().getEntryMethod();

        Port go = call.getGoPort();
        if (go.isUsed()) {
          Pin p = connectInputPin(design, call, go, call.getGoName());
          if (em != null) {
            p.setApiPin(em.getGoPin());
          }
        }

        List<Port> dataPorts = new ArrayList<Port>(call.getDataPorts());

        // 'this' port is handled specially.
        dataPorts.remove(call.getThisPort());
        int index = 0;
        for (Port port : dataPorts) {
          if (port.getTag().equals(Component.NORMAL)) {
            if (port.isUsed()) {
              Pin p = connectInputPin(design, call, port, null);
              if (em != null) {
                p.setApiPin(em.getArgPin(index));
              }
            }
          }

          index++;
        }

        Exit exit = call.getExit(Exit.DONE);
        Bus done = exit.getDoneBus();
        if (done.isUsed()) {
          OutputPin pin = connectOutputPin(design, call, done, call.getProcedure().getDoneName());
          if (em != null) {
            pin.setApiPin(em.getDonePin());
          }
        }

        for (Bus bus : exit.getDataBuses()) {
          if (bus.getTag().equals(Component.NORMAL)) {
            if (bus.isUsed()) {
              OutputPin pin =
                  connectOutputPin(design, call, bus, call.getProcedure().getResultName());
              if (em != null) {
                pin.setApiPin(em.getResultPin());
              }
            }
          }
        }
      }
    }
  }