From 2a8e7a9ee62ec5caf1c08817005466c10a04c6e3 Mon Sep 17 00:00:00 2001 From: Riken Gohil Date: Wed, 12 Jul 2017 17:33:11 +0100 Subject: cpu-tester: Refactoring traffic generators into separate files. Change-Id: I2372a0a88e276dcb0c06c3d0a789e010cfba8013 Reviewed-by: Matteo Andreozzi Reviewed-on: https://gem5-review.googlesource.com/5722 Maintainer: Andreas Sandberg Reviewed-by: Andreas Sandberg --- src/cpu/testers/traffic_gen/SConscript | 10 +- src/cpu/testers/traffic_gen/base_gen.cc | 78 ++++ src/cpu/testers/traffic_gen/base_gen.hh | 136 ++++++ src/cpu/testers/traffic_gen/dram_gen.cc | 166 +++++++ src/cpu/testers/traffic_gen/dram_gen.hh | 169 ++++++++ src/cpu/testers/traffic_gen/dram_rot_gen.cc | 140 ++++++ src/cpu/testers/traffic_gen/dram_rot_gen.hh | 129 ++++++ src/cpu/testers/traffic_gen/generators.cc | 541 ----------------------- src/cpu/testers/traffic_gen/generators.hh | 647 ---------------------------- src/cpu/testers/traffic_gen/idle_gen.cc | 66 +++ src/cpu/testers/traffic_gen/idle_gen.hh | 76 ++++ src/cpu/testers/traffic_gen/linear_gen.cc | 119 +++++ src/cpu/testers/traffic_gen/linear_gen.hh | 137 ++++++ src/cpu/testers/traffic_gen/random_gen.cc | 113 +++++ src/cpu/testers/traffic_gen/random_gen.hh | 132 ++++++ src/cpu/testers/traffic_gen/trace_gen.cc | 181 ++++++++ src/cpu/testers/traffic_gen/trace_gen.hh | 213 +++++++++ src/cpu/testers/traffic_gen/traffic_gen.hh | 11 +- 18 files changed, 1872 insertions(+), 1192 deletions(-) create mode 100644 src/cpu/testers/traffic_gen/base_gen.cc create mode 100644 src/cpu/testers/traffic_gen/base_gen.hh create mode 100644 src/cpu/testers/traffic_gen/dram_gen.cc create mode 100644 src/cpu/testers/traffic_gen/dram_gen.hh create mode 100644 src/cpu/testers/traffic_gen/dram_rot_gen.cc create mode 100644 src/cpu/testers/traffic_gen/dram_rot_gen.hh delete mode 100644 src/cpu/testers/traffic_gen/generators.cc delete mode 100644 src/cpu/testers/traffic_gen/generators.hh create mode 100644 src/cpu/testers/traffic_gen/idle_gen.cc create mode 100644 src/cpu/testers/traffic_gen/idle_gen.hh create mode 100644 src/cpu/testers/traffic_gen/linear_gen.cc create mode 100644 src/cpu/testers/traffic_gen/linear_gen.hh create mode 100644 src/cpu/testers/traffic_gen/random_gen.cc create mode 100644 src/cpu/testers/traffic_gen/random_gen.hh create mode 100644 src/cpu/testers/traffic_gen/trace_gen.cc create mode 100644 src/cpu/testers/traffic_gen/trace_gen.hh diff --git a/src/cpu/testers/traffic_gen/SConscript b/src/cpu/testers/traffic_gen/SConscript index 00a3a84bc..d73819b0c 100644 --- a/src/cpu/testers/traffic_gen/SConscript +++ b/src/cpu/testers/traffic_gen/SConscript @@ -1,6 +1,6 @@ # -*- mode:python -*- -# Copyright (c) 2012 ARM Limited +# Copyright (c) 2012, 2017 ARM Limited # All rights reserved. # # The license below extends only to copyright in the software and shall @@ -44,7 +44,13 @@ Import('*') if env['HAVE_PROTOBUF']: SimObject('TrafficGen.py') - Source('generators.cc') + Source('base_gen.cc') + Source('dram_gen.cc') + Source('dram_rot_gen.cc') + Source('idle_gen.cc') + Source('linear_gen.cc') + Source('random_gen.cc') + Source('trace_gen.cc') Source('traffic_gen.cc') DebugFlag('TrafficGen') diff --git a/src/cpu/testers/traffic_gen/base_gen.cc b/src/cpu/testers/traffic_gen/base_gen.cc new file mode 100644 index 000000000..cd568f151 --- /dev/null +++ b/src/cpu/testers/traffic_gen/base_gen.cc @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2012-2013, 2016-2017 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed here under. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * 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: Thomas Grass + * Andreas Hansson + * Sascha Bischoff + * Neha Agarwal + */ + +#include "cpu/testers/traffic_gen/base_gen.hh" + +#include + +#include "base/random.hh" +#include "base/trace.hh" +#include "debug/TrafficGen.hh" +#include "proto/packet.pb.h" + +BaseGen::BaseGen(const std::string& _name, MasterID master_id, Tick _duration) + : _name(_name), masterID(master_id), duration(_duration) +{ +} + +PacketPtr +BaseGen::getPacket(Addr addr, unsigned size, const MemCmd& cmd, + Request::FlagsType flags) +{ + // Create new request + Request *req = new Request(addr, size, flags, masterID); + // Dummy PC to have PC-based prefetchers latch on; get entropy into higher + // bits + req->setPC(((Addr)masterID) << 2); + + // Embed it in a packet + PacketPtr pkt = new Packet(req, cmd); + + uint8_t* pkt_data = new uint8_t[req->getSize()]; + pkt->dataDynamic(pkt_data); + + if (cmd.isWrite()) { + std::fill_n(pkt_data, req->getSize(), (uint8_t)masterID); + } + + return pkt; +} diff --git a/src/cpu/testers/traffic_gen/base_gen.hh b/src/cpu/testers/traffic_gen/base_gen.hh new file mode 100644 index 000000000..26aa62df4 --- /dev/null +++ b/src/cpu/testers/traffic_gen/base_gen.hh @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2012-2013, 2017 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed here under. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * 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: Thomas Grass + * Andreas Hansson + * Sascha Bischoff + * Neha Agarwal + */ + +/** + * @file + * Declaration of the base generator class for all generators. + */ + +#ifndef __CPU_TRAFFIC_GEN_BASE_GEN_HH__ +#define __CPU_TRAFFIC_GEN_BASE_GEN_HH__ + +#include "base/bitfield.hh" +#include "base/intmath.hh" +#include "mem/packet.hh" +#include "proto/protoio.hh" + +/** + * Base class for all generators, with the shared functionality and + * virtual functions for entering, executing and leaving the + * generator. + */ +class BaseGen +{ + + protected: + + /** Name to use for status and debug printing */ + const std::string _name; + + /** The MasterID used for generating requests */ + const MasterID masterID; + + /** + * Generate a new request and associated packet + * + * @param addr Physical address to use + * @param size Size of the request + * @param cmd Memory command to send + * @param flags Optional request flags + */ + PacketPtr getPacket(Addr addr, unsigned size, const MemCmd& cmd, + Request::FlagsType flags = 0); + + public: + + /** Time to spend in this state */ + const Tick duration; + + /** + * Create a base generator. + * + * @param _name Name to use for status and debug + * @param master_id MasterID set on each request + * @param _duration duration of this state before transitioning + */ + BaseGen(const std::string& _name, MasterID master_id, Tick _duration); + + virtual ~BaseGen() { } + + /** + * Get the name, useful for DPRINTFs. + * + * @return the given name + */ + std::string name() const { return _name; } + + /** + * Enter this generator state. + */ + virtual void enter() = 0; + + /** + * Get the next generated packet. + * + * @return A packet to be sent at the current tick + */ + virtual PacketPtr getNextPacket() = 0; + + /** + * Exit this generator state. By default do nothing. + */ + virtual void exit() { }; + + /** + * Determine the tick when the next packet is available. MaxTick + * means that there will not be any further packets in the current + * activation cycle of the generator. + * + * @param elastic should the injection respond to flow control or not + * @param delay time the previous packet spent waiting + * @return next tick when a packet is available + */ + virtual Tick nextPacketTick(bool elastic, Tick delay) const = 0; + +}; + +#endif diff --git a/src/cpu/testers/traffic_gen/dram_gen.cc b/src/cpu/testers/traffic_gen/dram_gen.cc new file mode 100644 index 000000000..bfa0ea948 --- /dev/null +++ b/src/cpu/testers/traffic_gen/dram_gen.cc @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2012-2013, 2016-2017 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed here under. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * 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: Thomas Grass + * Andreas Hansson + * Sascha Bischoff + * Neha Agarwal + */ + +#include "cpu/testers/traffic_gen/dram_gen.hh" + +#include + +#include "base/random.hh" +#include "base/trace.hh" +#include "debug/TrafficGen.hh" +#include "proto/packet.pb.h" + +PacketPtr +DramGen::getNextPacket() +{ + // if this is the first of the packets in series to be generated, + // start counting again + if (countNumSeqPkts == 0) { + countNumSeqPkts = numSeqPkts; + + // choose if we generate a read or a write here + isRead = readPercent != 0 && + (readPercent == 100 || random_mt.random(0, 100) < readPercent); + + assert((readPercent == 0 && !isRead) || + (readPercent == 100 && isRead) || + readPercent != 100); + + // pick a random bank + unsigned int new_bank = + random_mt.random(0, nbrOfBanksUtil - 1); + + // pick a random rank + unsigned int new_rank = + random_mt.random(0, nbrOfRanks - 1); + + // Generate the start address of the command series + // routine will update addr variable with bank, rank, and col + // bits updated for random traffic mode + genStartAddr(new_bank, new_rank); + + } else { + // increment the column by one + if (addrMapping == 1) + // addrMapping=1: RoRaBaCoCh/RoRaBaChCo + // Simply increment addr by blocksize to increment + // the column by one + addr += blocksize; + + else if (addrMapping == 0) { + // addrMapping=0: RoCoRaBaCh + // Explicity increment the column bits + unsigned int new_col = ((addr / blocksize / + nbrOfBanksDRAM / nbrOfRanks) % + (pageSize / blocksize)) + 1; + replaceBits(addr, blockBits + bankBits + rankBits + pageBits - 1, + blockBits + bankBits + rankBits, new_col); + } + } + + DPRINTF(TrafficGen, "DramGen::getNextPacket: %c to addr %x, " + "size %d, countNumSeqPkts: %d, numSeqPkts: %d\n", + isRead ? 'r' : 'w', addr, blocksize, countNumSeqPkts, numSeqPkts); + + // create a new request packet + PacketPtr pkt = getPacket(addr, blocksize, + isRead ? MemCmd::ReadReq : MemCmd::WriteReq); + + // add the amount of data manipulated to the total + dataManipulated += blocksize; + + // subtract the number of packets remained to be generated + --countNumSeqPkts; + + // return the generated packet + return pkt; +} + +void +DramGen::genStartAddr(unsigned int new_bank, unsigned int new_rank) +{ + // start by picking a random address in the range + addr = random_mt.random(startAddr, endAddr - 1); + + // round down to start address of a block, i.e. a DRAM burst + addr -= addr % blocksize; + + // insert the bank bits at the right spot, and align the + // address to achieve the required hit length, this involves + // finding the appropriate start address such that all + // sequential packets target successive columns in the same + // page + + // for example, if we have a stride size of 192B, which means + // for LPDDR3 where burstsize = 32B we have numSeqPkts = 6, + // the address generated previously can be such that these + // 192B cross the page boundary, hence it needs to be aligned + // so that they all belong to the same page for page hit + unsigned int columns_per_page = pageSize / blocksize; + + // pick a random column, but ensure that there is room for + // numSeqPkts sequential columns in the same page + unsigned int new_col = + random_mt.random(0, columns_per_page - numSeqPkts); + + if (addrMapping == 1) { + // addrMapping=1: RoRaBaCoCh/RoRaBaChCo + // Block bits, then page bits, then bank bits, then rank bits + replaceBits(addr, blockBits + pageBits + bankBits - 1, + blockBits + pageBits, new_bank); + replaceBits(addr, blockBits + pageBits - 1, blockBits, new_col); + if (rankBits != 0) { + replaceBits(addr, blockBits + pageBits + bankBits +rankBits - 1, + blockBits + pageBits + bankBits, new_rank); + } + } else if (addrMapping == 0) { + // addrMapping=0: RoCoRaBaCh + // Block bits, then bank bits, then rank bits, then page bits + replaceBits(addr, blockBits + bankBits - 1, blockBits, new_bank); + replaceBits(addr, blockBits + bankBits + rankBits + pageBits - 1, + blockBits + bankBits + rankBits, new_col); + if (rankBits != 0) { + replaceBits(addr, blockBits + bankBits + rankBits - 1, + blockBits + bankBits, new_rank); + } + } +} diff --git a/src/cpu/testers/traffic_gen/dram_gen.hh b/src/cpu/testers/traffic_gen/dram_gen.hh new file mode 100644 index 000000000..d18a14b1c --- /dev/null +++ b/src/cpu/testers/traffic_gen/dram_gen.hh @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2012-2013, 2017 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed here under. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * 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: Thomas Grass + * Andreas Hansson + * Sascha Bischoff + * Neha Agarwal + */ + +/** + * @file + * Declaration of the DRAM generator for issuing variable page + * hit length requests and bank utilisation. + */ + +#ifndef __CPU_TRAFFIC_GEN_DRAM_GEN_HH__ +#define __CPU_TRAFFIC_GEN_DRAM_GEN_HH__ + +#include "base/bitfield.hh" +#include "base/intmath.hh" +#include "mem/packet.hh" +#include "proto/protoio.hh" +#include "random_gen.hh" + +/** + * DRAM specific generator is for issuing request with variable page + * hit length and bank utilization. Currently assumes a single + * channel configuration. + */ +class DramGen : public RandomGen +{ + + public: + + /** + * Create a DRAM address sequence generator. + * + * @param _name Name to use for status and debug + * @param master_id MasterID set on each request + * @param _duration duration of this state before transitioning + * @param start_addr Start address + * @param end_addr End address + * @param _blocksize Size used for transactions injected + * @param min_period Lower limit of random inter-transaction time + * @param max_period Upper limit of random inter-transaction time + * @param read_percent Percent of transactions that are reads + * @param data_limit Upper limit on how much data to read/write + * @param num_seq_pkts Number of packets per stride, each of _blocksize + * @param page_size Page size (bytes) used in the DRAM + * @param nbr_of_banks_DRAM Total number of banks in DRAM + * @param nbr_of_banks_util Number of banks to utilized, + * for N banks, we will use banks: 0->(N-1) + * @param addr_mapping Address mapping to be used, + * 0: RoCoRaBaCh, 1: RoRaBaCoCh/RoRaBaChCo + * assumes single channel system + */ + DramGen(const std::string& _name, MasterID master_id, Tick _duration, + Addr start_addr, Addr end_addr, Addr _blocksize, + Tick min_period, Tick max_period, + uint8_t read_percent, Addr data_limit, + unsigned int num_seq_pkts, unsigned int page_size, + unsigned int nbr_of_banks_DRAM, unsigned int nbr_of_banks_util, + unsigned int addr_mapping, + unsigned int nbr_of_ranks) + : RandomGen(_name, master_id, _duration, start_addr, end_addr, + _blocksize, min_period, max_period, read_percent, data_limit), + numSeqPkts(num_seq_pkts), countNumSeqPkts(0), addr(0), + isRead(true), pageSize(page_size), + pageBits(floorLog2(page_size / _blocksize)), + bankBits(floorLog2(nbr_of_banks_DRAM)), + blockBits(floorLog2(_blocksize)), + nbrOfBanksDRAM(nbr_of_banks_DRAM), + nbrOfBanksUtil(nbr_of_banks_util), addrMapping(addr_mapping), + rankBits(floorLog2(nbr_of_ranks)), + nbrOfRanks(nbr_of_ranks) + { + if (addrMapping != 1 && addrMapping != 0) { + addrMapping = 1; + warn("Unknown address mapping specified, using RoRaBaCoCh\n"); + } + } + + PacketPtr getNextPacket(); + + /** Insert bank, rank, and column bits into packed + * address to create address for 1st command in a + * series + * @param new_bank Bank number of next packet series + * @param new_rank Rank value of next packet series + */ + void genStartAddr(unsigned int new_bank , unsigned int new_rank); + + protected: + + /** Number of sequential DRAM packets to be generated per cpu request */ + const unsigned int numSeqPkts; + + /** Track number of sequential packets generated for a request */ + unsigned int countNumSeqPkts; + + /** Address of request */ + Addr addr; + + /** Remember type of requests to be generated in series */ + bool isRead; + + /** Page size of DRAM */ + const unsigned int pageSize; + + /** Number of page bits in DRAM address */ + const unsigned int pageBits; + + /** Number of bank bits in DRAM address*/ + const unsigned int bankBits; + + /** Number of block bits in DRAM address */ + const unsigned int blockBits; + + /** Number of banks in DRAM */ + const unsigned int nbrOfBanksDRAM; + + /** Number of banks to be utilized for a given configuration */ + const unsigned int nbrOfBanksUtil; + + /** Address mapping to be used */ + unsigned int addrMapping; + + /** Number of rank bits in DRAM address*/ + const unsigned int rankBits; + + /** Number of ranks to be utilized for a given configuration */ + const unsigned int nbrOfRanks; + +}; + +#endif diff --git a/src/cpu/testers/traffic_gen/dram_rot_gen.cc b/src/cpu/testers/traffic_gen/dram_rot_gen.cc new file mode 100644 index 000000000..8d2948723 --- /dev/null +++ b/src/cpu/testers/traffic_gen/dram_rot_gen.cc @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2012-2013, 2016-2017 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed here under. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * 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: Thomas Grass + * Andreas Hansson + * Sascha Bischoff + * Neha Agarwal + */ + +#include "cpu/testers/traffic_gen/dram_rot_gen.hh" + +#include + +#include "base/random.hh" +#include "base/trace.hh" +#include "debug/TrafficGen.hh" +#include "proto/packet.pb.h" + +PacketPtr +DramRotGen::getNextPacket() +{ + // if this is the first of the packets in series to be generated, + // start counting again + if (countNumSeqPkts == 0) { + countNumSeqPkts = numSeqPkts; + + // choose if we generate a read or a write here + if (readPercent == 50) { + if ((nextSeqCount % nbrOfBanksUtil) == 0) { + // Change type after all banks have been rotated + // Otherwise, keep current value + isRead = !isRead; + } + } else { + // Set randomly based on percentage + isRead = readPercent != 0; + } + + assert((readPercent == 0 && !isRead) || + (readPercent == 100 && isRead) || + readPercent != 100); + + // Overwrite random bank value + // Rotate across banks + unsigned int new_bank = nextSeqCount % nbrOfBanksUtil; + + // Overwrite random rank value + // Will rotate to the next rank after rotating through all banks, + // for each specified command type. + + // Use modular function to ensure that calculated rank is within + // system limits after state transition + unsigned int new_rank = (nextSeqCount / maxSeqCountPerRank) % + nbrOfRanks; + + // Increment nextSeqCount + // Roll back to 0 after completing a full rotation across + // banks, command type, and ranks + nextSeqCount = (nextSeqCount + 1) % + (nbrOfRanks * maxSeqCountPerRank); + + DPRINTF(TrafficGen, "DramRotGen::getNextPacket nextSeqCount: %d " + "new_rank: %d new_bank: %d\n", + nextSeqCount, new_rank, new_bank); + + // Generate the start address of the command series + // routine will update addr variable with bank, rank, and col + // bits updated for rotation scheme + genStartAddr(new_bank, new_rank); + + } else { + // increment the column by one + if (addrMapping == 1) + // addrMapping=1: RoRaBaCoCh/RoRaBaChCo + // Simply increment addr by blocksize to + // increment the column by one + addr += blocksize; + + else if (addrMapping == 0) { + // addrMapping=0: RoCoRaBaCh + // Explicity increment the column bits + + unsigned int new_col = ((addr / blocksize / + nbrOfBanksDRAM / nbrOfRanks) % + (pageSize / blocksize)) + 1; + replaceBits(addr, blockBits + bankBits + rankBits + pageBits - 1, + blockBits + bankBits + rankBits, new_col); + } + } + + DPRINTF(TrafficGen, "DramRotGen::getNextPacket: %c to addr %x, " + "size %d, countNumSeqPkts: %d, numSeqPkts: %d\n", + isRead ? 'r' : 'w', addr, blocksize, countNumSeqPkts, numSeqPkts); + + // create a new request packet + PacketPtr pkt = getPacket(addr, blocksize, + isRead ? MemCmd::ReadReq : MemCmd::WriteReq); + + // add the amount of data manipulated to the total + dataManipulated += blocksize; + + // subtract the number of packets remained to be generated + --countNumSeqPkts; + + // return the generated packet + return pkt; +} diff --git a/src/cpu/testers/traffic_gen/dram_rot_gen.hh b/src/cpu/testers/traffic_gen/dram_rot_gen.hh new file mode 100644 index 000000000..e65537644 --- /dev/null +++ b/src/cpu/testers/traffic_gen/dram_rot_gen.hh @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2012-2013, 2017 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed here under. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * 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: Thomas Grass + * Andreas Hansson + * Sascha Bischoff + * Neha Agarwal + */ + +/** + * @file + * Declaration of DRAM rotation generator that rotates + * through each rank. + */ + +#ifndef __CPU_TRAFFIC_GEN_DRAM_ROT_GEN_HH__ +#define __CPU_TRAFFIC_GEN_DRAM_ROT_GEN_HH__ + +#include "base/bitfield.hh" +#include "base/intmath.hh" +#include "dram_gen.hh" +#include "mem/packet.hh" +#include "proto/protoio.hh" + +class DramRotGen : public DramGen +{ + + public: + + /** + * Create a DRAM address sequence generator. + * This sequence generator will rotate through: + * 1) Banks per rank + * 2) Command type (if applicable) + * 3) Ranks per channel + * + * @param _name Name to use for status and debug + * @param master_id MasterID set on each request + * @param _duration duration of this state before transitioning + * @param start_addr Start address + * @param end_addr End address + * @param _blocksize Size used for transactions injected + * @param min_period Lower limit of random inter-transaction time + * @param max_period Upper limit of random inter-transaction time + * @param read_percent Percent of transactions that are reads + * @param data_limit Upper limit on how much data to read/write + * @param num_seq_pkts Number of packets per stride, each of _blocksize + * @param page_size Page size (bytes) used in the DRAM + * @param nbr_of_banks_DRAM Total number of banks in DRAM + * @param nbr_of_banks_util Number of banks to utilized, + * for N banks, we will use banks: 0->(N-1) + * @param nbr_of_ranks Number of ranks utilized, + * @param addr_mapping Address mapping to be used, + * 0: RoCoRaBaCh, 1: RoRaBaCoCh/RoRaBaChCo + * assumes single channel system + */ + DramRotGen(const std::string& _name, MasterID master_id, Tick _duration, + Addr start_addr, Addr end_addr, Addr _blocksize, + Tick min_period, Tick max_period, + uint8_t read_percent, Addr data_limit, + unsigned int num_seq_pkts, unsigned int page_size, + unsigned int nbr_of_banks_DRAM, unsigned int nbr_of_banks_util, + unsigned int addr_mapping, + unsigned int nbr_of_ranks, + unsigned int max_seq_count_per_rank) + : DramGen(_name, master_id, _duration, start_addr, end_addr, + _blocksize, min_period, max_period, read_percent, data_limit, + num_seq_pkts, page_size, nbr_of_banks_DRAM, + nbr_of_banks_util, addr_mapping, + nbr_of_ranks), + maxSeqCountPerRank(max_seq_count_per_rank), + nextSeqCount(0) + { + // Rotating traffic generation can only support a read + // percentage of 0, 50, or 100 + if (readPercent != 50 && readPercent != 100 && readPercent != 0) { + fatal("%s: Unsupported read percentage for DramRotGen: %d", + _name, readPercent); + } + } + + PacketPtr getNextPacket(); + + private: + /** Number of command series issued before the rank is + changed. Should rotate to the next rank after rorating + throughall the banks for each specified command type */ + const unsigned int maxSeqCountPerRank; + + /** Next packet series count used to set rank and bank, + and update isRead Incremented at the start of a new + packet series */ + unsigned int nextSeqCount; +}; + +#endif diff --git a/src/cpu/testers/traffic_gen/generators.cc b/src/cpu/testers/traffic_gen/generators.cc deleted file mode 100644 index 190d0daa5..000000000 --- a/src/cpu/testers/traffic_gen/generators.cc +++ /dev/null @@ -1,541 +0,0 @@ -/* - * Copyright (c) 2012-2013, 2016 ARM Limited - * All rights reserved - * - * The license below extends only to copyright in the software and shall - * not be construed as granting a license to any other intellectual - * property including but not limited to intellectual property relating - * to a hardware implementation of the functionality of the software - * licensed hereunder. You may use the software subject to the license - * terms below provided that you ensure that this notice is replicated - * unmodified and in its entirety in all distributions of the software, - * modified or unmodified, in source code or in binary form. - * - * 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: Thomas Grass - * Andreas Hansson - * Sascha Bischoff - * Neha Agarwal - */ - -#include - -#include "base/random.hh" -#include "base/trace.hh" -#include "cpu/testers/traffic_gen/generators.hh" -#include "debug/TrafficGen.hh" -#include "proto/packet.pb.h" - -BaseGen::BaseGen(const std::string& _name, MasterID master_id, Tick _duration) - : _name(_name), masterID(master_id), duration(_duration) -{ -} - -PacketPtr -BaseGen::getPacket(Addr addr, unsigned size, const MemCmd& cmd, - Request::FlagsType flags) -{ - // Create new request - Request *req = new Request(addr, size, flags, masterID); - // Dummy PC to have PC-based prefetchers latch on; get entropy into higher - // bits - req->setPC(((Addr)masterID) << 2); - - // Embed it in a packet - PacketPtr pkt = new Packet(req, cmd); - - uint8_t* pkt_data = new uint8_t[req->getSize()]; - pkt->dataDynamic(pkt_data); - - if (cmd.isWrite()) { - std::fill_n(pkt_data, req->getSize(), (uint8_t)masterID); - } - - return pkt; -} - -void -LinearGen::enter() -{ - // reset the address and the data counter - nextAddr = startAddr; - dataManipulated = 0; -} - -PacketPtr -LinearGen::getNextPacket() -{ - // choose if we generate a read or a write here - bool isRead = readPercent != 0 && - (readPercent == 100 || random_mt.random(0, 100) < readPercent); - - assert((readPercent == 0 && !isRead) || (readPercent == 100 && isRead) || - readPercent != 100); - - DPRINTF(TrafficGen, "LinearGen::getNextPacket: %c to addr %x, size %d\n", - isRead ? 'r' : 'w', nextAddr, blocksize); - - // Add the amount of data manipulated to the total - dataManipulated += blocksize; - - PacketPtr pkt = getPacket(nextAddr, blocksize, - isRead ? MemCmd::ReadReq : MemCmd::WriteReq); - - // increment the address - nextAddr += blocksize; - - // If we have reached the end of the address space, reset the - // address to the start of the range - if (nextAddr > endAddr) { - DPRINTF(TrafficGen, "Wrapping address to the start of " - "the range\n"); - nextAddr = startAddr; - } - - return pkt; -} - -Tick -LinearGen::nextPacketTick(bool elastic, Tick delay) const -{ - // Check to see if we have reached the data limit. If dataLimit is - // zero we do not have a data limit and therefore we will keep - // generating requests for the entire residency in this state. - if (dataLimit && dataManipulated >= dataLimit) { - DPRINTF(TrafficGen, "Data limit for LinearGen reached.\n"); - // there are no more requests, therefore return MaxTick - return MaxTick; - } else { - // return the time when the next request should take place - Tick wait = random_mt.random(minPeriod, maxPeriod); - - // compensate for the delay experienced to not be elastic, by - // default the value we generate is from the time we are - // asked, so the elasticity happens automatically - if (!elastic) { - if (wait < delay) - wait = 0; - else - wait -= delay; - } - - return curTick() + wait; - } -} - -void -RandomGen::enter() -{ - // reset the counter to zero - dataManipulated = 0; -} - -PacketPtr -RandomGen::getNextPacket() -{ - // choose if we generate a read or a write here - bool isRead = readPercent != 0 && - (readPercent == 100 || random_mt.random(0, 100) < readPercent); - - assert((readPercent == 0 && !isRead) || (readPercent == 100 && isRead) || - readPercent != 100); - - // address of the request - Addr addr = random_mt.random(startAddr, endAddr - 1); - - // round down to start address of block - addr -= addr % blocksize; - - DPRINTF(TrafficGen, "RandomGen::getNextPacket: %c to addr %x, size %d\n", - isRead ? 'r' : 'w', addr, blocksize); - - // add the amount of data manipulated to the total - dataManipulated += blocksize; - - // create a new request packet - return getPacket(addr, blocksize, - isRead ? MemCmd::ReadReq : MemCmd::WriteReq); -} - -PacketPtr -DramGen::getNextPacket() -{ - // if this is the first of the packets in series to be generated, - // start counting again - if (countNumSeqPkts == 0) { - countNumSeqPkts = numSeqPkts; - - // choose if we generate a read or a write here - isRead = readPercent != 0 && - (readPercent == 100 || random_mt.random(0, 100) < readPercent); - - assert((readPercent == 0 && !isRead) || - (readPercent == 100 && isRead) || - readPercent != 100); - - // pick a random bank - unsigned int new_bank = - random_mt.random(0, nbrOfBanksUtil - 1); - - // pick a random rank - unsigned int new_rank = - random_mt.random(0, nbrOfRanks - 1); - - // Generate the start address of the command series - // routine will update addr variable with bank, rank, and col - // bits updated for random traffic mode - genStartAddr(new_bank, new_rank); - - } else { - // increment the column by one - if (addrMapping == 1) - // addrMapping=1: RoRaBaCoCh/RoRaBaChCo - // Simply increment addr by blocksize to increment the column by one - addr += blocksize; - - else if (addrMapping == 0) { - // addrMapping=0: RoCoRaBaCh - // Explicity increment the column bits - unsigned int new_col = ((addr / blocksize / nbrOfBanksDRAM / nbrOfRanks) % - (pageSize / blocksize)) + 1; - replaceBits(addr, blockBits + bankBits + rankBits + pageBits - 1, - blockBits + bankBits + rankBits, new_col); - } - } - - DPRINTF(TrafficGen, "DramGen::getNextPacket: %c to addr %x, " - "size %d, countNumSeqPkts: %d, numSeqPkts: %d\n", - isRead ? 'r' : 'w', addr, blocksize, countNumSeqPkts, numSeqPkts); - - // create a new request packet - PacketPtr pkt = getPacket(addr, blocksize, - isRead ? MemCmd::ReadReq : MemCmd::WriteReq); - - // add the amount of data manipulated to the total - dataManipulated += blocksize; - - // subtract the number of packets remained to be generated - --countNumSeqPkts; - - // return the generated packet - return pkt; -} - -PacketPtr -DramRotGen::getNextPacket() -{ - // if this is the first of the packets in series to be generated, - // start counting again - if (countNumSeqPkts == 0) { - countNumSeqPkts = numSeqPkts; - - // choose if we generate a read or a write here - if (readPercent == 50) { - if ((nextSeqCount % nbrOfBanksUtil) == 0) { - // Change type after all banks have been rotated - // Otherwise, keep current value - isRead = !isRead; - } - } else { - // Set randomly based on percentage - isRead = readPercent != 0; - } - - assert((readPercent == 0 && !isRead) || - (readPercent == 100 && isRead) || - readPercent != 100); - - // Overwrite random bank value - // Rotate across banks - unsigned int new_bank = nextSeqCount % nbrOfBanksUtil; - - // Overwrite random rank value - // Will rotate to the next rank after rotating through all banks, - // for each specified command type. - - // Use modular function to ensure that calculated rank is within - // system limits after state transition - unsigned int new_rank = (nextSeqCount / maxSeqCountPerRank) % - nbrOfRanks; - - // Increment nextSeqCount - // Roll back to 0 after completing a full rotation across - // banks, command type, and ranks - nextSeqCount = (nextSeqCount + 1) % - (nbrOfRanks * maxSeqCountPerRank); - - DPRINTF(TrafficGen, "DramRotGen::getNextPacket nextSeqCount: %d " - "new_rank: %d new_bank: %d\n", - nextSeqCount, new_rank, new_bank); - - // Generate the start address of the command series - // routine will update addr variable with bank, rank, and col - // bits updated for rotation scheme - genStartAddr(new_bank, new_rank); - - } else { - // increment the column by one - if (addrMapping == 1) - // addrMapping=1: RoRaBaCoCh/RoRaBaChCo - // Simply increment addr by blocksize to increment the column by one - addr += blocksize; - - else if (addrMapping == 0) { - // addrMapping=0: RoCoRaBaCh - // Explicity increment the column bits - unsigned int new_col = ((addr / blocksize / nbrOfBanksDRAM / nbrOfRanks) % - (pageSize / blocksize)) + 1; - replaceBits(addr, blockBits + bankBits + rankBits + pageBits - 1, - blockBits + bankBits + rankBits, new_col); - } - } - - DPRINTF(TrafficGen, "DramRotGen::getNextPacket: %c to addr %x, " - "size %d, countNumSeqPkts: %d, numSeqPkts: %d\n", - isRead ? 'r' : 'w', addr, blocksize, countNumSeqPkts, numSeqPkts); - - // create a new request packet - PacketPtr pkt = getPacket(addr, blocksize, - isRead ? MemCmd::ReadReq : MemCmd::WriteReq); - - // add the amount of data manipulated to the total - dataManipulated += blocksize; - - // subtract the number of packets remained to be generated - --countNumSeqPkts; - - // return the generated packet - return pkt; -} - -void -DramGen::genStartAddr(unsigned int new_bank, unsigned int new_rank) -{ - // start by picking a random address in the range - addr = random_mt.random(startAddr, endAddr - 1); - - // round down to start address of a block, i.e. a DRAM burst - addr -= addr % blocksize; - - // insert the bank bits at the right spot, and align the - // address to achieve the required hit length, this involves - // finding the appropriate start address such that all - // sequential packets target successive columns in the same - // page - - // for example, if we have a stride size of 192B, which means - // for LPDDR3 where burstsize = 32B we have numSeqPkts = 6, - // the address generated previously can be such that these - // 192B cross the page boundary, hence it needs to be aligned - // so that they all belong to the same page for page hit - unsigned int columns_per_page = pageSize / blocksize; - - // pick a random column, but ensure that there is room for - // numSeqPkts sequential columns in the same page - unsigned int new_col = - random_mt.random(0, columns_per_page - numSeqPkts); - - if (addrMapping == 1) { - // addrMapping=1: RoRaBaCoCh/RoRaBaChCo - // Block bits, then page bits, then bank bits, then rank bits - replaceBits(addr, blockBits + pageBits + bankBits - 1, - blockBits + pageBits, new_bank); - replaceBits(addr, blockBits + pageBits - 1, blockBits, new_col); - if (rankBits != 0) { - replaceBits(addr, blockBits + pageBits + bankBits +rankBits - 1, - blockBits + pageBits + bankBits, new_rank); - } - } else if (addrMapping == 0) { - // addrMapping=0: RoCoRaBaCh - // Block bits, then bank bits, then rank bits, then page bits - replaceBits(addr, blockBits + bankBits - 1, blockBits, new_bank); - replaceBits(addr, blockBits + bankBits + rankBits + pageBits - 1, - blockBits + bankBits + rankBits, new_col); - if (rankBits != 0) { - replaceBits(addr, blockBits + bankBits + rankBits - 1, - blockBits + bankBits, new_rank); - } - } -} - -Tick -RandomGen::nextPacketTick(bool elastic, Tick delay) const -{ - // Check to see if we have reached the data limit. If dataLimit is - // zero we do not have a data limit and therefore we will keep - // generating requests for the entire residency in this state. - if (dataLimit && dataManipulated >= dataLimit) - { - DPRINTF(TrafficGen, "Data limit for RandomGen reached.\n"); - // No more requests. Return MaxTick. - return MaxTick; - } else { - // return the time when the next request should take place - Tick wait = random_mt.random(minPeriod, maxPeriod); - - // compensate for the delay experienced to not be elastic, by - // default the value we generate is from the time we are - // asked, so the elasticity happens automatically - if (!elastic) { - if (wait < delay) - wait = 0; - else - wait -= delay; - } - - return curTick() + wait; - } -} - -TraceGen::InputStream::InputStream(const std::string& filename) - : trace(filename) -{ - init(); -} - -void -TraceGen::InputStream::init() -{ - // Create a protobuf message for the header and read it from the stream - ProtoMessage::PacketHeader header_msg; - if (!trace.read(header_msg)) { - panic("Failed to read packet header from trace\n"); - } else if (header_msg.tick_freq() != SimClock::Frequency) { - panic("Trace was recorded with a different tick frequency %d\n", - header_msg.tick_freq()); - } -} - -void -TraceGen::InputStream::reset() -{ - trace.reset(); - init(); -} - -bool -TraceGen::InputStream::read(TraceElement& element) -{ - ProtoMessage::Packet pkt_msg; - if (trace.read(pkt_msg)) { - element.cmd = pkt_msg.cmd(); - element.addr = pkt_msg.addr(); - element.blocksize = pkt_msg.size(); - element.tick = pkt_msg.tick(); - element.flags = pkt_msg.has_flags() ? pkt_msg.flags() : 0; - return true; - } - - // We have reached the end of the file - return false; -} - -Tick -TraceGen::nextPacketTick(bool elastic, Tick delay) const -{ - if (traceComplete) { - DPRINTF(TrafficGen, "No next tick as trace is finished\n"); - // We are at the end of the file, thus we have no more data in - // the trace Return MaxTick to signal that there will be no - // more transactions in this active period for the state. - return MaxTick; - } - - assert(nextElement.isValid()); - - DPRINTF(TrafficGen, "Next packet tick is %d\n", tickOffset + - nextElement.tick); - - // if the playback is supposed to be elastic, add the delay - if (elastic) - tickOffset += delay; - - return std::max(tickOffset + nextElement.tick, curTick()); -} - -void -TraceGen::enter() -{ - // update the trace offset to the time where the state was entered. - tickOffset = curTick(); - - // clear everything - currElement.clear(); - - // read the first element in the file and set the complete flag - traceComplete = !trace.read(nextElement); -} - -PacketPtr -TraceGen::getNextPacket() -{ - // shift things one step forward - currElement = nextElement; - nextElement.clear(); - - // read the next element and set the complete flag - traceComplete = !trace.read(nextElement); - - // it is the responsibility of the traceComplete flag to ensure we - // always have a valid element here - assert(currElement.isValid()); - - DPRINTF(TrafficGen, "TraceGen::getNextPacket: %c %d %d %d 0x%x\n", - currElement.cmd.isRead() ? 'r' : 'w', - currElement.addr, - currElement.blocksize, - currElement.tick, - currElement.flags); - - PacketPtr pkt = getPacket(currElement.addr + addrOffset, - currElement.blocksize, - currElement.cmd, currElement.flags); - - if (!traceComplete) - DPRINTF(TrafficGen, "nextElement: %c addr %d size %d tick %d (%d)\n", - nextElement.cmd.isRead() ? 'r' : 'w', - nextElement.addr, - nextElement.blocksize, - nextElement.tick + tickOffset, - nextElement.tick); - - return pkt; -} - -void -TraceGen::exit() -{ - // Check if we reached the end of the trace file. If we did not - // then we want to generate a warning stating that not the entire - // trace was played. - if (!traceComplete) { - warn("Trace player %s was unable to replay the entire trace!\n", - name()); - } - - // Clear any flags and start over again from the beginning of the - // file - trace.reset(); -} diff --git a/src/cpu/testers/traffic_gen/generators.hh b/src/cpu/testers/traffic_gen/generators.hh deleted file mode 100644 index 5604856a9..000000000 --- a/src/cpu/testers/traffic_gen/generators.hh +++ /dev/null @@ -1,647 +0,0 @@ -/* - * Copyright (c) 2012-2013 ARM Limited - * All rights reserved - * - * The license below extends only to copyright in the software and shall - * not be construed as granting a license to any other intellectual - * property including but not limited to intellectual property relating - * to a hardware implementation of the functionality of the software - * licensed hereunder. You may use the software subject to the license - * terms below provided that you ensure that this notice is replicated - * unmodified and in its entirety in all distributions of the software, - * modified or unmodified, in source code or in binary form. - * - * 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: Thomas Grass - * Andreas Hansson - * Sascha Bischoff - * Neha Agarwal - */ - -/** - * @file - * Declaration of a set of generator behaviours that are used by the - * stand-alone traffic generator, but can also be instantiated - * elsewhere. - */ - -#ifndef __CPU_TRAFFIC_GEN_GENERATORS_HH__ -#define __CPU_TRAFFIC_GEN_GENERATORS_HH__ - -#include "base/bitfield.hh" -#include "base/intmath.hh" -#include "mem/packet.hh" -#include "proto/protoio.hh" - -/** - * Base class for all generators, with the shared functionality and - * virtual functions for entering, executing and leaving the - * generator. - */ -class BaseGen -{ - - protected: - - /** Name to use for status and debug printing */ - const std::string _name; - - /** The MasterID used for generating requests */ - const MasterID masterID; - - /** - * Generate a new request and associated packet - * - * @param addr Physical address to use - * @param size Size of the request - * @param cmd Memory command to send - * @param flags Optional request flags - */ - PacketPtr getPacket(Addr addr, unsigned size, const MemCmd& cmd, - Request::FlagsType flags = 0); - - public: - - /** Time to spend in this state */ - const Tick duration; - - /** - * Create a base generator. - * - * @param _name Name to use for status and debug - * @param master_id MasterID set on each request - * @param _duration duration of this state before transitioning - */ - BaseGen(const std::string& _name, MasterID master_id, Tick _duration); - - virtual ~BaseGen() { } - - /** - * Get the name, useful for DPRINTFs. - * - * @return the given name - */ - std::string name() const { return _name; } - - /** - * Enter this generator state. - */ - virtual void enter() = 0; - - /** - * Get the next generated packet. - * - * @return A packet to be sent at the current tick - */ - virtual PacketPtr getNextPacket() = 0; - - /** - * Exit this generator state. By default do nothing. - */ - virtual void exit() { }; - - /** - * Determine the tick when the next packet is available. MaxTick - * means that there will not be any further packets in the current - * activation cycle of the generator. - * - * @param elastic should the injection respond to flow control or not - * @param delay time the previous packet spent waiting - * @return next tick when a packet is available - */ - virtual Tick nextPacketTick(bool elastic, Tick delay) const = 0; - -}; - -/** - * The idle generator does nothing. - */ -class IdleGen : public BaseGen -{ - - public: - - IdleGen(const std::string& _name, MasterID master_id, Tick _duration) - : BaseGen(_name, master_id, _duration) - { } - - void enter() { } - - PacketPtr getNextPacket() { return NULL; } - - Tick nextPacketTick(bool elastic, Tick delay) const { return MaxTick; } -}; - -/** - * The linear generator generates sequential requests from a - * start to an end address, with a fixed block size. A - * fraction of the requests are reads, as determined by the - * read percent. There is an optional data limit for when to - * stop generating new requests. - */ -class LinearGen : public BaseGen -{ - - public: - - /** - * Create a linear address sequence generator. Set - * min_period == max_period for a fixed inter-transaction - * time. - * - * @param _name Name to use for status and debug - * @param master_id MasterID set on each request - * @param _duration duration of this state before transitioning - * @param start_addr Start address - * @param end_addr End address - * @param _blocksize Size used for transactions injected - * @param min_period Lower limit of random inter-transaction time - * @param max_period Upper limit of random inter-transaction time - * @param read_percent Percent of transactions that are reads - * @param data_limit Upper limit on how much data to read/write - */ - LinearGen(const std::string& _name, MasterID master_id, Tick _duration, - Addr start_addr, Addr end_addr, Addr _blocksize, - Tick min_period, Tick max_period, - uint8_t read_percent, Addr data_limit) - : BaseGen(_name, master_id, _duration), - startAddr(start_addr), endAddr(end_addr), - blocksize(_blocksize), minPeriod(min_period), - maxPeriod(max_period), readPercent(read_percent), - dataLimit(data_limit), nextAddr(startAddr), dataManipulated(0) - { } - - void enter(); - - PacketPtr getNextPacket(); - - Tick nextPacketTick(bool elastic, Tick delay) const; - - private: - - /** Start of address range */ - const Addr startAddr; - - /** End of address range */ - const Addr endAddr; - - /** Blocksize and address increment */ - const Addr blocksize; - - /** Request generation period */ - const Tick minPeriod; - const Tick maxPeriod; - - /** - * Percent of generated transactions that should be reads - */ - const uint8_t readPercent; - - /** Maximum amount of data to manipulate */ - const Addr dataLimit; - - /** Address of next request */ - Addr nextAddr; - - /** - * Counter to determine the amount of data - * manipulated. Used to determine if we should continue - * generating requests. - */ - Addr dataManipulated; -}; - -/** - * The random generator is similar to the linear one, but does - * not generate sequential addresses. Instead it randomly - * picks an address in the range, aligned to the block size. - */ -class RandomGen : public BaseGen -{ - - public: - - /** - * Create a random address sequence generator. Set - * min_period == max_period for a fixed inter-transaction - * time. - * - * @param _name Name to use for status and debug - * @param master_id MasterID set on each request - * @param _duration duration of this state before transitioning - * @param start_addr Start address - * @param end_addr End address - * @param _blocksize Size used for transactions injected - * @param min_period Lower limit of random inter-transaction time - * @param max_period Upper limit of random inter-transaction time - * @param read_percent Percent of transactions that are reads - * @param data_limit Upper limit on how much data to read/write - */ - RandomGen(const std::string& _name, MasterID master_id, Tick _duration, - Addr start_addr, Addr end_addr, Addr _blocksize, - Tick min_period, Tick max_period, - uint8_t read_percent, Addr data_limit) - : BaseGen(_name, master_id, _duration), - startAddr(start_addr), endAddr(end_addr), - blocksize(_blocksize), minPeriod(min_period), - maxPeriod(max_period), readPercent(read_percent), - dataLimit(data_limit), dataManipulated(0) - { } - - void enter(); - - PacketPtr getNextPacket(); - - Tick nextPacketTick(bool elastic, Tick delay) const; - - protected: - - /** Start of address range */ - const Addr startAddr; - - /** End of address range */ - const Addr endAddr; - - /** Block size */ - const Addr blocksize; - - /** Request generation period */ - const Tick minPeriod; - const Tick maxPeriod; - - /** - * Percent of generated transactions that should be reads - */ - const uint8_t readPercent; - - /** Maximum amount of data to manipulate */ - const Addr dataLimit; - - /** - * Counter to determine the amount of data - * manipulated. Used to determine if we should continue - * generating requests. - */ - Addr dataManipulated; -}; - -/** - * DRAM specific generator is for issuing request with variable page - * hit length and bank utilization. Currently assumes a single - * channel configuration. - */ -class DramGen : public RandomGen -{ - - public: - - /** - * Create a DRAM address sequence generator. - * - * @param _name Name to use for status and debug - * @param master_id MasterID set on each request - * @param _duration duration of this state before transitioning - * @param start_addr Start address - * @param end_addr End address - * @param _blocksize Size used for transactions injected - * @param min_period Lower limit of random inter-transaction time - * @param max_period Upper limit of random inter-transaction time - * @param read_percent Percent of transactions that are reads - * @param data_limit Upper limit on how much data to read/write - * @param num_seq_pkts Number of packets per stride, each of _blocksize - * @param page_size Page size (bytes) used in the DRAM - * @param nbr_of_banks_DRAM Total number of banks in DRAM - * @param nbr_of_banks_util Number of banks to utilized, - * for N banks, we will use banks: 0->(N-1) - * @param addr_mapping Address mapping to be used, - * 0: RoCoRaBaCh, 1: RoRaBaCoCh/RoRaBaChCo - * assumes single channel system - */ - DramGen(const std::string& _name, MasterID master_id, Tick _duration, - Addr start_addr, Addr end_addr, Addr _blocksize, - Tick min_period, Tick max_period, - uint8_t read_percent, Addr data_limit, - unsigned int num_seq_pkts, unsigned int page_size, - unsigned int nbr_of_banks_DRAM, unsigned int nbr_of_banks_util, - unsigned int addr_mapping, - unsigned int nbr_of_ranks) - : RandomGen(_name, master_id, _duration, start_addr, end_addr, - _blocksize, min_period, max_period, read_percent, data_limit), - numSeqPkts(num_seq_pkts), countNumSeqPkts(0), addr(0), - isRead(true), pageSize(page_size), - pageBits(floorLog2(page_size / _blocksize)), - bankBits(floorLog2(nbr_of_banks_DRAM)), - blockBits(floorLog2(_blocksize)), - nbrOfBanksDRAM(nbr_of_banks_DRAM), - nbrOfBanksUtil(nbr_of_banks_util), addrMapping(addr_mapping), - rankBits(floorLog2(nbr_of_ranks)), - nbrOfRanks(nbr_of_ranks) - { - if (addrMapping != 1 && addrMapping != 0) { - addrMapping = 1; - warn("Unknown address mapping specified, using RoRaBaCoCh\n"); - } - } - - PacketPtr getNextPacket(); - - /** Insert bank, rank, and column bits into packed - * address to create address for 1st command in a - * series - * @param new_bank Bank number of next packet series - * @param new_rank Rank value of next packet series - */ - void genStartAddr(unsigned int new_bank , unsigned int new_rank); - - protected: - - /** Number of sequential DRAM packets to be generated per cpu request */ - const unsigned int numSeqPkts; - - /** Track number of sequential packets generated for a request */ - unsigned int countNumSeqPkts; - - /** Address of request */ - Addr addr; - - /** Remember type of requests to be generated in series */ - bool isRead; - - /** Page size of DRAM */ - const unsigned int pageSize; - - /** Number of page bits in DRAM address */ - const unsigned int pageBits; - - /** Number of bank bits in DRAM address*/ - const unsigned int bankBits; - - /** Number of block bits in DRAM address */ - const unsigned int blockBits; - - /** Number of banks in DRAM */ - const unsigned int nbrOfBanksDRAM; - - /** Number of banks to be utilized for a given configuration */ - const unsigned int nbrOfBanksUtil; - - /** Address mapping to be used */ - unsigned int addrMapping; - - /** Number of rank bits in DRAM address*/ - const unsigned int rankBits; - - /** Number of ranks to be utilized for a given configuration */ - const unsigned int nbrOfRanks; - -}; - -class DramRotGen : public DramGen -{ - - public: - - /** - * Create a DRAM address sequence generator. - * This sequence generator will rotate through: - * 1) Banks per rank - * 2) Command type (if applicable) - * 3) Ranks per channel - * - * @param _name Name to use for status and debug - * @param master_id MasterID set on each request - * @param _duration duration of this state before transitioning - * @param start_addr Start address - * @param end_addr End address - * @param _blocksize Size used for transactions injected - * @param min_period Lower limit of random inter-transaction time - * @param max_period Upper limit of random inter-transaction time - * @param read_percent Percent of transactions that are reads - * @param data_limit Upper limit on how much data to read/write - * @param num_seq_pkts Number of packets per stride, each of _blocksize - * @param page_size Page size (bytes) used in the DRAM - * @param nbr_of_banks_DRAM Total number of banks in DRAM - * @param nbr_of_banks_util Number of banks to utilized, - * for N banks, we will use banks: 0->(N-1) - * @param nbr_of_ranks Number of ranks utilized, - * @param addr_mapping Address mapping to be used, - * 0: RoCoRaBaCh, 1: RoRaBaCoCh/RoRaBaChCo - * assumes single channel system - */ - DramRotGen(const std::string& _name, MasterID master_id, Tick _duration, - Addr start_addr, Addr end_addr, Addr _blocksize, - Tick min_period, Tick max_period, - uint8_t read_percent, Addr data_limit, - unsigned int num_seq_pkts, unsigned int page_size, - unsigned int nbr_of_banks_DRAM, unsigned int nbr_of_banks_util, - unsigned int addr_mapping, - unsigned int nbr_of_ranks, - unsigned int max_seq_count_per_rank) - : DramGen(_name, master_id, _duration, start_addr, end_addr, - _blocksize, min_period, max_period, read_percent, data_limit, - num_seq_pkts, page_size, nbr_of_banks_DRAM, - nbr_of_banks_util, addr_mapping, - nbr_of_ranks), - maxSeqCountPerRank(max_seq_count_per_rank), - nextSeqCount(0) - { - // Rotating traffic generation can only support a read - // percentage of 0, 50, or 100 - if (readPercent != 50 && readPercent != 100 && readPercent != 0) { - fatal("%s: Unsupported read percentage for DramRotGen: %d", - _name, readPercent); - } - } - - PacketPtr getNextPacket(); - - private: - /** Number of command series issued before the rank is - changed. Should rotate to the next rank after rorating - throughall the banks for each specified command type */ - const unsigned int maxSeqCountPerRank; - - /** Next packet series count used to set rank and bank, - and update isRead Incremented at the start of a new - packet series */ - unsigned int nextSeqCount; -}; - -/** - * The trace replay generator reads a trace file and plays - * back the transactions. The trace is offset with respect to - * the time when the state was entered. - */ -class TraceGen : public BaseGen -{ - - private: - - /** - * This struct stores a line in the trace file. - */ - struct TraceElement { - - /** Specifies if the request is to be a read or a write */ - MemCmd cmd; - - /** The address for the request */ - Addr addr; - - /** The size of the access for the request */ - Addr blocksize; - - /** The time at which the request should be sent */ - Tick tick; - - /** Potential request flags to use */ - Request::FlagsType flags; - - /** - * Check validity of this element. - * - * @return if this element is valid - */ - bool isValid() const { - return cmd != MemCmd::InvalidCmd; - } - - /** - * Make this element invalid. - */ - void clear() { - cmd = MemCmd::InvalidCmd; - } - }; - - /** - * The InputStream encapsulates a trace file and the - * internal buffers and populates TraceElements based on - * the input. - */ - class InputStream - { - - private: - - /// Input file stream for the protobuf trace - ProtoInputStream trace; - - public: - - /** - * Create a trace input stream for a given file name. - * - * @param filename Path to the file to read from - */ - InputStream(const std::string& filename); - - /** - * Reset the stream such that it can be played once - * again. - */ - void reset(); - - /** - * Check the trace header to make sure that it is of the right - * format. - */ - void init(); - - /** - * Attempt to read a trace element from the stream, - * and also notify the caller if the end of the file - * was reached. - * - * @param element Trace element to populate - * @return True if an element could be read successfully - */ - bool read(TraceElement& element); - }; - - public: - - /** - * Create a trace generator. - * - * @param _name Name to use for status and debug - * @param master_id MasterID set on each request - * @param _duration duration of this state before transitioning - * @param trace_file File to read the transactions from - * @param addr_offset Positive offset to add to trace address - */ - TraceGen(const std::string& _name, MasterID master_id, Tick _duration, - const std::string& trace_file, Addr addr_offset) - : BaseGen(_name, master_id, _duration), - trace(trace_file), - tickOffset(0), - addrOffset(addr_offset), - traceComplete(false) - { - } - - void enter(); - - PacketPtr getNextPacket(); - - void exit(); - - /** - * Returns the tick when the next request should be generated. If - * the end of the file has been reached, it returns MaxTick to - * indicate that there will be no more requests. - */ - Tick nextPacketTick(bool elastic, Tick delay) const; - - private: - - /** Input stream used for reading the input trace file */ - InputStream trace; - - /** Store the current and next element in the trace */ - TraceElement currElement; - TraceElement nextElement; - - /** - * Stores the time when the state was entered. This is to add an - * offset to the times stored in the trace file. This is mutable - * to allow us to change it as part of nextPacketTick. - */ - mutable Tick tickOffset; - - /** - * Offset for memory requests. Used to shift the trace - * away from the CPU address space. - */ - Addr addrOffset; - - /** - * Set to true when the trace replay for one instance of - * state is complete. - */ - bool traceComplete; -}; - -#endif diff --git a/src/cpu/testers/traffic_gen/idle_gen.cc b/src/cpu/testers/traffic_gen/idle_gen.cc new file mode 100644 index 000000000..9c2ce7fef --- /dev/null +++ b/src/cpu/testers/traffic_gen/idle_gen.cc @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2012-2013, 2016-2017 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed here under. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * 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: Thomas Grass + * Andreas Hansson + * Sascha Bischoff + * Neha Agarwal + */ + +#include "cpu/testers/traffic_gen/idle_gen.hh" + +#include + +#include "base/random.hh" +#include "base/trace.hh" +#include "debug/TrafficGen.hh" +#include "proto/packet.pb.h" + +void +IdleGen::enter() { } + +PacketPtr +IdleGen::getNextPacket() +{ + return NULL; +} + +Tick +IdleGen::nextPacketTick(bool elastic, Tick delay) const +{ + return MaxTick; +} + diff --git a/src/cpu/testers/traffic_gen/idle_gen.hh b/src/cpu/testers/traffic_gen/idle_gen.hh new file mode 100644 index 000000000..d503abeb6 --- /dev/null +++ b/src/cpu/testers/traffic_gen/idle_gen.hh @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2012-2013, 2017 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed here under. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * 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: Thomas Grass + * Andreas Hansson + * Sascha Bischoff + * Neha Agarwal + */ + +/** + * @file + * Declaration of the idle generator that does nothing. + */ + +#ifndef __CPU_TRAFFIC_GEN_IDLE_GEN_HH__ +#define __CPU_TRAFFIC_GEN_IDLE_GEN_HH__ + +#include "base/bitfield.hh" +#include "base/intmath.hh" +#include "base_gen.hh" +#include "mem/packet.hh" +#include "proto/protoio.hh" + +/** + * The idle generator does nothing. + */ +class IdleGen : public BaseGen +{ + + public: + + IdleGen(const std::string& _name, MasterID master_id, Tick _duration) + : BaseGen(_name, master_id, _duration) + { } + + void enter(); + + PacketPtr getNextPacket(); + + Tick nextPacketTick(bool elastic, Tick delay) const ; +}; + +#endif diff --git a/src/cpu/testers/traffic_gen/linear_gen.cc b/src/cpu/testers/traffic_gen/linear_gen.cc new file mode 100644 index 000000000..412c6a3fb --- /dev/null +++ b/src/cpu/testers/traffic_gen/linear_gen.cc @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2012-2013, 2016-2017 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed here under. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * 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: Thomas Grass + * Andreas Hansson + * Sascha Bischoff + * Neha Agarwal + */ + +#include "cpu/testers/traffic_gen/linear_gen.hh" + +#include + +#include "base/random.hh" +#include "base/trace.hh" +#include "debug/TrafficGen.hh" +#include "proto/packet.pb.h" + +void +LinearGen::enter() +{ + // reset the address and the data counter + nextAddr = startAddr; + dataManipulated = 0; +} + +PacketPtr +LinearGen::getNextPacket() +{ + // choose if we generate a read or a write here + bool isRead = readPercent != 0 && + (readPercent == 100 || random_mt.random(0, 100) < readPercent); + + assert((readPercent == 0 && !isRead) || (readPercent == 100 && isRead) || + readPercent != 100); + + DPRINTF(TrafficGen, "LinearGen::getNextPacket: %c to addr %x, size %d\n", + isRead ? 'r' : 'w', nextAddr, blocksize); + + // Add the amount of data manipulated to the total + dataManipulated += blocksize; + + PacketPtr pkt = getPacket(nextAddr, blocksize, + isRead ? MemCmd::ReadReq : MemCmd::WriteReq); + + // increment the address + nextAddr += blocksize; + + // If we have reached the end of the address space, reset the + // address to the start of the range + if (nextAddr > endAddr) { + DPRINTF(TrafficGen, "Wrapping address to the start of " + "the range\n"); + nextAddr = startAddr; + } + + return pkt; +} + +Tick +LinearGen::nextPacketTick(bool elastic, Tick delay) const +{ + // Check to see if we have reached the data limit. If dataLimit is + // zero we do not have a data limit and therefore we will keep + // generating requests for the entire residency in this state. + if (dataLimit && dataManipulated >= dataLimit) { + DPRINTF(TrafficGen, "Data limit for LinearGen reached.\n"); + // there are no more requests, therefore return MaxTick + return MaxTick; + } else { + // return the time when the next request should take place + Tick wait = random_mt.random(minPeriod, maxPeriod); + + // compensate for the delay experienced to not be elastic, by + // default the value we generate is from the time we are + // asked, so the elasticity happens automatically + if (!elastic) { + if (wait < delay) + wait = 0; + else + wait -= delay; + } + + return curTick() + wait; + } +} diff --git a/src/cpu/testers/traffic_gen/linear_gen.hh b/src/cpu/testers/traffic_gen/linear_gen.hh new file mode 100644 index 000000000..18a1eb579 --- /dev/null +++ b/src/cpu/testers/traffic_gen/linear_gen.hh @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2012-2013, 2017 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed here under. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * 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: Thomas Grass + * Andreas Hansson + * Sascha Bischoff + * Neha Agarwal + */ + +/** + * @file + * Declaration of the linear generator that generates sequential + * requests. + */ + +#ifndef __CPU_TRAFFIC_GEN_LINEAR_GEN_HH__ +#define __CPU_TRAFFIC_GEN_LINEAR_GEN_HH__ + +#include "base/bitfield.hh" +#include "base/intmath.hh" +#include "base_gen.hh" +#include "mem/packet.hh" +#include "proto/protoio.hh" + +/** + * The linear generator generates sequential requests from a + * start to an end address, with a fixed block size. A + * fraction of the requests are reads, as determined by the + * read percent. There is an optional data limit for when to + * stop generating new requests. + */ +class LinearGen : public BaseGen +{ + + public: + + /** + * Create a linear address sequence generator. Set + * min_period == max_period for a fixed inter-transaction + * time. + * + * @param _name Name to use for status and debug + * @param master_id MasterID set on each request + * @param _duration duration of this state before transitioning + * @param start_addr Start address + * @param end_addr End address + * @param _blocksize Size used for transactions injected + * @param min_period Lower limit of random inter-transaction time + * @param max_period Upper limit of random inter-transaction time + * @param read_percent Percent of transactions that are reads + * @param data_limit Upper limit on how much data to read/write + */ + LinearGen(const std::string& _name, MasterID master_id, Tick _duration, + Addr start_addr, Addr end_addr, Addr _blocksize, + Tick min_period, Tick max_period, + uint8_t read_percent, Addr data_limit) + : BaseGen(_name, master_id, _duration), + startAddr(start_addr), endAddr(end_addr), + blocksize(_blocksize), minPeriod(min_period), + maxPeriod(max_period), readPercent(read_percent), + dataLimit(data_limit), nextAddr(startAddr), dataManipulated(0) + { } + + void enter(); + + PacketPtr getNextPacket(); + + Tick nextPacketTick(bool elastic, Tick delay) const; + + private: + + /** Start of address range */ + const Addr startAddr; + + /** End of address range */ + const Addr endAddr; + + /** Blocksize and address increment */ + const Addr blocksize; + + /** Request generation period */ + const Tick minPeriod; + const Tick maxPeriod; + + /** + * Percent of generated transactions that should be reads + */ + const uint8_t readPercent; + + /** Maximum amount of data to manipulate */ + const Addr dataLimit; + + /** Address of next request */ + Addr nextAddr; + + /** + * Counter to determine the amount of data + * manipulated. Used to determine if we should continue + * generating requests. + */ + Addr dataManipulated; +}; + +#endif diff --git a/src/cpu/testers/traffic_gen/random_gen.cc b/src/cpu/testers/traffic_gen/random_gen.cc new file mode 100644 index 000000000..bc241757d --- /dev/null +++ b/src/cpu/testers/traffic_gen/random_gen.cc @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2012-2013, 2016-2017 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed here under. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * 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: Thomas Grass + * Andreas Hansson + * Sascha Bischoff + * Neha Agarwal + */ + +#include "cpu/testers/traffic_gen/random_gen.hh" + +#include + +#include "base/random.hh" +#include "base/trace.hh" +#include "debug/TrafficGen.hh" +#include "proto/packet.pb.h" + +void +RandomGen::enter() +{ + // reset the counter to zero + dataManipulated = 0; +} + +PacketPtr +RandomGen::getNextPacket() +{ + // choose if we generate a read or a write here + bool isRead = readPercent != 0 && + (readPercent == 100 || random_mt.random(0, 100) < readPercent); + + assert((readPercent == 0 && !isRead) || (readPercent == 100 && isRead) || + readPercent != 100); + + // address of the request + Addr addr = random_mt.random(startAddr, endAddr - 1); + + // round down to start address of block + addr -= addr % blocksize; + + DPRINTF(TrafficGen, "RandomGen::getNextPacket: %c to addr %x, size %d\n", + isRead ? 'r' : 'w', addr, blocksize); + + // add the amount of data manipulated to the total + dataManipulated += blocksize; + + // create a new request packet + return getPacket(addr, blocksize, + isRead ? MemCmd::ReadReq : MemCmd::WriteReq); +} + +Tick +RandomGen::nextPacketTick(bool elastic, Tick delay) const +{ + // Check to see if we have reached the data limit. If dataLimit is + // zero we do not have a data limit and therefore we will keep + // generating requests for the entire residency in this state. + if (dataLimit && dataManipulated >= dataLimit) + { + DPRINTF(TrafficGen, "Data limit for RandomGen reached.\n"); + // No more requests. Return MaxTick. + return MaxTick; + } else { + // return the time when the next request should take place + Tick wait = random_mt.random(minPeriod, maxPeriod); + + // compensate for the delay experienced to not be elastic, by + // default the value we generate is from the time we are + // asked, so the elasticity happens automatically + if (!elastic) { + if (wait < delay) + wait = 0; + else + wait -= delay; + } + + return curTick() + wait; + } +} diff --git a/src/cpu/testers/traffic_gen/random_gen.hh b/src/cpu/testers/traffic_gen/random_gen.hh new file mode 100644 index 000000000..598abf7f1 --- /dev/null +++ b/src/cpu/testers/traffic_gen/random_gen.hh @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2012-2013, 2017 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed here under. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * 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: Thomas Grass + * Andreas Hansson + * Sascha Bischoff + * Neha Agarwal + */ + +/** + * @file + * Declaration of the random generator that randomly selects + * addresses within a range. + */ + +#ifndef __CPU_TRAFFIC_GEN_RANDOM_GEN_HH__ +#define __CPU_TRAFFIC_GEN_RANDOM_GEN_HH__ + +#include "base/bitfield.hh" +#include "base/intmath.hh" +#include "base_gen.hh" +#include "mem/packet.hh" +#include "proto/protoio.hh" + +/** + * The random generator is similar to the linear one, but does + * not generate sequential addresses. Instead it randomly + * picks an address in the range, aligned to the block size. + */ +class RandomGen : public BaseGen +{ + + public: + + /** + * Create a random address sequence generator. Set + * min_period == max_period for a fixed inter-transaction + * time. + * + * @param _name Name to use for status and debug + * @param master_id MasterID set on each request + * @param _duration duration of this state before transitioning + * @param start_addr Start address + * @param end_addr End address + * @param _blocksize Size used for transactions injected + * @param min_period Lower limit of random inter-transaction time + * @param max_period Upper limit of random inter-transaction time + * @param read_percent Percent of transactions that are reads + * @param data_limit Upper limit on how much data to read/write + */ + RandomGen(const std::string& _name, MasterID master_id, Tick _duration, + Addr start_addr, Addr end_addr, Addr _blocksize, + Tick min_period, Tick max_period, + uint8_t read_percent, Addr data_limit) + : BaseGen(_name, master_id, _duration), + startAddr(start_addr), endAddr(end_addr), + blocksize(_blocksize), minPeriod(min_period), + maxPeriod(max_period), readPercent(read_percent), + dataLimit(data_limit), dataManipulated(0) + { } + + void enter(); + + PacketPtr getNextPacket(); + + Tick nextPacketTick(bool elastic, Tick delay) const; + + protected: + + /** Start of address range */ + const Addr startAddr; + + /** End of address range */ + const Addr endAddr; + + /** Block size */ + const Addr blocksize; + + /** Request generation period */ + const Tick minPeriod; + const Tick maxPeriod; + + /** + * Percent of generated transactions that should be reads + */ + const uint8_t readPercent; + + /** Maximum amount of data to manipulate */ + const Addr dataLimit; + + /** + * Counter to determine the amount of data + * manipulated. Used to determine if we should continue + * generating requests. + */ + Addr dataManipulated; +}; + +#endif diff --git a/src/cpu/testers/traffic_gen/trace_gen.cc b/src/cpu/testers/traffic_gen/trace_gen.cc new file mode 100644 index 000000000..c2555eadf --- /dev/null +++ b/src/cpu/testers/traffic_gen/trace_gen.cc @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2012-2013, 2016-2017 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed here under. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * 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: Thomas Grass + * Andreas Hansson + * Sascha Bischoff + * Neha Agarwal + */ + +#include "cpu/testers/traffic_gen/trace_gen.hh" + +#include + +#include "base/random.hh" +#include "base/trace.hh" +#include "debug/TrafficGen.hh" +#include "proto/packet.pb.h" + +TraceGen::InputStream::InputStream(const std::string& filename) + : trace(filename) +{ + init(); +} + +void +TraceGen::InputStream::init() +{ + // Create a protobuf message for the header and read it from the stream + ProtoMessage::PacketHeader header_msg; + if (!trace.read(header_msg)) { + panic("Failed to read packet header from trace\n"); + } else if (header_msg.tick_freq() != SimClock::Frequency) { + panic("Trace was recorded with a different tick frequency %d\n", + header_msg.tick_freq()); + } +} + +void +TraceGen::InputStream::reset() +{ + trace.reset(); + init(); +} + +bool +TraceGen::InputStream::read(TraceElement& element) +{ + ProtoMessage::Packet pkt_msg; + if (trace.read(pkt_msg)) { + element.cmd = pkt_msg.cmd(); + element.addr = pkt_msg.addr(); + element.blocksize = pkt_msg.size(); + element.tick = pkt_msg.tick(); + element.flags = pkt_msg.has_flags() ? pkt_msg.flags() : 0; + return true; + } + + // We have reached the end of the file + return false; +} + +Tick +TraceGen::nextPacketTick(bool elastic, Tick delay) const +{ + if (traceComplete) { + DPRINTF(TrafficGen, "No next tick as trace is finished\n"); + // We are at the end of the file, thus we have no more data in + // the trace Return MaxTick to signal that there will be no + // more transactions in this active period for the state. + return MaxTick; + } + + assert(nextElement.isValid()); + + DPRINTF(TrafficGen, "Next packet tick is %d\n", tickOffset + + nextElement.tick); + + // if the playback is supposed to be elastic, add the delay + if (elastic) + tickOffset += delay; + + return std::max(tickOffset + nextElement.tick, curTick()); +} + +void +TraceGen::enter() +{ + // update the trace offset to the time where the state was entered. + tickOffset = curTick(); + + // clear everything + currElement.clear(); + + // read the first element in the file and set the complete flag + traceComplete = !trace.read(nextElement); +} + +PacketPtr +TraceGen::getNextPacket() +{ + // shift things one step forward + currElement = nextElement; + nextElement.clear(); + + // read the next element and set the complete flag + traceComplete = !trace.read(nextElement); + + // it is the responsibility of the traceComplete flag to ensure we + // always have a valid element here + assert(currElement.isValid()); + + DPRINTF(TrafficGen, "TraceGen::getNextPacket: %c %d %d %d 0x%x\n", + currElement.cmd.isRead() ? 'r' : 'w', + currElement.addr, + currElement.blocksize, + currElement.tick, + currElement.flags); + + PacketPtr pkt = getPacket(currElement.addr + addrOffset, + currElement.blocksize, + currElement.cmd, currElement.flags); + + if (!traceComplete) + DPRINTF(TrafficGen, "nextElement: %c addr %d size %d tick %d (%d)\n", + nextElement.cmd.isRead() ? 'r' : 'w', + nextElement.addr, + nextElement.blocksize, + nextElement.tick + tickOffset, + nextElement.tick); + + return pkt; +} + +void +TraceGen::exit() +{ + // Check if we reached the end of the trace file. If we did not + // then we want to generate a warning stating that not the entire + // trace was played. + if (!traceComplete) { + warn("Trace player %s was unable to replay the entire trace!\n", + name()); + } + + // Clear any flags and start over again from the beginning of the + // file + trace.reset(); +} diff --git a/src/cpu/testers/traffic_gen/trace_gen.hh b/src/cpu/testers/traffic_gen/trace_gen.hh new file mode 100644 index 000000000..cf4d4dd19 --- /dev/null +++ b/src/cpu/testers/traffic_gen/trace_gen.hh @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2012-2013, 2017 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed here under. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * 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: Thomas Grass + * Andreas Hansson + * Sascha Bischoff + * Neha Agarwal + */ + +/** + * @file + * Declaration of the trace generator that reads a trace file + * and plays the transactions. + */ + +#ifndef __CPU_TRAFFIC_GEN_TRACE_GEN_HH__ +#define __CPU_TRAFFIC_GEN_TRACE_GEN_HH__ + +#include "base/bitfield.hh" +#include "base/intmath.hh" +#include "base_gen.hh" +#include "mem/packet.hh" +#include "proto/protoio.hh" + +/** + * The trace replay generator reads a trace file and plays + * back the transactions. The trace is offset with respect to + * the time when the state was entered. + */ +class TraceGen : public BaseGen +{ + + private: + + /** + * This struct stores a line in the trace file. + */ + struct TraceElement { + + /** Specifies if the request is to be a read or a write */ + MemCmd cmd; + + /** The address for the request */ + Addr addr; + + /** The size of the access for the request */ + Addr blocksize; + + /** The time at which the request should be sent */ + Tick tick; + + /** Potential request flags to use */ + Request::FlagsType flags; + + /** + * Check validity of this element. + * + * @return if this element is valid + */ + bool isValid() const { + return cmd != MemCmd::InvalidCmd; + } + + /** + * Make this element invalid. + */ + void clear() { + cmd = MemCmd::InvalidCmd; + } + }; + + /** + * The InputStream encapsulates a trace file and the + * internal buffers and populates TraceElements based on + * the input. + */ + class InputStream + { + + private: + + /// Input file stream for the protobuf trace + ProtoInputStream trace; + + public: + + /** + * Create a trace input stream for a given file name. + * + * @param filename Path to the file to read from + */ + InputStream(const std::string& filename); + + /** + * Reset the stream such that it can be played once + * again. + */ + void reset(); + + /** + * Check the trace header to make sure that it is of the right + * format. + */ + void init(); + + /** + * Attempt to read a trace element from the stream, + * and also notify the caller if the end of the file + * was reached. + * + * @param element Trace element to populate + * @return True if an element could be read successfully + */ + bool read(TraceElement& element); + }; + + public: + + /** + * Create a trace generator. + * + * @param _name Name to use for status and debug + * @param master_id MasterID set on each request + * @param _duration duration of this state before transitioning + * @param trace_file File to read the transactions from + * @param addr_offset Positive offset to add to trace address + */ + TraceGen(const std::string& _name, MasterID master_id, Tick _duration, + const std::string& trace_file, Addr addr_offset) + : BaseGen(_name, master_id, _duration), + trace(trace_file), + tickOffset(0), + addrOffset(addr_offset), + traceComplete(false) + { + } + + void enter(); + + PacketPtr getNextPacket(); + + void exit(); + + /** + * Returns the tick when the next request should be generated. If + * the end of the file has been reached, it returns MaxTick to + * indicate that there will be no more requests. + */ + Tick nextPacketTick(bool elastic, Tick delay) const; + + private: + + /** Input stream used for reading the input trace file */ + InputStream trace; + + /** Store the current and next element in the trace */ + TraceElement currElement; + TraceElement nextElement; + + /** + * Stores the time when the state was entered. This is to add an + * offset to the times stored in the trace file. This is mutable + * to allow us to change it as part of nextPacketTick. + */ + mutable Tick tickOffset; + + /** + * Offset for memory requests. Used to shift the trace + * away from the CPU address space. + */ + Addr addrOffset; + + /** + * Set to true when the trace replay for one instance of + * state is complete. + */ + bool traceComplete; +}; + +#endif diff --git a/src/cpu/testers/traffic_gen/traffic_gen.hh b/src/cpu/testers/traffic_gen/traffic_gen.hh index b2039bef9..e78b82e95 100644 --- a/src/cpu/testers/traffic_gen/traffic_gen.hh +++ b/src/cpu/testers/traffic_gen/traffic_gen.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2013, 2016 ARM Limited + * Copyright (c) 2012-2013, 2016-2017 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -38,13 +38,20 @@ * Andreas Hansson * Sascha Bischoff */ + #ifndef __CPU_TRAFFIC_GEN_TRAFFIC_GEN_HH__ #define __CPU_TRAFFIC_GEN_TRAFFIC_GEN_HH__ #include #include "base/statistics.hh" -#include "cpu/testers/traffic_gen/generators.hh" +#include "cpu/testers/traffic_gen/base_gen.hh" +#include "cpu/testers/traffic_gen/dram_gen.hh" +#include "cpu/testers/traffic_gen/dram_rot_gen.hh" +#include "cpu/testers/traffic_gen/idle_gen.hh" +#include "cpu/testers/traffic_gen/linear_gen.hh" +#include "cpu/testers/traffic_gen/random_gen.hh" +#include "cpu/testers/traffic_gen/trace_gen.hh" #include "mem/mem_object.hh" #include "mem/qport.hh" #include "params/TrafficGen.hh" -- cgit v1.2.3