def __init__(self, id, coordinate, proc_engine): self.id = id self.coordinate = coordinate self.proc_engine = proc_engine self.logger = logging.getLogger(' ') # Process Attribute self.vcs_dictionary = NodeArray() self.vcs_target_north = [] self.vcs_target_south = [] self.vcs_target_east = [] self.vcs_target_west = [] self.vcs_target_pe = []
def __init__(self, env, id, coordinate, proc_engine): self.action = env.process(self.run()) self.env = env self.id = id self.coordinate = coordinate self.proc_engine = proc_engine self.logger = logging.getLogger(' ') self.noc = None # Process Attribute self.vcs_dictionary = NodeArray() self.vcs_target_north = [] self.vcs_target_south = [] self.vcs_target_east = [] self.vcs_target_west = [] self.vcs_target_pe = [] self.pipelined_sending = []
def setUp(self): self.nodeArray = NodeArray() self.vc_src = VirtualChannel(1, Direction.east, None, 1, 1) self.vc_target = VirtualChannel(1, Direction.east, None, 1, 1)
class TestNode(unittest.TestCase): def setUp(self): self.nodeArray = NodeArray() self.vc_src = VirtualChannel(1, Direction.east, None, 1, 1) self.vc_target = VirtualChannel(1, Direction.east, None, 1, 1) def test_add(self): node = Node(self.vc_src, self.vc_target) self.nodeArray.add(node) self.assertEqual(len(self.nodeArray.array), 1) node2 = Node(self.vc_src, self.vc_target) self.nodeArray.add(node2) self.assertEqual(len(self.nodeArray.array), 2) def test_remove(self): node = Node(self.vc_src, self.vc_target) self.nodeArray.add(node) node2 = Node(self.vc_src, self.vc_target) self.nodeArray.add(node2) self.nodeArray.remove(self.vc_src) self.assertEqual(len(self.nodeArray.array), 1) self.nodeArray.remove(self.vc_src) self.assertEqual(len(self.nodeArray.array), 0) def test_get_target(self): node = Node(self.vc_src, self.vc_target) self.nodeArray.add(node) self.assertEqual(self.nodeArray.get_target(self.vc_src), self.vc_target) self.nodeArray.remove(self.vc_src) self.assertIsNone(self.nodeArray.get_target(self.vc_src))
class Router: def __init__(self, id, coordinate, proc_engine): self.id = id self.coordinate = coordinate self.proc_engine = proc_engine self.logger = logging.getLogger(' ') # Process Attribute self.vcs_dictionary = NodeArray() self.vcs_target_north = [] self.vcs_target_south = [] self.vcs_target_east = [] self.vcs_target_west = [] self.vcs_target_pe = [] def inport_setting(self, inNorth, inSouth, inEast, inWest): self.inNorth = inNorth self.inSouth = inSouth self.inEast = inEast self.inWest = inWest def outport_setting(self, outNorth, outSouth, outEast, outWest): self.outNorth = outNorth self.outSouth = outSouth self.outEast = outEast self.outWest = outWest def proc_engine_setting(self, inPE, outPE): self.inPE = inPE self.outPE = outPE def route_computation(self, flit): # On X axe (Column) # By the West if self.coordinate.j > flit.destination.j: return self.outWest # By the East elif self.coordinate.j < flit.destination.j: return self.outEast # On Y axe (Row) else: if self.coordinate.i > flit.destination.i: return self.outNorth # By the East elif self.coordinate.i < flit.destination.i: return self.outSouth else: # Destination Reached return self.outPE def send_flit(self, vc, outport, time): if len(vc.flits) <= 0: return # getting the first flit in VC flit = vc.dequeue() if flit is None: return # if is a Head Flit if flit.type == FlitType.head: self.logger.debug('Time : (%d) - %s ready to be sent' % (time, flit)) # Get idle VC from next Input vc_allotted = outport.inPort.vc_allocator() if vc_allotted is not None: self.logger.debug('Time : (%d) - VC (%s) allotted' % (time, vc_allotted)) # send flit vc_allotted.enqueue(flit) self.logger.info('(%d) : %s - %s -> %s -> %s' % (time, flit, self, vc_allotted, vc_allotted.router)) vc.credit_out() # registering VC allotted in dictionary self.vcs_dictionary.add(Node(vc, vc_allotted)) # Next routing event = Event(EventType.VC_ELECTION, vc_allotted.router, time + 1) EVENT_LIST.push(event) else: # No idle VC vc.restore(flit) # restore # event push event = Event(EventType.SEND_FLIT, {'router': self, 'vc': vc, 'outport': outport}, time + 1) EVENT_LIST.push(event) self.logger.debug('Time : (%d) - %s was not sent - VC not allotted' % (time, flit)) # if is a Body Flit elif flit.type == FlitType.body: self.logger.debug('Time : (%d) - %s ready to be sent' % (time, flit)) # Getting the alloted vc vc_allotted = self.vcs_dictionary.get_target(vc) self.logger.debug('Time : (%d) - Retreiving allotted VC (%s)' % (time, vc_allotted)) # Sending to the next router sent = vc_allotted.enqueue(flit) if not sent: # No Place vc.restore(flit) # restore # event push event = Event(EventType.SEND_FLIT, {'router': self, 'vc': vc, 'outport': outport}, time + 1) EVENT_LIST.push(event) self.logger.debug('Time : (%d) - %s was not sent - No Place in VC (%s)' % (time, flit, vc_allotted)) else: # Next routing event = Event(EventType.VC_ELECTION, vc_allotted.router, time + 1) EVENT_LIST.push(event) self.logger.info('(%d) : %s - %s -> %s -> %s' % (time, flit, self, vc_allotted, vc_allotted.router)) vc.credit_out() # if is a Tail Flit elif flit.type == FlitType.tail: self.logger.debug('Time : (%d) - %s ready to be sent' % (time, flit)) # Getting the alloted vc vc_allotted = self.vcs_dictionary.get_target(vc) # Sending to the next router sent = vc_allotted.enqueue(flit) if not sent: # No Place vc.restore(flit) # restore # event push event = Event(EventType.SEND_FLIT, {'router': self, 'vc': vc, 'outport': outport}, time + 1) EVENT_LIST.push(event) self.logger.debug('Time : (%d) - %s was not sent - No Place in VC (%s)' % (time, flit, vc_allotted)) else: self.logger.info('(%d) : %s - %s -> %s -> %s' % (time, flit, self, vc_allotted, vc_allotted.router)) # Next routing event = Event(EventType.VC_ELECTION, vc_allotted.router, time + 1) EVENT_LIST.push(event) self.vcs_dictionary.remove(vc) vc.lock = False vc.credit_out() self.logger.debug('Time : (%d) - VC (%s) - released' % (time, vc)) # If Quantum is finished if vc.quantum <= 0: # print('Quantum or VC finished for : %s' % vc) self.logger.debug('Time : (%d) - VC (%s) - quantum finished' % (time, vc)) # new VC Election - event push event = Event(EventType.VC_ELECTION, self, time + 1) EVENT_LIST.push(event) elif len(vc.flits) <= 0: self.logger.debug('Time : (%d) - VC (%s) - NO Flits' % (time, vc)) # new VC Election - event push event = Event(EventType.VC_ELECTION, self, time + 1) EVENT_LIST.push(event) # Another Quantum else: self.logger.debug('Time : (%d) - VC (%s) - quantum NOT finished' % (time, vc)) event = Event(EventType.SEND_FLIT, {'router': self, 'vc': vc, 'outport': outport}, time + 1) EVENT_LIST.push(event) def arrived_flit(self, vc, time): flit = vc.dequeue() if flit.type == FlitType.tail: self.vcs_dictionary.remove(vc) vc.lock = False flit.set_arrival_time(time) # Flit store self.proc_engine.flit_receiving(flit) self.logger.info('(%d) : %s - %s -> %s' % (time, flit, self, self.proc_engine)) """ Fixed Round-Robin Arbitration """ def vc_target_outport(self, vc): if len(vc.flits) > 0: if self.route_computation(vc.flits[0]) == self.outNorth \ and vc not in self.vcs_target_north: self.vcs_target_north.append(vc) vc.reset_credit() elif self.route_computation(vc.flits[0]) == self.outSouth \ and vc not in self.vcs_target_south: self.vcs_target_south.append(vc) vc.reset_credit() elif self.route_computation(vc.flits[0]) == self.outEast \ and vc not in self.vcs_target_east: self.vcs_target_east.append(vc) vc.reset_credit() elif self.route_computation(vc.flits[0]) == self.outWest \ and vc not in self.vcs_target_west: self.vcs_target_west.append(vc) vc.reset_credit() elif self.route_computation(vc.flits[0]) == self.outPE \ and vc not in self.vcs_target_pe: self.vcs_target_pe.append(vc) def rr_arbiter(self, time): for vc in self.inPE.vcs: self.vc_target_outport(vc) # Checking North VC for vc in self.inNorth.vcs: self.vc_target_outport(vc) # Checking South VC for vc in self.inSouth.vcs: self.vc_target_outport(vc) # Checking East VC for vc in self.inEast.vcs: self.vc_target_outport(vc) # Checking West VC for vc in self.inWest.vcs: self.vc_target_outport(vc) # VC targeting -> North if len(self.vcs_target_north) > 0: vc = self.vcs_target_north.pop(0) self.logger.debug('Time : (%d) - %s -> Elected' % (time, vc)) # event push event = Event(EventType.SEND_FLIT, {'router': self, 'vc': vc, 'outport': self.outNorth}, time) EVENT_LIST.push(event) # VC targeting -> South if len(self.vcs_target_south) > 0: vc = self.vcs_target_south.pop(0) self.logger.debug('Time : (%d) - %s -> Elected' % (time, vc)) # event push event = Event(EventType.SEND_FLIT, {'router': self, 'vc': vc, 'outport': self.outSouth}, time) EVENT_LIST.push(event) # VC targeting -> East if len(self.vcs_target_east) > 0: vc = self.vcs_target_east.pop(0) self.logger.debug('Time : (%d) - %s -> Elected' % (time, vc)) # event push event = Event(EventType.SEND_FLIT, {'router': self, 'vc': vc, 'outport': self.outEast}, time) EVENT_LIST.push(event) # VC targeting -> West if len(self.vcs_target_west) > 0: vc = self.vcs_target_west.pop(0) self.logger.debug('Time : (%d) - %s -> Elected' % (time, vc)) # event push event = Event(EventType.SEND_FLIT, {'router': self, 'vc': vc, 'outport': self.outWest}, time) EVENT_LIST.push(event) # VC targeting -> PE if len(self.vcs_target_pe) > 0: vc = self.vcs_target_pe.pop(0) self.logger.debug('Time : (%d) - %s -> Elected' % (time, vc)) # event push event = Event(EventType.ARR_FLIT, {'router': self, 'vc': vc}, time) EVENT_LIST.push(event) """ Priority-based Arbitration """ def priority_arbiter(self, time): for vc in self.inPE.vcs: self.vc_target_outport(vc) # Checking North VC for vc in self.inNorth.vcs: self.vc_target_outport(vc) # Checking South VC for vc in self.inSouth.vcs: self.vc_target_outport(vc) # Checking East VC for vc in self.inEast.vcs: self.vc_target_outport(vc) # Checking West VC for vc in self.inWest.vcs: self.vc_target_outport(vc) # VC targeting -> North if len(self.vcs_target_north) > 0: vc = self.get_most_prioritized_vc(self.vcs_target_north) self.logger.debug('Time : (%d) - %s -> Elected' % (time, vc)) # event push event = Event(EventType.SEND_FLIT, {'router': self, 'vc': vc, 'outport': self.outNorth}, time) EVENT_LIST.push(event) # VC targeting -> South if len(self.vcs_target_south) > 0: vc = self.get_most_prioritized_vc(self.vcs_target_south) self.logger.debug('Time : (%d) - %s -> Elected' % (time, vc)) # event push event = Event(EventType.SEND_FLIT, {'router': self, 'vc': vc, 'outport': self.outSouth}, time) EVENT_LIST.push(event) # VC targeting -> East if len(self.vcs_target_east) > 0: vc = self.get_most_prioritized_vc(self.vcs_target_east) self.logger.debug('Time : (%d) - %s -> Elected' % (time, vc)) # event push event = Event(EventType.SEND_FLIT, {'router': self, 'vc': vc, 'outport': self.outEast}, time) EVENT_LIST.push(event) # VC targeting -> West if len(self.vcs_target_west) > 0: vc = self.get_most_prioritized_vc(self.vcs_target_west) self.logger.debug('Time : (%d) - %s -> Elected' % (time, vc)) # event push event = Event(EventType.SEND_FLIT, {'router': self, 'vc': vc, 'outport': self.outWest}, time) EVENT_LIST.push(event) # VC targeting -> PE if len(self.vcs_target_pe) > 0: vc = self.get_most_prioritized_vc(self.vcs_target_pe) self.logger.debug('Time : (%d) - %s -> Elected' % (time, vc)) # event push event = Event(EventType.ARR_FLIT, {'router': self, 'vc': vc}, time) EVENT_LIST.push(event) def send_flit_by_priority(self, vc, outport, time): if len(vc.flits) <= 0: return # getting the first flit in VC flit = vc.dequeue() if flit is None: return # if is a Head Flit if flit.type == FlitType.head: self.logger.debug('Time : (%d) - %s ready to be sent' % (time, flit)) # Get idle VC from next Input vc_allotted = outport.inPort.priority_vc_allocator(flit.get_priority()) if vc_allotted is not None: self.logger.debug('Time : (%d) - VC (%s) allotted' % (time, vc_allotted)) # send flit vc_allotted.enqueue(flit) self.logger.info('(%d) : %s - %s -> %s -> %s' % (time, flit, self, vc_allotted, vc_allotted.router)) vc.credit_out() # registering VC allotted in dictionary self.vcs_dictionary.add(Node(vc, vc_allotted)) # Next routing event = Event(EventType.VC_ELECTION, vc_allotted.router, time + 1) EVENT_LIST.push(event) else: # No idle VC vc.restore(flit) # restore # event push event = Event(EventType.SEND_FLIT, {'router': self, 'vc': vc, 'outport': outport}, time + 1) EVENT_LIST.push(event) self.logger.debug('Time : (%d) - %s was not sent - VC not allotted' % (time, flit)) # if is a Body Flit elif flit.type == FlitType.body: self.logger.debug('Time : (%d) - %s ready to be sent' % (time, flit)) # Getting the alloted vc vc_allotted = self.vcs_dictionary.get_target(vc) self.logger.debug('Time : (%d) - Retreiving allotted VC (%s)' % (time, vc_allotted)) # Sending to the next router sent = vc_allotted.enqueue(flit) if not sent: # No Place vc.restore(flit) # restore # event push event = Event(EventType.SEND_FLIT, {'router': self, 'vc': vc, 'outport': outport}, time + 1) EVENT_LIST.push(event) self.logger.debug('Time : (%d) - %s was not sent - No Place in VC (%s)' % (time, flit, vc_allotted)) else: # Next routing event = Event(EventType.VC_ELECTION, vc_allotted.router, time + 1) EVENT_LIST.push(event) self.logger.info('(%d) : %s - %s -> %s -> %s' % (time, flit, self, vc_allotted, vc_allotted.router)) vc.credit_out() # if is a Tail Flit elif flit.type == FlitType.tail: self.logger.debug('Time : (%d) - %s ready to be sent' % (time, flit)) # Getting the alloted vc vc_allotted = self.vcs_dictionary.get_target(vc) # Sending to the next router sent = vc_allotted.enqueue(flit) if not sent: # No Place vc.restore(flit) # restore # event push event = Event(EventType.SEND_FLIT, {'router': self, 'vc': vc, 'outport': outport}, time + 1) EVENT_LIST.push(event) self.logger.debug('Time : (%d) - %s was not sent - No Place in VC (%s)' % (time, flit, vc_allotted)) else: self.logger.info('(%d) : %s - %s -> %s -> %s' % (time, flit, self, vc_allotted, vc_allotted.router)) # Next routing event = Event(EventType.VC_ELECTION, vc_allotted.router, time + 1) EVENT_LIST.push(event) self.vcs_dictionary.remove(vc) vc.lock = False vc.credit_out() self.logger.debug('Time : (%d) - VC (%s) - released' % (time, vc)) # If Quantum is finished if vc.quantum <= 0: # print('Quantum or VC finished for : %s' % vc) self.logger.debug('Time : (%d) - VC (%s) - quantum finished' % (time, vc)) # new VC Election - event push event = Event(EventType.VC_ELECTION, self, time + 1) EVENT_LIST.push(event) elif len(vc.flits) <= 0: self.logger.debug('Time : (%d) - VC (%s) - NO Flits' % (time, vc)) # new VC Election - event push event = Event(EventType.VC_ELECTION, self, time + 1) EVENT_LIST.push(event) # Another Quantum else: self.logger.debug('Time : (%d) - VC (%s) - quantum NOT finished' % (time, vc)) event = Event(EventType.SEND_FLIT, {'router': self, 'vc': vc, 'outport': outport}, time + 1) EVENT_LIST.push(event) def get_most_prioritized_vc(self, vcs_target): priority = sys.maxsize # lowest priority for i in range(len(vcs_target)): if vcs_target[i].id < priority: priority = i return vcs_target[priority] def __str__(self): return 'Router (%d,%d)' % (self.coordinate.i, self.coordinate.j)
class Router: def __init__(self, env, id, coordinate, proc_engine): self.action = env.process(self.run()) self.env = env self.id = id self.coordinate = coordinate self.proc_engine = proc_engine self.logger = logging.getLogger(' ') self.noc = None # Process Attribute self.vcs_dictionary = NodeArray() self.vcs_target_north = [] self.vcs_target_south = [] self.vcs_target_east = [] self.vcs_target_west = [] self.vcs_target_pe = [] self.pipelined_sending = [] def inport_setting(self, inNorth, inSouth, inEast, inWest): self.inNorth = inNorth self.inSouth = inSouth self.inEast = inEast self.inWest = inWest def outport_setting(self, outNorth, outSouth, outEast, outWest): self.outNorth = outNorth self.outSouth = outSouth self.outEast = outEast self.outWest = outWest def proc_engine_setting(self, inPE, outPE): self.inPE = inPE self.outPE = outPE def noc_settings(self, noc): self.noc = noc def run(self): while True: yield self.env.timeout(1) if self.noc.arbitration == "RR": self.rr_arbitration() elif self.noc.arbitration == "PRIORITY_PREEMPT": self.priority_preemptive_arbitration() def route_computation(self, flit): # On X axe (Column) # By the West if self.coordinate.j > flit.destination.j: return self.outWest # By the East elif self.coordinate.j < flit.destination.j: return self.outEast # On Y axe (Row) else: if self.coordinate.i > flit.destination.i: return self.outNorth # By the East elif self.coordinate.i < flit.destination.i: return self.outSouth else: # Destination Reached return self.outPE def is_packet_still_in_vc(self, packet): if self.inPE.is_packet_still_in_vc(packet) or \ self.inSouth.is_packet_still_in_vc(packet) or \ self.inNorth.is_packet_still_in_vc(packet) or \ self.inWest.is_packet_still_in_vc(packet) or \ self.inEast.is_packet_still_in_vc(packet): return True else: return False def receiving_from_pe(self, packet): if self.is_packet_still_in_vc(packet): return False if self.noc.arbitration == "RR": requested_vc = self.inPE.vc_allocator() elif self.noc.arbitration == "PRIORITY_PREEMPT": requested_vc = self.inPE.priority_vc_allocator(packet.priority) else: requested_vc = None if requested_vc is not None: for flit in packet.flits: requested_vc.enqueue(flit) self.logger.info( '(%d) : %s - %s -> %s -> %s' % (self.env.now, flit, self.proc_engine, requested_vc, self)) # set depart time for the first first in the first packet if flit.id == 0 and flit.packet.id == 0: flit.packet.message.set_depart_time(self.env.now) return True else: return False def vc_target_outport(self, vc): if len(vc.flits) > 0: if self.route_computation(vc.flits[0]) == self.outNorth \ and vc not in self.vcs_target_north: self.vcs_target_north.append(vc) elif self.route_computation(vc.flits[0]) == self.outSouth \ and vc not in self.vcs_target_south: self.vcs_target_south.append(vc) elif self.route_computation(vc.flits[0]) == self.outEast \ and vc not in self.vcs_target_east: self.vcs_target_east.append(vc) elif self.route_computation(vc.flits[0]) == self.outWest \ and vc not in self.vcs_target_west: self.vcs_target_west.append(vc) elif self.route_computation(vc.flits[0]) == self.outPE \ and vc not in self.vcs_target_pe: self.vcs_target_pe.append(vc) def arrived_flit(self, vc): flit = vc.dequeue() # Flit Timestamp to avoid premature sending if flit.timestamp == self.env.now: vc.restore(flit) return flit.timestamp = copy.copy(self.env.now) if flit.type == FlitType.tail: self.vcs_dictionary.remove(vc) vc.release() vc.credit_out() # Flit store self.proc_engine.flit_receiving(flit) TRACESET.set_flit_arrival(flit.packet.message, self.env.now) # set arrival time to the last flit into the message nb_flit = PACKET_DEFAULT_SIZE / FLIT_DEFAULT_SIZE nb_packet = math.ceil(flit.packet.message.size / PACKET_DEFAULT_SIZE) if flit.id == nb_flit - 1 and flit.packet.id == nb_packet - 1: flit.packet.message.set_arrival_time(self.env.now + 1) self.logger.info('(%d) : %s - %s -> %s' % (self.env.now, flit, self, self.proc_engine)) def send_flit(self, vc, outport): # getting the first flit in VC flit = vc.dequeue() # Flit Timestamp to avoid premature sending if flit.timestamp == self.env.now: vc.restore(flit) return # if is a Head Flit if flit.type == FlitType.head: # Get idle VC from next Input if self.noc.arbitration == "RR": vc_allotted = outport.inPort.vc_allocator() elif self.noc.arbitration == "PRIORITY_PREEMPT": vc_allotted = outport.inPort.priority_vc_allocator(flit.packet.priority) else: vc_allotted = None if vc_allotted is not None: self.logger.debug('(%d) - VC (%s) allotted' % (self.env.now, vc_allotted)) vc_allotted.enqueue(flit) flit.timestamp = copy.copy(self.env.now) self.logger.info( '(%d) : %s ON %s- %s -> %s -> %s' % (self.env.now, flit, vc, self, vc_allotted, vc_allotted.router)) # vc.credit_out() # registering VC allotted in dictionary self.vcs_dictionary.add(Node(vc, vc_allotted)) else: # No idle VC vc.restore(flit) # restore self.logger.debug('(%d) - %s was not sent - VC not allotted ON %s' % (self.env.now, flit, outport.inPort.router)) # outport.inPort.vcs_status() # time.sleep(1) # if is a Body Flit elif flit.type == FlitType.body: # Getting the alloted vc vc_allotted = self.vcs_dictionary.get_target(vc) self.logger.debug('(%d) - Retreiving allotted VC (%s)' % (self.env.now, vc_allotted)) # Sending to the next router sent = vc_allotted.enqueue(flit) if not sent: # No Place vc.restore(flit) # restore self.logger.debug('(%d) - %s was not sent - No Place in VC (%s)' % (self.env.now, flit, vc_allotted)) else: self.logger.info( '(%d) : %s ON %s- %s -> %s -> %s' % (self.env.now, flit, vc, self, vc_allotted, vc_allotted.router)) # vc.credit_out() flit.timestamp = copy.copy(self.env.now) # if is a Tail Flit elif flit.type == FlitType.tail: # Getting the alloted vc vc_allotted = self.vcs_dictionary.get_target(vc) # Sending to the next router sent = vc_allotted.enqueue(flit) if not sent: # No Place vc.restore(flit) # restore self.logger.debug('(%d) - %s was not sent - No Place in VC (%s)' % (self.env.now, flit, vc_allotted)) else: self.vcs_dictionary.remove(vc) flit.timestamp = copy.copy(self.env.now) # vc.credit_out() vc.release() self.logger.debug('(%d) - VC (%s) - released' % (self.env.now, vc)) vc.credit_out() def rr_arbitration(self): # ---------- VC election ---------- for vc in self.inPE.vcs: self.vc_target_outport(vc) # Checking North VC for vc in self.inNorth.vcs: self.vc_target_outport(vc) # Checking South VC for vc in self.inSouth.vcs: self.vc_target_outport(vc) # Checking East VC for vc in self.inEast.vcs: self.vc_target_outport(vc) # Checking West VC for vc in self.inWest.vcs: self.vc_target_outport(vc) # VC targeting -> North if len(self.vcs_target_north) > 0: vc = self.vcs_target_north.pop(0) self.logger.debug('(%d) - %s From %s -> Elected' % (self.env.now, vc, self)) self.send_flit(vc, self.outNorth) # re-insert if credit is not finished self.vc_reinsertion(vc, self.vcs_target_north) # VC targeting -> South if len(self.vcs_target_south) > 0: vc = self.vcs_target_south.pop(0) self.logger.debug('(%d) - %s From %s -> Elected' % (self.env.now, vc, self)) self.send_flit(vc, self.outSouth) # re-insert if credit is not finished self.vc_reinsertion(vc, self.vcs_target_south) # VC targeting -> East if len(self.vcs_target_east) > 0: vc = self.vcs_target_east.pop(0) self.logger.debug('(%d) - %s From %s -> Elected' % (self.env.now, vc, self)) self.send_flit(vc, self.outEast) # re-insert if credit is not finished self.vc_reinsertion(vc, self.vcs_target_east) # VC targeting -> West if len(self.vcs_target_west) > 0: vc = self.vcs_target_west.pop(0) self.logger.debug('(%d) - %s From %s -> Elected' % (self.env.now, vc, self)) self.send_flit(vc, self.outWest) # re-insert if credit is not finished self.vc_reinsertion(vc, self.vcs_target_west) # VC targeting -> PE if len(self.vcs_target_pe) > 0: vc = self.vcs_target_pe.pop(0) self.logger.debug('(%d) - %s From %s -> Elected' % (self.env.now, vc, self)) self.arrived_flit(vc) # re-insert if credit is not finished self.vc_reinsertion(vc, self.vcs_target_pe) def vc_reinsertion(self, vc, target_queue): if vc.quantum > 0 and len(vc.flits) > 0: target_queue.insert(0, vc) else: vc.reset_credit() def get_highest_preemptive_priority_vc(self, candidates): # No Arbitration if len(candidates) == 1: return candidates[0] # filtering by timestamp for can in candidates: if can.flits[-1].timestamp == self.env.now: candidates.remove(can) priority_vc = candidates[0] # Arbitration according to Priority for candidate in candidates[1:]: if priority_vc.id > candidate.id: priority_vc = candidate return priority_vc def priority_preemptive_arbitration(self): # ---------- VC election ---------- for vc in self.inPE.vcs: self.vc_target_outport(vc) # Checking North VC for vc in self.inNorth.vcs: self.vc_target_outport(vc) # Checking South VC for vc in self.inSouth.vcs: self.vc_target_outport(vc) # Checking East VC for vc in self.inEast.vcs: self.vc_target_outport(vc) # Checking West VC for vc in self.inWest.vcs: self.vc_target_outport(vc) # VC targeting -> North if len(self.vcs_target_north) > 0: vc = self.get_highest_preemptive_priority_vc(self.vcs_target_north) self.vcs_target_north.clear() self.logger.debug('(%d) - %s From %s -> Elected' % (self.env.now, vc, self)) self.send_flit(vc, self.outNorth) # VC targeting -> South if len(self.vcs_target_south) > 0: vc = self.get_highest_preemptive_priority_vc(self.vcs_target_south) self.vcs_target_south.clear() self.logger.debug('(%d) - %s From %s -> Elected' % (self.env.now, vc, self)) self.send_flit(vc, self.outSouth) # VC targeting -> East if len(self.vcs_target_east) > 0: vc = self.get_highest_preemptive_priority_vc(self.vcs_target_east) self.vcs_target_east.clear() self.logger.debug('(%d) - %s From %s -> Elected' % (self.env.now, vc, self)) self.send_flit(vc, self.outEast) # VC targeting -> West if len(self.vcs_target_west) > 0: vc = self.get_highest_preemptive_priority_vc(self.vcs_target_west) self.vcs_target_west.clear() self.logger.debug('(%d) - %s From %s -> Elected' % (self.env.now, vc, self)) self.send_flit(vc, self.outWest) # VC targeting -> PE if len(self.vcs_target_pe) > 0: vc = self.get_highest_preemptive_priority_vc(self.vcs_target_pe) self.vcs_target_pe.clear() self.logger.debug('(%d) - %s From %s -> Elected' % (self.env.now, vc, self)) self.arrived_flit(vc) def __str__(self): return 'Router (%d,%d)' % (self.coordinate.i, self.coordinate.j)