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