traffic_gen.hh revision 9241
19241Sandreas.hansson@arm.com/*
29241Sandreas.hansson@arm.com * Copyright (c) 2012 ARM Limited
39241Sandreas.hansson@arm.com * All rights reserved
49241Sandreas.hansson@arm.com *
59241Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall
69241Sandreas.hansson@arm.com * not be construed as granting a license to any other intellectual
79241Sandreas.hansson@arm.com * property including but not limited to intellectual property relating
89241Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software
99241Sandreas.hansson@arm.com * licensed hereunder.  You may use the software subject to the license
109241Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated
119241Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software,
129241Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form.
139241Sandreas.hansson@arm.com *
149241Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without
159241Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are
169241Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright
179241Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer;
189241Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright
199241Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the
209241Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution;
219241Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its
229241Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from
239241Sandreas.hansson@arm.com * this software without specific prior written permission.
249241Sandreas.hansson@arm.com *
259241Sandreas.hansson@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
269241Sandreas.hansson@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
279241Sandreas.hansson@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
289241Sandreas.hansson@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
299241Sandreas.hansson@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
309241Sandreas.hansson@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
319241Sandreas.hansson@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
329241Sandreas.hansson@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
339241Sandreas.hansson@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
349241Sandreas.hansson@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
359241Sandreas.hansson@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
369241Sandreas.hansson@arm.com *
379241Sandreas.hansson@arm.com * Authors: Thomas Grass
389241Sandreas.hansson@arm.com *          Andreas Hansson
399241Sandreas.hansson@arm.com *          Sascha Bischoff
409241Sandreas.hansson@arm.com */
419241Sandreas.hansson@arm.com#ifndef __MEM_TRAFFIC_GEN_HH__
429241Sandreas.hansson@arm.com#define __MEM_TRAFFIC_GEN_HH__
439241Sandreas.hansson@arm.com
449241Sandreas.hansson@arm.com#include <fstream>
459241Sandreas.hansson@arm.com
469241Sandreas.hansson@arm.com#include "base/hashmap.hh"
479241Sandreas.hansson@arm.com#include "mem/mem_object.hh"
489241Sandreas.hansson@arm.com#include "mem/qport.hh"
499241Sandreas.hansson@arm.com#include "params/TrafficGen.hh"
509241Sandreas.hansson@arm.com
519241Sandreas.hansson@arm.com/**
529241Sandreas.hansson@arm.com * The traffic generator is a master module that generates stimuli for
539241Sandreas.hansson@arm.com * the memory system, based on a collection of simple behaviours that
549241Sandreas.hansson@arm.com * are either probabilistic or based on traces. It can be used stand
559241Sandreas.hansson@arm.com * alone for creating test cases for interconnect and memory
569241Sandreas.hansson@arm.com * controllers, or function as a black box replacement for system
579241Sandreas.hansson@arm.com * components that are not yet modelled in detail, e.g. a video engine
589241Sandreas.hansson@arm.com * or baseband subsystem.
599241Sandreas.hansson@arm.com */
609241Sandreas.hansson@arm.comclass TrafficGen : public MemObject
619241Sandreas.hansson@arm.com{
629241Sandreas.hansson@arm.com
639241Sandreas.hansson@arm.com  private:
649241Sandreas.hansson@arm.com
659241Sandreas.hansson@arm.com    /**
669241Sandreas.hansson@arm.com     * The system used to determine which mode we are currently operating
679241Sandreas.hansson@arm.com     * in.
689241Sandreas.hansson@arm.com     */
699241Sandreas.hansson@arm.com    System* system;
709241Sandreas.hansson@arm.com
719241Sandreas.hansson@arm.com    /**
729241Sandreas.hansson@arm.com     * MasterID used in generated requests.
739241Sandreas.hansson@arm.com     */
749241Sandreas.hansson@arm.com    MasterID masterID;
759241Sandreas.hansson@arm.com
769241Sandreas.hansson@arm.com  protected:
779241Sandreas.hansson@arm.com
789241Sandreas.hansson@arm.com    /**
799241Sandreas.hansson@arm.com     * The state graph is responsible for instantiating and keeping
809241Sandreas.hansson@arm.com     * track of the various generator states and also perform the
819241Sandreas.hansson@arm.com     * transitions and call the appropriate functions when entering,
829241Sandreas.hansson@arm.com     * executing and exiting a state.
839241Sandreas.hansson@arm.com     */
849241Sandreas.hansson@arm.com    class StateGraph
859241Sandreas.hansson@arm.com    {
869241Sandreas.hansson@arm.com
879241Sandreas.hansson@arm.com      public:
889241Sandreas.hansson@arm.com
899241Sandreas.hansson@arm.com        /**
909241Sandreas.hansson@arm.com         * Create a state graph from an input file.
919241Sandreas.hansson@arm.com         *
929241Sandreas.hansson@arm.com         * @param _owner used solely for the name
939241Sandreas.hansson@arm.com         * @param _port port used to send requests
949241Sandreas.hansson@arm.com         * @param file_name configuration description to read in
959241Sandreas.hansson@arm.com         * @param master_id the unique id used for all requests
969241Sandreas.hansson@arm.com         */
979241Sandreas.hansson@arm.com        StateGraph(TrafficGen& _owner, QueuedMasterPort& _port,
989241Sandreas.hansson@arm.com                   const std::string& file_name, MasterID master_id)
999241Sandreas.hansson@arm.com            : nextTransitionTick(0), owner(_owner), port(_port)
1009241Sandreas.hansson@arm.com        {
1019241Sandreas.hansson@arm.com            parseConfig(file_name, master_id);
1029241Sandreas.hansson@arm.com        }
1039241Sandreas.hansson@arm.com
1049241Sandreas.hansson@arm.com        /**
1059241Sandreas.hansson@arm.com         * Get the name, used for DPRINTFs.
1069241Sandreas.hansson@arm.com         *
1079241Sandreas.hansson@arm.com         * @return the owner's name
1089241Sandreas.hansson@arm.com         */
1099241Sandreas.hansson@arm.com        std::string name() const { return owner.name(); }
1109241Sandreas.hansson@arm.com
1119241Sandreas.hansson@arm.com        /**
1129241Sandreas.hansson@arm.com         * Either perform a state transition or execute the current
1139241Sandreas.hansson@arm.com         * state, depending on the current time.
1149241Sandreas.hansson@arm.com         */
1159241Sandreas.hansson@arm.com        void update();
1169241Sandreas.hansson@arm.com
1179241Sandreas.hansson@arm.com        /**
1189241Sandreas.hansson@arm.com         * Determine next state and perform the transition.
1199241Sandreas.hansson@arm.com         */
1209241Sandreas.hansson@arm.com        void transition();
1219241Sandreas.hansson@arm.com
1229241Sandreas.hansson@arm.com        /**
1239241Sandreas.hansson@arm.com         * Enter a new state.
1249241Sandreas.hansson@arm.com         *
1259241Sandreas.hansson@arm.com         * @param newState identifier of state to enter
1269241Sandreas.hansson@arm.com         */
1279241Sandreas.hansson@arm.com        void enterState(uint32_t newState);
1289241Sandreas.hansson@arm.com
1299241Sandreas.hansson@arm.com        /**
1309241Sandreas.hansson@arm.com         * Get the tick of the next event, either an execution or a
1319241Sandreas.hansson@arm.com         * transition.
1329241Sandreas.hansson@arm.com         *
1339241Sandreas.hansson@arm.com         * @return tick of the next state graph event
1349241Sandreas.hansson@arm.com         */
1359241Sandreas.hansson@arm.com        Tick nextEventTick()
1369241Sandreas.hansson@arm.com        {
1379241Sandreas.hansson@arm.com            return std::min(states[currState]->nextExecuteTick(),
1389241Sandreas.hansson@arm.com                            nextTransitionTick);
1399241Sandreas.hansson@arm.com
1409241Sandreas.hansson@arm.com        }
1419241Sandreas.hansson@arm.com
1429241Sandreas.hansson@arm.com        /** Time of next transition */
1439241Sandreas.hansson@arm.com        Tick nextTransitionTick;
1449241Sandreas.hansson@arm.com
1459241Sandreas.hansson@arm.com      private:
1469241Sandreas.hansson@arm.com
1479241Sandreas.hansson@arm.com        /**
1489241Sandreas.hansson@arm.com         * Parse the config file and build the state map and
1499241Sandreas.hansson@arm.com         * transition matrix.
1509241Sandreas.hansson@arm.com         *
1519241Sandreas.hansson@arm.com         * @param file_name Config file name to parse
1529241Sandreas.hansson@arm.com         * @param master_id MasterID to use for generated requests
1539241Sandreas.hansson@arm.com         */
1549241Sandreas.hansson@arm.com        void parseConfig(const std::string& file_name, MasterID master_id);
1559241Sandreas.hansson@arm.com
1569241Sandreas.hansson@arm.com        /** Struct to represent a probabilistic transition during parsing. */
1579241Sandreas.hansson@arm.com        struct Transition {
1589241Sandreas.hansson@arm.com            uint32_t from;
1599241Sandreas.hansson@arm.com            uint32_t to;
1609241Sandreas.hansson@arm.com            double p;
1619241Sandreas.hansson@arm.com        };
1629241Sandreas.hansson@arm.com
1639241Sandreas.hansson@arm.com        /** Base class for all generator states */
1649241Sandreas.hansson@arm.com        class BaseGen
1659241Sandreas.hansson@arm.com        {
1669241Sandreas.hansson@arm.com
1679241Sandreas.hansson@arm.com          protected:
1689241Sandreas.hansson@arm.com
1699241Sandreas.hansson@arm.com            /** Port used to send requests */
1709241Sandreas.hansson@arm.com            QueuedMasterPort& port;
1719241Sandreas.hansson@arm.com
1729241Sandreas.hansson@arm.com            /** The MasterID used for generating requests */
1739241Sandreas.hansson@arm.com            const MasterID masterID;
1749241Sandreas.hansson@arm.com
1759241Sandreas.hansson@arm.com          public:
1769241Sandreas.hansson@arm.com
1779241Sandreas.hansson@arm.com            /** Time to spend in this state */
1789241Sandreas.hansson@arm.com            const Tick duration;
1799241Sandreas.hansson@arm.com
1809241Sandreas.hansson@arm.com            /**
1819241Sandreas.hansson@arm.com             * Create a base generator.
1829241Sandreas.hansson@arm.com             *
1839241Sandreas.hansson@arm.com             * @param _port port used to send requests
1849241Sandreas.hansson@arm.com             * @param master_id MasterID set on each request
1859241Sandreas.hansson@arm.com             * @param _duration duration of this state before transitioning
1869241Sandreas.hansson@arm.com             */
1879241Sandreas.hansson@arm.com            BaseGen(QueuedMasterPort& _port, MasterID master_id,
1889241Sandreas.hansson@arm.com                    Tick _duration);
1899241Sandreas.hansson@arm.com
1909241Sandreas.hansson@arm.com            virtual ~BaseGen() { }
1919241Sandreas.hansson@arm.com
1929241Sandreas.hansson@arm.com            /**
1939241Sandreas.hansson@arm.com             * Get the name, useful for DPRINTFs.
1949241Sandreas.hansson@arm.com             *
1959241Sandreas.hansson@arm.com             * @return the port name
1969241Sandreas.hansson@arm.com             */
1979241Sandreas.hansson@arm.com            std::string name() const { return port.name(); }
1989241Sandreas.hansson@arm.com
1999241Sandreas.hansson@arm.com            /**
2009241Sandreas.hansson@arm.com             * Enter this generator state.
2019241Sandreas.hansson@arm.com             */
2029241Sandreas.hansson@arm.com            virtual void enter() = 0;
2039241Sandreas.hansson@arm.com
2049241Sandreas.hansson@arm.com            /**
2059241Sandreas.hansson@arm.com             * Execute this generator state.
2069241Sandreas.hansson@arm.com             */
2079241Sandreas.hansson@arm.com            virtual void execute() = 0;
2089241Sandreas.hansson@arm.com
2099241Sandreas.hansson@arm.com            /**
2109241Sandreas.hansson@arm.com             * Exit this generator state. By default do nothing.
2119241Sandreas.hansson@arm.com             */
2129241Sandreas.hansson@arm.com            virtual void exit() { };
2139241Sandreas.hansson@arm.com
2149241Sandreas.hansson@arm.com            /**
2159241Sandreas.hansson@arm.com             * Determine the next execute tick. MaxTick means that
2169241Sandreas.hansson@arm.com             * there will not be any further event in the current
2179241Sandreas.hansson@arm.com             * activation cycle of the state.
2189241Sandreas.hansson@arm.com             *
2199241Sandreas.hansson@arm.com             * @return next tick when the state should be executed
2209241Sandreas.hansson@arm.com             */
2219241Sandreas.hansson@arm.com            virtual Tick nextExecuteTick() = 0;
2229241Sandreas.hansson@arm.com
2239241Sandreas.hansson@arm.com        };
2249241Sandreas.hansson@arm.com
2259241Sandreas.hansson@arm.com        /**
2269241Sandreas.hansson@arm.com         * The idle generator does nothing.
2279241Sandreas.hansson@arm.com         */
2289241Sandreas.hansson@arm.com        class IdleGen : public BaseGen
2299241Sandreas.hansson@arm.com        {
2309241Sandreas.hansson@arm.com
2319241Sandreas.hansson@arm.com          public:
2329241Sandreas.hansson@arm.com
2339241Sandreas.hansson@arm.com            IdleGen(QueuedMasterPort& _port, MasterID master_id,
2349241Sandreas.hansson@arm.com                    Tick _duration)
2359241Sandreas.hansson@arm.com                : BaseGen(_port, master_id, _duration)
2369241Sandreas.hansson@arm.com            { }
2379241Sandreas.hansson@arm.com
2389241Sandreas.hansson@arm.com            void enter() { }
2399241Sandreas.hansson@arm.com
2409241Sandreas.hansson@arm.com            void execute() { }
2419241Sandreas.hansson@arm.com
2429241Sandreas.hansson@arm.com            Tick nextExecuteTick() { return MaxTick; }
2439241Sandreas.hansson@arm.com        };
2449241Sandreas.hansson@arm.com
2459241Sandreas.hansson@arm.com        /**
2469241Sandreas.hansson@arm.com         * The linear generator generates sequential requests from a
2479241Sandreas.hansson@arm.com         * start to an end address, with a fixed block size. A
2489241Sandreas.hansson@arm.com         * fraction of the requests are reads, as determined by the
2499241Sandreas.hansson@arm.com         * read percent. There is an optional data limit for when to
2509241Sandreas.hansson@arm.com         * stop generating new requests.
2519241Sandreas.hansson@arm.com         */
2529241Sandreas.hansson@arm.com        class LinearGen : public BaseGen
2539241Sandreas.hansson@arm.com        {
2549241Sandreas.hansson@arm.com
2559241Sandreas.hansson@arm.com          public:
2569241Sandreas.hansson@arm.com
2579241Sandreas.hansson@arm.com            /**
2589241Sandreas.hansson@arm.com             * Create a linear address sequence generator. Set
2599241Sandreas.hansson@arm.com             * min_period == max_period for a fixed inter-transaction
2609241Sandreas.hansson@arm.com             * time.
2619241Sandreas.hansson@arm.com             *
2629241Sandreas.hansson@arm.com             * @param _port port used to send requests
2639241Sandreas.hansson@arm.com             * @param master_id MasterID set on each request
2649241Sandreas.hansson@arm.com             * @param _duration duration of this state before transitioning
2659241Sandreas.hansson@arm.com             * @param start_addr Start address
2669241Sandreas.hansson@arm.com             * @param end_addr End address
2679241Sandreas.hansson@arm.com             * @param _blocksize Size used for transactions injected
2689241Sandreas.hansson@arm.com             * @param min_period Lower limit of random inter-transaction time
2699241Sandreas.hansson@arm.com             * @param max_period Upper limit of random inter-transaction time
2709241Sandreas.hansson@arm.com             * @param read_percent Percent of transactions that are reads
2719241Sandreas.hansson@arm.com             * @param data_limit Upper limit on how much data to read/write
2729241Sandreas.hansson@arm.com             */
2739241Sandreas.hansson@arm.com            LinearGen(QueuedMasterPort& _port, MasterID master_id,
2749241Sandreas.hansson@arm.com                      Tick _duration, Addr start_addr, Addr end_addr,
2759241Sandreas.hansson@arm.com                      Addr _blocksize, Tick min_period, Tick max_period,
2769241Sandreas.hansson@arm.com                      uint8_t read_percent, Addr data_limit)
2779241Sandreas.hansson@arm.com                : BaseGen(_port, master_id, _duration),
2789241Sandreas.hansson@arm.com                  startAddr(start_addr), endAddr(end_addr),
2799241Sandreas.hansson@arm.com                  blocksize(_blocksize), minPeriod(min_period),
2809241Sandreas.hansson@arm.com                  maxPeriod(max_period), readPercent(read_percent),
2819241Sandreas.hansson@arm.com                  dataLimit(data_limit)
2829241Sandreas.hansson@arm.com            { }
2839241Sandreas.hansson@arm.com
2849241Sandreas.hansson@arm.com            void enter();
2859241Sandreas.hansson@arm.com
2869241Sandreas.hansson@arm.com            void execute();
2879241Sandreas.hansson@arm.com
2889241Sandreas.hansson@arm.com            Tick nextExecuteTick();
2899241Sandreas.hansson@arm.com
2909241Sandreas.hansson@arm.com          private:
2919241Sandreas.hansson@arm.com
2929241Sandreas.hansson@arm.com            /** Start of address range */
2939241Sandreas.hansson@arm.com            const Addr startAddr;
2949241Sandreas.hansson@arm.com
2959241Sandreas.hansson@arm.com            /** End of address range */
2969241Sandreas.hansson@arm.com            const Addr endAddr;
2979241Sandreas.hansson@arm.com
2989241Sandreas.hansson@arm.com            /** Blocksize and address increment */
2999241Sandreas.hansson@arm.com            const Addr blocksize;
3009241Sandreas.hansson@arm.com
3019241Sandreas.hansson@arm.com            /** Request generation period */
3029241Sandreas.hansson@arm.com            const Tick minPeriod;
3039241Sandreas.hansson@arm.com            const Tick maxPeriod;
3049241Sandreas.hansson@arm.com
3059241Sandreas.hansson@arm.com            /**
3069241Sandreas.hansson@arm.com             * Percent of generated transactions that should be reads
3079241Sandreas.hansson@arm.com             */
3089241Sandreas.hansson@arm.com            const uint8_t readPercent;
3099241Sandreas.hansson@arm.com
3109241Sandreas.hansson@arm.com            /** Maximum amount of data to manipulate */
3119241Sandreas.hansson@arm.com            const Addr dataLimit;
3129241Sandreas.hansson@arm.com
3139241Sandreas.hansson@arm.com            /** Address of next request */
3149241Sandreas.hansson@arm.com            Addr nextAddr;
3159241Sandreas.hansson@arm.com
3169241Sandreas.hansson@arm.com            /**
3179241Sandreas.hansson@arm.com             * Counter to determine the amount of data
3189241Sandreas.hansson@arm.com             * manipulated. Used to determine if we should continue
3199241Sandreas.hansson@arm.com             * generating requests.
3209241Sandreas.hansson@arm.com             */
3219241Sandreas.hansson@arm.com            Addr dataManipulated;
3229241Sandreas.hansson@arm.com        };
3239241Sandreas.hansson@arm.com
3249241Sandreas.hansson@arm.com        /**
3259241Sandreas.hansson@arm.com         * The random generator is similar to the linear one, but does
3269241Sandreas.hansson@arm.com         * not generate sequential addresses. Instead it randomly
3279241Sandreas.hansson@arm.com         * picks an address in the range, aligned to the block size.
3289241Sandreas.hansson@arm.com         */
3299241Sandreas.hansson@arm.com        class RandomGen : public BaseGen
3309241Sandreas.hansson@arm.com        {
3319241Sandreas.hansson@arm.com
3329241Sandreas.hansson@arm.com          public:
3339241Sandreas.hansson@arm.com
3349241Sandreas.hansson@arm.com            /**
3359241Sandreas.hansson@arm.com             * Create a random address sequence generator. Set
3369241Sandreas.hansson@arm.com             * min_period == max_period for a fixed inter-transaction
3379241Sandreas.hansson@arm.com             * time.
3389241Sandreas.hansson@arm.com             *
3399241Sandreas.hansson@arm.com             * @param _port port used to send requests
3409241Sandreas.hansson@arm.com             * @param master_id MasterID set on each request
3419241Sandreas.hansson@arm.com             * @param _duration duration of this state before transitioning
3429241Sandreas.hansson@arm.com             * @param start_addr Start address
3439241Sandreas.hansson@arm.com             * @param end_addr End address
3449241Sandreas.hansson@arm.com             * @param _blocksize Size used for transactions injected
3459241Sandreas.hansson@arm.com             * @param min_period Lower limit of random inter-transaction time
3469241Sandreas.hansson@arm.com             * @param max_period Upper limit of random inter-transaction time
3479241Sandreas.hansson@arm.com             * @param read_percent Percent of transactions that are reads
3489241Sandreas.hansson@arm.com             * @param data_limit Upper limit on how much data to read/write
3499241Sandreas.hansson@arm.com             */
3509241Sandreas.hansson@arm.com            RandomGen(QueuedMasterPort& _port, MasterID master_id,
3519241Sandreas.hansson@arm.com                      Tick _duration, Addr start_addr, Addr end_addr,
3529241Sandreas.hansson@arm.com                      Addr _blocksize, Tick min_period, Tick max_period,
3539241Sandreas.hansson@arm.com                      uint8_t read_percent, Addr data_limit)
3549241Sandreas.hansson@arm.com                : BaseGen(_port, master_id, _duration),
3559241Sandreas.hansson@arm.com                  startAddr(start_addr), endAddr(end_addr),
3569241Sandreas.hansson@arm.com                  blocksize(_blocksize), minPeriod(min_period),
3579241Sandreas.hansson@arm.com                  maxPeriod(max_period), readPercent(read_percent),
3589241Sandreas.hansson@arm.com                  dataLimit(data_limit)
3599241Sandreas.hansson@arm.com            { }
3609241Sandreas.hansson@arm.com
3619241Sandreas.hansson@arm.com            void enter();
3629241Sandreas.hansson@arm.com
3639241Sandreas.hansson@arm.com            void execute();
3649241Sandreas.hansson@arm.com
3659241Sandreas.hansson@arm.com            Tick nextExecuteTick();
3669241Sandreas.hansson@arm.com
3679241Sandreas.hansson@arm.com          private:
3689241Sandreas.hansson@arm.com
3699241Sandreas.hansson@arm.com            /** Start of address range */
3709241Sandreas.hansson@arm.com            const Addr startAddr;
3719241Sandreas.hansson@arm.com
3729241Sandreas.hansson@arm.com            /** End of address range */
3739241Sandreas.hansson@arm.com            const Addr endAddr;
3749241Sandreas.hansson@arm.com
3759241Sandreas.hansson@arm.com            /** Block size */
3769241Sandreas.hansson@arm.com            const Addr blocksize;
3779241Sandreas.hansson@arm.com
3789241Sandreas.hansson@arm.com            /** Request generation period */
3799241Sandreas.hansson@arm.com            const Tick minPeriod;
3809241Sandreas.hansson@arm.com            const Tick maxPeriod;
3819241Sandreas.hansson@arm.com
3829241Sandreas.hansson@arm.com            /**
3839241Sandreas.hansson@arm.com             * Percent of generated transactions that should be reads
3849241Sandreas.hansson@arm.com             */
3859241Sandreas.hansson@arm.com            const uint8_t readPercent;
3869241Sandreas.hansson@arm.com
3879241Sandreas.hansson@arm.com            /** Maximum amount of data to manipulate */
3889241Sandreas.hansson@arm.com            const Addr dataLimit;
3899241Sandreas.hansson@arm.com
3909241Sandreas.hansson@arm.com            /**
3919241Sandreas.hansson@arm.com             * Counter to determine the amount of data
3929241Sandreas.hansson@arm.com             * manipulated. Used to determine if we should continue
3939241Sandreas.hansson@arm.com             * generating requests.
3949241Sandreas.hansson@arm.com             */
3959241Sandreas.hansson@arm.com            Addr dataManipulated;
3969241Sandreas.hansson@arm.com        };
3979241Sandreas.hansson@arm.com
3989241Sandreas.hansson@arm.com        /**
3999241Sandreas.hansson@arm.com         * The trace replay generator reads a trace file and plays
4009241Sandreas.hansson@arm.com         * back the transactions. The trace is offset with respect to
4019241Sandreas.hansson@arm.com         * the time when the state was entered.
4029241Sandreas.hansson@arm.com         */
4039241Sandreas.hansson@arm.com        class TraceGen : public BaseGen
4049241Sandreas.hansson@arm.com        {
4059241Sandreas.hansson@arm.com
4069241Sandreas.hansson@arm.com          private:
4079241Sandreas.hansson@arm.com
4089241Sandreas.hansson@arm.com            /**
4099241Sandreas.hansson@arm.com             * This struct stores a line in the trace file.
4109241Sandreas.hansson@arm.com             */
4119241Sandreas.hansson@arm.com            struct TraceElement {
4129241Sandreas.hansson@arm.com
4139241Sandreas.hansson@arm.com                /** Specifies if the request is to be a read or a write */
4149241Sandreas.hansson@arm.com                MemCmd cmd;
4159241Sandreas.hansson@arm.com
4169241Sandreas.hansson@arm.com                /** The address for the request */
4179241Sandreas.hansson@arm.com                Addr addr;
4189241Sandreas.hansson@arm.com
4199241Sandreas.hansson@arm.com                /** The size of the access for the request */
4209241Sandreas.hansson@arm.com                Addr blocksize;
4219241Sandreas.hansson@arm.com
4229241Sandreas.hansson@arm.com                /** The time at which the request should be sent */
4239241Sandreas.hansson@arm.com                Tick tick;
4249241Sandreas.hansson@arm.com
4259241Sandreas.hansson@arm.com                /**
4269241Sandreas.hansson@arm.com                 * Check validity of this element.
4279241Sandreas.hansson@arm.com                 *
4289241Sandreas.hansson@arm.com                 * @return if this element is valid
4299241Sandreas.hansson@arm.com                 */
4309241Sandreas.hansson@arm.com                bool isValid() const {
4319241Sandreas.hansson@arm.com                    return cmd != MemCmd::InvalidCmd;
4329241Sandreas.hansson@arm.com                }
4339241Sandreas.hansson@arm.com
4349241Sandreas.hansson@arm.com                /**
4359241Sandreas.hansson@arm.com                 * Make this element invalid.
4369241Sandreas.hansson@arm.com                 */
4379241Sandreas.hansson@arm.com                void clear() {
4389241Sandreas.hansson@arm.com                    cmd = MemCmd::InvalidCmd;
4399241Sandreas.hansson@arm.com                }
4409241Sandreas.hansson@arm.com            };
4419241Sandreas.hansson@arm.com
4429241Sandreas.hansson@arm.com          public:
4439241Sandreas.hansson@arm.com
4449241Sandreas.hansson@arm.com           /**
4459241Sandreas.hansson@arm.com             * Create a trace generator.
4469241Sandreas.hansson@arm.com             *
4479241Sandreas.hansson@arm.com             * @param _port port used to send requests
4489241Sandreas.hansson@arm.com             * @param master_id MasterID set on each request
4499241Sandreas.hansson@arm.com             * @param _duration duration of this state before transitioning
4509241Sandreas.hansson@arm.com             * @param trace_file File to read the transactions from
4519241Sandreas.hansson@arm.com             * @param addr_offset Positive offset to add to trace address
4529241Sandreas.hansson@arm.com             */
4539241Sandreas.hansson@arm.com            TraceGen(QueuedMasterPort& _port, MasterID master_id,
4549241Sandreas.hansson@arm.com                     Tick _duration, const std::string& trace_file,
4559241Sandreas.hansson@arm.com                     Addr addr_offset)
4569241Sandreas.hansson@arm.com                : BaseGen(_port, master_id, _duration),
4579241Sandreas.hansson@arm.com                  traceFile(trace_file),
4589241Sandreas.hansson@arm.com                  addrOffset(addr_offset),
4599241Sandreas.hansson@arm.com                  traceComplete(false)
4609241Sandreas.hansson@arm.com            {
4619241Sandreas.hansson@arm.com                /**
4629241Sandreas.hansson@arm.com                 * Create a 4MB read buffer for the input trace
4639241Sandreas.hansson@arm.com                 * file. This is to reduce the number of disk accesses
4649241Sandreas.hansson@arm.com                 * and thereby speed up the execution of the code.
4659241Sandreas.hansson@arm.com                 */
4669241Sandreas.hansson@arm.com                readBuffer = new char[4 * 1024 * 1024];
4679241Sandreas.hansson@arm.com                trace.rdbuf()->pubsetbuf(readBuffer, 4 * 1024 * 1024);
4689241Sandreas.hansson@arm.com                trace.open(traceFile.c_str(), std::ifstream::in);
4699241Sandreas.hansson@arm.com
4709241Sandreas.hansson@arm.com                if (!trace.is_open()) {
4719241Sandreas.hansson@arm.com                    fatal("Traffic generator %s trace file could not be"
4729241Sandreas.hansson@arm.com                          " opened: %s\n", name(), traceFile);
4739241Sandreas.hansson@arm.com                }
4749241Sandreas.hansson@arm.com            }
4759241Sandreas.hansson@arm.com
4769241Sandreas.hansson@arm.com            ~TraceGen() {
4779241Sandreas.hansson@arm.com                // free the memory used by the readBuffer
4789241Sandreas.hansson@arm.com                delete[] readBuffer;
4799241Sandreas.hansson@arm.com            }
4809241Sandreas.hansson@arm.com
4819241Sandreas.hansson@arm.com            void enter();
4829241Sandreas.hansson@arm.com
4839241Sandreas.hansson@arm.com            void execute();
4849241Sandreas.hansson@arm.com
4859241Sandreas.hansson@arm.com            void exit();
4869241Sandreas.hansson@arm.com
4879241Sandreas.hansson@arm.com            /**
4889241Sandreas.hansson@arm.com             * Read a line of the trace file. Returns the raw tick
4899241Sandreas.hansson@arm.com             * when the next request should be generated. If the end
4909241Sandreas.hansson@arm.com             * of the file has been reached, it returns MaxTick to
4919241Sandreas.hansson@arm.com             * indicate that there will be no more requests.
4929241Sandreas.hansson@arm.com             */
4939241Sandreas.hansson@arm.com            Tick nextExecuteTick();
4949241Sandreas.hansson@arm.com
4959241Sandreas.hansson@arm.com          private:
4969241Sandreas.hansson@arm.com
4979241Sandreas.hansson@arm.com            /** Path to the trace file */
4989241Sandreas.hansson@arm.com            std::string traceFile;
4999241Sandreas.hansson@arm.com
5009241Sandreas.hansson@arm.com            /** Input stream used for reading the input trace file */
5019241Sandreas.hansson@arm.com            std::ifstream trace;
5029241Sandreas.hansson@arm.com
5039241Sandreas.hansson@arm.com            /** Larger buffer used for reading from the stream */
5049241Sandreas.hansson@arm.com            char* readBuffer;
5059241Sandreas.hansson@arm.com
5069241Sandreas.hansson@arm.com            /** Store the current and next element in the trace */
5079241Sandreas.hansson@arm.com            TraceElement currElement;
5089241Sandreas.hansson@arm.com            TraceElement nextElement;
5099241Sandreas.hansson@arm.com
5109241Sandreas.hansson@arm.com            /**
5119241Sandreas.hansson@arm.com             * Stores the time when the state was entered. This is to add an
5129241Sandreas.hansson@arm.com             * offset to the times stored in the trace file.
5139241Sandreas.hansson@arm.com             */
5149241Sandreas.hansson@arm.com            Tick tickOffset;
5159241Sandreas.hansson@arm.com
5169241Sandreas.hansson@arm.com            /**
5179241Sandreas.hansson@arm.com             * Offset for memory requests. Used to shift the trace
5189241Sandreas.hansson@arm.com             * away from the CPU address space.
5199241Sandreas.hansson@arm.com             */
5209241Sandreas.hansson@arm.com            Addr addrOffset;
5219241Sandreas.hansson@arm.com
5229241Sandreas.hansson@arm.com            /**
5239241Sandreas.hansson@arm.com             * Set to true when the trace replay for one instance of
5249241Sandreas.hansson@arm.com             * state is complete.
5259241Sandreas.hansson@arm.com             */
5269241Sandreas.hansson@arm.com            bool traceComplete;
5279241Sandreas.hansson@arm.com
5289241Sandreas.hansson@arm.com            /**
5299241Sandreas.hansson@arm.com             * Used to store the Tick when the next generate should
5309241Sandreas.hansson@arm.com             * occur. It is to remove a transaction as soon as we
5319241Sandreas.hansson@arm.com             * enter the state.
5329241Sandreas.hansson@arm.com             */
5339241Sandreas.hansson@arm.com            Tick oldEmitTime;
5349241Sandreas.hansson@arm.com        };
5359241Sandreas.hansson@arm.com
5369241Sandreas.hansson@arm.com        /** Pointer to owner of request handler */
5379241Sandreas.hansson@arm.com        TrafficGen& owner;
5389241Sandreas.hansson@arm.com
5399241Sandreas.hansson@arm.com        /** Pointer to request handler */
5409241Sandreas.hansson@arm.com        QueuedMasterPort& port;
5419241Sandreas.hansson@arm.com
5429241Sandreas.hansson@arm.com        /** State transition matrix */
5439241Sandreas.hansson@arm.com        std::vector<std::vector<double> > transitionMatrix;
5449241Sandreas.hansson@arm.com
5459241Sandreas.hansson@arm.com      public:
5469241Sandreas.hansson@arm.com
5479241Sandreas.hansson@arm.com        /** Index of the current state */
5489241Sandreas.hansson@arm.com        uint32_t currState;
5499241Sandreas.hansson@arm.com
5509241Sandreas.hansson@arm.com        /** Map of states */
5519241Sandreas.hansson@arm.com        m5::hash_map<uint32_t, BaseGen*> states;
5529241Sandreas.hansson@arm.com    };
5539241Sandreas.hansson@arm.com
5549241Sandreas.hansson@arm.com
5559241Sandreas.hansson@arm.com    /** Queued handler */
5569241Sandreas.hansson@arm.com    class TrafficGenPort : public QueuedMasterPort
5579241Sandreas.hansson@arm.com    {
5589241Sandreas.hansson@arm.com      public:
5599241Sandreas.hansson@arm.com
5609241Sandreas.hansson@arm.com        TrafficGenPort(const std::string& name, TrafficGen& _owner)
5619241Sandreas.hansson@arm.com            : QueuedMasterPort(name, &_owner, queue), queue(_owner, *this),
5629241Sandreas.hansson@arm.com              owner(_owner)
5639241Sandreas.hansson@arm.com        { }
5649241Sandreas.hansson@arm.com
5659241Sandreas.hansson@arm.com      protected:
5669241Sandreas.hansson@arm.com
5679241Sandreas.hansson@arm.com        bool recvTimingResp(PacketPtr pkt);
5689241Sandreas.hansson@arm.com
5699241Sandreas.hansson@arm.com      private:
5709241Sandreas.hansson@arm.com
5719241Sandreas.hansson@arm.com        MasterPacketQueue queue;
5729241Sandreas.hansson@arm.com
5739241Sandreas.hansson@arm.com        // Owner of the port
5749241Sandreas.hansson@arm.com        TrafficGen& owner;
5759241Sandreas.hansson@arm.com
5769241Sandreas.hansson@arm.com    };
5779241Sandreas.hansson@arm.com
5789241Sandreas.hansson@arm.com    TrafficGenPort port;
5799241Sandreas.hansson@arm.com
5809241Sandreas.hansson@arm.com    /** Request generator state graph */
5819241Sandreas.hansson@arm.com    StateGraph stateGraph;
5829241Sandreas.hansson@arm.com
5839241Sandreas.hansson@arm.com    /**
5849241Sandreas.hansson@arm.com     * Schedules event for next update and executes an update on the
5859241Sandreas.hansson@arm.com     * state graph.
5869241Sandreas.hansson@arm.com     */
5879241Sandreas.hansson@arm.com    void updateStateGraph();
5889241Sandreas.hansson@arm.com
5899241Sandreas.hansson@arm.com    /** Event for updating the state graph */
5909241Sandreas.hansson@arm.com    EventWrapper<TrafficGen,
5919241Sandreas.hansson@arm.com                 &TrafficGen::updateStateGraph> updateStateGraphEvent;
5929241Sandreas.hansson@arm.com
5939241Sandreas.hansson@arm.com
5949241Sandreas.hansson@arm.com  public:
5959241Sandreas.hansson@arm.com
5969241Sandreas.hansson@arm.com    TrafficGen(const TrafficGenParams* p);
5979241Sandreas.hansson@arm.com
5989241Sandreas.hansson@arm.com    ~TrafficGen() {}
5999241Sandreas.hansson@arm.com
6009241Sandreas.hansson@arm.com    virtual MasterPort& getMasterPort(const std::string &if_name,
6019241Sandreas.hansson@arm.com                                      int idx = InvalidPortID);
6029241Sandreas.hansson@arm.com
6039241Sandreas.hansson@arm.com    void init();
6049241Sandreas.hansson@arm.com
6059241Sandreas.hansson@arm.com    void initState();
6069241Sandreas.hansson@arm.com
6079241Sandreas.hansson@arm.com    unsigned int drain(Event *drain_event);
6089241Sandreas.hansson@arm.com
6099241Sandreas.hansson@arm.com    void serialize(std::ostream &os);
6109241Sandreas.hansson@arm.com
6119241Sandreas.hansson@arm.com    void unserialize(Checkpoint* cp, const std::string& section);
6129241Sandreas.hansson@arm.com
6139241Sandreas.hansson@arm.com};
6149241Sandreas.hansson@arm.com
6159241Sandreas.hansson@arm.com#endif //__MEM_TRAFFIC_GEN_HH__
616