示例#1
0
void TrafficManager::_Step()
{
	Flit *f;
	Credit *cred;

	// Inject traffic
	if (_voqing)
	{
		_VOQInject();
	}
	else
	{
		_ClassInject();
	}

	// Advance network

	_net->ReadInputs();

	_partial_internal_cycles += _internal_speedup;
	while (_partial_internal_cycles >= 1.0)
	{
		_net->InternalStep();
		_partial_internal_cycles -= 1.0;
	}

	_net->WriteOutputs();

	++_time;

	// Eject traffic and send credits

	for (int output = 0; output < _dests; ++output)
	{
		f = _net->ReadFlit(output);

		if (f)
		{
			if (f->watch)
			{
				cout << "ejected flit " << f->id << " at output " << output
						<< endl;
				cout << "sending credit for " << f->vc << endl;
			}

			cred = new Credit(1);
			cred->vc[0] = f->vc;
			cred->vc_cnt = 1;
			cred->head = f->head;
			cred->tail = f->tail;

			_net->WriteCredit(cred, output);

			if (f->head && (f->dest != output))
			{
				cout << "At output " << output << endl;
				cout << *f;
				Error("Flit arrived at incorrect output");
			}

			if (_reorder)
			{
				if (f->watch)
				{
					cout << "adding flit " << f->id << " to reorder buffer"
							<< endl;
					cout << "flit's SN is " << f->sn << " buffer's SN is "
							<< _rob_sqn[f->src][f->dest] << endl;
				}

				if (f->sn > _rob_sqn_max[f->src][f->dest])
				{
					_rob_sqn_max[f->src][f->dest] = f->sn;
				}

				if (f->head)
				{
					_rob_size->AddSample(f->sn - _rob_sqn[f->src][f->dest]);
				}

				f->rob_time = _time;
				_rob[f->src][output].push(f);
			}
			else
			{
				_RetireFlit(f, output);
				if (!_empty_network)
				{
					_accepted_packets[output]->AddSample(1);
				}
			}
		}
		else
		{
			_net->WriteCredit(0, output);

			if (!_reorder && !_empty_network)
			{
				_accepted_packets[output]->AddSample(0);
			}
		}

		if (_reorder)
		{
			f = _ReadROB(output);

			if (f)
			{
				if (f->watch)
				{
					cout << "flit " << f->id << " removed from ROB at output "
							<< output << endl;
				}

				_RetireFlit(f, output);
				if (!_empty_network)
				{
					_accepted_packets[output]->AddSample(1);
				}
			}
			else
			{
				if (!_empty_network)
				{
					_accepted_packets[output]->AddSample(0);
				}
			}
		}
	}
}
示例#2
0
void TrafficManager::_Step( )
{
    Flit   *f;
    Credit *cred;

    // Inject traffic
    if ( _voqing ) {
        _VOQInject( );
    } else {
        _ClassInject( );
    }

    // Advance network

    _net->ReadInputs( );

    _partial_internal_cycles += _internal_speedup;
    while ( _partial_internal_cycles >= 1.0 ) {
        _net->InternalStep( );
        _partial_internal_cycles -= 1.0;
    }

    _net->WriteOutputs( );

    ++_time;

    // Eject traffic and send credits
    Flit   *last_valid_flit; //= new Flit;
    for ( int output = 0; output < _dests; ++output ) {
        f = _net->ReadFlit( output );

        if ( f ) {
            if (1 || f->tail) {
                write_out_buf(output, f); // it should have space!
                if ( f->watch ) {
                    cout << "Sent flit " << f->id << " to output buffer " << output << endl;
                    cout << " Not sending the credit yet! " <<endl;
                }
            } else {
                if ( f->watch ) {
                    cout << "ejected flit " << f->id << " at output " << output << endl;
                    cout << "sending credit for " << f->vc << endl;
                }

                if ( _reorder ) {
                    if ( f->watch ) {
                        cout << "adding flit " << f->id << " to reorder buffer" << endl;
                        cout << "flit's SN is " << f->sn << " buffer's SN is "
                             << _rob_sqn[f->src][f->dest] << endl;
                    }

                    if ( f->sn > _rob_sqn_max[f->src][f->dest] ) {
                        _rob_sqn_max[f->src][f->dest] = f->sn;
                    }

                    if ( f->head ) {
                        _rob_size->AddSample( f->sn - _rob_sqn[f->src][f->dest] );
                    }

                    f->rob_time = _time;
                    _rob[f->src][output].push( f );
                } else {
                    _RetireFlit( f, output );
                    if ( !_empty_network ) {
                        _accepted_packets[output]->AddSample( 1 );
                    }
                }
            }
        }
        transfer2boundary_buf( output );
        if (!credit_return_queue[output].empty()) {
            last_valid_flit = credit_return_queue[output].front();
            credit_return_queue[output].pop();
        } else {
            last_valid_flit=NULL;
        }
        if (last_valid_flit) {


            cred = new Credit( 1 );
            cred->vc[0] =last_valid_flit->vc;
            cred->vc_cnt = 1;
            cred->head = last_valid_flit->head;
            cred->tail =last_valid_flit->tail;

            _net->WriteCredit( cred, output );
            if (last_valid_flit->watch) {
                cout <<"WE WROTE A CREDIT for flit "<<last_valid_flit->id<<"To output "<<output<< endl;
            }
            _RetireFlit(last_valid_flit, output );
            if ( !_empty_network ) {
                _accepted_packets[output]->AddSample( 1 );
            }
        } else {
            _net->WriteCredit( 0, output );

            if ( !_reorder && !_empty_network) {
                _accepted_packets[output]->AddSample( 0 );
            }
        }

        if ( _reorder ) {
            f = _ReadROB( output );

            if ( f ) {
                if ( f->watch ) {
                    cout << "flit " << f->id << " removed from ROB at output " << output << endl;
                }

                _RetireFlit( f, output );
                if ( !_empty_network ) {
                    _accepted_packets[output]->AddSample( 1 );
                }
            } else {
                if ( !_empty_network ) {
                    _accepted_packets[output]->AddSample( 0 );
                }
            }
        }
    }
}
示例#3
0
void GPUTrafficManager::_Step()
{
  bool flits_in_flight = false;
  for(int c = 0; c < _classes; ++c) {
    flits_in_flight |= !_total_in_flight_flits[c].empty();
  }
  if(flits_in_flight && (_deadlock_timer++ >= _deadlock_warn_timeout)){
    _deadlock_timer = 0;
    cout << "WARNING: Possible network deadlock.\n";
  }
  
  vector<map<int, Flit *> > flits(_subnets);
  
  for ( int subnet = 0; subnet < _subnets; ++subnet ) {
    for ( int n = 0; n < _nodes; ++n ) {
      Flit * const f = _net[subnet]->ReadFlit( n );
      if ( f ) {
        if(f->watch) {
          *gWatchOut << GetSimTime() << " | "
          << "node" << n << " | "
          << "Ejecting flit " << f->id
          << " (packet " << f->pid << ")"
          << " from VC " << f->vc
          << "." << endl;
        }

        if(g_hpcl_comp_config.hpcl_comp_en == 0) {
          g_icnt_interface->WriteOutBuffer(subnet, n, f);
          //added by kh(030816)
          g_hpcl_network_anal->add_sample(hpcl_network_anal::NORMAL_FLIT_NO, 1);
          ///

        } else {
	  //added by kh (030816)
	  //(2.1.a) all reply flits (even write reply) are injected to decompressor for maintaining the order of flits.
	  //coming from the same vc
	  //Decompression: WRITE_REPLY should go through decomp, although no data is compressed.
	  //READ_REPLY = {f1,f2,f3,f4,f5}, WRITE_REPLY = {f6}
	  //Problematic case queue: f1,f2,f6,f3,f4,f5.
	  if(f->type == Flit::READ_REPLY || f->type == Flit::WRITE_REPLY) {	//only sm receives

	    assert(g_hpcl_global_decomp_pl_2B[n]);
	    //inject a flit to decompressor
	    hpcl_comp_pl_data* pl_data = new hpcl_comp_pl_data;
	    pl_data->add_comp_pl_data(f);
	    g_hpcl_global_decomp_pl_2B[n]->set_input_data(pl_data);

	    //added by kh (030316)
	    //set vc info to compressed flits.
	    for(int i = 0; i < f->compressed_other_flits.size(); i++) {
	      Flit* cf = f->compressed_other_flits[i];
	      assert(cf);
	      cf->vc = f->vc;
	    }
	    ///
	    //delete pl_data;

	    //added by kh (030816)
	    g_hpcl_network_anal->add_sample(hpcl_network_anal::NORMAL_FLIT_NO, 1);

	    if(f->compressed_other_flits.size() > 0) {
	      g_hpcl_network_anal->add_sample(hpcl_network_anal::READ_REPLY_COMP_FLIT_NO, f->compressed_other_flits.size()+1);
	    } else {
	      g_hpcl_network_anal->add_sample(hpcl_network_anal::READ_REPLY_UNCOMP_FLIT_NO, 1);
	    }
	    ///

	  } else if(f->type == Flit::CTRL_MSG) {	//(2.2.a) all ctrl flits are injected to decompressor

	    //std::cout << "f->id " << f->id << " f->src " << f->src << " f->dest " << f->dest << " node " << n << std::endl;
	    hpcl_comp_pl_data* pl_data = new hpcl_comp_pl_data;
	    pl_data->add_comp_pl_data(f);
	    g_hpcl_global_decomp_pl_2B[n]->set_input_data(pl_data);

	    //added by kh (030816)
	    g_hpcl_network_anal->add_sample(hpcl_network_anal::CTRL_FLIT_NO,1);
	    ///

	  } else {

	    g_icnt_interface->WriteOutBuffer(subnet, n, f);

	    //added by kh (030816)
	    g_hpcl_network_anal->add_sample(hpcl_network_anal::NORMAL_FLIT_NO, 1);
	    ///

	  }
	  ///
        }
      }
      

      g_icnt_interface->Transfer2BoundaryBuffer(subnet, n);
      Flit* const ejected_flit = g_icnt_interface->GetEjectedFlit(subnet, n);
      if (ejected_flit) {
        if(ejected_flit->head)
          assert(ejected_flit->dest == n);
        if(ejected_flit->watch) {
          *gWatchOut << GetSimTime() << " | "
          << "node" << n << " | "
          << "Ejected flit " << ejected_flit->id
          << " (packet " << ejected_flit->pid
          << " VC " << ejected_flit->vc << ")"
          << "from ejection buffer." << endl;
        }
        flits[subnet].insert(make_pair(n, ejected_flit));
        if((_sim_state == warming_up) || (_sim_state == running)) {
          ++_accepted_flits[ejected_flit->cl][n];
          if(ejected_flit->tail) {
            ++_accepted_packets[ejected_flit->cl][n];
          }
        }
      }
    
      // Processing the credit From the network
      Credit * const c = _net[subnet]->ReadCredit( n );
      if ( c ) {
#ifdef TRACK_FLOWS
        for(set<int>::const_iterator iter = c->vc.begin(); iter != c->vc.end(); ++iter) {
          int const vc = *iter;
          assert(!_outstanding_classes[n][subnet][vc].empty());
          int cl = _outstanding_classes[n][subnet][vc].front();
          _outstanding_classes[n][subnet][vc].pop();
          assert(_outstanding_credits[cl][subnet][n] > 0);
          --_outstanding_credits[cl][subnet][n];
        }
#endif
        _buf_states[n][subnet]->ProcessCredit(c);
        c->Free();
      }
    }
    _net[subnet]->ReadInputs( );
  }


  if(g_hpcl_comp_config.hpcl_comp_en == 1)
  {
    //added by kh (030816)
    //(2.3) Decompressor
    for(int i = 0; i < g_hpcl_global_decomp_pl_2B.size(); i++)
    {
      if(!g_hpcl_global_decomp_pl_2B[i])	continue;

      g_hpcl_global_decomp_pl_2B[i]->run(getTime()+getTotalTime());
      hpcl_comp_pl_data* comp_pl_data = g_hpcl_global_decomp_pl_2B[i]->get_output_data();
      Flit* flit = comp_pl_data->get_flit_ptr();
      if(flit) {
	int subnet = 0;
	assert(flit->const_dest == i);
	//std::cout << "Flit " << flit->id << " type " << flit->type << " is out from decomp" << std::endl;
	/*
	std::cout << GetSimTime() << "| MYEJECT | node " << i << " Flit " << flit->id << " type " << flit->type << " tail " << flit->tail << " vc " << flit->vc;
	if(flit->type == Flit::ANY_TYPE)	std::cout << " ctrl " << std::endl;
	else				std::cout << " mf " << ((mem_fetch*)flit->data)->get_request_uid() << std::endl;
	*/

	//std::cout << "Flit " << flit->id << " enc_status " << flit->m_enc_status;
	#ifdef CORRECTNESS_CHECK
	if(flit->m_enc_status == 1) {
	  std::cout << "dec_status " << flit->check_correctness() << std::endl;
	  if(flit->check_correctness() == false) {

	    printf("flit %d has incorrect decoding!\n", flit->id);

	    printf("\traw_data = ");
	    for(int k = flit->raw_data.size()-1; k >=0; k--) {
		    printf("%02x", flit->raw_data[k]);
	    }
	    printf("\n");

	    printf("\tdec_data = ");
	    for(int k = flit->decomp_data.size()-1; k >=0; k--) {
		    printf("%02x", flit->decomp_data[k]);
	    }
	    printf("\n");
	  }
	}
	#endif

	g_icnt_interface->WriteOutBuffer(subnet, i, flit);
      }

      //reset output data
      g_hpcl_global_decomp_pl_2B[i]->reset_output_data();
    }
    ///


    //added by kh (030816)
    //(1.2.c) generate/inject ctrl flit is injected to NI injection buffer
    for(int i = 0; i < g_hpcl_global_comp_pl_2B.size(); i++)
    {
      if(!g_hpcl_global_comp_pl_2B[i])	continue;
      if(g_hpcl_global_comp_pl_2B[i]->has_out_dict_ctrl_msg() == false)	continue;
      if(g_hpcl_global_comp_pl_2B[i]->get_state() == hpcl_comp_pl<unsigned short>::HPCL_COMP_RUN)	continue;

      hpcl_dict_ctrl_msg<unsigned short>* ctrl_msg = g_hpcl_global_comp_pl_2B[i]->front_out_dict_ctrl_msg();
      int packet_size = 1;	//1 flit
      Flit::FlitType packet_type = Flit::CTRL_MSG;
      void* data = NULL;
      assert(ctrl_msg->get_dest_node()>=0);
      int subnet = 0;
      int response_size = 32; 	//32bytes

      //send ctrl from MC
      int sender_device_id = -1;
      if(g_mc_placement_config.is_mc_node(i)) {
	sender_device_id = g_mc_placement_config.get_mc_node_index(i) + 56;	//56 SMs and 8 MCs
      }
      assert(sender_device_id >= 0);

      int sender_node_id = i;
      int receiver_node_id = ctrl_msg->get_dest_node();
      int receiver_device_id = g_mc_placement_config.get_sm_node_index(receiver_node_id);

      assert(sender_node_id>=0);
      assert(receiver_node_id>=0);
      if(g_icnt_interface->HasBuffer(sender_device_id, response_size)) {
	//std::cout << getTime()+getTotalTime() << " | " << " PUSH2 | " << " input " << sender_device_id << " output " << receiver_device_id << " ctrl_msg " << ctrl_msg->get_id();
	//std::cout << std::endl;
	_GeneratePacket(sender_node_id, -1, 0, getTime(), subnet, packet_size, packet_type, ctrl_msg, receiver_node_id);
	g_hpcl_global_comp_pl_2B[i]->pop_out_dict_ctrl_msg();

  //      std::cout << "ctrl_msg | id " << ctrl_msg->get_id();
  //      std::cout << " | src_node " << ctrl_msg->get_src_node();
  //      std::cout << " | dest_node " << ctrl_msg->get_dest_node();
  //      std::cout << " | word_index " << ctrl_msg->get_word_index();
  //      std::cout << " | word " << ctrl_msg->get_new_word() << std::endl;;
  //
  //      g_hpcl_global_comp_pl_2B[i]->validate_word(ctrl_msg->get_dest_node(), ctrl_msg->get_word_index(), ctrl_msg->get_new_word());
      }
    }
    ///

  }

// GPGPUSim will generate/inject packets from interconnection interface
#if 0
  if ( !_empty_network ) {
    _Inject();
  }
#endif
  
  for(int subnet = 0; subnet < _subnets; ++subnet) {
    
    for(int n = 0; n < _nodes; ++n) {
      
      Flit * f = NULL;
      
      BufferState * const dest_buf = _buf_states[n][subnet];
      
      int const last_class = _last_class[n][subnet];
      
      int class_limit = _classes;
      
      if(_hold_switch_for_packet) {
        list<Flit *> const & pp = _input_queue[subnet][n][last_class];
        if(!pp.empty() && !pp.front()->head &&
           !dest_buf->IsFullFor(pp.front()->vc)) {
          f = pp.front();
          assert(f->vc == _last_vc[n][subnet][last_class]);
          
          // if we're holding the connection, we don't need to check that class
          // again in the for loop
          --class_limit;
        }
      }
      
      for(int i = 1; i <= class_limit; ++i) {
        
        int const c = (last_class + i) % _classes;
        
        list<Flit *> const & pp = _input_queue[subnet][n][c];
        
        if(pp.empty()) {
          continue;
        }
        
        Flit * const cf = pp.front();
        assert(cf);
        assert(cf->cl == c);
        assert(cf->subnetwork == subnet);

        if(g_hpcl_comp_config.hpcl_comp_en == 1) {
	  //added by kh (030816)
	  //If compressor is busy with compressing flits of a packet,
	  //don't inject a head flit of a new packet to the busy compressor
	  //compressor is only for read reply, but write reply goes through the compressor to avoid intermixed flits from different packets
	  //Thus, the following filtering is not restricted to read reply, thus we have no flit type checking to read reply.
	  if(g_mc_placement_config.is_mc_node(n) == true && cf->head == true) {
	    if(g_hpcl_global_comp_pl_2B[n] && g_hpcl_global_comp_pl_2B[n]->get_state() == hpcl_comp_pl<unsigned short>::HPCL_COMP_RUN) {
	      f = NULL;
	      break;
	    }
	  }
	  ///
        }

        if(f && (f->pri >= cf->pri)) {
          continue;
        }
        
        //KH: routing output port is decided here.
        if(cf->head && cf->vc == -1) { // Find first available VC
          
          //std::cout << "_Step is called!!!!" << std::endl;
          //assert(1 == 0);

          OutputSet route_set;
          _rf(NULL, cf, -1, &route_set, true);
          set<OutputSet::sSetElement> const & os = route_set.GetSet();
          assert(os.size() == 1);
          OutputSet::sSetElement const & se = *os.begin();
          assert(se.output_port == -1);
          int vc_start = se.vc_start;
          int vc_end = se.vc_end;
          int vc_count = vc_end - vc_start + 1;
          if(_noq) {
            assert(_lookahead_routing);
            const FlitChannel * inject = _net[subnet]->GetInject(n);
            const Router * router = inject->GetSink();
            assert(router);
            int in_channel = inject->GetSinkPort();
            

            // NOTE: Because the lookahead is not for injection, but for the
            // first hop, we have to temporarily set cf's VC to be non-negative
            // in order to avoid seting of an assertion in the routing function.
            cf->vc = vc_start;
            _rf(router, cf, in_channel, &cf->la_route_set, false);
            cf->vc = -1;
            
            if(cf->watch) {
              *gWatchOut << GetSimTime() << " | "
              << "node" << n << " | "
              << "Generating lookahead routing info for flit " << cf->id
              << " (NOQ)." << endl;
            }
            set<OutputSet::sSetElement> const sl = cf->la_route_set.GetSet();
            assert(sl.size() == 1);
            int next_output = sl.begin()->output_port;
            vc_count /= router->NumOutputs();
            vc_start += next_output * vc_count;
            vc_end = vc_start + vc_count - 1;
            assert(vc_start >= se.vc_start && vc_start <= se.vc_end);
            assert(vc_end >= se.vc_start && vc_end <= se.vc_end);
            assert(vc_start <= vc_end);
          }
          if(cf->watch) {
            *gWatchOut << GetSimTime() << " | " << FullName() << " | "
            << "Finding output VC for flit " << cf->id
            << ":" << endl;
          }
          for(int i = 1; i <= vc_count; ++i) {
            int const lvc = _last_vc[n][subnet][c];
            int const vc =
            (lvc < vc_start || lvc > vc_end) ?
            vc_start :
            (vc_start + (lvc - vc_start + i) % vc_count);
            assert((vc >= vc_start) && (vc <= vc_end));
            if(!dest_buf->IsAvailableFor(vc)) {
              if(cf->watch) {
                *gWatchOut << GetSimTime() << " | " << FullName() << " | "
                << "  Output VC " << vc << " is busy." << endl;
              }
            } else {
              if(dest_buf->IsFullFor(vc)) {
                if(cf->watch) {
                  *gWatchOut << GetSimTime() << " | " << FullName() << " | "
                  << "  Output VC " << vc << " is full." << endl;
                }
              } else {
                if(cf->watch) {
                  *gWatchOut << GetSimTime() << " | " << FullName() << " | "
                  << "  Selected output VC " << vc << "." << endl;
                }
                cf->vc = vc;
                break;
              }
            }
          }
        }
        
        if(cf->vc == -1) {
          if(cf->watch) {
            *gWatchOut << GetSimTime() << " | " << FullName() << " | "
            << "No output VC found for flit " << cf->id
            << "." << endl;
          }
        } else {
          if(dest_buf->IsFullFor(cf->vc)) {
            if(cf->watch) {
              *gWatchOut << GetSimTime() << " | " << FullName() << " | "
              << "Selected output VC " << cf->vc
              << " is full for flit " << cf->id
              << "." << endl;
            }
          } else {
            f = cf;
          }
        }
      }
      
      if(f) {
        
        assert(f->subnetwork == subnet);
        
        int const c = f->cl;
        
        if(f->head) {
          
          if (_lookahead_routing) {
            if(!_noq) {
              const FlitChannel * inject = _net[subnet]->GetInject(n);
              const Router * router = inject->GetSink();
              assert(router);
              int in_channel = inject->GetSinkPort();
              _rf(router, f, in_channel, &f->la_route_set, false);
              if(f->watch) {
                *gWatchOut << GetSimTime() << " | "
                << "node" << n << " | "
                << "Generating lookahead routing info for flit " << f->id
                << "." << endl;
              }
            } else if(f->watch) {
              *gWatchOut << GetSimTime() << " | "
              << "node" << n << " | "
              << "Already generated lookahead routing info for flit " << f->id
              << " (NOQ)." << endl;
            }
          } else {
            f->la_route_set.Clear();
          }
          
          dest_buf->TakeBuffer(f->vc);
          _last_vc[n][subnet][c] = f->vc;
        }
        
        _last_class[n][subnet] = c;
        
        _input_queue[subnet][n][c].pop_front();
        
#ifdef TRACK_FLOWS
        ++_outstanding_credits[c][subnet][n];
        _outstanding_classes[n][subnet][f->vc].push(c);
#endif
        

        if(g_hpcl_comp_config.hpcl_comp_en == 0) {
	  dest_buf->SendingFlit(f);
        } else {
	  //added by kh(030816)
	  //(1.1.a) send a head flit first: update buffer state
	  if(g_mc_placement_config.is_mc_node(n) == true && f->type == Flit::READ_REPLY) {
	      if(f->head)	dest_buf->SendingFlit(f);
	      //skip for other flits
	  } else {
	      dest_buf->SendingFlit(f);
	  }
	  ///
        }

        if(_pri_type == network_age_based) {
          f->pri = numeric_limits<int>::max() - _time;
          assert(f->pri >= 0);
        }
        
        if(f->watch) {
          *gWatchOut << GetSimTime() << " | "
          << "node" << n << " | "
          << "Injecting flit " << f->id
          << " into subnet " << subnet
          << " at time " << _time
          << " with priority " << f->pri
          << "." << endl;
        }
        f->itime = _time;
        
        // Pass VC "back"
        if(!_input_queue[subnet][n][c].empty() && !f->tail) {
          Flit * const nf = _input_queue[subnet][n][c].front();
          nf->vc = f->vc;
        }
        
        if((_sim_state == warming_up) || (_sim_state == running)) {
          ++_sent_flits[c][n];

          //added by kh(070215)
          ++_sent_flits_net[subnet][n];


          if(f->head) {
            ++_sent_packets[c][n];

            //added by kh(030816)
            if(f->type < Flit::ANY_TYPE) {
	      //added by kh(121715)
	      if(g_mc_placement_config.is_sm_node(n)) {
		  ((mem_fetch*)f->data)->set_status(HEAD_FLIT_INJECTED_TO_INJECT_BUF_IN_SM, _time);

		  //added by kh(122815)
		  double req_queuing_lat_in_sm = _time - ((mem_fetch*)f->data)->get_timestamp(HEAD_FLIT_INJECTED_TO_NI_INPUT_BUF_IN_SM);
		  g_hpcl_network_anal->add_sample(hpcl_network_anal::REQ_QUEUING_LAT_IN_SM, req_queuing_lat_in_sm);
		  ///

	      } else if(g_mc_placement_config.is_mc_node(n)) {
		  ((mem_fetch*)f->data)->set_status(HEAD_FLIT_INJECTED_TO_INJECT_BUF_IN_MEM, _time);
		  //added by kh(122815)
		  double rep_queuing_lat_in_mc = _time - ((mem_fetch*)f->data)->get_timestamp(HEAD_FLIT_INJECTED_TO_NI_INPUT_BUF_IN_MEM);
		  g_hpcl_network_anal->add_sample(hpcl_network_anal::REP_QUEUING_LAT_IN_MC, rep_queuing_lat_in_mc);
		  ///
	      }
	      ///
            }
          }
        }
        
#ifdef TRACK_FLOWS
        ++_injected_flits[c][n];
#endif
        
        if(g_hpcl_comp_config.hpcl_comp_en == 0) {

	  _net[subnet]->WriteFlit(f, n);

        } else {
	  //added by kh (021416)
	  //Compression
	  //(1.1.b) flits but a head flit are injected to the compressor
	  if(g_mc_placement_config.is_mc_node(n) == true && f->type == Flit::READ_REPLY) {

	     hpcl_comp_pl_data* pl_data = NULL;

	     //A head flit is found. It means other flits are in _input_queue now.
	     //flits move from _input_queue to compressor by force.
	     //Those flits are sent to network in different paths such that we set info for
	     //flit navigation here.
	     if(f->head == true) {
		assert(!_input_queue[subnet][n][c].empty());
		Flit * body_flit = _input_queue[subnet][n][c].front();
		_input_queue[subnet][n][c].pop_front();

		if(_pri_type == network_age_based) {
		  body_flit->pri = numeric_limits<int>::max() - _time;
		  assert(body_flit->pri >= 0);
		}
		body_flit->itime = _time;

		// Pass VC "back" for next flit
		if(!_input_queue[subnet][n][c].empty() && !body_flit->tail) {
		  Flit * const nf = _input_queue[subnet][n][c].front();
		  nf->vc = body_flit->vc;
		}

		++_sent_flits[c][n];
		++_sent_flits_net[subnet][n];

		pl_data = new hpcl_comp_pl_data;
		pl_data->add_comp_pl_data(body_flit);
		g_hpcl_global_comp_pl_2B[n]->set_input_data(pl_data);
		//delete pl_data;

		//(1.1.a)	send a head flit first
		_net[subnet]->WriteFlit(f, n);

	    } else {

		pl_data = new hpcl_comp_pl_data;
		pl_data->add_comp_pl_data(f);
		g_hpcl_global_comp_pl_2B[n]->set_input_data(pl_data);
		//delete pl_data;
	    }


	    //(1.2.a) words in a flit are pushed to a queue in a compressor
	    if(pl_data) {

		Flit* flit = pl_data->get_flit_ptr();
		assert(flit);

		//Use receiver's id as global dict index
		int global_dict_index = flit->const_dest;

		//Push words to be updated to word_queue (this is done at zero-time)
		vector<unsigned short> word_list;
		g_hpcl_global_comp_pl_2B[n]->decompose(flit->raw_data, word_list);
		for(int i = 0; i < word_list.size(); i++)
		  g_hpcl_global_comp_pl_2B[n]->push_word_to_queue(word_list[i], global_dict_index);

		delete pl_data;
	    }

	  } else if (g_mc_placement_config.is_mc_node(n) == true && f->type == Flit::CTRL_MSG) {


	      hpcl_dict_ctrl_msg<unsigned short>* ctrl_msg = (hpcl_dict_ctrl_msg<unsigned short>*)f->data;

	      /*
	      std::cout << "ctrl_msg | id " << ctrl_msg->get_id();
	      std::cout << " | src_node " << ctrl_msg->get_src_node();
	      std::cout << " | dest_node " << ctrl_msg->get_dest_node();
	      std::cout << " | word_index " << ctrl_msg->get_word_index();
	      std::cout << " | word " << ctrl_msg->get_new_word();
	      std::cout << " | n " << n;
	      std::cout << std::endl;;
	      */

	      g_hpcl_global_comp_pl_2B[n]->release_word(ctrl_msg->get_dest_node(), ctrl_msg->get_word_index(), ctrl_msg->get_new_word());
	      g_hpcl_global_comp_pl_2B[n]->validate_word(ctrl_msg->get_dest_node(), ctrl_msg->get_word_index(), ctrl_msg->get_new_word());

	      _net[subnet]->WriteFlit(f, n);

	  } else {

	      _net[subnet]->WriteFlit(f, n);
	  }
	  ///
        }
      }
    }
  }

  if(g_hpcl_comp_config.hpcl_comp_en == 1) {

    //added by kh(030816)
    //(1.3) Compression: Pipelined Compression
    for(int i = 0; i < g_hpcl_global_comp_pl_2B.size(); i++)
    {
      if(!g_hpcl_global_comp_pl_2B[i])	continue;

      //(1.2.b) words in the queue are updated to dictionary, when idle state
      //(1.2.d) ctrl msgs for words with frequency (>= threshold) are generated in compressor's run function, when idle state
      g_hpcl_global_comp_pl_2B[i]->run(getTime()+getTotalTime());
      hpcl_comp_pl_data* comp_pl_rsl = g_hpcl_global_comp_pl_2B[i]->get_output_data();
      Flit* flit = comp_pl_rsl->get_flit_ptr();
      if(flit) {
	//std::cout << "node " << i << " flit->id " << flit->id << std::endl;

	//(1.1.c) flits are injected from the compressor to an input buffer
	if(HasBufferSpace(i, flit)) {
	  SendFlitToBuffer(i, flit);		//for credit management.
	  SendFlitToNetwork(i, flit);
	  //std::cout << "\t" << " send flit " << flit->id << std::endl;

	  if(g_hpcl_global_comp_pl_2B[i]->get_comp_done() == true)
	  {
	      assert(g_hpcl_global_comp_pl_2B[i]->get_state() == hpcl_comp_pl<unsigned short>::HPCL_COMP_RUN);
	      g_hpcl_global_comp_pl_2B[i]->set_state(hpcl_comp_pl<unsigned short>::HPCL_COMP_IDLE);
	      g_hpcl_global_comp_pl_2B[i]->reset_comp_done();
	  }

	  //reset output data
	  g_hpcl_global_comp_pl_2B[i]->reset_output_data();

	} else {
	  //std::cout << "\t" << " cannot send flit " << flit->id << " due to no space!!!!!!!!!!" << std::endl;
	}
      }
    }
    ///

  }

  //Send the credit To the network
  for(int subnet = 0; subnet < _subnets; ++subnet) {
    for(int n = 0; n < _nodes; ++n) {
      map<int, Flit *>::const_iterator iter = flits[subnet].find(n);
      if(iter != flits[subnet].end()) {
        Flit * const f = iter->second;

        f->atime = _time;

        //added by kh(070715)
        if(f->tail) {

          //added by kh(030816)
	  if(f->type < Flit::ANY_TYPE) {
	    //added by kh(121715)
	    if(g_mc_placement_config.is_sm_node(n)) {
	      //std::cout << "mf's id: " << ((mem_fetch*)f->data)->get_request_uid() << ", time: " << _time << std::endl;
	      ((mem_fetch*)f->data)->set_status(TAIL_FLIT_EJECTED_FROM_EJECT_BUF_IN_SM, _time);
	      //added by kh(122815)
	      double rep_net_lat = _time - ((mem_fetch*)f->data)->get_timestamp(HEAD_FLIT_INJECTED_TO_INJECT_BUF_IN_MEM);
	      g_hpcl_network_anal->add_sample(hpcl_network_anal::REP_NET_LAT, rep_net_lat);
	      ///

	    } else if(g_mc_placement_config.is_mc_node(n)) {
	      ((mem_fetch*)f->data)->set_status(TAIL_FLIT_EJECTED_FROM_EJECT_BUF_IN_MEM, _time);

	      //added by kh(122815)
	      double req_net_lat = _time - ((mem_fetch*)f->data)->get_timestamp(HEAD_FLIT_INJECTED_TO_INJECT_BUF_IN_SM);
	      g_hpcl_network_anal->add_sample(hpcl_network_anal::REQ_NET_LAT, req_net_lat);
	      ///
	    }
          }
        }
        ///

        if(f->watch) {
          *gWatchOut << GetSimTime() << " | "
          << "node" << n << " | "
          << "Injecting credit for VC " << f->vc
          << " into subnet " << subnet
          << "." << endl;
        }
        

        if(g_hpcl_comp_config.hpcl_comp_en == 0) {

          Credit * const c = Credit::New();
	  c->vc.insert(f->vc);
	  _net[subnet]->WriteCredit(c, n);

        } else {
	  //added by kh(030816)
	  if(f->type == Flit::READ_REPLY) {
	      if(f->tail == false && f->m_enc_status == 1) {

	      } else {
		Credit * const c = Credit::New();
		c->vc.insert(f->vc);
		_net[subnet]->WriteCredit(c, n);
		//std::cout << "\tf->vc " << f->vc << " f->id " << f->id << std::endl;
	      }

	  } else {
	    Credit * const c = Credit::New();
	    c->vc.insert(f->vc);
	    _net[subnet]->WriteCredit(c, n);
	  }
	  ///
        }

#ifdef TRACK_FLOWS
        ++_ejected_flits[f->cl][n];
#endif
        
        _RetireFlit(f, n);
      }
    }
    flits[subnet].clear();
    // _InteralStep here
    _net[subnet]->Evaluate( );					//run router's pipeline
    _net[subnet]->WriteOutputs( );				//send flits..
  }
  
  ++_time;
  assert(_time);
  if(gTrace){
    cout<<"TIME "<<_time<<endl;
  }
  
}