GarnetSyntheticTraffic.cc revision 13784
172SN/A/*
211274Sshingarov@labware.com * Copyright (c) 2016 Georgia Institute of Technology
310597Sgabeblack@google.com * All rights reserved.
41762SN/A *
572SN/A * Redistribution and use in source and binary forms, with or without
672SN/A * modification, are permitted provided that the following conditions are
772SN/A * met: redistributions of source code must retain the above copyright
872SN/A * notice, this list of conditions and the following disclaimer;
972SN/A * redistributions in binary form must reproduce the above copyright
1072SN/A * notice, this list of conditions and the following disclaimer in the
1172SN/A * documentation and/or other materials provided with the distribution;
1272SN/A * neither the name of the copyright holders nor the names of its
1372SN/A * contributors may be used to endorse or promote products derived from
1472SN/A * this software without specific prior written permission.
1572SN/A *
1672SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1772SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1872SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1972SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2072SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2172SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2272SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2372SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2472SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2572SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2672SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2772SN/A *
2872SN/A * Authors: Tushar Krishna
292665Ssaidi@eecs.umich.edu */
302665Ssaidi@eecs.umich.edu
3111274Sshingarov@labware.com#include "cpu/testers/garnet_synthetic_traffic/GarnetSyntheticTraffic.hh"
3272SN/A
3372SN/A#include <cmath>
342SN/A#include <iomanip>
358332Snate@binkert.org#include <set>
368332Snate@binkert.org#include <string>
372SN/A#include <vector>
382SN/A
392SN/A#include "base/logging.hh"
402SN/A#include "base/random.hh"
412SN/A#include "base/statistics.hh"
422SN/A#include "debug/GarnetSyntheticTraffic.hh"
432SN/A#include "mem/mem_object.hh"
445543Ssaidi@eecs.umich.edu#include "mem/packet.hh"
455543Ssaidi@eecs.umich.edu#include "mem/port.hh"
462SN/A#include "mem/request.hh"
472SN/A#include "sim/sim_events.hh"
482SN/A#include "sim/stats.hh"
492SN/A#include "sim/system.hh"
502SN/A
512SN/Ausing namespace std;
522SN/A
532SN/Aint TESTER_NETWORK=0;
542SN/A
552SN/Abool
562SN/AGarnetSyntheticTraffic::CpuPort::recvTimingResp(PacketPtr pkt)
575543Ssaidi@eecs.umich.edu{
585543Ssaidi@eecs.umich.edu    tester->completeRequest(pkt);
592SN/A    return true;
602SN/A}
612SN/A
622SN/Avoid
632SN/AGarnetSyntheticTraffic::CpuPort::recvReqRetry()
642SN/A{
652SN/A    tester->doRetry();
662SN/A}
672SN/A
682SN/Avoid
692SN/AGarnetSyntheticTraffic::sendPkt(PacketPtr pkt)
702SN/A{
712SN/A    if (!cachePort.sendTimingReq(pkt)) {
722SN/A        retryPkt = pkt; // RubyPort will retry sending
732SN/A    }
742SN/A    numPacketsSent++;
755543Ssaidi@eecs.umich.edu}
762SN/A
772SN/AGarnetSyntheticTraffic::GarnetSyntheticTraffic(const Params *p)
782SN/A    : MemObject(p),
792SN/A      tickEvent([this]{ tick(); }, "GarnetSyntheticTraffic tick",
802SN/A                false, Event::CPU_Tick_Pri),
812SN/A      cachePort("GarnetSyntheticTraffic", this),
822SN/A      retryPkt(NULL),
832SN/A      size(p->memory_size),
842SN/A      blockSizeBits(p->block_offset),
852SN/A      numDestinations(p->num_dest),
862SN/A      simCycles(p->sim_cycles),
872SN/A      numPacketsMax(p->num_packets_max),
882SN/A      numPacketsSent(0),
892SN/A      singleSender(p->single_sender),
902SN/A      singleDest(p->single_dest),
912SN/A      trafficType(p->traffic_type),
922SN/A      injRate(p->inj_rate),
932SN/A      injVnet(p->inj_vnet),
942SN/A      precision(p->precision),
955543Ssaidi@eecs.umich.edu      responseLimit(p->response_limit),
965543Ssaidi@eecs.umich.edu      masterId(p->system->getMasterId(this))
972SN/A{
982SN/A    // set up counters
992SN/A    noResponseCycles = 0;
1002SN/A    schedule(tickEvent, 0);
1012SN/A
1022SN/A    initTrafficType();
1032SN/A    if (trafficStringToEnum.count(trafficType) == 0) {
1042SN/A        fatal("Unknown Traffic Type: %s!\n", traffic);
1052SN/A    }
1062SN/A    traffic = trafficStringToEnum[trafficType];
1072SN/A
1082SN/A    id = TESTER_NETWORK++;
1092SN/A    DPRINTF(GarnetSyntheticTraffic,"Config Created: Name = %s , and id = %d\n",
1102SN/A            name(), id);
1112SN/A}
1122SN/A
1132SN/APort &
1142SN/AGarnetSyntheticTraffic::getPort(const std::string &if_name, PortID idx)
1152SN/A{
1162SN/A    if (if_name == "test")
1172SN/A        return cachePort;
1182SN/A    else
1192SN/A        return MemObject::getPort(if_name, idx);
1202SN/A}
1212SN/A
12211793Sbrandon.potter@amd.comvoid
12311793Sbrandon.potter@amd.comGarnetSyntheticTraffic::init()
1242SN/A{
1258229Snate@binkert.org    numPacketsSent = 0;
1262SN/A}
12711793Sbrandon.potter@amd.com
12812019Sgabeblack@google.com
1296712Snate@binkert.orgvoid
1301717SN/AGarnetSyntheticTraffic::completeRequest(PacketPtr pkt)
1312SN/A{
1322521SN/A    DPRINTF(GarnetSyntheticTraffic,
13356SN/A            "Completed injection of %s packet for address %x\n",
13456SN/A            pkt->isWrite() ? "write" : "read\n",
13556SN/A            pkt->req->getPaddr());
1366658Snate@binkert.org
13710597Sgabeblack@google.com    assert(pkt->isResponse());
1388229Snate@binkert.org    noResponseCycles = 0;
1392680Sktlim@umich.edu    delete pkt;
1408232Snate@binkert.org}
14111793Sbrandon.potter@amd.com
1422521SN/A
1438706Sandreas.hansson@arm.comvoid
1448784Sgblack@eecs.umich.eduGarnetSyntheticTraffic::tick()
1451717SN/A{
1462SN/A    if (++noResponseCycles >= responseLimit) {
1472SN/A        fatal("%s deadlocked at cycle %d\n", name(), curTick());
1482107SN/A    }
1492SN/A
15012031Sgabeblack@google.com    // make new request based on injection rate
15112031Sgabeblack@google.com    // (injection rate's range depends on precision)
15212031Sgabeblack@google.com    // - generate a random number between 0 and 10^precision
15312031Sgabeblack@google.com    // - send pkt if this number is < injRate*(10^precision)
15412031Sgabeblack@google.com    bool sendAllowedThisCycle;
15512031Sgabeblack@google.com    double injRange = pow((double) 10, (double) precision);
15612031Sgabeblack@google.com    unsigned trySending = random_mt.random<unsigned>(0, (int) injRange);
1573536Sgblack@eecs.umich.edu    if (trySending < injRate*injRange)
1582SN/A        sendAllowedThisCycle = true;
15912449Sgabeblack@google.com    else
16012449Sgabeblack@google.com        sendAllowedThisCycle = false;
16112449Sgabeblack@google.com
16212449Sgabeblack@google.com    // always generatePkt unless fixedPkts or singleSender is enabled
16312449Sgabeblack@google.com    if (sendAllowedThisCycle) {
16412449Sgabeblack@google.com        bool senderEnable = true;
16512449Sgabeblack@google.com
16612449Sgabeblack@google.com        if (numPacketsMax >= 0 && numPacketsSent >= numPacketsMax)
16712449Sgabeblack@google.com            senderEnable = false;
16812449Sgabeblack@google.com
16912449Sgabeblack@google.com        if (singleSender >= 0 && id != singleSender)
17012449Sgabeblack@google.com            senderEnable = false;
17112449Sgabeblack@google.com
17212449Sgabeblack@google.com        if (senderEnable)
17312449Sgabeblack@google.com            generatePkt();
17412449Sgabeblack@google.com    }
17512466Sgabeblack@google.com
17612449Sgabeblack@google.com    // Schedule wakeup
17712449Sgabeblack@google.com    if (curTick() >= simCycles)
17812449Sgabeblack@google.com        exitSimLoop("Network Tester completed simCycles");
17912449Sgabeblack@google.com    else {
18012449Sgabeblack@google.com        if (!tickEvent.scheduled())
18112449Sgabeblack@google.com            schedule(tickEvent, clockEdge(Cycles(1)));
18212449Sgabeblack@google.com    }
18312449Sgabeblack@google.com}
18412449Sgabeblack@google.com
18512449Sgabeblack@google.comvoid
18612449Sgabeblack@google.comGarnetSyntheticTraffic::generatePkt()
18712449Sgabeblack@google.com{
18812449Sgabeblack@google.com    int num_destinations = numDestinations;
18912449Sgabeblack@google.com    int radix = (int) sqrt(num_destinations);
19012449Sgabeblack@google.com    unsigned destination = id;
19112449Sgabeblack@google.com    int dest_x = -1;
19212449Sgabeblack@google.com    int dest_y = -1;
19312449Sgabeblack@google.com    int source = id;
19412449Sgabeblack@google.com    int src_x = id%radix;
19512449Sgabeblack@google.com    int src_y = id/radix;
19612449Sgabeblack@google.com
19712449Sgabeblack@google.com    if (singleDest >= 0)
19812449Sgabeblack@google.com    {
19912449Sgabeblack@google.com        destination = singleDest;
20012449Sgabeblack@google.com    } else if (traffic == UNIFORM_RANDOM_) {
20112449Sgabeblack@google.com        destination = random_mt.random<unsigned>(0, num_destinations - 1);
20212449Sgabeblack@google.com    } else if (traffic == BIT_COMPLEMENT_) {
20312449Sgabeblack@google.com        dest_x = radix - src_x - 1;
20412449Sgabeblack@google.com        dest_y = radix - src_y - 1;
20512449Sgabeblack@google.com        destination = dest_y*radix + dest_x;
20612449Sgabeblack@google.com    } else if (traffic == BIT_REVERSE_) {
20712449Sgabeblack@google.com        unsigned int straight = source;
20812449Sgabeblack@google.com        unsigned int reverse = source & 1; // LSB
20912449Sgabeblack@google.com
21012449Sgabeblack@google.com        int num_bits = (int) log2(num_destinations);
21112449Sgabeblack@google.com
21212449Sgabeblack@google.com        for (int i = 1; i < num_bits; i++)
21312449Sgabeblack@google.com        {
21412449Sgabeblack@google.com            reverse <<= 1;
21512449Sgabeblack@google.com            straight >>= 1;
21612449Sgabeblack@google.com            reverse |= (straight & 1); // LSB
21712449Sgabeblack@google.com        }
21812449Sgabeblack@google.com        destination = reverse;
21912449Sgabeblack@google.com    } else if (traffic == BIT_ROTATION_) {
22012449Sgabeblack@google.com        if (source%2 == 0)
22112449Sgabeblack@google.com            destination = source/2;
22212449Sgabeblack@google.com        else // (source%2 == 1)
22312449Sgabeblack@google.com            destination = ((source/2) + (num_destinations/2));
22412449Sgabeblack@google.com    } else if (traffic == NEIGHBOR_) {
22512449Sgabeblack@google.com            dest_x = (src_x + 1) % radix;
22612449Sgabeblack@google.com            dest_y = src_y;
22712449Sgabeblack@google.com            destination = dest_y*radix + dest_x;
22812449Sgabeblack@google.com    } else if (traffic == SHUFFLE_) {
22912449Sgabeblack@google.com        if (source < num_destinations/2)
23012449Sgabeblack@google.com            destination = source*2;
2312SN/A        else
23212449Sgabeblack@google.com            destination = (source*2 - num_destinations + 1);
2332SN/A    } else if (traffic == TRANSPOSE_) {
23412449Sgabeblack@google.com            dest_x = src_y;
23512449Sgabeblack@google.com            dest_y = src_x;
23612449Sgabeblack@google.com            destination = dest_y*radix + dest_x;
23712449Sgabeblack@google.com    } else if (traffic == TORNADO_) {
23812449Sgabeblack@google.com        dest_x = (src_x + (int) ceil(radix/2) - 1) % radix;
23912449Sgabeblack@google.com        dest_y = src_y;
24012449Sgabeblack@google.com        destination = dest_y*radix + dest_x;
24112449Sgabeblack@google.com    }
24212449Sgabeblack@google.com    else {
24312449Sgabeblack@google.com        fatal("Unknown Traffic Type: %s!\n", traffic);
24412449Sgabeblack@google.com    }
24512449Sgabeblack@google.com
24612449Sgabeblack@google.com    // The source of the packets is a cache.
24712449Sgabeblack@google.com    // The destination of the packets is a directory.
24812449Sgabeblack@google.com    // The destination bits are embedded in the address after byte-offset.
24912449Sgabeblack@google.com    Addr paddr =  destination;
25012449Sgabeblack@google.com    paddr <<= blockSizeBits;
25112449Sgabeblack@google.com    unsigned access_size = 1; // Does not affect Ruby simulation
25212449Sgabeblack@google.com
25312449Sgabeblack@google.com    // Modeling different coherence msg types over different msg classes.
25412449Sgabeblack@google.com    //
25512449Sgabeblack@google.com    // GarnetSyntheticTraffic assumes the Garnet_standalone coherence protocol
25612449Sgabeblack@google.com    // which models three message classes/virtual networks.
25712449Sgabeblack@google.com    // These are: request, forward, response.
25812449Sgabeblack@google.com    // requests and forwards are "control" packets (typically 8 bytes),
25912449Sgabeblack@google.com    // while responses are "data" packets (typically 72 bytes).
26012449Sgabeblack@google.com    //
26112449Sgabeblack@google.com    // Life of a packet from the tester into the network:
26212449Sgabeblack@google.com    // (1) This function generatePkt() generates packets of one of the
26312449Sgabeblack@google.com    //     following 3 types (randomly) : ReadReq, INST_FETCH, WriteReq
26412449Sgabeblack@google.com    // (2) mem/ruby/system/RubyPort.cc converts these to RubyRequestType_LD,
26512449Sgabeblack@google.com    //     RubyRequestType_IFETCH, RubyRequestType_ST respectively
26612449Sgabeblack@google.com    // (3) mem/ruby/system/Sequencer.cc sends these to the cache controllers
26712449Sgabeblack@google.com    //     in the coherence protocol.
26812449Sgabeblack@google.com    // (4) Network_test-cache.sm tags RubyRequestType:LD,
26912449Sgabeblack@google.com    //     RubyRequestType:IFETCH and RubyRequestType:ST as
27012449Sgabeblack@google.com    //     Request, Forward, and Response events respectively;
27112449Sgabeblack@google.com    //     and injects them into virtual networks 0, 1 and 2 respectively.
27212449Sgabeblack@google.com    //     It immediately calls back the sequencer.
27312449Sgabeblack@google.com    // (5) The packet traverses the network (simple/garnet) and reaches its
27412449Sgabeblack@google.com    //     destination (Directory), and network stats are updated.
27512449Sgabeblack@google.com    // (6) Network_test-dir.sm simply drops the packet.
27612449Sgabeblack@google.com    //
27712449Sgabeblack@google.com    MemCmd::Command requestType;
27812449Sgabeblack@google.com
27912449Sgabeblack@google.com    RequestPtr req = nullptr;
28012449Sgabeblack@google.com    Request::Flags flags;
28112449Sgabeblack@google.com
28212449Sgabeblack@google.com    // Inject in specific Vnet
28312449Sgabeblack@google.com    // Vnet 0 and 1 are for control packets (1-flit)
28412449Sgabeblack@google.com    // Vnet 2 is for data packets (5-flit)
28512449Sgabeblack@google.com    int injReqType = injVnet;
28612449Sgabeblack@google.com
28712449Sgabeblack@google.com    if (injReqType < 0 || injReqType > 2)
28812449Sgabeblack@google.com    {
28912449Sgabeblack@google.com        // randomly inject in any vnet
29012449Sgabeblack@google.com        injReqType = random_mt.random(0, 2);
29112449Sgabeblack@google.com    }
29212449Sgabeblack@google.com
29312449Sgabeblack@google.com    if (injReqType == 0) {
29412449Sgabeblack@google.com        // generate packet for virtual network 0
29512449Sgabeblack@google.com        requestType = MemCmd::ReadReq;
29612449Sgabeblack@google.com        req = std::make_shared<Request>(paddr, access_size, flags, masterId);
29712449Sgabeblack@google.com    } else if (injReqType == 1) {
29812449Sgabeblack@google.com        // generate packet for virtual network 1
29912449Sgabeblack@google.com        requestType = MemCmd::ReadReq;
30012449Sgabeblack@google.com        flags.set(Request::INST_FETCH);
30112449Sgabeblack@google.com        req = std::make_shared<Request>(
30212449Sgabeblack@google.com            0, 0x0, access_size, flags, masterId, 0x0, 0);
3031910SN/A        req->setPaddr(paddr);
3042SN/A    } else {  // if (injReqType == 2)
3052SN/A        // generate packet for virtual network 2
30612449Sgabeblack@google.com        requestType = MemCmd::WriteReq;
3072SN/A        req = std::make_shared<Request>(paddr, access_size, flags, masterId);
30812449Sgabeblack@google.com    }
30912449Sgabeblack@google.com
3102SN/A    req->setContext(id);
31112449Sgabeblack@google.com
3122SN/A    //No need to do functional simulation
3132SN/A    //We just do timing simulation of the network
3141910SN/A
3152SN/A    DPRINTF(GarnetSyntheticTraffic,
31612449Sgabeblack@google.com            "Generated packet with destination %d, embedded in address %x\n",
31712449Sgabeblack@google.com            destination, req->getPaddr());
31812449Sgabeblack@google.com
31912449Sgabeblack@google.com    PacketPtr pkt = new Packet(req, requestType);
3202SN/A    pkt->dataDynamic(new uint8_t[req->getSize()]);
32112449Sgabeblack@google.com    pkt->senderState = NULL;
32212449Sgabeblack@google.com
32312449Sgabeblack@google.com    sendPkt(pkt);
32412449Sgabeblack@google.com}
32512449Sgabeblack@google.com
32612449Sgabeblack@google.comvoid
32712449Sgabeblack@google.comGarnetSyntheticTraffic::initTrafficType()
3282SN/A{
3292SN/A    trafficStringToEnum["bit_complement"] = BIT_COMPLEMENT_;
330507SN/A    trafficStringToEnum["bit_reverse"] = BIT_REVERSE_;
33112449Sgabeblack@google.com    trafficStringToEnum["bit_rotation"] = BIT_ROTATION_;
332507SN/A    trafficStringToEnum["neighbor"] = NEIGHBOR_;
33312449Sgabeblack@google.com    trafficStringToEnum["shuffle"] = SHUFFLE_;
334507SN/A    trafficStringToEnum["tornado"] = TORNADO_;
335507SN/A    trafficStringToEnum["transpose"] = TRANSPOSE_;
3362SN/A    trafficStringToEnum["uniform_random"] = UNIFORM_RANDOM_;
33712449Sgabeblack@google.com}
3382SN/A
3395523Snate@binkert.orgvoid
3405523Snate@binkert.orgGarnetSyntheticTraffic::doRetry()
3415523Snate@binkert.org{
3425523Snate@binkert.org    if (cachePort.sendTimingReq(retryPkt)) {
3435523Snate@binkert.org        retryPkt = NULL;
34412449Sgabeblack@google.com    }
34512449Sgabeblack@google.com}
34612449Sgabeblack@google.com
3472SN/Avoid
3482SN/AGarnetSyntheticTraffic::printAddr(Addr a)
34912449Sgabeblack@google.com{
35012449Sgabeblack@google.com    cachePort.printAddr(a);
3511910SN/A}
3521910SN/A
35312449Sgabeblack@google.com
3542SN/AGarnetSyntheticTraffic *
3552SN/AGarnetSyntheticTrafficParams::create()
3562SN/A{
35712449Sgabeblack@google.com    return new GarnetSyntheticTraffic(this);
3582SN/A}
35912449Sgabeblack@google.com