/**
   * Return a list of source ports connected to this port on the same layer that can send data to
   * this port. This includes output ports that are connected on the outside to this port, and input
   * ports that are connected on the inside to this port.
   *
   * @param input TypedIOPort
   * @return A list of IOPort objects.
   */
  private LinkedList _shallowSourcePortList(TypedIOPort input) {
    try {
      _workspace.getReadAccess();

      Actor container = (Actor) input.getContainer();
      Director excDirector = ((Actor) container).getExecutiveDirector();
      int depthOfContainer = ((NamedObj) container).depthInHierarchy();
      LinkedList result = new LinkedList();
      Iterator ports = input.connectedPortList().iterator();

      while (ports.hasNext()) {
        IOPort port = (IOPort) ports.next();
        int depth = port.depthInHierarchy();

        if (port.isInput() && (depth <= depthOfContainer)) {
          result.addLast(port);
        } else if (port.isOutput() && (depth == (depthOfContainer + 1))) {
          result.addLast(port);
        }
      }

      return result;
    } finally {
      _workspace.doneReading();
    }
  }
Exemple #2
0
  /**
   * Return true if the receiver containing this boundary detector is contained on the outside of a
   * boundary port. A boundary port is an opaque port that is contained by a composite actor. If the
   * containing receiver is contained on the outside of a boundary port then return true; otherwise
   * return false. This method is not synchronized so the caller should be.
   *
   * @return True if the containing receiver is contained on the outside of a boundary port; return
   *     false otherwise.
   */
  public boolean isOutsideBoundary() {
    if (_outsideBoundaryCacheIsOn) {
      return _isInsideBoundaryValue;
    } else {
      IOPort innerPort = _receiver.getContainer();

      if (innerPort == null) {
        _outsideBoundaryCacheIsOn = false;
        _isOutsideBoundaryValue = false;
        return _isOutsideBoundaryValue;
      }

      ComponentEntity innerEntity = (ComponentEntity) innerPort.getContainer();

      if ((innerEntity != null) && !innerEntity.isAtomic() && innerPort.isOpaque()) {
        // The containing receiver is contained by the port
        // of a composite actor.
        if (innerPort.isOutput() && !innerPort.isInput()) {
          _isOutsideBoundaryValue = false;
        } else if (!innerPort.isOutput() && innerPort.isInput()) {
          _isOutsideBoundaryValue = true;
        } else if (!innerPort.isOutput() && !innerPort.isInput()) {
          _isOutsideBoundaryValue = false;
        } else {
          // CONCERN: The following only works if the port
          // is not both an input and output.
          throw new IllegalArgumentException(
              "A port that "
                  + "is both an input and output can not be "
                  + "properly dealt with by "
                  + "PNQueueReceiver.isInsideBoundary");
        }

        _outsideBoundaryCacheIsOn = true;
        return _isOutsideBoundaryValue;
      }

      _outsideBoundaryCacheIsOn = true;
      _isOutsideBoundaryValue = false;
      return _isOutsideBoundaryValue;
    }
  }
