From 09c3a97a4c9aace6e2c52823679b31323cab42f6 Mon Sep 17 00:00:00 2001 From: Tushar Krishna Date: Mon, 21 Mar 2011 22:51:58 -0400 Subject: This patch adds the network tester for simple and garnet networks. The tester code is in testers/networktest. The tester can be invoked by configs/example/ruby_network_test.py. A dummy coherence protocol called Network_test is also addded for network-only simulations and testing. The protocol takes in messages from the tester and just pushes them into the network in the appropriate vnet, without storing any state. --- src/cpu/testers/networktest/NetworkTest.py | 42 ++++ src/cpu/testers/networktest/SConscript | 37 ++++ src/cpu/testers/networktest/networktest.cc | 333 +++++++++++++++++++++++++++++ src/cpu/testers/networktest/networktest.hh | 158 ++++++++++++++ 4 files changed, 570 insertions(+) create mode 100644 src/cpu/testers/networktest/NetworkTest.py create mode 100644 src/cpu/testers/networktest/SConscript create mode 100644 src/cpu/testers/networktest/networktest.cc create mode 100644 src/cpu/testers/networktest/networktest.hh (limited to 'src/cpu/testers/networktest') diff --git a/src/cpu/testers/networktest/NetworkTest.py b/src/cpu/testers/networktest/NetworkTest.py new file mode 100644 index 000000000..d4eef09c5 --- /dev/null +++ b/src/cpu/testers/networktest/NetworkTest.py @@ -0,0 +1,42 @@ +# Copyright (c) 2009 Advanced Micro Devices, Inc. +# 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 * + +class NetworkTest(MemObject): + type = 'NetworkTest' + block_offset = Param.Int(6, "block offset in bits") + num_memories = Param.Int(1, "Num Memories") + memory_size = Param.Int(65536, "memory size") + fixed_pkts = Param.Bool(False, "Send fixed number of packets") + max_packets = Param.Counter(0, "Number of packets to send when in fixed_pkts mode") + traffic_type = Param.Counter(0, "Traffic type: uniform random, tornado, bit complement") + inj_rate = Param.Float(0.1, "Packet injection rate") + precision = Param.Int(3, "Number of digits of precision after decimal point") + test = Port("Port to the memory system to test") diff --git a/src/cpu/testers/networktest/SConscript b/src/cpu/testers/networktest/SConscript new file mode 100644 index 000000000..b658ac079 --- /dev/null +++ b/src/cpu/testers/networktest/SConscript @@ -0,0 +1,37 @@ +# -*- mode:python -*- + +# Copyright (c) 2009 Advanced Micro Devices, Inc. +# 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('NetworkTest.py') + +Source('networktest.cc', Werror=False) + +TraceFlag('NetworkTest') diff --git a/src/cpu/testers/networktest/networktest.cc b/src/cpu/testers/networktest/networktest.cc new file mode 100644 index 000000000..4f4c30931 --- /dev/null +++ b/src/cpu/testers/networktest/networktest.cc @@ -0,0 +1,333 @@ +/* + * Copyright (c) 2009 Advanced Micro Devices, Inc. + * 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 +#include +#include +#include +#include + +#include "base/misc.hh" +#include "base/statistics.hh" +#include "cpu/testers/networktest/networktest.hh" +#include "mem/mem_object.hh" +#include "mem/port.hh" +#include "mem/packet.hh" +#include "mem/request.hh" +#include "sim/sim_events.hh" +#include "sim/stats.hh" + +using namespace std; + +int TESTER_NETWORK=0; + +bool +NetworkTest::CpuPort::recvTiming(PacketPtr pkt) +{ + if (pkt->isResponse()) { + networktest->completeRequest(pkt); + } else { + // must be snoop upcall + assert(pkt->isRequest()); + assert(pkt->getDest() == Packet::Broadcast); + } + return true; +} + +Tick +NetworkTest::CpuPort::recvAtomic(PacketPtr pkt) +{ + panic("NetworkTest doesn't expect recvAtomic call!"); + // Will not be used + assert(pkt->isRequest()); + assert(pkt->getDest() == Packet::Broadcast); + return curTick(); +} + +void +NetworkTest::CpuPort::recvFunctional(PacketPtr pkt) +{ + panic("NetworkTest doesn't expect recvFunctional call!"); + // Will not be used + return; +} + +void +NetworkTest::CpuPort::recvStatusChange(Status status) +{ + if (status == RangeChange) { + if (!snoopRangeSent) { + snoopRangeSent = true; + sendStatusChange(Port::RangeChange); + } + return; + } + + panic("NetworkTest doesn't expect recvStatusChange callback!"); +} + +void +NetworkTest::CpuPort::recvRetry() +{ + networktest->doRetry(); +} + +void +NetworkTest::sendPkt(PacketPtr pkt) +{ + if (cachePort.sendTiming(pkt)) { + numPacketsSent++; + accessRetry = false; + } else { + accessRetry = true; + retryPkt = pkt; + } +} + +NetworkTest::NetworkTest(const Params *p) + : MemObject(p), + tickEvent(this), + cachePort("network-test", this), + retryPkt(NULL), + size(p->memory_size), + blockSizeBits(p->block_offset), + numMemories(p->num_memories), + fixedPkts(p->fixed_pkts), + maxPackets(p->max_packets), + trafficType(p->traffic_type), + injRate(p->inj_rate), + precision(p->precision) +{ + cachePort.snoopRangeSent = false; + + // set up counters + noResponseCycles = 0; + schedule(tickEvent, 0); + + id = TESTER_NETWORK++; + DPRINTF(NetworkTest,"Config Created: Name = %s , and id = %d\n", + name(), id); + + accessRetry = false; +} + +Port * +NetworkTest::getPort(const std::string &if_name, int idx) +{ + if (if_name == "test") + return &cachePort; + else + panic("No Such Port\n"); +} + +void +NetworkTest::init() +{ + numPacketsSent = 0; +} + + +void +NetworkTest::completeRequest(PacketPtr pkt) +{ + Request *req = pkt->req; + + DPRINTF(NetworkTest, "Completed injection of %s packet for address %x\n", + pkt->isWrite() ? "write" : "read\n", + req->getPaddr()); + + assert(pkt->isResponse()); + noResponseCycles = 0; + delete pkt->req; + delete pkt; +} + + +void +NetworkTest::tick() +{ + if (!tickEvent.scheduled()) + schedule(tickEvent, curTick() + ticks(1)); + + if (++noResponseCycles >= 500000) { + cerr << name() << ": deadlocked at cycle " << curTick() << endl; + fatal(""); + } + + if (accessRetry) { + sendPkt(retryPkt); + return; + } + + // 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 send_this_cycle; + int injRange = pow(10, precision); + unsigned trySending = random() % injRange; + if (trySending < injRate*injRange) + send_this_cycle = true; + else + send_this_cycle = false; + + // always generatePkt unless fixedPkts is enabled + if (send_this_cycle) { + if (fixedPkts) { + if (numPacketsSent < maxPackets) { + generatePkt(); + } + } else { + generatePkt(); + } + } +} + +void +NetworkTest::generatePkt() +{ + unsigned destination = id; + if (trafficType == 0) { // Uniform Random + while (destination == id) + destination = random() % numMemories; + } else if (trafficType == 1) { // Tornado + int networkDimension = (int) sqrt(numMemories); + int my_x = id%networkDimension; + int my_y = id/networkDimension; + + int dest_x = my_x + (int) ceil(networkDimension/2) - 1; + dest_x = dest_x%networkDimension; + int dest_y = my_y; + + destination = dest_y*networkDimension + dest_x; + } else if (trafficType == 2) { // Bit Complement + int networkDimension = (int) sqrt(numMemories); + int my_x = id%networkDimension; + int my_y = id/networkDimension; + + int dest_x = networkDimension - my_x - 1; + int dest_y = networkDimension - my_y - 1; + + destination = dest_y*networkDimension + dest_x; + } + + Request *req = new Request(); + Request::Flags flags; + + // 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. + // + // networktest assumes the Network_test 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; + + unsigned randomReqType = random() % 3; + if (randomReqType == 0) { + // generate packet for virtual network 0 + requestType = MemCmd::ReadReq; + req->setPhys(paddr, access_size, flags); + } else if (randomReqType == 1) { + // generate packet for virtual network 1 + requestType = MemCmd::ReadReq; + flags.set(Request::INST_FETCH); + req->setVirt(0, 0x0, access_size, flags, 0x0); + req->setPaddr(paddr); + } else { // if (randomReqType == 2) + // generate packet for virtual network 2 + requestType = MemCmd::WriteReq; + req->setPhys(paddr, access_size, flags); + } + + req->setThreadContext(id,0); + uint8_t *result = new uint8_t[8]; + + //No need to do functional simulation + //We just do timing simulation of the network + + DPRINTF(NetworkTest, + "Generated packet with destination %d, embedded in address %x\n", + destination, req->getPaddr()); + + PacketPtr pkt = new Packet(req, requestType, 0); + pkt->setSrc(0); //Not used + pkt->dataDynamicArray(new uint8_t[req->getSize()]); + NetworkTestSenderState *state = new NetworkTestSenderState(result); + pkt->senderState = state; + + sendPkt(pkt); +} + +void +NetworkTest::doRetry() +{ + if (cachePort.sendTiming(retryPkt)) { + accessRetry = false; + retryPkt = NULL; + } +} + +void +NetworkTest::printAddr(Addr a) +{ + cachePort.printAddr(a); +} + + +NetworkTest * +NetworkTestParams::create() +{ + return new NetworkTest(this); +} diff --git a/src/cpu/testers/networktest/networktest.hh b/src/cpu/testers/networktest/networktest.hh new file mode 100644 index 000000000..923f47df2 --- /dev/null +++ b/src/cpu/testers/networktest/networktest.hh @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2009 Advanced Micro Devices, Inc. + * 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_NETWORKTEST_NETWORKTEST_HH__ +#define __CPU_NETWORKTEST_NETWORKTEST_HH__ + +#include + +#include "base/statistics.hh" +#include "base/fast_alloc.hh" +#include "params/NetworkTest.hh" +#include "sim/eventq.hh" +#include "sim/sim_exit.hh" +#include "sim/sim_object.hh" +#include "sim/stats.hh" +#include "mem/mem_object.hh" +#include "mem/port.hh" + +class Packet; +class NetworkTest : public MemObject +{ + public: + typedef NetworkTestParams Params; + NetworkTest(const Params *p); + + virtual void init(); + + inline Tick ticks(int numCycles) const { return numCycles; } + + // main simulation loop (one cycle) + void tick(); + + virtual Port *getPort(const std::string &if_name, int idx = -1); + + /** + * Print state of address in memory system via PrintReq (for + * debugging). + */ + void printAddr(Addr a); + + protected: + class TickEvent : public Event + { + private: + NetworkTest *cpu; + + public: + TickEvent(NetworkTest *c) : Event(CPU_Tick_Pri), cpu(c) {} + void process() { cpu->tick(); } + virtual const char *description() const { return "NetworkTest tick"; } + }; + + TickEvent tickEvent; + + class CpuPort : public Port + { + NetworkTest *networktest; + + public: + + CpuPort(const std::string &_name, NetworkTest *_networktest) + : Port(_name, _networktest), networktest(_networktest) + { } + + bool snoopRangeSent; + + protected: + + virtual bool recvTiming(PacketPtr pkt); + + virtual Tick recvAtomic(PacketPtr pkt); + + virtual void recvFunctional(PacketPtr pkt); + + virtual void recvStatusChange(Status status); + + virtual void recvRetry(); + + virtual void getDeviceAddressRanges(AddrRangeList &resp, + bool &snoop) + { resp.clear(); snoop = false; } + }; + + CpuPort cachePort; + + bool snoopRangeSent; + + class NetworkTestSenderState : public Packet::SenderState, public FastAlloc + { + public: + /** Constructor. */ + NetworkTestSenderState(uint8_t *_data) + : data(_data) + { } + + // Hold onto data pointer + uint8_t *data; + }; + + PacketPtr retryPkt; + bool accessRetry; + unsigned size; + int id; + + unsigned blockSizeBits; + + Tick noResponseCycles; + + int numMemories; + bool fixedPkts; + int maxPackets; + int numPacketsSent; + + int trafficType; + double injRate; + int precision; + + void completeRequest(PacketPtr pkt); + + void generatePkt(); + void sendPkt(PacketPtr pkt); + + void doRetry(); + + friend class MemCompleteEvent; +}; + +#endif // __CPU_NETWORKTEST_NETWORKTEST_HH__ + + + -- cgit v1.2.3