Source code for NetworkSim.simulation.process.receiver.tunable

__all__ = ["TR"]
__author__ = ["Hongyi Yang"]

import numpy as np

from NetworkSim.simulation.process.receiver.base import BaseReceiver


[docs]class TR(BaseReceiver): """ Tunable receiver simulator. Parameters ---------- env : simpy Environment The simulation environment. receiver_id : int The receiver ID. model : Model, optional The network model used for the simulation. Default is ``Model()``. Attributes ---------- received_data_packet_df : pandas DataFrame A DataFrame keeping the information of the received data packets, containing the columns: - `Timestamp` - `Raw Packet` - `Source ID` received_control_packet_df : pandas DataFrame A DataFrame keeping the information of the received control packets, containing the columns: - `Timestamp` - `Raw Packet` - `Source ID` """ def __init__( self, env, until, receiver_id, simulator, model=None ): super().__init__( env=env, until=until, receiver_id=receiver_id, simulator=simulator, model=model ) self.data_packet_received = True
[docs] def receive_on_control_ring(self): """ Receiver process to remove a new control packet from the ring. This process operates at the control clock frequency, and the control packet would only be removed from the \ ring if the destination ID of the packet corresponds to the receiver ID. The receiver would also check \ if the data packets reception precess is ready before receiving control packets. In this process: 1. The receiver starts detecting for incoming control packets; 2. The receiver checks the destination ID of the control packet received; 3. When the IDs match, the receiver removes the control packet from the ring, keeps a record of the \ transmission. and informs the data reception subsystem. 4. Depends on the control_code, the packet will be added to a queue or remove a packet from the queue; """ while self.env.now <= self.until: present, packet = self.check_control_packet() # Check if a control packet is detected if present: # Check if control packet destination ID matches own ID if self.control_id_match(packet=packet): # Add received control packet into queue self.ram_queue_input(packet=packet) # Remove packet from the ring, keep a record of its information self.receive_control_packet(packet=packet) yield self.env.timeout(self._receiver_data_clock_cycle)
[docs] def receive_on_data_ring(self): """ Receiver process to remove a new data packet from the ring. This process operates at the unit clock frequency, and the data packet would only be from the \ ring once its corresponding control packet has been received. In this process: 1. The receiver takes ``'tuning_time'`` to tune to the data ring; 2. The receiver waits and receives the data packet, \ removes it from the ring and keeps a record of the transmission. 3. The latency of the transmission is recorded. """ while self.env.now <= self.until: if self.queue: # Assign flag self.data_packet_received = False # Obtain the first control packet in RAM queue _control_packet = self.queue.popleft() # Tune to incoming data packet wavelength _transmitter_id = self.ram_queue_output(_control_packet) # Wait for the data packet while not self.data_packet_received: # Receive data packet _present, _packet = self.check_data_packet(ring_id=_transmitter_id) _time_difference = self.env.now - _control_packet[6] # Check if a data packet is received and time is correct if _present and \ (np.isclose(_time_difference % self.model.circulation_time, 0, atol=1e-2) or np.isclose(_time_difference % self.model.circulation_time, self.model.circulation_time, atol=1e-2)): # Remove packet from the ring and keep a record of its information self.record_error(_packet) self.receive_data_packet(ring_id=_transmitter_id, packet=_packet) # Wait for the end of the data packet yield self.env.timeout(self.model.data_packet_duration) # Record latency information self.record_latency(packet=_packet) # Assign flag self.data_packet_received = True # Sync with clock yield self.env.timeout(self._time_compensation) else: yield self.env.timeout(self._receiver_data_clock_cycle) else: yield self.env.timeout(self._receiver_data_clock_cycle)