Exemple #3
0
  /**
   * Return the buffer size of a given channel (i.e, a given port and a given channel number). The
   * default value is 1. If the port is an output port, then the buffer size is obtained from the
   * inside receiver. If it is an input port, then it is obtained from the specified port.
   *
   * @param port The given port.
   * @param channelNumber The given channel number.
   * @return The buffer size of the given channel.
   * @exception IllegalActionException If the channel number is out of range or if the port is
   *     neither an input nor an output.
   */
  public int getBufferSize(IOPort port, int channelNumber) throws IllegalActionException {
    Receiver[][] receivers = null;

    if (port.isInput()) {
      receivers = port.getReceivers();
    } else if (port.isOutput()) {
      receivers = port.getInsideReceivers();
    }
    // else {
    // throw new IllegalActionException(port,
    // "Port is neither an input nor an output.");
    // }

    // try {
    int size = 0;

    for (int copy = 0; copy < receivers[channelNumber].length; copy++) {
      int copySize = ((SDFReceiver) receivers[channelNumber][copy]).getCapacity();

      if (copySize > size) {
        size = copySize;
      }

      // When an output port of a composite actor is directly
      // connected to an input port of the same composite actor,
      // calling getCapacity() will return 0. Therefore we use
      // the rate to determine the buffer size.
      if (port.isOutput()) {
        copySize = DFUtilities.getRate(port);
        if (copySize > size) {
          size = copySize;
        }
      }
    }

    return size;
    // }
    // catch (ArrayIndexOutOfBoundsException ex) {
    // throw new IllegalActionException(port, "Channel out of bounds: "
    // + channelNumber);
    // }
  }
  /**
   * Create a guarded communication with a send communication. This constructor allows actors which
   * are not CSPActors access to CSP functionality by providing their own
   * ConditionalBranchController.
   *
   * @param guard The guard for the guarded communication statement represented by this object.
   * @param port The IOPort containing the channel (and thus receiver) that this branch will try to
   *     rendezvous with.
   * @param channel The channel in the IOPort that this branch is trying to rendezvous with.
   * @param branchID The identification number assigned to this branch upon creation by the
   *     CSPActor.
   * @param token The token this branch is trying to send.
   * @param controller The controller that this branch uses.
   * @exception IllegalActionException If the channel has more than one receiver or if the receiver
   *     is not of type CSPReceiver.
   */
  public ConditionalSend(
      boolean guard,
      IOPort port,
      int channel,
      int branchID,
      Token token,
      ConditionalBranchController controller)
      throws IllegalActionException {
    super(guard, port, branchID, controller);
    _port = port;
    _channel = channel;

    try {
      port.workspace().getReadAccess();

      if (!port.isOutput()) {
        throw new IllegalActionException(
            port, "ConditionalSend: " + "tokens only sent from an output port.");
      }

      if (channel >= port.getWidth() || channel < 0) {
        throw new IllegalActionException(port, "ConditionalSend: " + "channel index out of range.");
      }

      Receiver[][] receivers = port.getRemoteReceivers();

      if (receivers == null || receivers[channel] == null) {
        throw new IllegalActionException(
            port, "ConditionalSend: " + "Trying to rendezvous with null receiver");
      }
      if (!(receivers[channel][0] instanceof CSPReceiver)) {
        throw new IllegalActionException(
            port,
            "ConditionalSend: "
                + "channel "
                + channel
                + " does not have a receiver "
                + "of type CSPReceiver.");
      }
      _setReceivers(receivers[channel]);
    } finally {
      port.workspace().doneReading();
    }

    _setToken(token);
  }
Exemple #5
0
  /**
   * Return true if the receiver containing this boundary detector is connected to the outside of an
   * output boundary port; return false otherwise. A boundary port is an opaque port that is
   * contained by a composite actor. If the receiver containing this boundary detector is contained
   * on the inside of a boundary port, then return false. This method is not synchronized so the
   * caller should be.
   *
   * @return True if the containing receiver is connected to the outside of a boundary port; return
   *     false otherwise.
   * @exception IllegalActionException
   */
  public boolean isConnectedToBoundaryOutside() throws IllegalActionException {
    if (_connectedOutsideOfBoundaryCacheIsOn) {
      return _isConnectedOutsideOfBoundaryValue;
    } else {
      IOPort contPort = _receiver.getContainer();

      if (contPort == null) {
        _connectedOutsideOfBoundaryCacheIsOn = false;
        _isConnectedOutsideOfBoundaryValue = false;
        return _isConnectedOutsideOfBoundaryValue;
      }

      Iterator ports = contPort.connectedPortList().iterator();

      while (ports.hasNext()) {
        IOPort connectedPort = (IOPort) ports.next();
        ComponentEntity connectedEntity = (ComponentEntity) connectedPort.getContainer();

        if (connectedPort.isOpaque() && !connectedEntity.isAtomic() && connectedPort.isOutput()) {
          // The port container of this receiver is
          // connected to the outside of a boundary port.
          // Now determine if this receiver's channel is
          // connected to the boundary port.
          Receiver[][] receivers = connectedPort.getRemoteReceivers();

          for (int i = 0; i < receivers.length; i++) {
            for (int j = 0; j < receivers[i].length; j++) {
              if (_receiver == receivers[i][j]) {
                _connectedOutsideOfBoundaryCacheIsOn = true;
                _isConnectedOutsideOfBoundaryValue = true;
                return true;
              }
            }
          }
        }
      }

      _connectedOutsideOfBoundaryCacheIsOn = true;
      _isConnectedOutsideOfBoundaryValue = false;
      return _isConnectedOutsideOfBoundaryValue;
    }
  }
