void TrafficManager::_ClassInject() { Flit *f, *nf; Credit *cred; int psize; // Receive credits and inject new traffic for (int input = 0; input < _net->NumSources(); ++input) { cred = _net->ReadCredit(input); if (cred) { _buf_states[input]->ProcessCredit(cred); delete cred; } bool write_flit = false; int highest_class = 0; bool generated; for (int c = 0; c < _classes; ++c) { // Potentially generate packets for any (input,class) // that is currently empty if (_partial_packets[input][c].empty()) { generated = false; if (!_empty_network) { // Lagging injection process while (!generated && (_qtime[input][c] <= _time)) { psize = _IssuePacket(input, c); if (psize) { _GeneratePacket(input, psize, c, _include_queuing ? _qtime[input][c] : _time); generated = true; } ++_qtime[input][c]; } if ((_sim_state == draining) && (_qtime[input][c] > _drain_time)) { _qdrained[input][c] = true; } } if (generated) { highest_class = c; } } else { highest_class = c; } } // Now, check partially issued packet to // see if it can be issued if (!_partial_packets[input][highest_class].empty()) { f = _partial_packets[input][highest_class].front(); if (f->head && (f->vc == -1)) { // Find first available VC f->vc = _buf_states[input]->FindAvailable(); if (f->vc != -1) { _buf_states[input]->TakeBuffer(f->vc); } } if (f->vc != -1) { if (!_buf_states[input]->IsFullFor(f->vc)) { _partial_packets[input][highest_class].pop_front(); _buf_states[input]->SendingFlit(f); write_flit = true; // Pass VC "back" if (!_partial_packets[input][highest_class].empty() && !f->tail) { nf = _partial_packets[input][highest_class].front(); nf->vc = f->vc; } } if (f->watch) { cout << "Flit " << f->id << " written into injection port at time " << _time << endl; } } else { if (f->watch) { cout << "Flit " << f->id << " stalled at injection waiting for available VC at time " << _time << endl; } } } _net->WriteFlit(write_flit ? f : 0, input); } }
void TrafficManager::_VOQInject() { Flit *f; Credit *cred; int vc; int dest; int psize; for (int input = 0; input < _net->NumSources(); ++input) { // Receive credits cred = _net->ReadCredit(input); if (cred) { _buf_states[input]->ProcessCredit(cred); for (int i = 0; i < cred->vc_cnt; i++) { vc = cred->vc[i]; // If this credit enables a VC that has packets waiting, // set the VC to active (append it to the active list) if (!_voq[input][vc].empty() && !_active_vc[input][vc]) { f = _voq[input][vc].front(); if ((f->head && _buf_states[input]->IsAvailableFor(vc)) || (!f->head && !_buf_states[input]->IsFullFor(vc))) { _active_list[input].push_back(vc); _active_vc[input][vc] = true; } } } delete cred; } if (!_empty_network) { // Inject packets psize = _IssuePacket(input, 0); } else { psize = 0; } if (psize) { _GeneratePacket(input, psize, 0, _time); dest = -1; bool wasempty = false; // Move a generated packet to the appropriate VOQ while (!_partial_packets[input][0].empty()) { f = _partial_packets[input][0].front(); _partial_packets[input][0].pop_front(); if (f->head) { dest = f->dest; wasempty = _voq[input][dest].empty(); } if (dest == -1) { Error("Didn't see head flit in VOQ injection"); } f->dest = dest; f->vc = dest; _voq[input][dest].push_back(f); } // If this packet enables a VC, // set the VC to active (append it to the active list) if (wasempty && (!_active_vc[input][dest]) && (_buf_states[input]->IsAvailableFor(dest))) { _active_list[input].push_back(dest); _active_vc[input][dest] = true; } } // Write packets to the network if (!_active_list[input].empty()) { dest = _active_list[input].front(); _active_list[input].pop_front(); if (_voq[input][dest].empty()) { Error("VOQ marked as active, but empty"); } f = _voq[input][dest].front(); _voq[input][dest].pop_front(); if (f->head) { _buf_states[input]->TakeBuffer(dest); } _buf_states[input]->SendingFlit(f); _net->WriteFlit(f, input); // Inactivate VC if it can't accept any more flits or // no more flits are available to be sent if ((f->tail && _buf_states[input]->IsAvailableFor(dest)) || (!f->tail && !_buf_states[input]->IsFullFor(dest))) { _active_list[input].push_back(dest); } else { _active_vc[input][dest] = false; } } else { _net->WriteFlit(0, input); } } }
void PTrafficManager::_NormalInjectP(int tid){ short ** class_array; class_array = new short* [duplicate_networks]; for (int i=0; i < duplicate_networks; ++i) { class_array[i] = new short [_classes]; memset(class_array[i], 0, sizeof(short)*_classes); } Flit *f, *nf; Credit *cred; int psize; // Receive credits and inject new traffic for ( int input_pos = 0; input_pos < node_count[tid]; ++input_pos ) { int input = node_list[tid][input_pos]; for (int i = 0; i < duplicate_networks; ++i) { cred = _net[i]->ReadCredit( input ); if ( cred ) { _buf_states[input][i]->ProcessCredit( cred ); delete cred; } } bool write_flit = false; int highest_class = 0; bool generated; for ( int c = 0; c < _classes; ++c ) { // Potentially generate packets for any (input,class) // that is currently empty if ( (duplicate_networks > 1) || _partial_packets[input][c][0].empty() ) { // For multiple networks, always flip coin because now you have multiple send buffers so you can't choose one only to check. generated = false; if ( !_empty_network ) { while( !generated && ( _qtime[input][c] <= thread_time[tid] ) ) { psize = _IssuePacket( input, c ); if ( psize ) { //generate a packet _GeneratePacketP( input, psize, c, _include_queuing==1 ? _qtime[input][c] : thread_time[tid], tid ); generated = true; } //this is not a request packet //don't advance time if(_use_read_write && psize>0){ assert(false); } else { ++_qtime[input][c]; } } if ( ( _sim_state == draining ) && ( _qtime[input][c] > _drain_time ) ) { _qdrained[input][c] = true; } } if ( generated ) { //highest_class = c; class_array[sub_network][c]++; // One more packet for this class. } } //else { //highest_class = c; //} This is not necessary with class_array because it stays. } // Now, check partially issued packets to // see if they can be issued for (int i = 0; i < duplicate_networks; ++i) { write_flit = false; highest_class = 0; // // Now just find which is the highest_class. // for (short a = _classes - 1; a >= 0; --a) { // if (class_array[i][a]) { // highest_class = a; // break; // } // } if ( !_partial_packets[input][highest_class][i].empty( ) ) { f = _partial_packets[input][highest_class][i].front( ); if ( f->head && f->vc == -1) { // Find first available VC if ( _voqing ) { if ( _buf_states[input][i]->IsAvailableFor( f->dest ) ) { f->vc = f->dest; } } else { f->vc = _buf_states[input][i]->FindAvailable( ); } if ( f->vc != -1 ) { _buf_states[input][i]->TakeBuffer( f->vc ); } } if ( ( f->vc != -1 ) && ( !_buf_states[input][i]->IsFullFor( f->vc ) ) ) { _partial_packets[input][highest_class][i].pop_front( ); _buf_states[input][i]->SendingFlit( f ); write_flit = true; // Pass VC "back" if ( !_partial_packets[input][highest_class][i].empty( ) && !f->tail ) { nf = _partial_packets[input][highest_class][i].front( ); nf->vc = f->vc; } } } _net[i]->WriteFlit( write_flit ? f : 0, input ); if (write_flit && f->tail) // If a tail flit, reduce the number of packets of this class. class_array[i][highest_class]--; } } for (int i=0; i < duplicate_networks; ++i) { delete [] class_array[i]; } delete [] class_array; }