protected void statsEjectFlit(Flit f) { // Keep track of how many packets get ejected ejectPacketCount++; // actually eject flit count // per-flit latency stats ulong net_latency = Simulator.CurrentRound - f.injectionTime; ulong total_latency = Simulator.CurrentRound - f.packet.creationTime; ulong inj_latency = total_latency - net_latency; #if DEBUG Console.WriteLine("Cycle: {2} PID: {0} FID: {1} | EJECT Coord ({4},{5}) createTime {3}", f.packet.ID, f.flitNr, Simulator.CurrentRound, f.packet.injectionTime, coord.x, coord.y); #endif Simulator.stats.flit_inj_latency.Add(inj_latency); Simulator.stats.flit_net_latency.Add(net_latency); // A rough estimate of number of cycles it would take for a flit to go Simulator.stats.flit_net_latency_alone_byreqID[f.packet.requesterID].Add( (int)Simulator.distance(f.packet.src, f.packet.dest) * Config.router.linkLatency); // Record the net latency for each requester to take care of data reply from random sources Simulator.stats.flit_net_latency_byreqID[f.packet.requesterID].Add(net_latency); Simulator.stats.mshrThrottle_flit_net_latency.Add(net_latency); Simulator.stats.flit_total_latency.Add(inj_latency); Simulator.stats.eject_flit.Add(); Simulator.stats.eject_flit_bydest[f.packet.dest.ID].Add(); int id = f.packet.dest.ID; // Collect stats on my own data reply only if (id == f.packet.requesterID) { Simulator.stats.eject_flit_myReply[id].Add(); } Simulator.stats.eject_flit_byreqID[f.packet.requesterID].Add(); int minpath = Math.Abs(f.packet.dest.x - f.packet.src.x) + Math.Abs(f.packet.dest.y - f.packet.src.y); Simulator.stats.minpath.Add(minpath); Simulator.stats.minpath_bysrc[f.packet.src.ID].Add(minpath); //f.dumpDeflections(); Simulator.stats.deflect_perdist[f.distance].Add(f.nrOfDeflections); if (f.nrOfDeflections != 0) { Simulator.stats.deflect_perflit_byreq[f.packet.requesterID].Add(f.nrOfDeflections); } }
// closest out of 'nodes' set int closest(int node, CmpCache_Owners nodes) { int best = -1; int best_dist = m_N; Coord here = new Coord(node); for (int i = 0; i < m_N; i++) { if (nodes.is_set(i)) { int dist = (int)Simulator.distance(new Coord(i), here); if (dist < best_dist) { best = i; best_dist = dist; } } } return(best); }
protected override void _doStep() { stepNacks(); /* bool ejectedThisCycle = */ ejectLocal(); for (int i = 0; i < 4; i++) { input[i] = null; } // first, propagate the non-head flits along their worm paths // (no truncation, so this is very simple) for (int dir = 0; dir < 4; dir++) { if (linkIn[dir] != null && linkIn[dir].Out != null && !linkIn[dir].Out.isHeadFlit) { #if DEBUG Console.WriteLine("non-head flit: {0}", linkIn[dir].Out); #endif Flit f = linkIn[dir].Out; // grab the input flit from the link linkIn[dir].Out = null; if (wormRouting[dir] == -1) { // AGH: worm not routed throw new Exception("SHOULDN'T HAPPEN!"); } if (wormRouting[dir] != -2) // if not dropping, propagate the flit { linkOut[wormRouting[dir]].In = f; } if (f.isTailFlit) // if last flit, close the wormhole { wormRouting[dir] = -1; } } } if (m_injectSlot != null && !m_injectSlot.isHeadFlit) { linkOut[wormRouting[4]].In = m_injectSlot; if (m_injectSlot.isTailFlit) { wormRouting[4] = -1; } m_injectSlot = null; } // grab inputs into a local array int c = 0; for (int dir = 0; dir < 4; dir++) { if (linkIn[dir] != null && linkIn[dir].Out != null) { linkIn[dir].Out.inDir = dir; // record this for below input[c++] = linkIn[dir].Out; linkIn[dir].Out = null; } } // step 1: get possible-output vectors for each input bool[,] possible = new bool[4, 4]; // (input,direction) int[] possible_count = new int[4]; for (int i = 0; i < 4 && input[i] != null; i++) { PreferredDirection pd = determineDirection(input[i].dest); if (pd.xDir != Simulator.DIR_NONE && linkOut[pd.xDir].In == null) { if (nackAvailable(pd.xDir)) { possible[i, pd.xDir] = true; } else { Simulator.stats.nack_unavail.Add(); Simulator.stats.nack_unavail_by_src[ID].Add(); } } if (pd.yDir != Simulator.DIR_NONE && linkOut[pd.yDir].In == null) { if (nackAvailable(pd.yDir)) { possible[i, pd.yDir] = true; } else { Simulator.stats.nack_unavail.Add(); Simulator.stats.nack_unavail_by_src[ID].Add(); } } } // step 2: count possible requests per output for (int i = 0; i < 4; i++) { for (int dir = 0; dir < 4; dir++) { if (possible[i, dir]) { possible_count[dir]++; } } } // step 3: if more than one possible for a given request, pick one with least // requests; if tie, break randomly for (int i = 0; i < 4; i++) { int min_req = 10, min_req_j = -1; for (int j = 0; j < 4; j++) { if (possible[i, j]) { if (possible_count[j] < min_req) { min_req_j = j; min_req = possible_count[j]; } } } for (int j = 0; j < 4; j++) { possible[i, j] = false; } if (min_req_j != -1) { possible[i, min_req_j] = true; } } // step 4,5: compute maximum priority requesting each output; set everyone // below this prio to false for (int dir = 0; dir < 4; dir++) { int max_prio = -1; for (int i = 0; i < 4; i++) { if (possible[i, dir]) { if (input[i].packet.scarab_retransmit_count > max_prio) { max_prio = input[i].packet.scarab_retransmit_count; } } } for (int i = 0; i < 4; i++) { if (possible[i, dir] && input[i].packet.scarab_retransmit_count < max_prio) { possible[i, dir] = false; } } } // step 6: select a winner in round-robin fashion int offset = getRR(); int[] assignments = new int[4]; for (int i = 0; i < 4; i++) { assignments[i] = -1; } for (int i_ = 0; i_ < 4; i_++) { int i = (i_ + offset) % 4; for (int dir = 0; dir < 4; dir++) { if (possible[i, dir]) { assignments[i] = dir; for (int j = 0; j < 4; j++) { possible[j, dir] = false; } } } } //Flit oppBufferable = null; // assign outputs, choose a flit to opp. buffer if appropriate for (int i = 0; i < 4 && input[i] != null; i++) { int dir = assignments[i]; if (dir == -1) { // drop! sendNack(input[i]); wormRouting[input[i].inDir] = -2; Simulator.stats.drop.Add(); Simulator.stats.drop_by_src[ID].Add(); } else { double decay = 0.875; //TODO parameterize avgOutPriority[dir] = avgOutPriority[dir] * (1 - decay) + input[i].packet.scarab_retransmit_count * decay; /* * if (Config.opp_buffering * && !ejectedThisCycle * && input[i].packet.nrOfFlits == 1 * && myProcessor.msh.hasOppBufferSpace() * && input[i].packet.scarab_retransmit_count < avgOutPriority[dir] * ) * { * // buffer opportunistically! (choose highest priority packet) * if (oppBufferable == null || input[i].packet.scarab_retransmit_count > oppBufferable.packet.scarab_retransmit_count) * oppBufferable = input[i]; * } */ } } for (int i = 0; i < 4 && input[i] != null; i++) { int dir = assignments[i]; if (dir == -1) { continue; } int nackWire; ulong due = Simulator.CurrentRound + 4 * (1 + Simulator.distance(coord, input[i].dest)); //nack_due[input[i].packet] = due; /* * if (input[i] == oppBufferable) * { * Console.WriteLine("Opp Buffering flit!"); * sendTeardown(oppBufferable); * myProcessor.ejectFlit(oppBufferable); * * nackWire = allocateNack(dir, -2, due); * } * else */ nackWire = allocateNack(dir, nackNr(input[i].inDir, input[i].nackWire), due); if (nackWire == -1) { throw new Exception("shouldn't happen"); } input[i].nackWire = nackWire; linkOut[dir].In = input[i]; wormRouting[input[i].inDir] = dir; } // now try to inject if (m_injectSlot != null) { PreferredDirection pd = determineDirection(m_injectSlot.dest); ulong due = Simulator.CurrentRound + 4 * (1 + Simulator.distance(coord, m_injectSlot.dest)); //nack_due[m_injectSlot.packet] = due; if (pd.xDir != Simulator.DIR_NONE && linkOut[pd.xDir].In == null) { int nackWire = allocateNack(pd.xDir, -2, due); if (nackWire != -1) { linkOut[pd.xDir].In = m_injectSlot; m_injectSlot.nackWire = nackWire; m_injectSlot = null; wormRouting[4] = pd.xDir; } } if (m_injectSlot != null && // check this again: only try y if x didn't work pd.yDir != Simulator.DIR_NONE && linkOut[pd.yDir].In == null) { int nackWire = allocateNack(pd.yDir, -2, due); if (nackWire != -1) { linkOut[pd.yDir].In = m_injectSlot; m_injectSlot.nackWire = nackWire; m_injectSlot = null; wormRouting[4] = pd.yDir; } } } }