Exemple #6
0
  /**
   * Return the parameterized scheduling sequence. An exception will be thrown if the graph is not
   * schedulable.
   *
   * @return A schedule of the deeply contained opaque entities in the firing order.
   * @exception NotSchedulableException If a parameterized schedule cannot be derived for the model.
   * @exception IllegalActionException If the rate parameters of the model are not correct, or the
   *     computed rates for external ports are not correct.
   */
  @SuppressWarnings("unused")
  protected Schedule _getSchedule() throws NotSchedulableException, IllegalActionException {
    PSDFDirector director = (PSDFDirector) getContainer();
    CompositeActor model = (CompositeActor) director.getContainer();

    // Get the vectorization factor.
    String vectorizationFactorExpression = "1";

    String vectorizationName = director.vectorizationFactor.getName(model);
    vectorizationFactorExpression = vectorizationName.replaceAll("\\.", "::");

    if (vectorizationFactorExpression.indexOf(" ") != -1) {
      throw new InternalErrorException(
          "The vectorizationFactor "
              + "PSDFDirector parameter must "
              + "not have spaces in its value.  The original value "
              + "was \""
              + vectorizationName
              + "\". Try changing the name of "
              + "director.");
    }

    PSDFGraphReader graphReader = new PSDFGraphReader();
    PSDFGraph graph = (PSDFGraph) graphReader.convert(model);
    _debug("PSDF graph = \n" + graph.toString());

    if (_debugFlag) {
      graph.printEdgeRateExpressions();
    }

    PSDFAPGANStrategy strategy = new PSDFAPGANStrategy(graph);
    ptolemy.graph.sched.Schedule graphSchedule = strategy.schedule();
    _debug("P-APGAN schedule = \n" + graphSchedule.toString());

    SymbolicScheduleElement resultSchedule =
        _expandAPGAN(graph, strategy.getClusterManager().getRootNode(), strategy);
    resultSchedule.setIterationCount(vectorizationFactorExpression);

    _debug("Final schedule = \n" + resultSchedule.toString());

    if (_debugging) {
      _debug("The buffer size map:\n");

      Iterator relations = _bufferSizeMap.keySet().iterator();

      while (relations.hasNext()) {
        Relation relation = (Relation) relations.next();
        _debug(relation.getName() + ": " + _bufferSizeMap.get(relation) + "\n");
      }
    }

    _saveBufferSizes(_bufferSizeMap);

    // Crazy hack to infer firing counts for each actor.
    try {
      _inferFiringCounts(resultSchedule, null);
    } catch (NameDuplicationException ex) {
      throw new NotSchedulableException(new LinkedList(), ex, "Error recording firing counts");
    }

    // Crazy hack to Infer port production: FIXME: This should be
    // done as part of the APGAN expansion where the rates of
    // external ports are unknown The reason is that it will make
    // rate information propagate from an actor input port to
    // another actors input port that are connected on the inside
    // to the same external input port.  See
    // BaseSDFScheduler.setContainerRates.
    Iterator ports = model.portList().iterator();

    while (ports.hasNext()) {
      IOPort port = (IOPort) ports.next();

      if (_debugging && VERBOSE) {
        _debug("External Port " + port.getName());
      }

      if (port.isInput() && port.isOutput()) {
        throw new NotSchedulableException(
            port,
            "External port is both an input and an output, " + "which is not allowed in SDF.");
      } else if (port.isInput()) {
        List sinks = port.insideSinkPortList();

        if (sinks.size() > 0) {
          IOPort connectedPort = (IOPort) sinks.get(0);
          Entity entity = (Entity) connectedPort.getContainer();
          String name = connectedPort.getName(model);
          String identifier = name.replaceAll("\\.", "::");

          String sinkExpression;
          Variable sinkRateVariable =
              DFUtilities.getRateVariable(connectedPort, "tokenConsumptionRate");

          if (sinkRateVariable == null) {
            sinkExpression = "1";
          } else {
            sinkExpression = identifier + "::" + sinkRateVariable.getName();
          }

          String expression = sinkExpression + " * " + entity.getName() + "::firingsPerIteration";

          DFUtilities.setExpressionIfNotDefined(port, "tokenConsumptionRate", expression);

          if (_debugging && VERBOSE) {
            _debug("Setting tokenConsumptionRate to " + expression);
          }
        }
      } else if (port.isOutput()) {
        List sources = port.insideSourcePortList();

        if (sources.size() > 0) {
          IOPort connectedPort = (IOPort) sources.get(0);
          Entity entity = (Entity) connectedPort.getContainer();
          String name = connectedPort.getName(model);
          String identifier = name.replaceAll("\\.", "::");
          Variable sourceRateVariable =
              DFUtilities.getRateVariable(connectedPort, "tokenProductionRate");
          String sourceExpression;

          if (sourceRateVariable == null) {
            sourceExpression = "1";
          } else {
            sourceExpression = identifier + "::" + sourceRateVariable.getName();
          }

          String expression = sourceExpression + " * " + entity.getName() + "::firingsPerIteration";

          DFUtilities.setExpressionIfNotDefined(port, "tokenProductionRate", expression);

          if (_debugging && VERBOSE) {
            _debug("Setting tokenProductionRate to " + expression);
          }
        }

        // Infer init production.
        // Note that this is a very simple type of inference...
        // However, in general, we don't want to try to
        // flatten this model...
        //  Iterator connectedPorts =
        //                     port.insideSourcePortList().iterator();
        //                 IOPort foundOutputPort = null;
        //                 int inferredRate = 0;
        //                 while (connectedPorts.hasNext()) {
        //                     IOPort connectedPort = (IOPort) connectedPorts.next();
        //                     int newRate;
        //                     if (connectedPort.isOutput()) {
        //                         newRate =
        //                             DFUtilities.getTokenInitProduction(connectedPort);
        //                     } else {
        //                         newRate = 0;
        //                     }
        //                     // If we've already set the rate, then check that the
        //                     // rate for any other internal port is correct.
        //                     if (foundOutputPort != null &&
        //                             newRate != inferredRate) {
        //                         throw new NotSchedulableException(
        //                                 "External output port " + port
        //                                 + " is connected on the inside to ports "
        //                                 + "with different initial production: "
        //                                 + foundOutputPort + " and "
        //                                 + connectedPort);
        //                     }
        //                     foundOutputPort = connectedPort;
        //                     inferredRate = newRate;
        //                 }
        //                 DFUtilities._setIfNotDefined(
        //                         port, "tokenInitProduction", inferredRate);
        //                 if (_debugging && VERBOSE) {
        //                     _debug("Setting tokenInitProduction to "
        //                             + inferredRate);
        //                 }
      } else {
        throw new NotSchedulableException(
            port,
            "External port is neither an input and an output, " + "which is not allowed in SDF.");
      }
    }

    // Set the schedule to be valid.
    setValid(true);

    if (resultSchedule instanceof Schedule) {
      return (Schedule) resultSchedule;
    } else {
      // Must be ScheduleElement.
      Schedule schedule = new Schedule();
      schedule.add((ScheduleElement) resultSchedule);
      return schedule;
    }
  }
  /**
   * Interconnect all the remote actors in the same manner as the model's topology. In other words,
   * the connections defined by the model's topology are created virtually over the distributed
   * platform. For each actor, a portReceiverMap is created. A portReceiverMap is a data structure
   * representing for a given port the receivers it contains. In case the port is and input port it
   * consists of a set of receivers ID's i.e. (inputport, (ID1, ..., IDn). In case of an outputport,
   * it contains a map of services to receiver's IDs, i.e. (outputport, ((service1, (ID1, ..., IDi),
   * ..., (servicen, (IDj, ..., IDr))). This structure is sent over the network to the corresponding
   * service. The types of the port are also set on the remote actor.
   *
   * @exception IllegalActionException If the remote receivers can't be created.
   */
  private void connectActors() throws IllegalActionException {
    if (VERBOSE) {
      System.out.println("Connecting Actors");
      System.out.println(">> Creating Ports Receivers Map: ");
    }

    for (Iterator keysIterator = actorsThreadsMap.keySet().iterator(); keysIterator.hasNext(); ) {
      ComponentEntity actor = (ComponentEntity) keysIterator.next();

      HashMap portsReceiversMap = new HashMap();
      HashMap portTypes = new HashMap();

      Iterator allPorts = actor.portList().iterator();

      while (allPorts.hasNext()) {
        IOPort currentPort = (IOPort) allPorts.next();
        Receiver[][] receivers = new Receiver[0][0];

        if (currentPort.isOutput()) {
          receivers = currentPort.getRemoteReceivers();
        }

        if (currentPort.isInput()) {
          receivers = currentPort.getReceivers();
        }

        if (!currentPort.connectedPortList().isEmpty()) {
          portTypes.put(currentPort.getName(), ((TypedIOPort) currentPort).getType());
        }

        if (receivers.length > 0) {
          if (VERBOSE) {
            System.out.print(
                "Port: "
                    + currentPort.getFullName()
                    + "\n"
                    + DistributedUtilities.receiversArrayToString(receivers));
          }

          if (currentPort.isOutput()) {
            portsReceiversMap.put(currentPort.getName(), createServicesReceiversMap(receivers));
          }

          if (currentPort.isInput()) {
            portsReceiversMap.put(
                currentPort.getName(), DistributedUtilities.convertReceiversToIntegers(receivers));
          }
        }
      }

      ServiceItem server = ((ClientThread) actorsThreadsMap.get(actor)).getService();
      DistributedActor distributedActor = (DistributedActor) server.service;

      try {
        if (VERBOSE) {
          System.out.println(
              "Setting connections to: "
                  + actor.getFullName()
                  + " in: "
                  + server.serviceID.toString());
          System.out.println(
              "Setting port Types: " + actor.getFullName() + " in: " + server.serviceID.toString());
        }

        distributedActor.setConnections(portsReceiversMap);
        distributedActor.setPortTypes(portTypes);
      } catch (RemoteException e) {
        KernelException.stackTraceToString(e);
      }
    }
  }