NetworkInterface.cc revision 11762
111666Stushar@ece.gatech.edu/*
211666Stushar@ece.gatech.edu * Copyright (c) 2008 Princeton University
311666Stushar@ece.gatech.edu * Copyright (c) 2016 Georgia Institute of Technology
411666Stushar@ece.gatech.edu * All rights reserved.
511666Stushar@ece.gatech.edu *
611666Stushar@ece.gatech.edu * Redistribution and use in source and binary forms, with or without
711666Stushar@ece.gatech.edu * modification, are permitted provided that the following conditions are
811666Stushar@ece.gatech.edu * met: redistributions of source code must retain the above copyright
911666Stushar@ece.gatech.edu * notice, this list of conditions and the following disclaimer;
1011666Stushar@ece.gatech.edu * redistributions in binary form must reproduce the above copyright
1111666Stushar@ece.gatech.edu * notice, this list of conditions and the following disclaimer in the
1211666Stushar@ece.gatech.edu * documentation and/or other materials provided with the distribution;
1311666Stushar@ece.gatech.edu * neither the name of the copyright holders nor the names of its
1411666Stushar@ece.gatech.edu * contributors may be used to endorse or promote products derived from
1511666Stushar@ece.gatech.edu * this software without specific prior written permission.
1611666Stushar@ece.gatech.edu *
1711666Stushar@ece.gatech.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1811666Stushar@ece.gatech.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1911666Stushar@ece.gatech.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2011666Stushar@ece.gatech.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2111666Stushar@ece.gatech.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2211666Stushar@ece.gatech.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2311666Stushar@ece.gatech.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2411666Stushar@ece.gatech.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2511666Stushar@ece.gatech.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2611666Stushar@ece.gatech.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2711666Stushar@ece.gatech.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2811666Stushar@ece.gatech.edu *
2911666Stushar@ece.gatech.edu * Authors: Niket Agarwal
3011666Stushar@ece.gatech.edu *          Tushar Krishna
3111666Stushar@ece.gatech.edu */
3211666Stushar@ece.gatech.edu
3311666Stushar@ece.gatech.edu
3411666Stushar@ece.gatech.edu#include "mem/ruby/network/garnet2.0/NetworkInterface.hh"
3511666Stushar@ece.gatech.edu
3611666Stushar@ece.gatech.edu#include <cassert>
3711666Stushar@ece.gatech.edu#include <cmath>
3811666Stushar@ece.gatech.edu
3911666Stushar@ece.gatech.edu#include "base/cast.hh"
4011666Stushar@ece.gatech.edu#include "base/stl_helpers.hh"
4111666Stushar@ece.gatech.edu#include "debug/RubyNetwork.hh"
4211666Stushar@ece.gatech.edu#include "mem/ruby/network/MessageBuffer.hh"
4311666Stushar@ece.gatech.edu#include "mem/ruby/network/garnet2.0/Credit.hh"
4411666Stushar@ece.gatech.edu#include "mem/ruby/network/garnet2.0/flitBuffer.hh"
4511666Stushar@ece.gatech.edu#include "mem/ruby/slicc_interface/Message.hh"
4611666Stushar@ece.gatech.edu
4711666Stushar@ece.gatech.eduusing namespace std;
4811666Stushar@ece.gatech.eduusing m5::stl_helpers::deletePointers;
4911666Stushar@ece.gatech.edu
5011666Stushar@ece.gatech.eduNetworkInterface::NetworkInterface(const Params *p)
5111666Stushar@ece.gatech.edu    : ClockedObject(p), Consumer(this), m_id(p->id),
5211666Stushar@ece.gatech.edu      m_virtual_networks(p->virt_nets), m_vc_per_vnet(p->vcs_per_vnet),
5311762Sjieming.yin@amd.com      m_num_vcs(m_vc_per_vnet * m_virtual_networks),
5411762Sjieming.yin@amd.com      m_deadlock_threshold(p->garnet_deadlock_threshold),
5511762Sjieming.yin@amd.com      vc_busy_counter(m_virtual_networks, 0)
5611666Stushar@ece.gatech.edu{
5711666Stushar@ece.gatech.edu    m_router_id = -1;
5811666Stushar@ece.gatech.edu    m_vc_round_robin = 0;
5911666Stushar@ece.gatech.edu    m_ni_out_vcs.resize(m_num_vcs);
6011666Stushar@ece.gatech.edu    m_ni_out_vcs_enqueue_time.resize(m_num_vcs);
6111666Stushar@ece.gatech.edu    outCreditQueue = new flitBuffer();
6211666Stushar@ece.gatech.edu
6311666Stushar@ece.gatech.edu    // instantiating the NI flit buffers
6411666Stushar@ece.gatech.edu    for (int i = 0; i < m_num_vcs; i++) {
6511666Stushar@ece.gatech.edu        m_ni_out_vcs[i] = new flitBuffer();
6611666Stushar@ece.gatech.edu        m_ni_out_vcs_enqueue_time[i] = Cycles(INFINITE_);
6711666Stushar@ece.gatech.edu    }
6811666Stushar@ece.gatech.edu
6911666Stushar@ece.gatech.edu    m_vc_allocator.resize(m_virtual_networks); // 1 allocator per vnet
7011666Stushar@ece.gatech.edu    for (int i = 0; i < m_virtual_networks; i++) {
7111666Stushar@ece.gatech.edu        m_vc_allocator[i] = 0;
7211666Stushar@ece.gatech.edu    }
7311666Stushar@ece.gatech.edu}
7411666Stushar@ece.gatech.edu
7511666Stushar@ece.gatech.eduvoid
7611666Stushar@ece.gatech.eduNetworkInterface::init()
7711666Stushar@ece.gatech.edu{
7811666Stushar@ece.gatech.edu    for (int i = 0; i < m_num_vcs; i++) {
7911666Stushar@ece.gatech.edu        m_out_vc_state.push_back(new OutVcState(i, m_net_ptr));
8011666Stushar@ece.gatech.edu    }
8111666Stushar@ece.gatech.edu}
8211666Stushar@ece.gatech.edu
8311666Stushar@ece.gatech.eduNetworkInterface::~NetworkInterface()
8411666Stushar@ece.gatech.edu{
8511666Stushar@ece.gatech.edu    deletePointers(m_out_vc_state);
8611666Stushar@ece.gatech.edu    deletePointers(m_ni_out_vcs);
8711666Stushar@ece.gatech.edu    delete outCreditQueue;
8811666Stushar@ece.gatech.edu    delete outFlitQueue;
8911666Stushar@ece.gatech.edu}
9011666Stushar@ece.gatech.edu
9111666Stushar@ece.gatech.eduvoid
9211666Stushar@ece.gatech.eduNetworkInterface::addInPort(NetworkLink *in_link,
9311666Stushar@ece.gatech.edu                              CreditLink *credit_link)
9411666Stushar@ece.gatech.edu{
9511666Stushar@ece.gatech.edu    inNetLink = in_link;
9611666Stushar@ece.gatech.edu    in_link->setLinkConsumer(this);
9711666Stushar@ece.gatech.edu    outCreditLink = credit_link;
9811666Stushar@ece.gatech.edu    credit_link->setSourceQueue(outCreditQueue);
9911666Stushar@ece.gatech.edu}
10011666Stushar@ece.gatech.edu
10111666Stushar@ece.gatech.eduvoid
10211666Stushar@ece.gatech.eduNetworkInterface::addOutPort(NetworkLink *out_link,
10311666Stushar@ece.gatech.edu                             CreditLink *credit_link,
10411666Stushar@ece.gatech.edu                             SwitchID router_id)
10511666Stushar@ece.gatech.edu{
10611666Stushar@ece.gatech.edu    inCreditLink = credit_link;
10711666Stushar@ece.gatech.edu    credit_link->setLinkConsumer(this);
10811666Stushar@ece.gatech.edu
10911666Stushar@ece.gatech.edu    outNetLink = out_link;
11011666Stushar@ece.gatech.edu    outFlitQueue = new flitBuffer();
11111666Stushar@ece.gatech.edu    out_link->setSourceQueue(outFlitQueue);
11211666Stushar@ece.gatech.edu
11311666Stushar@ece.gatech.edu    m_router_id = router_id;
11411666Stushar@ece.gatech.edu}
11511666Stushar@ece.gatech.edu
11611666Stushar@ece.gatech.eduvoid
11711666Stushar@ece.gatech.eduNetworkInterface::addNode(vector<MessageBuffer *>& in,
11811666Stushar@ece.gatech.edu                            vector<MessageBuffer *>& out)
11911666Stushar@ece.gatech.edu{
12011666Stushar@ece.gatech.edu    inNode_ptr = in;
12111666Stushar@ece.gatech.edu    outNode_ptr = out;
12211666Stushar@ece.gatech.edu
12311666Stushar@ece.gatech.edu    for (auto& it : in) {
12411666Stushar@ece.gatech.edu        if (it != nullptr) {
12511666Stushar@ece.gatech.edu            it->setConsumer(this);
12611666Stushar@ece.gatech.edu        }
12711666Stushar@ece.gatech.edu    }
12811666Stushar@ece.gatech.edu}
12911666Stushar@ece.gatech.edu
13011666Stushar@ece.gatech.edu
13111666Stushar@ece.gatech.edu/*
13211666Stushar@ece.gatech.edu * The NI wakeup checks whether there are any ready messages in the protocol
13311666Stushar@ece.gatech.edu * buffer. If yes, it picks that up, flitisizes it into a number of flits and
13411666Stushar@ece.gatech.edu * puts it into an output buffer and schedules the output link. On a wakeup
13511666Stushar@ece.gatech.edu * it also checks whether there are flits in the input link. If yes, it picks
13611666Stushar@ece.gatech.edu * them up and if the flit is a tail, the NI inserts the corresponding message
13711666Stushar@ece.gatech.edu * into the protocol buffer. It also checks for credits being sent by the
13811666Stushar@ece.gatech.edu * downstream router.
13911666Stushar@ece.gatech.edu */
14011666Stushar@ece.gatech.edu
14111666Stushar@ece.gatech.eduvoid
14211666Stushar@ece.gatech.eduNetworkInterface::wakeup()
14311666Stushar@ece.gatech.edu{
14411666Stushar@ece.gatech.edu    DPRINTF(RubyNetwork, "Network Interface %d connected to router %d "
14511666Stushar@ece.gatech.edu            "woke up at time: %lld\n", m_id, m_router_id, curCycle());
14611666Stushar@ece.gatech.edu
14711666Stushar@ece.gatech.edu    MsgPtr msg_ptr;
14811666Stushar@ece.gatech.edu    Tick curTime = clockEdge();
14911666Stushar@ece.gatech.edu
15011666Stushar@ece.gatech.edu    // Checking for messages coming from the protocol
15111666Stushar@ece.gatech.edu    // can pick up a message/cycle for each virtual net
15211666Stushar@ece.gatech.edu    for (int vnet = 0; vnet < inNode_ptr.size(); ++vnet) {
15311666Stushar@ece.gatech.edu        MessageBuffer *b = inNode_ptr[vnet];
15411666Stushar@ece.gatech.edu        if (b == nullptr) {
15511666Stushar@ece.gatech.edu            continue;
15611666Stushar@ece.gatech.edu        }
15711666Stushar@ece.gatech.edu
15811666Stushar@ece.gatech.edu        if (b->isReady(curTime)) { // Is there a message waiting
15911666Stushar@ece.gatech.edu            msg_ptr = b->peekMsgPtr();
16011666Stushar@ece.gatech.edu            if (flitisizeMessage(msg_ptr, vnet)) {
16111666Stushar@ece.gatech.edu                b->dequeue(curTime);
16211666Stushar@ece.gatech.edu            } else {
16311666Stushar@ece.gatech.edu                break;
16411666Stushar@ece.gatech.edu            }
16511666Stushar@ece.gatech.edu        }
16611666Stushar@ece.gatech.edu    }
16711666Stushar@ece.gatech.edu
16811666Stushar@ece.gatech.edu    scheduleOutputLink();
16911666Stushar@ece.gatech.edu    checkReschedule();
17011666Stushar@ece.gatech.edu
17111666Stushar@ece.gatech.edu    /*********** Check the incoming flit link **********/
17211666Stushar@ece.gatech.edu
17311666Stushar@ece.gatech.edu    if (inNetLink->isReady(curCycle())) {
17411666Stushar@ece.gatech.edu        flit *t_flit = inNetLink->consumeLink();
17511666Stushar@ece.gatech.edu        bool free_signal = false;
17611666Stushar@ece.gatech.edu        if (t_flit->get_type() == TAIL_ || t_flit->get_type() == HEAD_TAIL_) {
17711666Stushar@ece.gatech.edu            free_signal = true;
17811666Stushar@ece.gatech.edu
17911666Stushar@ece.gatech.edu            // enqueue into the protocol buffers
18011666Stushar@ece.gatech.edu            outNode_ptr[t_flit->get_vnet()]->enqueue(
18111666Stushar@ece.gatech.edu                t_flit->get_msg_ptr(), curTime, cyclesToTicks(Cycles(1)));
18211666Stushar@ece.gatech.edu        }
18311666Stushar@ece.gatech.edu        // Simply send a credit back since we are not buffering
18411666Stushar@ece.gatech.edu        // this flit in the NI
18511666Stushar@ece.gatech.edu        Credit *t_credit = new Credit(t_flit->get_vc(), free_signal,
18611666Stushar@ece.gatech.edu                                         curCycle());
18711666Stushar@ece.gatech.edu        outCreditQueue->insert(t_credit);
18811666Stushar@ece.gatech.edu        outCreditLink->
18911666Stushar@ece.gatech.edu            scheduleEventAbsolute(clockEdge(Cycles(1)));
19011666Stushar@ece.gatech.edu
19111666Stushar@ece.gatech.edu        int vnet = t_flit->get_vnet();
19211666Stushar@ece.gatech.edu
19311666Stushar@ece.gatech.edu        // Update Stats
19411666Stushar@ece.gatech.edu
19511666Stushar@ece.gatech.edu        // Latency
19611666Stushar@ece.gatech.edu        m_net_ptr->increment_received_flits(vnet);
19711666Stushar@ece.gatech.edu        Cycles network_delay = curCycle() - t_flit->get_enqueue_time();
19811666Stushar@ece.gatech.edu        Cycles queueing_delay = t_flit->get_src_delay();
19911666Stushar@ece.gatech.edu
20011666Stushar@ece.gatech.edu        m_net_ptr->increment_flit_network_latency(network_delay, vnet);
20111666Stushar@ece.gatech.edu        m_net_ptr->increment_flit_queueing_latency(queueing_delay, vnet);
20211666Stushar@ece.gatech.edu
20311666Stushar@ece.gatech.edu        if (t_flit->get_type() == TAIL_ || t_flit->get_type() == HEAD_TAIL_) {
20411666Stushar@ece.gatech.edu            m_net_ptr->increment_received_packets(vnet);
20511666Stushar@ece.gatech.edu            m_net_ptr->increment_packet_network_latency(network_delay, vnet);
20611666Stushar@ece.gatech.edu            m_net_ptr->increment_packet_queueing_latency(queueing_delay, vnet);
20711666Stushar@ece.gatech.edu        }
20811666Stushar@ece.gatech.edu
20911666Stushar@ece.gatech.edu        // Hops
21011666Stushar@ece.gatech.edu        m_net_ptr->increment_total_hops(t_flit->get_route().hops_traversed);
21111666Stushar@ece.gatech.edu
21211666Stushar@ece.gatech.edu        delete t_flit;
21311666Stushar@ece.gatech.edu    }
21411666Stushar@ece.gatech.edu
21511666Stushar@ece.gatech.edu    /****************** Check the incoming credit link *******/
21611666Stushar@ece.gatech.edu
21711666Stushar@ece.gatech.edu    if (inCreditLink->isReady(curCycle())) {
21811666Stushar@ece.gatech.edu        Credit *t_credit = (Credit*) inCreditLink->consumeLink();
21911666Stushar@ece.gatech.edu        m_out_vc_state[t_credit->get_vc()]->increment_credit();
22011666Stushar@ece.gatech.edu        if (t_credit->is_free_signal()) {
22111666Stushar@ece.gatech.edu            m_out_vc_state[t_credit->get_vc()]->setState(IDLE_, curCycle());
22211666Stushar@ece.gatech.edu        }
22311666Stushar@ece.gatech.edu        delete t_credit;
22411666Stushar@ece.gatech.edu    }
22511666Stushar@ece.gatech.edu}
22611666Stushar@ece.gatech.edu
22711666Stushar@ece.gatech.edu
22811666Stushar@ece.gatech.edu// Embed the protocol message into flits
22911666Stushar@ece.gatech.edubool
23011666Stushar@ece.gatech.eduNetworkInterface::flitisizeMessage(MsgPtr msg_ptr, int vnet)
23111666Stushar@ece.gatech.edu{
23211666Stushar@ece.gatech.edu    Message *net_msg_ptr = msg_ptr.get();
23311666Stushar@ece.gatech.edu    NetDest net_msg_dest = net_msg_ptr->getDestination();
23411666Stushar@ece.gatech.edu
23511666Stushar@ece.gatech.edu    // gets all the destinations associated with this message.
23611666Stushar@ece.gatech.edu    vector<NodeID> dest_nodes = net_msg_dest.getAllDest();
23711666Stushar@ece.gatech.edu
23811666Stushar@ece.gatech.edu    // Number of flits is dependent on the link bandwidth available.
23911666Stushar@ece.gatech.edu    // This is expressed in terms of bytes/cycle or the flit size
24011666Stushar@ece.gatech.edu    int num_flits = (int) ceil((double) m_net_ptr->MessageSizeType_to_int(
24111666Stushar@ece.gatech.edu        net_msg_ptr->getMessageSize())/m_net_ptr->getNiFlitSize());
24211666Stushar@ece.gatech.edu
24311666Stushar@ece.gatech.edu    // loop to convert all multicast messages into unicast messages
24411666Stushar@ece.gatech.edu    for (int ctr = 0; ctr < dest_nodes.size(); ctr++) {
24511666Stushar@ece.gatech.edu
24611666Stushar@ece.gatech.edu        // this will return a free output virtual channel
24711666Stushar@ece.gatech.edu        int vc = calculateVC(vnet);
24811666Stushar@ece.gatech.edu
24911666Stushar@ece.gatech.edu        if (vc == -1) {
25011666Stushar@ece.gatech.edu            return false ;
25111666Stushar@ece.gatech.edu        }
25211666Stushar@ece.gatech.edu        MsgPtr new_msg_ptr = msg_ptr->clone();
25311666Stushar@ece.gatech.edu        NodeID destID = dest_nodes[ctr];
25411666Stushar@ece.gatech.edu
25511666Stushar@ece.gatech.edu        Message *new_net_msg_ptr = new_msg_ptr.get();
25611666Stushar@ece.gatech.edu        if (dest_nodes.size() > 1) {
25711666Stushar@ece.gatech.edu            NetDest personal_dest;
25811666Stushar@ece.gatech.edu            for (int m = 0; m < (int) MachineType_NUM; m++) {
25911666Stushar@ece.gatech.edu                if ((destID >= MachineType_base_number((MachineType) m)) &&
26011666Stushar@ece.gatech.edu                    destID < MachineType_base_number((MachineType) (m+1))) {
26111666Stushar@ece.gatech.edu                    // calculating the NetDest associated with this destID
26211666Stushar@ece.gatech.edu                    personal_dest.clear();
26311666Stushar@ece.gatech.edu                    personal_dest.add((MachineID) {(MachineType) m, (destID -
26411666Stushar@ece.gatech.edu                        MachineType_base_number((MachineType) m))});
26511666Stushar@ece.gatech.edu                    new_net_msg_ptr->getDestination() = personal_dest;
26611666Stushar@ece.gatech.edu                    break;
26711666Stushar@ece.gatech.edu                }
26811666Stushar@ece.gatech.edu            }
26911666Stushar@ece.gatech.edu            net_msg_dest.removeNetDest(personal_dest);
27011666Stushar@ece.gatech.edu            // removing the destination from the original message to reflect
27111666Stushar@ece.gatech.edu            // that a message with this particular destination has been
27211666Stushar@ece.gatech.edu            // flitisized and an output vc is acquired
27311666Stushar@ece.gatech.edu            net_msg_ptr->getDestination().removeNetDest(personal_dest);
27411666Stushar@ece.gatech.edu        }
27511666Stushar@ece.gatech.edu
27611666Stushar@ece.gatech.edu        // Embed Route into the flits
27711666Stushar@ece.gatech.edu        // NetDest format is used by the routing table
27811666Stushar@ece.gatech.edu        // Custom routing algorithms just need destID
27911666Stushar@ece.gatech.edu        RouteInfo route;
28011666Stushar@ece.gatech.edu        route.vnet = vnet;
28111666Stushar@ece.gatech.edu        route.net_dest = new_net_msg_ptr->getDestination();
28211666Stushar@ece.gatech.edu        route.src_ni = m_id;
28311666Stushar@ece.gatech.edu        route.src_router = m_router_id;
28411666Stushar@ece.gatech.edu        route.dest_ni = destID;
28511666Stushar@ece.gatech.edu        route.dest_router = m_net_ptr->get_router_id(destID);
28611666Stushar@ece.gatech.edu
28711666Stushar@ece.gatech.edu        // initialize hops_traversed to -1
28811666Stushar@ece.gatech.edu        // so that the first router increments it to 0
28911666Stushar@ece.gatech.edu        route.hops_traversed = -1;
29011666Stushar@ece.gatech.edu
29111666Stushar@ece.gatech.edu        m_net_ptr->increment_injected_packets(vnet);
29211666Stushar@ece.gatech.edu        for (int i = 0; i < num_flits; i++) {
29311666Stushar@ece.gatech.edu            m_net_ptr->increment_injected_flits(vnet);
29411666Stushar@ece.gatech.edu            flit *fl = new flit(i, vc, vnet, route, num_flits, new_msg_ptr,
29511666Stushar@ece.gatech.edu                curCycle());
29611666Stushar@ece.gatech.edu
29711666Stushar@ece.gatech.edu            fl->set_src_delay(curCycle() - ticksToCycles(msg_ptr->getTime()));
29811666Stushar@ece.gatech.edu            m_ni_out_vcs[vc]->insert(fl);
29911666Stushar@ece.gatech.edu        }
30011666Stushar@ece.gatech.edu
30111666Stushar@ece.gatech.edu        m_ni_out_vcs_enqueue_time[vc] = curCycle();
30211666Stushar@ece.gatech.edu        m_out_vc_state[vc]->setState(ACTIVE_, curCycle());
30311666Stushar@ece.gatech.edu    }
30411666Stushar@ece.gatech.edu    return true ;
30511666Stushar@ece.gatech.edu}
30611666Stushar@ece.gatech.edu
30711666Stushar@ece.gatech.edu// Looking for a free output vc
30811666Stushar@ece.gatech.eduint
30911666Stushar@ece.gatech.eduNetworkInterface::calculateVC(int vnet)
31011666Stushar@ece.gatech.edu{
31111666Stushar@ece.gatech.edu    for (int i = 0; i < m_vc_per_vnet; i++) {
31211666Stushar@ece.gatech.edu        int delta = m_vc_allocator[vnet];
31311666Stushar@ece.gatech.edu        m_vc_allocator[vnet]++;
31411666Stushar@ece.gatech.edu        if (m_vc_allocator[vnet] == m_vc_per_vnet)
31511666Stushar@ece.gatech.edu            m_vc_allocator[vnet] = 0;
31611666Stushar@ece.gatech.edu
31711666Stushar@ece.gatech.edu        if (m_out_vc_state[(vnet*m_vc_per_vnet) + delta]->isInState(
31811666Stushar@ece.gatech.edu                    IDLE_, curCycle())) {
31911762Sjieming.yin@amd.com            vc_busy_counter[vnet] = 0;
32011666Stushar@ece.gatech.edu            return ((vnet*m_vc_per_vnet) + delta);
32111666Stushar@ece.gatech.edu        }
32211666Stushar@ece.gatech.edu    }
32311762Sjieming.yin@amd.com
32411762Sjieming.yin@amd.com    vc_busy_counter[vnet] += 1;
32511762Sjieming.yin@amd.com    panic_if(vc_busy_counter[vnet] > m_deadlock_threshold,
32611762Sjieming.yin@amd.com        "%s: Possible network deadlock in vnet: %d at time: %llu \n",
32711762Sjieming.yin@amd.com        name(), vnet, curTick());
32811762Sjieming.yin@amd.com
32911666Stushar@ece.gatech.edu    return -1;
33011666Stushar@ece.gatech.edu}
33111666Stushar@ece.gatech.edu
33211666Stushar@ece.gatech.edu
33311666Stushar@ece.gatech.edu/** This function looks at the NI buffers
33411666Stushar@ece.gatech.edu *  if some buffer has flits which are ready to traverse the link in the next
33511666Stushar@ece.gatech.edu *  cycle, and the downstream output vc associated with this flit has buffers
33611666Stushar@ece.gatech.edu *  left, the link is scheduled for the next cycle
33711666Stushar@ece.gatech.edu */
33811666Stushar@ece.gatech.edu
33911666Stushar@ece.gatech.eduvoid
34011666Stushar@ece.gatech.eduNetworkInterface::scheduleOutputLink()
34111666Stushar@ece.gatech.edu{
34211666Stushar@ece.gatech.edu    int vc = m_vc_round_robin;
34311666Stushar@ece.gatech.edu    m_vc_round_robin++;
34411666Stushar@ece.gatech.edu    if (m_vc_round_robin == m_num_vcs)
34511666Stushar@ece.gatech.edu        m_vc_round_robin = 0;
34611666Stushar@ece.gatech.edu
34711666Stushar@ece.gatech.edu    for (int i = 0; i < m_num_vcs; i++) {
34811666Stushar@ece.gatech.edu        vc++;
34911666Stushar@ece.gatech.edu        if (vc == m_num_vcs)
35011666Stushar@ece.gatech.edu            vc = 0;
35111666Stushar@ece.gatech.edu
35211666Stushar@ece.gatech.edu        // model buffer backpressure
35311666Stushar@ece.gatech.edu        if (m_ni_out_vcs[vc]->isReady(curCycle()) &&
35411666Stushar@ece.gatech.edu            m_out_vc_state[vc]->has_credit()) {
35511666Stushar@ece.gatech.edu
35611666Stushar@ece.gatech.edu            bool is_candidate_vc = true;
35711666Stushar@ece.gatech.edu            int t_vnet = get_vnet(vc);
35811666Stushar@ece.gatech.edu            int vc_base = t_vnet * m_vc_per_vnet;
35911666Stushar@ece.gatech.edu
36011666Stushar@ece.gatech.edu            if (m_net_ptr->isVNetOrdered(t_vnet)) {
36111666Stushar@ece.gatech.edu                for (int vc_offset = 0; vc_offset < m_vc_per_vnet;
36211666Stushar@ece.gatech.edu                     vc_offset++) {
36311666Stushar@ece.gatech.edu                    int t_vc = vc_base + vc_offset;
36411666Stushar@ece.gatech.edu                    if (m_ni_out_vcs[t_vc]->isReady(curCycle())) {
36511666Stushar@ece.gatech.edu                        if (m_ni_out_vcs_enqueue_time[t_vc] <
36611666Stushar@ece.gatech.edu                            m_ni_out_vcs_enqueue_time[vc]) {
36711666Stushar@ece.gatech.edu                            is_candidate_vc = false;
36811666Stushar@ece.gatech.edu                            break;
36911666Stushar@ece.gatech.edu                        }
37011666Stushar@ece.gatech.edu                    }
37111666Stushar@ece.gatech.edu                }
37211666Stushar@ece.gatech.edu            }
37311666Stushar@ece.gatech.edu            if (!is_candidate_vc)
37411666Stushar@ece.gatech.edu                continue;
37511666Stushar@ece.gatech.edu
37611666Stushar@ece.gatech.edu            m_out_vc_state[vc]->decrement_credit();
37711666Stushar@ece.gatech.edu            // Just removing the flit
37811666Stushar@ece.gatech.edu            flit *t_flit = m_ni_out_vcs[vc]->getTopFlit();
37911666Stushar@ece.gatech.edu            t_flit->set_time(curCycle() + Cycles(1));
38011666Stushar@ece.gatech.edu            outFlitQueue->insert(t_flit);
38111666Stushar@ece.gatech.edu            // schedule the out link
38211666Stushar@ece.gatech.edu            outNetLink->scheduleEventAbsolute(clockEdge(Cycles(1)));
38311666Stushar@ece.gatech.edu
38411666Stushar@ece.gatech.edu            if (t_flit->get_type() == TAIL_ ||
38511666Stushar@ece.gatech.edu               t_flit->get_type() == HEAD_TAIL_) {
38611666Stushar@ece.gatech.edu                m_ni_out_vcs_enqueue_time[vc] = Cycles(INFINITE_);
38711666Stushar@ece.gatech.edu            }
38811666Stushar@ece.gatech.edu            return;
38911666Stushar@ece.gatech.edu        }
39011666Stushar@ece.gatech.edu    }
39111666Stushar@ece.gatech.edu}
39211666Stushar@ece.gatech.edu
39311666Stushar@ece.gatech.eduint
39411666Stushar@ece.gatech.eduNetworkInterface::get_vnet(int vc)
39511666Stushar@ece.gatech.edu{
39611666Stushar@ece.gatech.edu    for (int i = 0; i < m_virtual_networks; i++) {
39711666Stushar@ece.gatech.edu        if (vc >= (i*m_vc_per_vnet) && vc < ((i+1)*m_vc_per_vnet)) {
39811666Stushar@ece.gatech.edu            return i;
39911666Stushar@ece.gatech.edu        }
40011666Stushar@ece.gatech.edu    }
40111666Stushar@ece.gatech.edu    fatal("Could not determine vc");
40211666Stushar@ece.gatech.edu}
40311666Stushar@ece.gatech.edu
40411666Stushar@ece.gatech.edu
40511666Stushar@ece.gatech.edu// Wakeup the NI in the next cycle if there are waiting
40611666Stushar@ece.gatech.edu// messages in the protocol buffer, or waiting flits in the
40711666Stushar@ece.gatech.edu// output VC buffer
40811666Stushar@ece.gatech.eduvoid
40911666Stushar@ece.gatech.eduNetworkInterface::checkReschedule()
41011666Stushar@ece.gatech.edu{
41111666Stushar@ece.gatech.edu    for (const auto& it : inNode_ptr) {
41211666Stushar@ece.gatech.edu        if (it == nullptr) {
41311666Stushar@ece.gatech.edu            continue;
41411666Stushar@ece.gatech.edu        }
41511666Stushar@ece.gatech.edu
41611666Stushar@ece.gatech.edu        while (it->isReady(clockEdge())) { // Is there a message waiting
41711666Stushar@ece.gatech.edu            scheduleEvent(Cycles(1));
41811666Stushar@ece.gatech.edu            return;
41911666Stushar@ece.gatech.edu        }
42011666Stushar@ece.gatech.edu    }
42111666Stushar@ece.gatech.edu
42211666Stushar@ece.gatech.edu    for (int vc = 0; vc < m_num_vcs; vc++) {
42311666Stushar@ece.gatech.edu        if (m_ni_out_vcs[vc]->isReady(curCycle() + Cycles(1))) {
42411666Stushar@ece.gatech.edu            scheduleEvent(Cycles(1));
42511666Stushar@ece.gatech.edu            return;
42611666Stushar@ece.gatech.edu        }
42711666Stushar@ece.gatech.edu    }
42811666Stushar@ece.gatech.edu}
42911666Stushar@ece.gatech.edu
43011666Stushar@ece.gatech.eduvoid
43111666Stushar@ece.gatech.eduNetworkInterface::print(std::ostream& out) const
43211666Stushar@ece.gatech.edu{
43311666Stushar@ece.gatech.edu    out << "[Network Interface]";
43411666Stushar@ece.gatech.edu}
43511666Stushar@ece.gatech.edu
43611666Stushar@ece.gatech.eduuint32_t
43711666Stushar@ece.gatech.eduNetworkInterface::functionalWrite(Packet *pkt)
43811666Stushar@ece.gatech.edu{
43911666Stushar@ece.gatech.edu    uint32_t num_functional_writes = 0;
44011666Stushar@ece.gatech.edu    for (unsigned int i  = 0; i < m_num_vcs; ++i) {
44111666Stushar@ece.gatech.edu        num_functional_writes += m_ni_out_vcs[i]->functionalWrite(pkt);
44211666Stushar@ece.gatech.edu    }
44311666Stushar@ece.gatech.edu
44411666Stushar@ece.gatech.edu    num_functional_writes += outFlitQueue->functionalWrite(pkt);
44511666Stushar@ece.gatech.edu    return num_functional_writes;
44611666Stushar@ece.gatech.edu}
44711666Stushar@ece.gatech.edu
44811666Stushar@ece.gatech.eduNetworkInterface *
44911666Stushar@ece.gatech.eduGarnetNetworkInterfaceParams::create()
45011666Stushar@ece.gatech.edu{
45111666Stushar@ece.gatech.edu    return new NetworkInterface(this);
45211666Stushar@ece.gatech.edu}
453