[Gems-users] Modeling back-pressure effect in Garnet fixed pipeline


Date: Mon, 19 Apr 2010 12:33:03 +0300
From: "Arseniy Vitkovskiy" <arseniy.vitkovskiy@xxxxxxxxx>
Subject: [Gems-users] Modeling back-pressure effect in Garnet fixed pipeline

For those who want to simulate back-pressure effect in Garnet fixed pipeline model for the case when output link has non-unit serial latency, here is the solution.

The idea is to pause flits at SA stage by rescheduling them for the later time while the output port is busy with sending current flit through the slow link. In order to implement this mechanism we create a new time vector m_output_schedule which holds new scheduling for each output port. During SA stage we set m_output_schedule of the current output port to the current time plus output link latency. Thus, we advance flits to ST stage only when current time is bigger or equal to the schedule in m_output_schedule[outport]. The exact implementation is presented below.

 

SWallocator_d.C:

 

void SWallocator_d::init()

{

            m_output_schedule.setSize(m_num_outports);

            for (int i = 0; i < m_num_outports; i++)

              {

                m_output_schedule[i] = 0;

              }

}

 

void SWallocator_d::arbitrate_outports()

{

// now I have a set of input vc requests for output vcs. Again do round robin arbitration on these requests

        for(int outport = 0; outport < m_num_outports; outport++)

            {

                        int in_port = m_round_robin_outport[outport];

                        m_round_robin_outport[outport]++;

 

                        if(m_round_robin_outport[outport] >= m_num_outports)

                                    m_round_robin_outport[outport] = 0;

 

                        for(int inport = 0; inport < m_num_inports; inport++)

                        {

                                    in_port++;

                                    if(in_port >= m_num_inports)

                                                in_port = 0;

                                    if(m_port_req[outport][in_port]) // This Inport has a request this cycle for this port

                                    {

                                      if (g_eventQueue_ptr->getTime() >= m_output_schedule[outport]) // Checking schedule

                                        {

                                                m_port_req[outport][in_port] = false;

                                                int invc = m_vc_winners[outport][in_port];

                                                int outvc = m_input_unit[in_port]->get_outvc(invc);

                                                flit_d *t_flit = m_input_unit[in_port]->getTopFlit(invc); // removes flit from Input Unit

                                                t_flit->advance_stage(ST_);

                                                t_flit->set_vc(outvc);

                                                t_flit->set_outport(outport);

                                                t_flit->set_time(g_eventQueue_ptr->getTime() + 1);

                                                m_output_unit[outport]->decrement_credit(outvc);

                                                m_router->update_sw_winner(in_port, t_flit);

                                                m_global_arbiter_activity++;

 

                                                if((t_flit->get_type() == TAIL_) || t_flit->get_type() == HEAD_TAIL_)

                                                {

                                                            m_input_unit[in_port]->increment_credit(invc, true); // Send a credit back along with the information that this VC is not idle

                                                            assert(m_input_unit[in_port]->isReady(invc) == false); // This Input VC should now be empty

 

                                                            m_input_unit[in_port]->set_vc_state(IDLE_, invc);

                                                            m_input_unit[in_port]->set_enqueue_time(invc, INFINITE_);          

                                                }

                                                else

                                                {

                                                            m_input_unit[in_port]->increment_credit(invc, false); // Send a credit back but do not indicate that the VC is idle

                                                }

 

                                                m_output_schedule[outport] = g_eventQueue_ptr->getTime() + m_output_unit[outport]->get_outlink_latency(); // Creating schedule for the outport

                                        }

                                    }

                        }

            }

}                                  

 

SWallocator_d.h:

private:

            Vector<Time > m_output_schedule;

};

 

OutputUnit_d.h:

 

            inline int get_outlink_latency()

              {

                return m_out_link->get_latency();

              }

           

NetworkLink_d.h:

 

            inline int get_latency()

            {

              return m_latency;

            }

 

Thanks to Niket for the idea.

 

Kind regards,
Arseniy 

 

[← Prev in Thread] Current Thread [Next in Thread→]