diff options
Diffstat (limited to 'src/cpu/testers/garnet_synthetic_traffic')
4 files changed, 617 insertions, 0 deletions
diff --git a/src/cpu/testers/garnet_synthetic_traffic/GarnetSyntheticTraffic.cc b/src/cpu/testers/garnet_synthetic_traffic/GarnetSyntheticTraffic.cc new file mode 100644 index 000000000..f5a718697 --- /dev/null +++ b/src/cpu/testers/garnet_synthetic_traffic/GarnetSyntheticTraffic.cc @@ -0,0 +1,358 @@ +/* + * Copyright (c) 2016 Georgia Institute of Technology + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Tushar Krishna + */ + +#include <cmath> +#include <iomanip> +#include <set> +#include <string> +#include <vector> + +#include "base/misc.hh" +#include "base/random.hh" +#include "base/statistics.hh" +#include "cpu/testers/garnet_synthetic_traffic/GarnetSyntheticTraffic.hh" +#include "debug/GarnetSyntheticTraffic.hh" +#include "mem/mem_object.hh" +#include "mem/packet.hh" +#include "mem/port.hh" +#include "mem/request.hh" +#include "sim/sim_events.hh" +#include "sim/stats.hh" +#include "sim/system.hh" + +using namespace std; + +int TESTER_NETWORK=0; + +bool +GarnetSyntheticTraffic::CpuPort::recvTimingResp(PacketPtr pkt) +{ + tester->completeRequest(pkt); + return true; +} + +void +GarnetSyntheticTraffic::CpuPort::recvReqRetry() +{ + tester->doRetry(); +} + +void +GarnetSyntheticTraffic::sendPkt(PacketPtr pkt) +{ + if (!cachePort.sendTimingReq(pkt)) { + retryPkt = pkt; // RubyPort will retry sending + } + numPacketsSent++; +} + +GarnetSyntheticTraffic::GarnetSyntheticTraffic(const Params *p) + : MemObject(p), + tickEvent(this), + cachePort("GarnetSyntheticTraffic", this), + retryPkt(NULL), + size(p->memory_size), + blockSizeBits(p->block_offset), + numDestinations(p->num_dest), + simCycles(p->sim_cycles), + numPacketsMax(p->num_packets_max), + numPacketsSent(0), + singleSender(p->single_sender), + singleDest(p->single_dest), + trafficType(p->traffic_type), + injRate(p->inj_rate), + injVnet(p->inj_vnet), + precision(p->precision), + responseLimit(p->response_limit), + masterId(p->system->getMasterId(name())) +{ + // set up counters + noResponseCycles = 0; + schedule(tickEvent, 0); + + initTrafficType(); + if (trafficStringToEnum.count(trafficType) == 0) { + fatal("Unknown Traffic Type: %s!\n", traffic); + } + traffic = trafficStringToEnum[trafficType]; + + id = TESTER_NETWORK++; + DPRINTF(GarnetSyntheticTraffic,"Config Created: Name = %s , and id = %d\n", + name(), id); +} + +BaseMasterPort & +GarnetSyntheticTraffic::getMasterPort(const std::string &if_name, PortID idx) +{ + if (if_name == "test") + return cachePort; + else + return MemObject::getMasterPort(if_name, idx); +} + +void +GarnetSyntheticTraffic::init() +{ + numPacketsSent = 0; +} + + +void +GarnetSyntheticTraffic::completeRequest(PacketPtr pkt) +{ + Request *req = pkt->req; + + DPRINTF(GarnetSyntheticTraffic, + "Completed injection of %s packet for address %x\n", + pkt->isWrite() ? "write" : "read\n", + req->getPaddr()); + + assert(pkt->isResponse()); + noResponseCycles = 0; + delete req; + delete pkt; +} + + +void +GarnetSyntheticTraffic::tick() +{ + if (++noResponseCycles >= responseLimit) { + fatal("%s deadlocked at cycle %d\n", name(), curTick()); + } + + // make new request based on injection rate + // (injection rate's range depends on precision) + // - generate a random number between 0 and 10^precision + // - send pkt if this number is < injRate*(10^precision) + bool sendAllowedThisCycle; + double injRange = pow((double) 10, (double) precision); + unsigned trySending = random_mt.random<unsigned>(0, (int) injRange); + if (trySending < injRate*injRange) + sendAllowedThisCycle = true; + else + sendAllowedThisCycle = false; + + // always generatePkt unless fixedPkts or singleSender is enabled + if (sendAllowedThisCycle) { + bool senderEnable = true; + + if (numPacketsMax >= 0 && numPacketsSent >= numPacketsMax) + senderEnable = false; + + if (singleSender >= 0 && id != singleSender) + senderEnable = false; + + if (senderEnable) + generatePkt(); + } + + // Schedule wakeup + if (curTick() >= simCycles) + exitSimLoop("Network Tester completed simCycles"); + else { + if (!tickEvent.scheduled()) + schedule(tickEvent, clockEdge(Cycles(1))); + } +} + +void +GarnetSyntheticTraffic::generatePkt() +{ + int num_destinations = numDestinations; + int radix = (int) sqrt(num_destinations); + unsigned destination = id; + int dest_x = -1; + int dest_y = -1; + int source = id; + int src_x = id%radix; + int src_y = id/radix; + + if (singleDest >= 0) + { + destination = singleDest; + } else if (traffic == UNIFORM_RANDOM_) { + destination = random_mt.random<unsigned>(0, num_destinations - 1); + } else if (traffic == BIT_COMPLEMENT_) { + dest_x = radix - src_x - 1; + dest_y = radix - src_y - 1; + destination = dest_y*radix + dest_x; + } else if (traffic == BIT_REVERSE_) { + unsigned int straight = source; + unsigned int reverse = source & 1; // LSB + + int num_bits = (int) log2(num_destinations); + + for (int i = 1; i < num_bits; i++) + { + reverse <<= 1; + straight >>= 1; + reverse |= (straight & 1); // LSB + } + destination = reverse; + } else if (traffic == BIT_ROTATION_) { + if (source%2 == 0) + destination = source/2; + else // (source%2 == 1) + destination = ((source/2) + (num_destinations/2)); + } else if (traffic == NEIGHBOR_) { + dest_x = (src_x + 1) % radix; + dest_y = src_y; + destination = dest_y*radix + dest_x; + } else if (traffic == SHUFFLE_) { + if (source < num_destinations/2) + destination = source*2; + else + destination = (source*2 - num_destinations + 1); + } else if (traffic == TRANSPOSE_) { + dest_x = src_y; + dest_y = src_x; + destination = dest_y*radix + dest_x; + } else if (traffic == TORNADO_) { + dest_x = (src_x + (int) ceil(radix/2) - 1) % radix; + dest_y = src_y; + destination = dest_y*radix + dest_x; + } + else { + fatal("Unknown Traffic Type: %s!\n", traffic); + } + + // The source of the packets is a cache. + // The destination of the packets is a directory. + // The destination bits are embedded in the address after byte-offset. + Addr paddr = destination; + paddr <<= blockSizeBits; + unsigned access_size = 1; // Does not affect Ruby simulation + + // Modeling different coherence msg types over different msg classes. + // + // GarnetSyntheticTraffic assumes the Garnet_standalone coherence protocol + // which models three message classes/virtual networks. + // These are: request, forward, response. + // requests and forwards are "control" packets (typically 8 bytes), + // while responses are "data" packets (typically 72 bytes). + // + // Life of a packet from the tester into the network: + // (1) This function generatePkt() generates packets of one of the + // following 3 types (randomly) : ReadReq, INST_FETCH, WriteReq + // (2) mem/ruby/system/RubyPort.cc converts these to RubyRequestType_LD, + // RubyRequestType_IFETCH, RubyRequestType_ST respectively + // (3) mem/ruby/system/Sequencer.cc sends these to the cache controllers + // in the coherence protocol. + // (4) Network_test-cache.sm tags RubyRequestType:LD, + // RubyRequestType:IFETCH and RubyRequestType:ST as + // Request, Forward, and Response events respectively; + // and injects them into virtual networks 0, 1 and 2 respectively. + // It immediately calls back the sequencer. + // (5) The packet traverses the network (simple/garnet) and reaches its + // destination (Directory), and network stats are updated. + // (6) Network_test-dir.sm simply drops the packet. + // + MemCmd::Command requestType; + + Request *req = nullptr; + Request::Flags flags; + + // Inject in specific Vnet + // Vnet 0 and 1 are for control packets (1-flit) + // Vnet 2 is for data packets (5-flit) + int injReqType = injVnet; + + if (injReqType < 0 || injReqType > 2) + { + // randomly inject in any vnet + injReqType = random_mt.random(0, 2); + } + + if (injReqType == 0) { + // generate packet for virtual network 0 + requestType = MemCmd::ReadReq; + req = new Request(paddr, access_size, flags, masterId); + } else if (injReqType == 1) { + // generate packet for virtual network 1 + requestType = MemCmd::ReadReq; + flags.set(Request::INST_FETCH); + req = new Request(0, 0x0, access_size, flags, masterId, 0x0, 0); + req->setPaddr(paddr); + } else { // if (injReqType == 2) + // generate packet for virtual network 2 + requestType = MemCmd::WriteReq; + req = new Request(paddr, access_size, flags, masterId); + } + + req->setContext(id); + + //No need to do functional simulation + //We just do timing simulation of the network + + DPRINTF(GarnetSyntheticTraffic, + "Generated packet with destination %d, embedded in address %x\n", + destination, req->getPaddr()); + + PacketPtr pkt = new Packet(req, requestType); + pkt->dataDynamic(new uint8_t[req->getSize()]); + pkt->senderState = NULL; + + sendPkt(pkt); +} + +void +GarnetSyntheticTraffic::initTrafficType() +{ + trafficStringToEnum["bit_complement"] = BIT_COMPLEMENT_; + trafficStringToEnum["bit_reverse"] = BIT_REVERSE_; + trafficStringToEnum["bit_rotation"] = BIT_ROTATION_; + trafficStringToEnum["neighbor"] = NEIGHBOR_; + trafficStringToEnum["shuffle"] = SHUFFLE_; + trafficStringToEnum["tornado"] = TORNADO_; + trafficStringToEnum["transpose"] = TRANSPOSE_; + trafficStringToEnum["uniform_random"] = UNIFORM_RANDOM_; +} + +void +GarnetSyntheticTraffic::doRetry() +{ + if (cachePort.sendTimingReq(retryPkt)) { + retryPkt = NULL; + } +} + +void +GarnetSyntheticTraffic::printAddr(Addr a) +{ + cachePort.printAddr(a); +} + + +GarnetSyntheticTraffic * +GarnetSyntheticTrafficParams::create() +{ + return new GarnetSyntheticTraffic(this); +} diff --git a/src/cpu/testers/garnet_synthetic_traffic/GarnetSyntheticTraffic.hh b/src/cpu/testers/garnet_synthetic_traffic/GarnetSyntheticTraffic.hh new file mode 100644 index 000000000..94eee44d7 --- /dev/null +++ b/src/cpu/testers/garnet_synthetic_traffic/GarnetSyntheticTraffic.hh @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2016 Georgia Institute of Technology + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Tushar Krishna + */ + +#ifndef __CPU_GARNET_SYNTHETIC_TRAFFIC_HH__ +#define __CPU_GARNET_SYNTHETIC_TRAFFIC_HH__ + +#include <set> + +#include "base/statistics.hh" +#include "mem/mem_object.hh" +#include "mem/port.hh" +#include "params/GarnetSyntheticTraffic.hh" +#include "sim/eventq.hh" +#include "sim/sim_exit.hh" +#include "sim/sim_object.hh" +#include "sim/stats.hh" + +enum TrafficType {BIT_COMPLEMENT_ = 0, + BIT_REVERSE_ = 1, + BIT_ROTATION_ = 2, + NEIGHBOR_ = 3, + SHUFFLE_ = 4, + TORNADO_ = 5, + TRANSPOSE_ = 6, + UNIFORM_RANDOM_ = 7, + NUM_TRAFFIC_PATTERNS_}; + +class Packet; +class GarnetSyntheticTraffic : public MemObject +{ + public: + typedef GarnetSyntheticTrafficParams Params; + GarnetSyntheticTraffic(const Params *p); + + virtual void init(); + + // main simulation loop (one cycle) + void tick(); + + virtual BaseMasterPort &getMasterPort(const std::string &if_name, + PortID idx = InvalidPortID); + + /** + * Print state of address in memory system via PrintReq (for + * debugging). + */ + void printAddr(Addr a); + + protected: + class TickEvent : public Event + { + private: + GarnetSyntheticTraffic *cpu; + + public: + TickEvent(GarnetSyntheticTraffic *c) : Event(CPU_Tick_Pri), cpu(c) {} + void process() { cpu->tick(); } + virtual const char *description() const + { + return "GarnetSyntheticTraffic tick"; + } + }; + + TickEvent tickEvent; + + class CpuPort : public MasterPort + { + GarnetSyntheticTraffic *tester; + + public: + + CpuPort(const std::string &_name, GarnetSyntheticTraffic *_tester) + : MasterPort(_name, _tester), tester(_tester) + { } + + protected: + + virtual bool recvTimingResp(PacketPtr pkt); + + virtual void recvReqRetry(); + }; + + CpuPort cachePort; + + class GarnetSyntheticTrafficSenderState : public Packet::SenderState + { + public: + /** Constructor. */ + GarnetSyntheticTrafficSenderState(uint8_t *_data) + : data(_data) + { } + + // Hold onto data pointer + uint8_t *data; + }; + + PacketPtr retryPkt; + unsigned size; + int id; + + std::map<std::string, TrafficType> trafficStringToEnum; + + unsigned blockSizeBits; + + Tick noResponseCycles; + + int numDestinations; + Tick simCycles; + int numPacketsMax; + int numPacketsSent; + int singleSender; + int singleDest; + + std::string trafficType; // string + TrafficType traffic; // enum from string + double injRate; + int injVnet; + int precision; + + const Cycles responseLimit; + + MasterID masterId; + + void completeRequest(PacketPtr pkt); + + void generatePkt(); + void sendPkt(PacketPtr pkt); + void initTrafficType(); + + void doRetry(); + + friend class MemCompleteEvent; +}; + +#endif // __CPU_GARNET_SYNTHETIC_TRAFFIC_HH__ + + + diff --git a/src/cpu/testers/garnet_synthetic_traffic/GarnetSyntheticTraffic.py b/src/cpu/testers/garnet_synthetic_traffic/GarnetSyntheticTraffic.py new file mode 100644 index 000000000..261e643c1 --- /dev/null +++ b/src/cpu/testers/garnet_synthetic_traffic/GarnetSyntheticTraffic.py @@ -0,0 +1,57 @@ +# Copyright (c) 2016 Georgia Institute of Technology +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Tushar Krishna + +from MemObject import MemObject +from m5.params import * +from m5.proxy import * + +class GarnetSyntheticTraffic(MemObject): + type = 'GarnetSyntheticTraffic' + cxx_header = \ + "cpu/testers/garnet_synthetic_traffic/GarnetSyntheticTraffic.hh" + block_offset = Param.Int(6, "block offset in bits") + num_dest = Param.Int(1, "Number of Destinations") + memory_size = Param.Int(65536, "memory size") + sim_cycles = Param.Int(1000, "Number of simulation cycles") + num_packets_max = Param.Int(-1, "Max number of packets to send. \ + Default is to keep sending till simulation ends") + single_sender = Param.Int(-1, "Send only from this node. \ + By default every node sends") + single_dest = Param.Int(-1, "Send only to this dest. \ + Default depends on traffic_type") + traffic_type = Param.String("uniform_random", "Traffic type") + inj_rate = Param.Float(0.1, "Packet injection rate") + inj_vnet = Param.Int(-1, "Vnet to inject in. \ + 0 and 1 are 1-flit, 2 is 5-flit. \ + Default is to inject in all three vnets") + precision = Param.Int(3, "Number of digits of precision \ + after decimal point") + response_limit = Param.Cycles(5000000, "Cycles before exiting \ + due to lack of progress") + test = MasterPort("Port to the memory system to test") + system = Param.System(Parent.any, "System we belong to") diff --git a/src/cpu/testers/garnet_synthetic_traffic/SConscript b/src/cpu/testers/garnet_synthetic_traffic/SConscript new file mode 100644 index 000000000..f1624b05e --- /dev/null +++ b/src/cpu/testers/garnet_synthetic_traffic/SConscript @@ -0,0 +1,37 @@ +# -*- mode:python -*- + +# Copyright (c) 2016 Georgia Institute of Technology. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Tushar Krishna + +Import('*') + +SimObject('GarnetSyntheticTraffic.py') + +Source('GarnetSyntheticTraffic.cc') + +DebugFlag('GarnetSyntheticTraffic') |