NetworkInterface.cc revision 11666
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),
5311666Stushar@ece.gatech.edu      m_num_vcs(m_vc_per_vnet * m_virtual_networks)
5411666Stushar@ece.gatech.edu{
5511666Stushar@ece.gatech.edu    m_router_id = -1;
5611666Stushar@ece.gatech.edu    m_vc_round_robin = 0;
5711666Stushar@ece.gatech.edu    m_ni_out_vcs.resize(m_num_vcs);
5811666Stushar@ece.gatech.edu    m_ni_out_vcs_enqueue_time.resize(m_num_vcs);
5911666Stushar@ece.gatech.edu    outCreditQueue = new flitBuffer();
6011666Stushar@ece.gatech.edu
6111666Stushar@ece.gatech.edu    // instantiating the NI flit buffers
6211666Stushar@ece.gatech.edu    for (int i = 0; i < m_num_vcs; i++) {
6311666Stushar@ece.gatech.edu        m_ni_out_vcs[i] = new flitBuffer();
6411666Stushar@ece.gatech.edu        m_ni_out_vcs_enqueue_time[i] = Cycles(INFINITE_);
6511666Stushar@ece.gatech.edu    }
6611666Stushar@ece.gatech.edu
6711666Stushar@ece.gatech.edu    m_vc_allocator.resize(m_virtual_networks); // 1 allocator per vnet
6811666Stushar@ece.gatech.edu    for (int i = 0; i < m_virtual_networks; i++) {
6911666Stushar@ece.gatech.edu        m_vc_allocator[i] = 0;
7011666Stushar@ece.gatech.edu    }
7111666Stushar@ece.gatech.edu}
7211666Stushar@ece.gatech.edu
7311666Stushar@ece.gatech.eduvoid
7411666Stushar@ece.gatech.eduNetworkInterface::init()
7511666Stushar@ece.gatech.edu{
7611666Stushar@ece.gatech.edu    for (int i = 0; i < m_num_vcs; i++) {
7711666Stushar@ece.gatech.edu        m_out_vc_state.push_back(new OutVcState(i, m_net_ptr));
7811666Stushar@ece.gatech.edu    }
7911666Stushar@ece.gatech.edu}
8011666Stushar@ece.gatech.edu
8111666Stushar@ece.gatech.eduNetworkInterface::~NetworkInterface()
8211666Stushar@ece.gatech.edu{
8311666Stushar@ece.gatech.edu    deletePointers(m_out_vc_state);
8411666Stushar@ece.gatech.edu    deletePointers(m_ni_out_vcs);
8511666Stushar@ece.gatech.edu    delete outCreditQueue;
8611666Stushar@ece.gatech.edu    delete outFlitQueue;
8711666Stushar@ece.gatech.edu}
8811666Stushar@ece.gatech.edu
8911666Stushar@ece.gatech.eduvoid
9011666Stushar@ece.gatech.eduNetworkInterface::addInPort(NetworkLink *in_link,
9111666Stushar@ece.gatech.edu                              CreditLink *credit_link)
9211666Stushar@ece.gatech.edu{
9311666Stushar@ece.gatech.edu    inNetLink = in_link;
9411666Stushar@ece.gatech.edu    in_link->setLinkConsumer(this);
9511666Stushar@ece.gatech.edu    outCreditLink = credit_link;
9611666Stushar@ece.gatech.edu    credit_link->setSourceQueue(outCreditQueue);
9711666Stushar@ece.gatech.edu}
9811666Stushar@ece.gatech.edu
9911666Stushar@ece.gatech.eduvoid
10011666Stushar@ece.gatech.eduNetworkInterface::addOutPort(NetworkLink *out_link,
10111666Stushar@ece.gatech.edu                             CreditLink *credit_link,
10211666Stushar@ece.gatech.edu                             SwitchID router_id)
10311666Stushar@ece.gatech.edu{
10411666Stushar@ece.gatech.edu    inCreditLink = credit_link;
10511666Stushar@ece.gatech.edu    credit_link->setLinkConsumer(this);
10611666Stushar@ece.gatech.edu
10711666Stushar@ece.gatech.edu    outNetLink = out_link;
10811666Stushar@ece.gatech.edu    outFlitQueue = new flitBuffer();
10911666Stushar@ece.gatech.edu    out_link->setSourceQueue(outFlitQueue);
11011666Stushar@ece.gatech.edu
11111666Stushar@ece.gatech.edu    m_router_id = router_id;
11211666Stushar@ece.gatech.edu}
11311666Stushar@ece.gatech.edu
11411666Stushar@ece.gatech.eduvoid
11511666Stushar@ece.gatech.eduNetworkInterface::addNode(vector<MessageBuffer *>& in,
11611666Stushar@ece.gatech.edu                            vector<MessageBuffer *>& out)
11711666Stushar@ece.gatech.edu{
11811666Stushar@ece.gatech.edu    inNode_ptr = in;
11911666Stushar@ece.gatech.edu    outNode_ptr = out;
12011666Stushar@ece.gatech.edu
12111666Stushar@ece.gatech.edu    for (auto& it : in) {
12211666Stushar@ece.gatech.edu        if (it != nullptr) {
12311666Stushar@ece.gatech.edu            it->setConsumer(this);
12411666Stushar@ece.gatech.edu        }
12511666Stushar@ece.gatech.edu    }
12611666Stushar@ece.gatech.edu}
12711666Stushar@ece.gatech.edu
12811666Stushar@ece.gatech.edu
12911666Stushar@ece.gatech.edu/*
13011666Stushar@ece.gatech.edu * The NI wakeup checks whether there are any ready messages in the protocol
13111666Stushar@ece.gatech.edu * buffer. If yes, it picks that up, flitisizes it into a number of flits and
13211666Stushar@ece.gatech.edu * puts it into an output buffer and schedules the output link. On a wakeup
13311666Stushar@ece.gatech.edu * it also checks whether there are flits in the input link. If yes, it picks
13411666Stushar@ece.gatech.edu * them up and if the flit is a tail, the NI inserts the corresponding message
13511666Stushar@ece.gatech.edu * into the protocol buffer. It also checks for credits being sent by the
13611666Stushar@ece.gatech.edu * downstream router.
13711666Stushar@ece.gatech.edu */
13811666Stushar@ece.gatech.edu
13911666Stushar@ece.gatech.eduvoid
14011666Stushar@ece.gatech.eduNetworkInterface::wakeup()
14111666Stushar@ece.gatech.edu{
14211666Stushar@ece.gatech.edu    DPRINTF(RubyNetwork, "Network Interface %d connected to router %d "
14311666Stushar@ece.gatech.edu            "woke up at time: %lld\n", m_id, m_router_id, curCycle());
14411666Stushar@ece.gatech.edu
14511666Stushar@ece.gatech.edu    MsgPtr msg_ptr;
14611666Stushar@ece.gatech.edu    Tick curTime = clockEdge();
14711666Stushar@ece.gatech.edu
14811666Stushar@ece.gatech.edu    // Checking for messages coming from the protocol
14911666Stushar@ece.gatech.edu    // can pick up a message/cycle for each virtual net
15011666Stushar@ece.gatech.edu    for (int vnet = 0; vnet < inNode_ptr.size(); ++vnet) {
15111666Stushar@ece.gatech.edu        MessageBuffer *b = inNode_ptr[vnet];
15211666Stushar@ece.gatech.edu        if (b == nullptr) {
15311666Stushar@ece.gatech.edu            continue;
15411666Stushar@ece.gatech.edu        }
15511666Stushar@ece.gatech.edu
15611666Stushar@ece.gatech.edu        if (b->isReady(curTime)) { // Is there a message waiting
15711666Stushar@ece.gatech.edu            msg_ptr = b->peekMsgPtr();
15811666Stushar@ece.gatech.edu            if (flitisizeMessage(msg_ptr, vnet)) {
15911666Stushar@ece.gatech.edu                b->dequeue(curTime);
16011666Stushar@ece.gatech.edu            } else {
16111666Stushar@ece.gatech.edu                break;
16211666Stushar@ece.gatech.edu            }
16311666Stushar@ece.gatech.edu        }
16411666Stushar@ece.gatech.edu    }
16511666Stushar@ece.gatech.edu
16611666Stushar@ece.gatech.edu    scheduleOutputLink();
16711666Stushar@ece.gatech.edu    checkReschedule();
16811666Stushar@ece.gatech.edu
16911666Stushar@ece.gatech.edu    /*********** Check the incoming flit link **********/
17011666Stushar@ece.gatech.edu
17111666Stushar@ece.gatech.edu    if (inNetLink->isReady(curCycle())) {
17211666Stushar@ece.gatech.edu        flit *t_flit = inNetLink->consumeLink();
17311666Stushar@ece.gatech.edu        bool free_signal = false;
17411666Stushar@ece.gatech.edu        if (t_flit->get_type() == TAIL_ || t_flit->get_type() == HEAD_TAIL_) {
17511666Stushar@ece.gatech.edu            free_signal = true;
17611666Stushar@ece.gatech.edu
17711666Stushar@ece.gatech.edu            // enqueue into the protocol buffers
17811666Stushar@ece.gatech.edu            outNode_ptr[t_flit->get_vnet()]->enqueue(
17911666Stushar@ece.gatech.edu                t_flit->get_msg_ptr(), curTime, cyclesToTicks(Cycles(1)));
18011666Stushar@ece.gatech.edu        }
18111666Stushar@ece.gatech.edu        // Simply send a credit back since we are not buffering
18211666Stushar@ece.gatech.edu        // this flit in the NI
18311666Stushar@ece.gatech.edu        Credit *t_credit = new Credit(t_flit->get_vc(), free_signal,
18411666Stushar@ece.gatech.edu                                         curCycle());
18511666Stushar@ece.gatech.edu        outCreditQueue->insert(t_credit);
18611666Stushar@ece.gatech.edu        outCreditLink->
18711666Stushar@ece.gatech.edu            scheduleEventAbsolute(clockEdge(Cycles(1)));
18811666Stushar@ece.gatech.edu
18911666Stushar@ece.gatech.edu        int vnet = t_flit->get_vnet();
19011666Stushar@ece.gatech.edu
19111666Stushar@ece.gatech.edu        // Update Stats
19211666Stushar@ece.gatech.edu
19311666Stushar@ece.gatech.edu        // Latency
19411666Stushar@ece.gatech.edu        m_net_ptr->increment_received_flits(vnet);
19511666Stushar@ece.gatech.edu        Cycles network_delay = curCycle() - t_flit->get_enqueue_time();
19611666Stushar@ece.gatech.edu        Cycles queueing_delay = t_flit->get_src_delay();
19711666Stushar@ece.gatech.edu
19811666Stushar@ece.gatech.edu        m_net_ptr->increment_flit_network_latency(network_delay, vnet);
19911666Stushar@ece.gatech.edu        m_net_ptr->increment_flit_queueing_latency(queueing_delay, vnet);
20011666Stushar@ece.gatech.edu
20111666Stushar@ece.gatech.edu        if (t_flit->get_type() == TAIL_ || t_flit->get_type() == HEAD_TAIL_) {
20211666Stushar@ece.gatech.edu            m_net_ptr->increment_received_packets(vnet);
20311666Stushar@ece.gatech.edu            m_net_ptr->increment_packet_network_latency(network_delay, vnet);
20411666Stushar@ece.gatech.edu            m_net_ptr->increment_packet_queueing_latency(queueing_delay, vnet);
20511666Stushar@ece.gatech.edu        }
20611666Stushar@ece.gatech.edu
20711666Stushar@ece.gatech.edu        // Hops
20811666Stushar@ece.gatech.edu        m_net_ptr->increment_total_hops(t_flit->get_route().hops_traversed);
20911666Stushar@ece.gatech.edu
21011666Stushar@ece.gatech.edu        delete t_flit;
21111666Stushar@ece.gatech.edu    }
21211666Stushar@ece.gatech.edu
21311666Stushar@ece.gatech.edu    /****************** Check the incoming credit link *******/
21411666Stushar@ece.gatech.edu
21511666Stushar@ece.gatech.edu    if (inCreditLink->isReady(curCycle())) {
21611666Stushar@ece.gatech.edu        Credit *t_credit = (Credit*) inCreditLink->consumeLink();
21711666Stushar@ece.gatech.edu        m_out_vc_state[t_credit->get_vc()]->increment_credit();
21811666Stushar@ece.gatech.edu        if (t_credit->is_free_signal()) {
21911666Stushar@ece.gatech.edu            m_out_vc_state[t_credit->get_vc()]->setState(IDLE_, curCycle());
22011666Stushar@ece.gatech.edu        }
22111666Stushar@ece.gatech.edu        delete t_credit;
22211666Stushar@ece.gatech.edu    }
22311666Stushar@ece.gatech.edu}
22411666Stushar@ece.gatech.edu
22511666Stushar@ece.gatech.edu
22611666Stushar@ece.gatech.edu// Embed the protocol message into flits
22711666Stushar@ece.gatech.edubool
22811666Stushar@ece.gatech.eduNetworkInterface::flitisizeMessage(MsgPtr msg_ptr, int vnet)
22911666Stushar@ece.gatech.edu{
23011666Stushar@ece.gatech.edu    Message *net_msg_ptr = msg_ptr.get();
23111666Stushar@ece.gatech.edu    NetDest net_msg_dest = net_msg_ptr->getDestination();
23211666Stushar@ece.gatech.edu
23311666Stushar@ece.gatech.edu    // gets all the destinations associated with this message.
23411666Stushar@ece.gatech.edu    vector<NodeID> dest_nodes = net_msg_dest.getAllDest();
23511666Stushar@ece.gatech.edu
23611666Stushar@ece.gatech.edu    // Number of flits is dependent on the link bandwidth available.
23711666Stushar@ece.gatech.edu    // This is expressed in terms of bytes/cycle or the flit size
23811666Stushar@ece.gatech.edu    int num_flits = (int) ceil((double) m_net_ptr->MessageSizeType_to_int(
23911666Stushar@ece.gatech.edu        net_msg_ptr->getMessageSize())/m_net_ptr->getNiFlitSize());
24011666Stushar@ece.gatech.edu
24111666Stushar@ece.gatech.edu    // loop to convert all multicast messages into unicast messages
24211666Stushar@ece.gatech.edu    for (int ctr = 0; ctr < dest_nodes.size(); ctr++) {
24311666Stushar@ece.gatech.edu
24411666Stushar@ece.gatech.edu        // this will return a free output virtual channel
24511666Stushar@ece.gatech.edu        int vc = calculateVC(vnet);
24611666Stushar@ece.gatech.edu
24711666Stushar@ece.gatech.edu        if (vc == -1) {
24811666Stushar@ece.gatech.edu            return false ;
24911666Stushar@ece.gatech.edu        }
25011666Stushar@ece.gatech.edu        MsgPtr new_msg_ptr = msg_ptr->clone();
25111666Stushar@ece.gatech.edu        NodeID destID = dest_nodes[ctr];
25211666Stushar@ece.gatech.edu
25311666Stushar@ece.gatech.edu        Message *new_net_msg_ptr = new_msg_ptr.get();
25411666Stushar@ece.gatech.edu        if (dest_nodes.size() > 1) {
25511666Stushar@ece.gatech.edu            NetDest personal_dest;
25611666Stushar@ece.gatech.edu            for (int m = 0; m < (int) MachineType_NUM; m++) {
25711666Stushar@ece.gatech.edu                if ((destID >= MachineType_base_number((MachineType) m)) &&
25811666Stushar@ece.gatech.edu                    destID < MachineType_base_number((MachineType) (m+1))) {
25911666Stushar@ece.gatech.edu                    // calculating the NetDest associated with this destID
26011666Stushar@ece.gatech.edu                    personal_dest.clear();
26111666Stushar@ece.gatech.edu                    personal_dest.add((MachineID) {(MachineType) m, (destID -
26211666Stushar@ece.gatech.edu                        MachineType_base_number((MachineType) m))});
26311666Stushar@ece.gatech.edu                    new_net_msg_ptr->getDestination() = personal_dest;
26411666Stushar@ece.gatech.edu                    break;
26511666Stushar@ece.gatech.edu                }
26611666Stushar@ece.gatech.edu            }
26711666Stushar@ece.gatech.edu            net_msg_dest.removeNetDest(personal_dest);
26811666Stushar@ece.gatech.edu            // removing the destination from the original message to reflect
26911666Stushar@ece.gatech.edu            // that a message with this particular destination has been
27011666Stushar@ece.gatech.edu            // flitisized and an output vc is acquired
27111666Stushar@ece.gatech.edu            net_msg_ptr->getDestination().removeNetDest(personal_dest);
27211666Stushar@ece.gatech.edu        }
27311666Stushar@ece.gatech.edu
27411666Stushar@ece.gatech.edu        // Embed Route into the flits
27511666Stushar@ece.gatech.edu        // NetDest format is used by the routing table
27611666Stushar@ece.gatech.edu        // Custom routing algorithms just need destID
27711666Stushar@ece.gatech.edu        RouteInfo route;
27811666Stushar@ece.gatech.edu        route.vnet = vnet;
27911666Stushar@ece.gatech.edu        route.net_dest = new_net_msg_ptr->getDestination();
28011666Stushar@ece.gatech.edu        route.src_ni = m_id;
28111666Stushar@ece.gatech.edu        route.src_router = m_router_id;
28211666Stushar@ece.gatech.edu        route.dest_ni = destID;
28311666Stushar@ece.gatech.edu        route.dest_router = m_net_ptr->get_router_id(destID);
28411666Stushar@ece.gatech.edu
28511666Stushar@ece.gatech.edu        // initialize hops_traversed to -1
28611666Stushar@ece.gatech.edu        // so that the first router increments it to 0
28711666Stushar@ece.gatech.edu        route.hops_traversed = -1;
28811666Stushar@ece.gatech.edu
28911666Stushar@ece.gatech.edu        m_net_ptr->increment_injected_packets(vnet);
29011666Stushar@ece.gatech.edu        for (int i = 0; i < num_flits; i++) {
29111666Stushar@ece.gatech.edu            m_net_ptr->increment_injected_flits(vnet);
29211666Stushar@ece.gatech.edu            flit *fl = new flit(i, vc, vnet, route, num_flits, new_msg_ptr,
29311666Stushar@ece.gatech.edu                curCycle());
29411666Stushar@ece.gatech.edu
29511666Stushar@ece.gatech.edu            fl->set_src_delay(curCycle() - ticksToCycles(msg_ptr->getTime()));
29611666Stushar@ece.gatech.edu            m_ni_out_vcs[vc]->insert(fl);
29711666Stushar@ece.gatech.edu        }
29811666Stushar@ece.gatech.edu
29911666Stushar@ece.gatech.edu        m_ni_out_vcs_enqueue_time[vc] = curCycle();
30011666Stushar@ece.gatech.edu        m_out_vc_state[vc]->setState(ACTIVE_, curCycle());
30111666Stushar@ece.gatech.edu    }
30211666Stushar@ece.gatech.edu    return true ;
30311666Stushar@ece.gatech.edu}
30411666Stushar@ece.gatech.edu
30511666Stushar@ece.gatech.edu// Looking for a free output vc
30611666Stushar@ece.gatech.eduint
30711666Stushar@ece.gatech.eduNetworkInterface::calculateVC(int vnet)
30811666Stushar@ece.gatech.edu{
30911666Stushar@ece.gatech.edu    for (int i = 0; i < m_vc_per_vnet; i++) {
31011666Stushar@ece.gatech.edu        int delta = m_vc_allocator[vnet];
31111666Stushar@ece.gatech.edu        m_vc_allocator[vnet]++;
31211666Stushar@ece.gatech.edu        if (m_vc_allocator[vnet] == m_vc_per_vnet)
31311666Stushar@ece.gatech.edu            m_vc_allocator[vnet] = 0;
31411666Stushar@ece.gatech.edu
31511666Stushar@ece.gatech.edu        if (m_out_vc_state[(vnet*m_vc_per_vnet) + delta]->isInState(
31611666Stushar@ece.gatech.edu                    IDLE_, curCycle())) {
31711666Stushar@ece.gatech.edu            return ((vnet*m_vc_per_vnet) + delta);
31811666Stushar@ece.gatech.edu        }
31911666Stushar@ece.gatech.edu    }
32011666Stushar@ece.gatech.edu    return -1;
32111666Stushar@ece.gatech.edu}
32211666Stushar@ece.gatech.edu
32311666Stushar@ece.gatech.edu
32411666Stushar@ece.gatech.edu/** This function looks at the NI buffers
32511666Stushar@ece.gatech.edu *  if some buffer has flits which are ready to traverse the link in the next
32611666Stushar@ece.gatech.edu *  cycle, and the downstream output vc associated with this flit has buffers
32711666Stushar@ece.gatech.edu *  left, the link is scheduled for the next cycle
32811666Stushar@ece.gatech.edu */
32911666Stushar@ece.gatech.edu
33011666Stushar@ece.gatech.eduvoid
33111666Stushar@ece.gatech.eduNetworkInterface::scheduleOutputLink()
33211666Stushar@ece.gatech.edu{
33311666Stushar@ece.gatech.edu    int vc = m_vc_round_robin;
33411666Stushar@ece.gatech.edu    m_vc_round_robin++;
33511666Stushar@ece.gatech.edu    if (m_vc_round_robin == m_num_vcs)
33611666Stushar@ece.gatech.edu        m_vc_round_robin = 0;
33711666Stushar@ece.gatech.edu
33811666Stushar@ece.gatech.edu    for (int i = 0; i < m_num_vcs; i++) {
33911666Stushar@ece.gatech.edu        vc++;
34011666Stushar@ece.gatech.edu        if (vc == m_num_vcs)
34111666Stushar@ece.gatech.edu            vc = 0;
34211666Stushar@ece.gatech.edu
34311666Stushar@ece.gatech.edu        // model buffer backpressure
34411666Stushar@ece.gatech.edu        if (m_ni_out_vcs[vc]->isReady(curCycle()) &&
34511666Stushar@ece.gatech.edu            m_out_vc_state[vc]->has_credit()) {
34611666Stushar@ece.gatech.edu
34711666Stushar@ece.gatech.edu            bool is_candidate_vc = true;
34811666Stushar@ece.gatech.edu            int t_vnet = get_vnet(vc);
34911666Stushar@ece.gatech.edu            int vc_base = t_vnet * m_vc_per_vnet;
35011666Stushar@ece.gatech.edu
35111666Stushar@ece.gatech.edu            if (m_net_ptr->isVNetOrdered(t_vnet)) {
35211666Stushar@ece.gatech.edu                for (int vc_offset = 0; vc_offset < m_vc_per_vnet;
35311666Stushar@ece.gatech.edu                     vc_offset++) {
35411666Stushar@ece.gatech.edu                    int t_vc = vc_base + vc_offset;
35511666Stushar@ece.gatech.edu                    if (m_ni_out_vcs[t_vc]->isReady(curCycle())) {
35611666Stushar@ece.gatech.edu                        if (m_ni_out_vcs_enqueue_time[t_vc] <
35711666Stushar@ece.gatech.edu                            m_ni_out_vcs_enqueue_time[vc]) {
35811666Stushar@ece.gatech.edu                            is_candidate_vc = false;
35911666Stushar@ece.gatech.edu                            break;
36011666Stushar@ece.gatech.edu                        }
36111666Stushar@ece.gatech.edu                    }
36211666Stushar@ece.gatech.edu                }
36311666Stushar@ece.gatech.edu            }
36411666Stushar@ece.gatech.edu            if (!is_candidate_vc)
36511666Stushar@ece.gatech.edu                continue;
36611666Stushar@ece.gatech.edu
36711666Stushar@ece.gatech.edu            m_out_vc_state[vc]->decrement_credit();
36811666Stushar@ece.gatech.edu            // Just removing the flit
36911666Stushar@ece.gatech.edu            flit *t_flit = m_ni_out_vcs[vc]->getTopFlit();
37011666Stushar@ece.gatech.edu            t_flit->set_time(curCycle() + Cycles(1));
37111666Stushar@ece.gatech.edu            outFlitQueue->insert(t_flit);
37211666Stushar@ece.gatech.edu            // schedule the out link
37311666Stushar@ece.gatech.edu            outNetLink->scheduleEventAbsolute(clockEdge(Cycles(1)));
37411666Stushar@ece.gatech.edu
37511666Stushar@ece.gatech.edu            if (t_flit->get_type() == TAIL_ ||
37611666Stushar@ece.gatech.edu               t_flit->get_type() == HEAD_TAIL_) {
37711666Stushar@ece.gatech.edu                m_ni_out_vcs_enqueue_time[vc] = Cycles(INFINITE_);
37811666Stushar@ece.gatech.edu            }
37911666Stushar@ece.gatech.edu            return;
38011666Stushar@ece.gatech.edu        }
38111666Stushar@ece.gatech.edu    }
38211666Stushar@ece.gatech.edu}
38311666Stushar@ece.gatech.edu
38411666Stushar@ece.gatech.eduint
38511666Stushar@ece.gatech.eduNetworkInterface::get_vnet(int vc)
38611666Stushar@ece.gatech.edu{
38711666Stushar@ece.gatech.edu    for (int i = 0; i < m_virtual_networks; i++) {
38811666Stushar@ece.gatech.edu        if (vc >= (i*m_vc_per_vnet) && vc < ((i+1)*m_vc_per_vnet)) {
38911666Stushar@ece.gatech.edu            return i;
39011666Stushar@ece.gatech.edu        }
39111666Stushar@ece.gatech.edu    }
39211666Stushar@ece.gatech.edu    fatal("Could not determine vc");
39311666Stushar@ece.gatech.edu}
39411666Stushar@ece.gatech.edu
39511666Stushar@ece.gatech.edu
39611666Stushar@ece.gatech.edu// Wakeup the NI in the next cycle if there are waiting
39711666Stushar@ece.gatech.edu// messages in the protocol buffer, or waiting flits in the
39811666Stushar@ece.gatech.edu// output VC buffer
39911666Stushar@ece.gatech.eduvoid
40011666Stushar@ece.gatech.eduNetworkInterface::checkReschedule()
40111666Stushar@ece.gatech.edu{
40211666Stushar@ece.gatech.edu    for (const auto& it : inNode_ptr) {
40311666Stushar@ece.gatech.edu        if (it == nullptr) {
40411666Stushar@ece.gatech.edu            continue;
40511666Stushar@ece.gatech.edu        }
40611666Stushar@ece.gatech.edu
40711666Stushar@ece.gatech.edu        while (it->isReady(clockEdge())) { // Is there a message waiting
40811666Stushar@ece.gatech.edu            scheduleEvent(Cycles(1));
40911666Stushar@ece.gatech.edu            return;
41011666Stushar@ece.gatech.edu        }
41111666Stushar@ece.gatech.edu    }
41211666Stushar@ece.gatech.edu
41311666Stushar@ece.gatech.edu    for (int vc = 0; vc < m_num_vcs; vc++) {
41411666Stushar@ece.gatech.edu        if (m_ni_out_vcs[vc]->isReady(curCycle() + Cycles(1))) {
41511666Stushar@ece.gatech.edu            scheduleEvent(Cycles(1));
41611666Stushar@ece.gatech.edu            return;
41711666Stushar@ece.gatech.edu        }
41811666Stushar@ece.gatech.edu    }
41911666Stushar@ece.gatech.edu}
42011666Stushar@ece.gatech.edu
42111666Stushar@ece.gatech.eduvoid
42211666Stushar@ece.gatech.eduNetworkInterface::print(std::ostream& out) const
42311666Stushar@ece.gatech.edu{
42411666Stushar@ece.gatech.edu    out << "[Network Interface]";
42511666Stushar@ece.gatech.edu}
42611666Stushar@ece.gatech.edu
42711666Stushar@ece.gatech.eduuint32_t
42811666Stushar@ece.gatech.eduNetworkInterface::functionalWrite(Packet *pkt)
42911666Stushar@ece.gatech.edu{
43011666Stushar@ece.gatech.edu    uint32_t num_functional_writes = 0;
43111666Stushar@ece.gatech.edu    for (unsigned int i  = 0; i < m_num_vcs; ++i) {
43211666Stushar@ece.gatech.edu        num_functional_writes += m_ni_out_vcs[i]->functionalWrite(pkt);
43311666Stushar@ece.gatech.edu    }
43411666Stushar@ece.gatech.edu
43511666Stushar@ece.gatech.edu    num_functional_writes += outFlitQueue->functionalWrite(pkt);
43611666Stushar@ece.gatech.edu    return num_functional_writes;
43711666Stushar@ece.gatech.edu}
43811666Stushar@ece.gatech.edu
43911666Stushar@ece.gatech.eduNetworkInterface *
44011666Stushar@ece.gatech.eduGarnetNetworkInterfaceParams::create()
44111666Stushar@ece.gatech.edu{
44211666Stushar@ece.gatech.edu    return new NetworkInterface(this);
44311666Stushar@ece.gatech.edu}
444