Source code for NetworkSim.simulation.process.transmitter.base

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

from NetworkSim.architecture.setup.model import Model
from NetworkSim.simulation.tools.clock import TransmitterDataClock, ControlClock, ReceiverDataClock


[docs]class BaseTransmitter: """ Transmitter processes creator for the simulation. Parameters ---------- env : simpy Environment The simulation environment. ram : RAM The RAM at which the transmitter access its information. transmitter_id : int The transmitter ID. simulator : BaseSimulator The simulator used. model : Model, optional The network model used for the simulation. Default is ``Model()``. Attributes ---------- transmitted_data_packet : list A list keeping the information of the transmitted data packets, containing the columns: - `Timestamp` - `Raw Packet` - `Destination ID` transmitted_control_packet : list A list keeping the information of the transmitted control packets, containing the columns: - `Timestamp` - `Raw Packet` - `Destination ID` """ def __init__( self, env, ram, transmitter_id, simulator, until, model=None ): self.env = env self.ram = ram self.transmitter_id = transmitter_id self.simulator = simulator self.until = until if model is None: model = Model() self.model = model self._transmitter_data_clock_cycle = TransmitterDataClock(model=model).clock_cycle self._receiver_data_clock_cycle = ReceiverDataClock(model=model).clock_cycle self._control_clock_cycle = ControlClock(model=model).clock_cycle self.transmitted_data_packet = [] self.transmitted_control_packet = [] self._tunable_keywords = {'tunable', 't', 'T'}
[docs] def get_packet_from_ram(self, is_upstream=False): """ Get first packet from RAM queue. Parameters ---------- is_upstream : bool, optional If the packet is in upstream queue. Default is ``False``. \ This is used only for bi-directional systems. Returns ------- generation_timestamp : float Time of packet generation. data_packet : str Data packet to be transmitted. destination_id : int The ID of the destination node. """ if self.simulator.bidirectional: if is_upstream: generation_timestamp, data_packet, destination_id = self.ram.upstream_queue.popleft() else: generation_timestamp, data_packet, destination_id = self.ram.downstream_queue.popleft() else: generation_timestamp, data_packet, destination_id = self.ram.queue.popleft() self.ram.record_queue_size() self.ram.pop_from_queue_record.append([generation_timestamp, data_packet, destination_id]) self.simulator.ram_queue_delay.append(self.env.now - generation_timestamp) return generation_timestamp, data_packet, destination_id
[docs] def transmit_control_packet(self, packet, destination_id, generation_timestamp): """ Control packet transmission function. This function adds the control packet onto the ring and keeps a record of the transmission. Parameters ---------- packet : packet The control packet. destination_id : int The ID of the node to which the control packet is transmitted. generation_timestamp : float The timestamp when the control packet is generated and stored in RAM. """ # Add control packet onto the ring self.model.control_ring.add_packet( packet=packet, generation_timestamp=generation_timestamp, transmission_timestamp=self.env.now, node_id=self.transmitter_id, destination_id=destination_id ) # Store control packet information self.transmitted_control_packet.append([ self.env.now, packet, destination_id ])
[docs] def transmit_data_packet(self, ring_id, packet, destination_id, generation_timestamp, reversed=False): """ Data packet transmission function. This function adds the data packet onto the ring and keeps a record of the transmission. Parameters ---------- ring_id : int The ID of the data ring on which the packet is transmitted. packet : packet The data packet. destination_id : int The ID of the node to which the data packet is transmitted. generation_timestamp : float The timestamp when the data packet is generated and stored in RAM. reversed : bool, optional If checking the reversed ring. Defaults is ``False``. """ # Add data packet onto the ring if reversed: self.model.reversed_data_rings[ring_id].add_packet( packet=packet, generation_timestamp=generation_timestamp, transmission_timestamp=self.env.now, node_id=self.transmitter_id, destination_id=destination_id ) else: self.model.data_rings[ring_id].add_packet( packet=packet, generation_timestamp=generation_timestamp, transmission_timestamp=self.env.now, node_id=self.transmitter_id, destination_id=destination_id ) # Store data packet information self.transmitted_data_packet.append([ self.env.now, packet, destination_id ])
[docs] def ring_is_full(self, ring_id, reversed=False): """ Function to check if the data ring is fully occupied. Parameters ---------- ring_id : int The ID of the data ring on which the packet is transmitted. reversed : bool, optional If checking the reversed ring. Defaults is ``False``. Returns ------- ring_is_full : bool ``True`` if the data ring is full, otherwise ``False``. """ if self.simulator.bidirectional: if reversed: if self.model.reversed_data_rings[ring_id].packet_count == self.model.max_data_packet_num_on_ring: return True else: return False if self.model.data_rings[ring_id].packet_count == self.model.max_data_packet_num_on_ring: return True return False
[docs] def check_data_packet(self, ring_id, reversed=False): """ Function to check if there is a data packet present at the transmitter Parameters ---------- ring_id : int The ID of the data ring on which the packet is transmitted. reversed : bool, optional If checking the reversed ring. Defaults is ``False``. Returns ------- present : bool Presence of the data packet. ``True`` if present, ``False`` if not present. packet : packet Packet information, in the format: - `raw_packet` - `generation_timestamp` - `transmission_timestamp` - `packet_entry_point` - `entry_node_id` - `destination_node_id` """ if reversed: return self.model.reversed_data_rings[ring_id].check_packet( current_time=self.env.now, node_id=self.transmitter_id ) else: return self.model.data_rings[ring_id].check_packet( current_time=self.env.now, node_id=self.transmitter_id )
[docs] def check_data_packet_after_guard_interval(self, ring_id): """ Function to check if there is a data packet present at the transmitter after the guard interval Returns ------- present : bool Presence of the data packet. ``True`` if present, ``False`` if not present. packet : packet Packet information, in the format: - `raw_packet` - `generation_timestamp` - `transmission_timestamp` - `packet_entry_point` - `entry_node_id` - `destination_node_id` """ return self.model.data_rings[ring_id].check_packet( current_time=self.env.now + self.model.constants.get('data_guard_interval'), node_id=self.transmitter_id )
[docs] def check_control_packet(self): """ Function to check if there is a control packet present at the transmitter Returns ------- present : bool Presence of the data packet. ``True`` if present, ``False`` if not present. packet : packet Packet information, in the format: - `raw_packet` - `generation_timestamp` - `transmission_timestamp` - `packet_entry_point` - `entry_node_id` - `destination_node_id` """ return self.model.control_ring.check_packet( current_time=self.env.now, node_id=self.transmitter_id )
[docs] def generate_control_packet(self, destination, control): """ Function to generate a control packet. Returns ------- control_packet : str The raw control packet string in binary """ return self.model.control_signal.generate_packet( source=self.transmitter_id, destination=destination, control_code=control )
[docs] def transmit_on_data_ring(self): """ Process to transmit data packets. """ raise NotImplementedError("This is an abstract data packet transmission process method.")
[docs] def transmit_on_control_ring(self): """ Process to transmit control packets. """ raise NotImplementedError("This is an abstract control packet transmission process method.")
[docs] def initialise(self): """ Initialisation of the transmitter simulation. """ if self.simulator.receiver_type in self._tunable_keywords: self.env.process(self.transmit_on_control_ring()) self.env.process(self.transmit_on_data_ring())