private void handleFirstRX(SinkData channel, Time currentTime) throws NoTokenException, IllegalActionException { // Method to handle the first stage, receiving the first synchronisation pulse IntToken token = (IntToken) input.get(0); // Retrieve the token from the input Time timeDelta = currentTime.subtract( waitTime); // Calculate a delta between the current time and when the channel was // changed, to find the waiting time if (timeDelta.getDoubleValue() <= 1.5 && token.equals( 1)) { // Token is 1, and we have been waiting for longer than 1.5s. So we will not have // a follow-up token, so can't be used for determining t channelQueue .remove(); // Send the current channel to the back of the queue so we can do something // useful while it is in its sleep state channelQueue.add(currentChannel); return; } if (!channel .secondRun) { // If this is the first time we have received packets on the channel we will // need the current time to calculate a t channel.t = currentTime; } channel.state = states.SECONDRX; // Set the channel state to the next stage channel.firstValue = token.intValue(); // Store the value we have received System.out.println("FIRSTRX on channel " + currentChannel + " currentTime is " + currentTime); }
/** * If the argument is the meanTime parameter, check that it is positive. * * @param attribute The attribute that changed. * @exception IllegalActionException If the meanTime value is not positive. */ @Override public void attributeChanged(Attribute attribute) throws IllegalActionException { if (attribute == meanTime) { double mean = ((DoubleToken) meanTime.getToken()).doubleValue(); if (mean <= 0.0) { throw new IllegalActionException( this, "meanTime is required to be positive. meanTime given: " + mean); } } else if (attribute == values) { ArrayToken val = (ArrayToken) values.getToken(); $ASSIGN$_length(val.length()); } else if (attribute == stopTime) { double newStopTimeValue = ((DoubleToken) stopTime.getToken()).doubleValue(); if (_executing) { Time newStopTime = new Time(getDirector(), newStopTimeValue); Director director = getDirector(); if (director != null) { Time currentTime = director.getModelTime(); if (newStopTime.compareTo(currentTime) > 0) { director.fireAt(this, newStopTime); } else { throw new IllegalActionException( this, "The stop time " + "is earlier than the current time."); } } $ASSIGN$_stopTime(newStopTime); } } else { super.attributeChanged(attribute); } }
private void handleFirstTX(SinkData channel, Time currentTime) throws NoRoomException, IllegalActionException { // Method to handle the third stage, transmitting the first packet to a sink IntToken token = new IntToken(currentChannel); // Create a token to send output.send(0, token); // Send the token if (channel.n != null) { // If we have already calculated n in a previous stage (if n is 1) we can skip // straight to the next transmission period setNextFireTime(channel, currentTime.getDoubleValue() + (channel.t.getDoubleValue() * 12)); channel.state = states.SECONDTX; } else { // If we do not know n then we need to next fire at the beginning of the next // synchronisation phase so we can receive the first pulse and find n setNextFireTime( channel, currentTime.getDoubleValue() + (channel.t.getDoubleValue() * 11) - 0.02); channel.state = states.NCALC; } System.out.println( "FIRSTTX on channel " + currentChannel + ". t is " + channel.t + ". nextFireTime is " + channel.nextFireTime + " currentTime is " + currentTime); }
/** * Request the first firing either at the start time or at a random time, depending on * <i>fireAtStart</i>. * * @exception IllegalActionException If the fireAt() method of the director throws it, or if the * director does not agree to fire the actor at the specified time. */ @Override public void initialize() throws IllegalActionException { super.initialize(); Director director = getDirector(); if (director == null) { throw new IllegalActionException(this, "No director!"); } double stopTimeValue = ((DoubleToken) stopTime.getToken()).doubleValue(); $ASSIGN$_stopTime(new Time(getDirector(), stopTimeValue)); Time currentTime = director.getModelTime(); if (!_stopTime.isInfinite() && _stopTime.compareTo(currentTime) > 0) { director.fireAt(this, _stopTime); $ASSIGN$_executing(true); } $ASSIGN$_nextOutputIndex(0); $ASSIGN$_nextFiringTime(currentTime); $ASSIGN$_outputProduced(false); if (((BooleanToken) fireAtStart.getToken()).booleanValue()) { _fireAt(currentTime); } else { _generateRandomNumber(); $ASSIGN$_nextFiringTime(director.getModelTime().add(_current)); _fireAt(_nextFiringTime); } }
/** * If this firing is triggered by an event at <i>waitee</i>, then output the waiting time for each * prior event arrival at <i>waiter</i> since the last arrival of waitee. If there is no event at * <i>waitee</i>, then record the time of arrival of the events at <i>waiter</i>, and produce no * output. * * @exception IllegalActionException If get() or send() throws it. */ public void fire() throws IllegalActionException { super.fire(); Time currentTime = ((DEDirector) getDirector()).getModelTime(); while (waiter.hasToken(0)) { waiter.get(0); _waiting.addElement(currentTime); } boolean godot = false; while (waitee.hasToken(0)) { waitee.get(0); godot = true; } if (godot) { for (int i = 0; i < _waiting.size(); i++) { Time previousTime = (Time) _waiting.elementAt(i); DoubleToken outToken = new DoubleToken(currentTime.subtract(previousTime).getDoubleValue()); output.send(0, outToken); } _waiting.removeAllElements(); } }
/** * If the <i>stopTime</i> parameter is changed and the model is executing, then if the new value * is greater than zero and greater than the current time, then ask the director to fire this * actor at that time. If the new value is less than the current time, then request refiring at * the current time. * * @exception IllegalActionException If the superclass throws it. */ public void attributeChanged(Attribute attribute) throws IllegalActionException { if (attribute == stopTime) { double newStopTimeValue = ((DoubleToken) stopTime.getToken()).doubleValue(); if (_executing) { Time newStopTime = new Time(getDirector(), newStopTimeValue); Director director = getDirector(); if (director != null) { Time currentTime = director.getModelTime(); if (newStopTime.compareTo(currentTime) > 0) { director.fireAt(this, newStopTime); } else { throw new IllegalActionException( this, "The stop time " + "is earlier than the current time."); } } _stopTime = newStopTime; } } else { super.attributeChanged(attribute); } }
/** * Return false if the current time is greater than or equal to the <i>stopTime</i> parameter * value. Otherwise, return true. Derived classes should call this at the end of their postfire() * method and return its returned value. * * @exception IllegalActionException Not thrown in this base class. */ public boolean postfire() throws IllegalActionException { Time currentTime = getDirector().getModelTime(); if (currentTime.compareTo(_stopTime) >= 0) { return false; } return true; }
private void handleNCalc(SinkData channel, Time currentTime) throws NoTokenException, IllegalActionException { // Method to handle the fourth stage, where we listen to the first synchronisation pulse to find // the value of n System.out.println(channel.nextFireTime.getDoubleValue() >= currentTime.getDoubleValue() + 0.4); if (channel.nextFireTime.getDoubleValue() >= currentTime.getDoubleValue()) { input.get(0); return; } else if (channel .secondRun) { // If we are on the second run through, we have already transmitted twice so // we can stop here channel.state = states.FINISHED; return; } else if (currentTime.subtract(channel.nextFireTime).getDoubleValue() > 2) { // There is a large delta between when we were supposed to fire and when we fired, so // we probably have a collision with another channel channel.secondRun = true; // Store that we will need to go around again for this channel channel.state = states.FIRSTRX; // Set the stage back to the beginning so we can restart System.out.println( "NCALC on channel " + currentChannel + " n is: " + channel.n + ". t is " + channel.t + ". nextFireTime is " + channel.nextFireTime + " currentTime is " + currentTime); nextChannel(currentChannel, currentTime); } else { channel.n = ((IntToken) input.get(0)).intValue(); setNextFireTime( channel, currentTime.getDoubleValue() + (channel.t.getDoubleValue() * channel.n)); channel.state = states.SECONDTX; System.out.println( "NCALC on channel " + currentChannel + " n is: " + channel.n + ". t is " + channel.t + ". nextFireTime is " + channel.nextFireTime + " currentTime is " + currentTime); nextChannel(currentChannel, currentTime); removeFromQueue(currentChannel); } }
/** * If the current time matches the expected time for the next output, then return true. Also * return true if the trigger input is connected and has events. Otherwise, return false. * * @exception IllegalActionException If there is no director. */ @Override public boolean prefire() throws IllegalActionException { if (_debugging) { _debug("Called prefire()"); } for (int i = 0; i < trigger.getWidth(); i++) { if (trigger.isKnown() && trigger.hasToken(i)) { return true; } } Time currentTime = getDirector().getModelTime(); if (currentTime.compareTo(_nextFiringTime) == 0) { return true; } return false; }
private void nextChannel(int currentChannel, Time currentTime) throws IllegalActionException { System.out.println("NEXT CHANNEL at" + currentTime); removeFromQueue(currentChannel); channelQueue.add(currentChannel); nextChannel = channelQueue.peek(); changeChan = true; getDirector().fireAt(this, currentTime.add(0.0000001)); }
public void initialize() throws IllegalActionException { super.initialize(); init_tim = ((DoubleToken) initial_time.getToken()).doubleValue(); current_time = getDirector().getModelTime(); firstSend = current_time.add(init_tim); getDirector().fireAt(this, firstSend); // Get the simulation Stop time DEstop_time = getDirector().getModelStopTime(); stop_time = DEstop_time.getDoubleValue(); if (_debugging) _debug("GET STOP TIME: "); }
/** * If the current time matches one of the times that we have previously recorded as the reception * time for a transmission, then deliver the token to the receiver. * * @exception IllegalActionException If the _transmitTo() method of the base class throws it, i.e. * the token attribute of the reception cannot be converted or the token attribute is null and * the receiver attribute of the receptions does not support clear. */ public void fire() throws IllegalActionException { super.fire(); if (_receptions != null) { // We may be getting fired because of an impending event. Time currentTime = getDirector().getModelTime(); Double timeDouble = Double.valueOf(currentTime.getDoubleValue()); Reception reception = (Reception) _receptions.get(timeDouble); if (reception != null) { // The time matches a pending reception. _receptions.remove(timeDouble); // Use the superclass, not this class, or we just delay again. super._transmitTo( reception.token, reception.sender, reception.receiver, reception.properties); } } }
/** * Generate an exponential random number and schedule the next firing. * * @exception IllegalActionException If the director throws it when scheduling the next firing, or * if the director does not agree to fire the actor at the specified time. */ @Override public boolean postfire() throws IllegalActionException { boolean result = super.postfire(); Time currentTime = getDirector().getModelTime(); if (_outputProduced) { $ASSIGN$_outputProduced(false); $ASSIGN$SPECIAL$_nextOutputIndex(11, _nextOutputIndex); if (_nextOutputIndex >= _length) { $ASSIGN$_nextOutputIndex(0); } $ASSIGN$_nextFiringTime(currentTime.add(_current)); _fireAt(_nextFiringTime); } else if (currentTime.compareTo(_nextFiringTime) >= 0) { _fireAt(currentTime); } if (currentTime.compareTo(_stopTime) >= 0) { return false; } return result; }
/** * Transmit the specified token to the specified receiver with the specified properties. If * <i>propagationSpeed</i> is less than Infinity, then this results in a call to fireAt() of the * director for each receiver that is in range. The token is not actually transmitted to the * receiver until the corresponding invocation of fire() occurs. The time delay is equal to * distance/<i>propagationSpeed</i>. See the class comments for the assumptions that make this * correct. * * <p>If the <i>lossProbability</i> is zero, (the default) then the specified receiver will * receive the token if it has room. If <i>lossProbability</i> is greater than zero, the token * will be lost with the specified probability, independently for each receiver in range. Note * that in this base class, a port is in range if it refers to this channel by name and is at the * right place in the hierarchy. This base class makes no use of the properties argument. But * derived classes may limit the range or otherwise change transmission properties using this * argument. * * @param token The token to transmit, or null to clear the specified receiver. * @param sender The sending port. * @param receiver The receiver to which to transmit. * @param properties The transmit properties (ignored in this base class). * @exception IllegalActionException If the token cannot be converted or if the token argument is * null and the destination receiver does not support clear. */ protected void _transmitTo( Token token, WirelessIOPort sender, WirelessReceiver receiver, RecordToken properties) throws IllegalActionException { double speed = ((DoubleToken) propagationSpeed.getToken()).doubleValue(); if (speed == Double.POSITIVE_INFINITY) { super._transmitTo(token, sender, receiver, properties); } else { Director director = getDirector(); // FIXME: This isn't right because the receiver // may have moved during propagation. Maybe // register a ValueListener to the _location attributes // of the receiver actors, and continually recalculate // the correct arrival time for the message each time the // receiver location changes. Even so, this will be // an approximation, and needs to be fully characterized. // Also, the receiver needs to be in range at the // conclusion of the propagation, whereas this method is // called only if the receiver is in range at the // initiation of the transmission. WirelessIOPort destination = (WirelessIOPort) receiver.getContainer(); double distance = _distanceBetween(sender, destination); Time time = director.getModelTime().add(distance / speed); if (_receptions == null) { _receptions = new HashMap(); } Double timeDouble = Double.valueOf(time.getDoubleValue()); Reception reception = new Reception(); reception.token = token; reception.sender = sender; reception.receiver = receiver; reception.properties = properties; _receptions.put(timeDouble, reception); _fireAt(time); } }
private void handleSecondRX(SinkData channel, Time currentTime) throws NoTokenException, IllegalActionException { // Method to handle the second stage, receiving the second synchronisation pulse if (!channel .secondRun) { // If this is the second time we have received packets on the channel we // already have t so no need to calculate it channel.t = currentTime.subtract(channel.t); } int currentValue = ((IntToken) input.get(0)).intValue(); // Retrieve the value from the input if (channel.firstValue == 1 && currentValue == 1) { // If the first two values are 1 then n is 1 channel.n = 1; channel.t = new Time(getDirector()) .add( channel.t.getDoubleValue() / 12); // Calculate t given that n is 1, i.e divide the period by 12 as per // the protocol } setNextFireTime( channel, currentTime.getDoubleValue() + (channel.t.getDoubleValue() * currentValue)); // Manually set the next fire time for this channel channel.state = states.FIRSTTX; // Set the channel state to the next stage System.out.println( "SECONDRX on channel " + currentChannel + ". Current value is " + currentValue + ". t is " + channel.t + ". nextFireTime is " + channel.nextFireTime + " currentTime is " + currentTime); nextChannel(currentChannel, currentTime); removeFromQueue(currentChannel); // We can now move onto listening on the next channel }
// NOTE: No clone() method, so don't clone this. public void fire() throws IllegalActionException { super.fire(); double increment = 0.0; if ((input.getWidth() > 0) && input.hasToken(0)) { DoubleToken in = (DoubleToken) input.get(0); increment = in.doubleValue(); } output.broadcast(new DoubleToken(value + increment)); value += 1.0; Director director = getDirector(); Time time = director.getModelTime(); count++; if (count >= 5) { director.fireAt(this, time.add(1.0)); count = 0; } else { director.fireAt(this, time); } }
/** * Output the current value. * * @exception IllegalActionException If there is no director. */ @Override public void fire() throws IllegalActionException { boolean triggerInputPresent = false; for (int i = 0; i < trigger.getWidth(); i++) { if (trigger.isKnown() && trigger.hasToken(i)) { triggerInputPresent = true; } } Director director = getDirector(); Time currentTime = director.getModelTime(); boolean timeForOutput = currentTime.compareTo(_nextFiringTime) >= 0; if (!timeForOutput && !triggerInputPresent) { return; } if (director instanceof SuperdenseTimeDirector) { int currentMicrostep = ((SuperdenseTimeDirector) director).getIndex(); if (currentMicrostep < 1 && !triggerInputPresent) { return; } } super.fire(); output.send(0, _getValue(_nextOutputIndex)); $ASSIGN$_outputProduced(true); }
/** * State machine responsable by receiving the traffic from the data_in port, disassembly the * pcredit_outage and send its flits to the output ports (file). If the data_in does not have a * token, suspend firing and return. * * @exception IllegalActionException If there is no director. */ public void fire() throws IllegalActionException { super.fire(); if (_debugging) _debug("fire current_time: " + getDirector().getModelTime()); // getting current Time current_time = getDirector().getModelTime(); compare_time = current_time.getDoubleValue(); // if(firstSend.compareTo(compare_time) == 0.0){ if (compare_time == init_tim) { send_msg.send(0, new IntToken("1")); if (_debugging) _debug("FIRST sent at: " + compare_time); if (compare_time <= stop_time) { new_send = ((DoubleToken) interval.getToken()).doubleValue(); nextSend = current_time.add(new_send); getDirector().fireAt(this, nextSend); if (_debugging) _debug("after first send at: " + nextSend); // Requests to the director to be fire() at the window sample } } else if (compare_time < init_tim) { firstSend = current_time.add(init_tim); getDirector().fireAt(this, firstSend); if (_debugging) _debug("init_tim at: " + init_tim + " first send at " + firstSend); } else if (current_time.getDoubleValue() == nextSend.getDoubleValue()) { nextSend = nextSend.add(new_send); send_msg.send(0, new IntToken("2")); if (_debugging) _debug("msg sent at: " + compare_time); if (_debugging) _debug("NEXT SEND AT: " + nextSend); getDirector().fireAt(this, nextSend); } else if (current_time.getDoubleValue() != nextSend.getDoubleValue()) { if (_debugging) _debug("NAO ROLOU " + compare_time); } } // end public
public void fire() throws IllegalActionException { Time currentTime = getDirector().getModelTime(); // Get the model time to be used for various calculations if (changeChan) { // Check if we need to change the channel in this fire period setChannel(nextChannel); // Change to the next required channel changeChan = false; // Return to normal operation upon the next fire if (input.hasToken( 0)) { // If this fire was initiated by a token on the input, consume it to avoid loops input.get(0); } } else if (input.hasToken(0)) { // Wireless token has been received f SinkData channel = channelStore.get(currentChannel); // Retrieve the information for the current channel switch (channel.state) { // Determine what stage of the system we are at case FIRSTRX: // Stage one, we will be receiving the first synchronisation packet handleFirstRX(channel, currentTime); break; case SECONDRX: // Stage two, we will be receiving the second synchronisation packet handleSecondRX(channel, currentTime); break; case NCALC: // Stage 4, we will be receiving the first synchronisation packet of the // sequence to ascertain the n value handleNCalc(channel, currentTime); break; default: // We are in a state that does not require an input token, so we discard it input.get(0); break; } } else { // No token has been received so it is a fire initiated by the source and not a token // on the input SinkData channel = null; // Initialise a channel to be used later int desiredChannelNum = currentChannel; // Initialise a variable to store the channel required for this firing for (int channelNum : channelStore .keySet()) { // We need to find the channel that has caused the actor to be fired in // this time period channel = channelStore.get(channelNum); // Retrieve the information for the channel being checked if (channel.nextFireTime != null && channel.state != states.FINISHED) { // If we have a valid firing time, that has been initialised if (!channel.nextFireTime.equals( currentTime)) { // We are on an incorrect channel, continue searching continue; } else { // We have found the correct channel desiredChannelNum = channelNum; // Set the desired channel to the channel we have found break; } } } if (currentChannel == desiredChannelNum) { // If we are on the channel that we desire System.out.println( channel.nextFireTime.getDoubleValue() <= currentTime.getDoubleValue() + 0.4); if (channel.nextFireTime.getDoubleValue() <= currentTime.getDoubleValue() + 0.4) { // If we are not too early for the firing time switch (channel.state) { // Determine what stage of the system we are at case FIRSTTX: // Stage 3, we are in the receive period for the channels sink so we can // transmit a packet handleFirstTX(channel, currentTime); changeChan = true; // Change back to the channel back to what we had previously getDirector().fireAt(this, currentTime.add(0.000001)); break; case SECONDTX: // Stage 5, we are in the receive period for the second time, so we can // transmit a packet handleSecondTX(channel, currentTime); changeChan = true; // Change back to the channel back to what we had previously getDirector().fireAt(this, currentTime.add(0.000001)); break; } } } else if (desiredChannelNum != 0) { // We are not on the desired channel, so we have to change to it // System.out.println(currentChannel + " : " + desiredChannelNum); nextChannel = currentChannel; // Set the channel we will change back to after the transmit to our // current channel setChannel(desiredChannelNum); // Set the channel to the desired channel channel.nextFireTime = currentTime.add( 0.0000001); // Set the channels fire time to when we are firing it so we can detect // which channel fired getDirector() .fireAt( this, currentTime.add(0.0000001)); // Fire the actor again so we can process the transmit } } }
/** * Schedule a new actor for execution on the next available scheduler and return the next time * this scheduler has to perform a reschedule. * * @param actor The actor to be scheduled. * @param currentPlatformTime The current platform time. * @param deadline The deadline of the event. * @param executionTime The execution time of the actor. * @return Relative time when this Scheduler has to be executed again. * @exception IllegalActionException Thrown if actor parameters such as execution time or priority * cannot be read. */ @Override public Time schedule(NamedObj actor, Time currentPlatformTime, Time deadline, Time executionTime) throws IllegalActionException { super.schedule(actor, currentPlatformTime, deadline, executionTime); Time minimumRemainingTime = null; // Check if is already executing somewhere. for (NamedObj schedulerActor : _actors) { AtomicExecutionAspect scheduler = (AtomicExecutionAspect) schedulerActor; if (scheduler.getRemainingTime(actor) != null && scheduler.getRemainingTime(actor).getDoubleValue() > 0.0) { // This actor is currently executing on this scheduler. Time time = scheduler.schedule(actor, currentPlatformTime, deadline, executionTime); notifyExecutionListeners( scheduler, currentPlatformTime.getDoubleValue(), ExecutionEventType.START); if (time.getDoubleValue() == 0.0) { notifyExecutionListeners( scheduler, currentPlatformTime.getDoubleValue(), ExecutionEventType.STOP); } _remainingTimeOnCore.put(scheduler, time); _lastActorFinished = scheduler.lastActorFinished(); return time; } } // Its not executing anywhere, find free core. for (NamedObj schedulerActor : _actors) { AtomicExecutionAspect scheduler = (AtomicExecutionAspect) schedulerActor; if (scheduler == this) { continue; } Time remainingTime = _remainingTimeOnCore.get(scheduler); if (remainingTime == null || remainingTime.getDoubleValue() == 0.0) { Time time = scheduler.schedule(actor, currentPlatformTime, deadline, executionTime); notifyExecutionListeners( scheduler, currentPlatformTime.getDoubleValue(), ExecutionEventType.START); if (time.getDoubleValue() == 0.0) { notifyExecutionListeners( scheduler, currentPlatformTime.getDoubleValue(), ExecutionEventType.STOP); } _remainingTimeOnCore.put(scheduler, time); _lastActorFinished = scheduler.lastActorFinished(); return time; } else { if (minimumRemainingTime == null || minimumRemainingTime.compareTo(remainingTime) > 0) { minimumRemainingTime = remainingTime; } } } return minimumRemainingTime; }
/** * Get the predicted quantization-event time for a state (QSS-specific). * * @param stateIdx The state index. * @param quantEvtTimeMax The maximum quantization event time. */ protected final Time _predictQuantizationEventTimeWorker( final int stateIdx, final Time quantEvtTimeMax) { // Note the superclass takes care of updating status variables and // storing the returned result. // Initialize. final ModelPolynomial qStateMdl = _qStateMdls[stateIdx]; final ModelPolynomial cStateMdl = _cStateMdls[stateIdx]; final double dq = _dqs[stateIdx]; // Check internal consistency. assert (dq > 0); assert (quantEvtTimeMax.getDoubleValue() > 0); assert (quantEvtTimeMax.compareTo(qStateMdl.tMdl) > 0); assert (quantEvtTimeMax.compareTo(cStateMdl.tMdl) > 0); // Find predicted quantization-event time, as change from {tMostRecent}. Time tMostRecent; double dt; if (qStateMdl.tMdl.compareTo(cStateMdl.tMdl) > 0) { // Here, most recent event was a quantization-event. tMostRecent = qStateMdl.tMdl; dt = _predictQuantizationEventDeltaTimeQSS2QFromC(qStateMdl, cStateMdl, dq, _exactInputs); } else { // Here, most recent event was a rate-event. tMostRecent = cStateMdl.tMdl; dt = _predictQuantizationEventDeltaTimeQSS2General(qStateMdl, cStateMdl, dq, _exactInputs); } // Require {dt} > 0. if (dt <= 0) { // In exact arithmetic, and if the integrator is being stepped properly, // this should never happen. However, if the integrator stepped to a // time very close to the previous predicted quantization-event time, // or given a small numerator and large denominator in expressions // above, can get nonpositive {dt}. // Reset to as small a value as can manage. // Use the `ulp`, the "units in the last place". From the // documentation at {http://docs.oracle.com/javase/7/docs/api/java/lang/Math.html}: // "For a given floating-point format, an ulp of a specific real // number value is the distance between the two floating-point // values bracketing that numerical value." // TODO: Construct integrator with "min time step" parameter, // and pass it in for use it here. dt = java.lang.Math.ulp(tMostRecent.getDoubleValue()); } // Bound result to reasonable limits. // At lower end, need a positive number that, when added to {tMostRecent}, // produces a distinct time. // At upper end, can't be larger than {quantEvtTimeMax}. Time predQuantEvtTime; while (true) { if (quantEvtTimeMax.subtractToDouble(tMostRecent) <= dt) { // Here, tMostRecent + dt >= quantEvtTimeMax. // Note determined this case in a slightly roundabout way, since // simply adding {dt} to {tMostRecent} may cause problems if {quantEvtTimeMax} // reflects some inherent limitation of class {Time}. predQuantEvtTime = quantEvtTimeMax; break; } // Here, tMostRecent + dt < quantEvtTimeMax. predQuantEvtTime = tMostRecent.addUnchecked(dt); if (predQuantEvtTime.compareTo(tMostRecent) > 0) { // Here, added {dt} and got a distinct, greater, time. break; } // Here, {dt} so small that can't resolve difference from {tMostRecent}. dt *= 2; } return (predQuantEvtTime); }
/** * If a new message is available at the inputs, record it in the list indexed with the time that * the message shall be completed, and loop through the list to check whether there is collision. * If the current time matches one of the times that we have previously recorded as the completion * time for a transmission, then output the received message to the <i>received</i> output port if * it is not lost to a collision; otherwise, output it to the <i>collided</i> output port. * * @exception IllegalActionException If an error occurs reading or writing inputs or outputs. */ public void fire() throws IllegalActionException { super.fire(); Time currentTime = getDirector().getModelTime(); if (_debugging) { _debug("---------------------------------"); _debug("Current time is: " + currentTime); } if (message.hasToken(0) && power.hasToken(0) && duration.hasToken(0)) { double powerValue = ((DoubleToken) power.get(0)).doubleValue(); if (_debugging) { _debug("Received message with power: " + powerValue); } if (powerValue < _powerThreshold) { // The signal it too weak to be detected, simply drop it. message.get(0); duration.get(0); if (_debugging) { _debug("Message power is below threshold. Ignoring."); } } else { // Record the reception. Reception reception = new Reception(); reception.data = message.get(0); reception.power = powerValue; reception.arrivalTime = currentTime.getDoubleValue(); reception.collided = false; reception.duration = ((DoubleToken) duration.get(0)).doubleValue(); if (_debugging) { _debug("Message is above threshold and has duration: " + reception.duration); } // Update the total power density. _totalPower = _totalPower + reception.power; // Put the new reception into the list of prior receptions. Time time = currentTime.add(reception.duration); reception.expiration = time.getDoubleValue(); _receptions.add(reception); // Schedule this actor to be fired at the end of // the duration of the message. _fireAt(time); } } // Loop through the prior receptions (and the new one) // to mark whether a message is collided according to the new total // power density. Also, any prior receptions that are now // expiring are sent to one of the two outputs. Iterator priorReceptions = _receptions.listIterator(); while (priorReceptions.hasNext()) { Reception priorReception = (Reception) priorReceptions.next(); if (_debugging) { _debug("Checking reception with arrival time: " + priorReception.arrivalTime); } // If the reception is now expiring, send it to one of the two // output ports. if (priorReception.expiration == currentTime.getDoubleValue()) { if (_debugging) { _debug( "Current time matches expiration " + "time of a prior message that arrived at: " + priorReception.arrivalTime); } // The time matches a pending reception. priorReceptions.remove(); // Update the total power. _totalPower = _totalPower - priorReception.power; // Quantization errors may take this negative. Do not allow. if (_totalPower < 0.0) { _totalPower = 0.0; } if (!priorReception.collided) { received.send(0, priorReception.data); if (_debugging) { _debug("Message has been received: " + priorReception.data); } } else { collided.send(0, priorReception.data); if (_debugging) { _debug("Message has been lost: " + priorReception.data); } } continue; } // Check the snr to see whether to mark this prior reception // collided. double powerWithoutThisOne = _totalPower - priorReception.power; // Quantization errors may make this negative. if (powerWithoutThisOne < 0.0) { powerWithoutThisOne = 0.0; } double snr = priorReception.power / powerWithoutThisOne; if (!priorReception.collided && (snr <= _SNRThresholdInDB)) { priorReception.collided = true; if (_debugging) { _debug( "Message now has a collision. SNR is: " + snr + ". Total power is: " + _totalPower); } } } }