traffic_gen.hh revision 9294:8fb03b13de02
110037SARM gem5 Developers/*
210844Sandreas.sandberg@arm.com * Copyright (c) 2012 ARM Limited
310037SARM gem5 Developers * All rights reserved
410037SARM gem5 Developers *
510037SARM gem5 Developers * The license below extends only to copyright in the software and shall
610037SARM gem5 Developers * not be construed as granting a license to any other intellectual
710037SARM gem5 Developers * property including but not limited to intellectual property relating
810037SARM gem5 Developers * to a hardware implementation of the functionality of the software
910037SARM gem5 Developers * licensed hereunder.  You may use the software subject to the license
1010037SARM gem5 Developers * terms below provided that you ensure that this notice is replicated
1110037SARM gem5 Developers * unmodified and in its entirety in all distributions of the software,
1210037SARM gem5 Developers * modified or unmodified, in source code or in binary form.
1310037SARM gem5 Developers *
1410037SARM gem5 Developers * Redistribution and use in source and binary forms, with or without
1510037SARM gem5 Developers * modification, are permitted provided that the following conditions are
1610037SARM gem5 Developers * met: redistributions of source code must retain the above copyright
1710037SARM gem5 Developers * notice, this list of conditions and the following disclaimer;
1810037SARM gem5 Developers * redistributions in binary form must reproduce the above copyright
1910037SARM gem5 Developers * notice, this list of conditions and the following disclaimer in the
2010037SARM gem5 Developers * documentation and/or other materials provided with the distribution;
2110037SARM gem5 Developers * neither the name of the copyright holders nor the names of its
2210037SARM gem5 Developers * contributors may be used to endorse or promote products derived from
2310037SARM gem5 Developers * this software without specific prior written permission.
2410037SARM gem5 Developers *
2510037SARM gem5 Developers * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2610037SARM gem5 Developers * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2710037SARM gem5 Developers * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2810037SARM gem5 Developers * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2910037SARM gem5 Developers * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3010037SARM gem5 Developers * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3110037SARM gem5 Developers * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3210037SARM gem5 Developers * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3310037SARM gem5 Developers * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3410037SARM gem5 Developers * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3510037SARM gem5 Developers * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3610037SARM gem5 Developers *
3710037SARM gem5 Developers * Authors: Thomas Grass
3810844Sandreas.sandberg@arm.com *          Andreas Hansson
3910037SARM gem5 Developers *          Sascha Bischoff
4010037SARM gem5 Developers */
4110844Sandreas.sandberg@arm.com#ifndef __MEM_TRAFFIC_GEN_HH__
4210844Sandreas.sandberg@arm.com#define __MEM_TRAFFIC_GEN_HH__
4310037SARM gem5 Developers
4410037SARM gem5 Developers#include <fstream>
4510037SARM gem5 Developers
4610847Sandreas.sandberg@arm.com#include "base/hashmap.hh"
4710844Sandreas.sandberg@arm.com#include "mem/mem_object.hh"
4810847Sandreas.sandberg@arm.com#include "mem/qport.hh"
4910844Sandreas.sandberg@arm.com#include "params/TrafficGen.hh"
5010844Sandreas.sandberg@arm.com
5110844Sandreas.sandberg@arm.com/**
5210844Sandreas.sandberg@arm.com * The traffic generator is a master module that generates stimuli for
5310844Sandreas.sandberg@arm.com * the memory system, based on a collection of simple behaviours that
5410844Sandreas.sandberg@arm.com * are either probabilistic or based on traces. It can be used stand
5510037SARM gem5 Developers * alone for creating test cases for interconnect and memory
5610037SARM gem5 Developers * controllers, or function as a black box replacement for system
5710844Sandreas.sandberg@arm.com * components that are not yet modelled in detail, e.g. a video engine
5810037SARM gem5 Developers * or baseband subsystem.
5910037SARM gem5 Developers */
6010037SARM gem5 Developersclass TrafficGen : public MemObject
6110037SARM gem5 Developers{
6210037SARM gem5 Developers
6310037SARM gem5 Developers  private:
6410037SARM gem5 Developers
6510037SARM gem5 Developers    /**
6610037SARM gem5 Developers     * The system used to determine which mode we are currently operating
6710037SARM gem5 Developers     * in.
6810037SARM gem5 Developers     */
6910905Sandreas.sandberg@arm.com    System* system;
7010037SARM gem5 Developers
7110844Sandreas.sandberg@arm.com    /**
7210037SARM gem5 Developers     * MasterID used in generated requests.
7310037SARM gem5 Developers     */
7410037SARM gem5 Developers    MasterID masterID;
7510037SARM gem5 Developers
7610037SARM gem5 Developers  protected:
7710037SARM gem5 Developers
7810905Sandreas.sandberg@arm.com    /**
7910037SARM gem5 Developers     * The state graph is responsible for instantiating and keeping
8010844Sandreas.sandberg@arm.com     * track of the various generator states and also perform the
8110844Sandreas.sandberg@arm.com     * transitions and call the appropriate functions when entering,
8210844Sandreas.sandberg@arm.com     * executing and exiting a state.
8310844Sandreas.sandberg@arm.com     */
8410037SARM gem5 Developers    class StateGraph
8510037SARM gem5 Developers    {
8610037SARM gem5 Developers
8710037SARM gem5 Developers      public:
8810037SARM gem5 Developers
8910844Sandreas.sandberg@arm.com        /**
9010844Sandreas.sandberg@arm.com         * Create a state graph from an input file.
9110844Sandreas.sandberg@arm.com         *
9210844Sandreas.sandberg@arm.com         * @param _owner used solely for the name
9310844Sandreas.sandberg@arm.com         * @param _port port used to send requests
9410844Sandreas.sandberg@arm.com         * @param file_name configuration description to read in
9510844Sandreas.sandberg@arm.com         * @param master_id the unique id used for all requests
9610844Sandreas.sandberg@arm.com         */
9710845Sandreas.sandberg@arm.com        StateGraph(TrafficGen& _owner, QueuedMasterPort& _port,
9810844Sandreas.sandberg@arm.com                   const std::string& file_name, MasterID master_id)
9910844Sandreas.sandberg@arm.com            : nextTransitionTick(0), owner(_owner), port(_port)
10010844Sandreas.sandberg@arm.com        {
10110844Sandreas.sandberg@arm.com            parseConfig(file_name, master_id);
10210037SARM gem5 Developers        }
10310844Sandreas.sandberg@arm.com
10410037SARM gem5 Developers        /**
10510037SARM gem5 Developers         * Get the name, used for DPRINTFs.
10610037SARM gem5 Developers         *
10710037SARM gem5 Developers         * @return the owner's name
10810037SARM gem5 Developers         */
10910037SARM gem5 Developers        std::string name() const { return owner.name(); }
11010844Sandreas.sandberg@arm.com
11110037SARM gem5 Developers        /**
11210844Sandreas.sandberg@arm.com         * Either perform a state transition or execute the current
11310844Sandreas.sandberg@arm.com         * state, depending on the current time.
11410037SARM gem5 Developers         */
11510037SARM gem5 Developers        void update();
11610037SARM gem5 Developers
11710037SARM gem5 Developers        /**
11810844Sandreas.sandberg@arm.com         * Determine next state and perform the transition.
11910037SARM gem5 Developers         */
12010037SARM gem5 Developers        void transition();
12110844Sandreas.sandberg@arm.com
12210844Sandreas.sandberg@arm.com        /**
12310037SARM gem5 Developers         * Enter a new state.
12410037SARM gem5 Developers         *
12510844Sandreas.sandberg@arm.com         * @param newState identifier of state to enter
12610037SARM gem5 Developers         */
12710844Sandreas.sandberg@arm.com        void enterState(uint32_t newState);
12810844Sandreas.sandberg@arm.com
12910037SARM gem5 Developers        /**
13010037SARM gem5 Developers         * Get the tick of the next event, either an execution or a
13110037SARM gem5 Developers         * transition.
13210037SARM gem5 Developers         *
13310844Sandreas.sandberg@arm.com         * @return tick of the next state graph event
13410037SARM gem5 Developers         */
13510844Sandreas.sandberg@arm.com        Tick nextEventTick()
13610844Sandreas.sandberg@arm.com        {
13710037SARM gem5 Developers            return std::min(states[currState]->nextExecuteTick(),
13810037SARM gem5 Developers                            nextTransitionTick);
13910037SARM gem5 Developers
14010844Sandreas.sandberg@arm.com        }
14110844Sandreas.sandberg@arm.com
14210844Sandreas.sandberg@arm.com        /** Time of next transition */
14310844Sandreas.sandberg@arm.com        Tick nextTransitionTick;
14410844Sandreas.sandberg@arm.com
14510844Sandreas.sandberg@arm.com      private:
14610844Sandreas.sandberg@arm.com
14710037SARM gem5 Developers        /**
14810037SARM gem5 Developers         * Parse the config file and build the state map and
14910037SARM gem5 Developers         * transition matrix.
15010037SARM gem5 Developers         *
15110037SARM gem5 Developers         * @param file_name Config file name to parse
15210844Sandreas.sandberg@arm.com         * @param master_id MasterID to use for generated requests
15310037SARM gem5 Developers         */
15410037SARM gem5 Developers        void parseConfig(const std::string& file_name, MasterID master_id);
15510037SARM gem5 Developers
15610844Sandreas.sandberg@arm.com        /** Struct to represent a probabilistic transition during parsing. */
15710037SARM gem5 Developers        struct Transition {
15810037SARM gem5 Developers            uint32_t from;
15910037SARM gem5 Developers            uint32_t to;
16010037SARM gem5 Developers            double p;
16110037SARM gem5 Developers        };
16210037SARM gem5 Developers
16310845Sandreas.sandberg@arm.com        /** Base class for all generator states */
16410845Sandreas.sandberg@arm.com        class BaseGen
16510845Sandreas.sandberg@arm.com        {
16610845Sandreas.sandberg@arm.com
16710845Sandreas.sandberg@arm.com          protected:
16810845Sandreas.sandberg@arm.com
16910845Sandreas.sandberg@arm.com            /** Port used to send requests */
17010844Sandreas.sandberg@arm.com            QueuedMasterPort& port;
17110844Sandreas.sandberg@arm.com
17210844Sandreas.sandberg@arm.com            /** The MasterID used for generating requests */
17310845Sandreas.sandberg@arm.com            const MasterID masterID;
17410844Sandreas.sandberg@arm.com
17510844Sandreas.sandberg@arm.com          public:
17610037SARM gem5 Developers
17710905Sandreas.sandberg@arm.com            /** Time to spend in this state */
17810037SARM gem5 Developers            const Tick duration;
17910905Sandreas.sandberg@arm.com
18010037SARM gem5 Developers            /**
18110845Sandreas.sandberg@arm.com             * Create a base generator.
18210844Sandreas.sandberg@arm.com             *
18310844Sandreas.sandberg@arm.com             * @param _port port used to send requests
18410037SARM gem5 Developers             * @param master_id MasterID set on each request
18510037SARM gem5 Developers             * @param _duration duration of this state before transitioning
18610844Sandreas.sandberg@arm.com             */
18710037SARM gem5 Developers            BaseGen(QueuedMasterPort& _port, MasterID master_id,
18810037SARM gem5 Developers                    Tick _duration);
18910037SARM gem5 Developers
19010037SARM gem5 Developers            virtual ~BaseGen() { }
19110037SARM gem5 Developers
19210905Sandreas.sandberg@arm.com            /**
19310037SARM gem5 Developers             * Get the name, useful for DPRINTFs.
19410905Sandreas.sandberg@arm.com             *
19510845Sandreas.sandberg@arm.com             * @return the port name
19610845Sandreas.sandberg@arm.com             */
19710845Sandreas.sandberg@arm.com            std::string name() const { return port.name(); }
19810845Sandreas.sandberg@arm.com
19910845Sandreas.sandberg@arm.com            /**
20010037SARM gem5 Developers             * Enter this generator state.
20110037SARM gem5 Developers             */
20210037SARM gem5 Developers            virtual void enter() = 0;
20310844Sandreas.sandberg@arm.com
20410037SARM gem5 Developers            /**
20510844Sandreas.sandberg@arm.com             * Execute this generator state.
20610037SARM gem5 Developers             */
20710037SARM gem5 Developers            virtual void execute() = 0;
20810037SARM gem5 Developers
20910844Sandreas.sandberg@arm.com            /**
21010844Sandreas.sandberg@arm.com             * Exit this generator state. By default do nothing.
21110037SARM gem5 Developers             */
21210844Sandreas.sandberg@arm.com            virtual void exit() { };
21310844Sandreas.sandberg@arm.com
21410844Sandreas.sandberg@arm.com            /**
21510844Sandreas.sandberg@arm.com             * Determine the next execute tick. MaxTick means that
21610844Sandreas.sandberg@arm.com             * there will not be any further event in the current
21710844Sandreas.sandberg@arm.com             * activation cycle of the state.
21810037SARM gem5 Developers             *
21910844Sandreas.sandberg@arm.com             * @return next tick when the state should be executed
22010844Sandreas.sandberg@arm.com             */
22110844Sandreas.sandberg@arm.com            virtual Tick nextExecuteTick() = 0;
22210844Sandreas.sandberg@arm.com
22310844Sandreas.sandberg@arm.com        };
22410844Sandreas.sandberg@arm.com
22510844Sandreas.sandberg@arm.com        /**
22610844Sandreas.sandberg@arm.com         * The idle generator does nothing.
22710844Sandreas.sandberg@arm.com         */
22810844Sandreas.sandberg@arm.com        class IdleGen : public BaseGen
22910844Sandreas.sandberg@arm.com        {
23010844Sandreas.sandberg@arm.com
23110844Sandreas.sandberg@arm.com          public:
23210844Sandreas.sandberg@arm.com
23310844Sandreas.sandberg@arm.com            IdleGen(QueuedMasterPort& _port, MasterID master_id,
23410845Sandreas.sandberg@arm.com                    Tick _duration)
23510845Sandreas.sandberg@arm.com                : BaseGen(_port, master_id, _duration)
23610844Sandreas.sandberg@arm.com            { }
23710844Sandreas.sandberg@arm.com
23810037SARM gem5 Developers            void enter() { }
23910037SARM gem5 Developers
24010037SARM gem5 Developers            void execute() { }
24110905Sandreas.sandberg@arm.com
24210037SARM gem5 Developers            Tick nextExecuteTick() { return MaxTick; }
24310905Sandreas.sandberg@arm.com        };
24410844Sandreas.sandberg@arm.com
24510905Sandreas.sandberg@arm.com        /**
24610844Sandreas.sandberg@arm.com         * The linear generator generates sequential requests from a
24710844Sandreas.sandberg@arm.com         * start to an end address, with a fixed block size. A
24810905Sandreas.sandberg@arm.com         * fraction of the requests are reads, as determined by the
24910844Sandreas.sandberg@arm.com         * read percent. There is an optional data limit for when to
25010905Sandreas.sandberg@arm.com         * stop generating new requests.
25110905Sandreas.sandberg@arm.com         */
25210905Sandreas.sandberg@arm.com        class LinearGen : public BaseGen
25310905Sandreas.sandberg@arm.com        {
25410037SARM gem5 Developers
25510037SARM gem5 Developers          public:
25610037SARM gem5 Developers
25710037SARM gem5 Developers            /**
25810905Sandreas.sandberg@arm.com             * Create a linear address sequence generator. Set
25910037SARM gem5 Developers             * min_period == max_period for a fixed inter-transaction
26010905Sandreas.sandberg@arm.com             * time.
26110844Sandreas.sandberg@arm.com             *
26210844Sandreas.sandberg@arm.com             * @param _port port used to send requests
26310844Sandreas.sandberg@arm.com             * @param master_id MasterID set on each request
26410844Sandreas.sandberg@arm.com             * @param _duration duration of this state before transitioning
26510844Sandreas.sandberg@arm.com             * @param start_addr Start address
26610844Sandreas.sandberg@arm.com             * @param end_addr End address
26710844Sandreas.sandberg@arm.com             * @param _blocksize Size used for transactions injected
26810844Sandreas.sandberg@arm.com             * @param min_period Lower limit of random inter-transaction time
26910844Sandreas.sandberg@arm.com             * @param max_period Upper limit of random inter-transaction time
27010844Sandreas.sandberg@arm.com             * @param read_percent Percent of transactions that are reads
27110844Sandreas.sandberg@arm.com             * @param data_limit Upper limit on how much data to read/write
27210844Sandreas.sandberg@arm.com             */
27310844Sandreas.sandberg@arm.com            LinearGen(QueuedMasterPort& _port, MasterID master_id,
27410844Sandreas.sandberg@arm.com                      Tick _duration, Addr start_addr, Addr end_addr,
27510844Sandreas.sandberg@arm.com                      Addr _blocksize, Tick min_period, Tick max_period,
27610844Sandreas.sandberg@arm.com                      uint8_t read_percent, Addr data_limit)
27710905Sandreas.sandberg@arm.com                : BaseGen(_port, master_id, _duration),
27810905Sandreas.sandberg@arm.com                  startAddr(start_addr), endAddr(end_addr),
27910037SARM gem5 Developers                  blocksize(_blocksize), minPeriod(min_period),
28010037SARM gem5 Developers                  maxPeriod(max_period), readPercent(read_percent),
28110037SARM gem5 Developers                  dataLimit(data_limit)
28210844Sandreas.sandberg@arm.com            { }
28310844Sandreas.sandberg@arm.com
28410844Sandreas.sandberg@arm.com            void enter();
28510844Sandreas.sandberg@arm.com
28610844Sandreas.sandberg@arm.com            void execute();
28710844Sandreas.sandberg@arm.com
28810844Sandreas.sandberg@arm.com            Tick nextExecuteTick();
28910844Sandreas.sandberg@arm.com
29010844Sandreas.sandberg@arm.com          private:
29110844Sandreas.sandberg@arm.com
29210844Sandreas.sandberg@arm.com            /** Start of address range */
29310844Sandreas.sandberg@arm.com            const Addr startAddr;
29410844Sandreas.sandberg@arm.com
29510844Sandreas.sandberg@arm.com            /** End of address range */
29610844Sandreas.sandberg@arm.com            const Addr endAddr;
29710844Sandreas.sandberg@arm.com
29810844Sandreas.sandberg@arm.com            /** Blocksize and address increment */
29910844Sandreas.sandberg@arm.com            const Addr blocksize;
30010844Sandreas.sandberg@arm.com
30110845Sandreas.sandberg@arm.com            /** Request generation period */
30210844Sandreas.sandberg@arm.com            const Tick minPeriod;
30310844Sandreas.sandberg@arm.com            const Tick maxPeriod;
30410844Sandreas.sandberg@arm.com
30510844Sandreas.sandberg@arm.com            /**
30610844Sandreas.sandberg@arm.com             * Percent of generated transactions that should be reads
30710844Sandreas.sandberg@arm.com             */
30810844Sandreas.sandberg@arm.com            const uint8_t readPercent;
30910844Sandreas.sandberg@arm.com
31010844Sandreas.sandberg@arm.com            /** Maximum amount of data to manipulate */
31110844Sandreas.sandberg@arm.com            const Addr dataLimit;
31210844Sandreas.sandberg@arm.com
31310844Sandreas.sandberg@arm.com            /** Address of next request */
31410844Sandreas.sandberg@arm.com            Addr nextAddr;
31510844Sandreas.sandberg@arm.com
31610844Sandreas.sandberg@arm.com            /**
31710844Sandreas.sandberg@arm.com             * Counter to determine the amount of data
31810844Sandreas.sandberg@arm.com             * manipulated. Used to determine if we should continue
31910844Sandreas.sandberg@arm.com             * generating requests.
32010844Sandreas.sandberg@arm.com             */
32110844Sandreas.sandberg@arm.com            Addr dataManipulated;
32210844Sandreas.sandberg@arm.com        };
32310844Sandreas.sandberg@arm.com
32410844Sandreas.sandberg@arm.com        /**
32510844Sandreas.sandberg@arm.com         * The random generator is similar to the linear one, but does
32610844Sandreas.sandberg@arm.com         * not generate sequential addresses. Instead it randomly
32710844Sandreas.sandberg@arm.com         * picks an address in the range, aligned to the block size.
32810844Sandreas.sandberg@arm.com         */
32910844Sandreas.sandberg@arm.com        class RandomGen : public BaseGen
33010844Sandreas.sandberg@arm.com        {
33110844Sandreas.sandberg@arm.com
33210844Sandreas.sandberg@arm.com          public:
33310844Sandreas.sandberg@arm.com
33410844Sandreas.sandberg@arm.com            /**
33510844Sandreas.sandberg@arm.com             * Create a random address sequence generator. Set
33610844Sandreas.sandberg@arm.com             * min_period == max_period for a fixed inter-transaction
33710844Sandreas.sandberg@arm.com             * time.
33810844Sandreas.sandberg@arm.com             *
33910844Sandreas.sandberg@arm.com             * @param _port port used to send requests
34010844Sandreas.sandberg@arm.com             * @param master_id MasterID set on each request
34110844Sandreas.sandberg@arm.com             * @param _duration duration of this state before transitioning
34210844Sandreas.sandberg@arm.com             * @param start_addr Start address
34310844Sandreas.sandberg@arm.com             * @param end_addr End address
34410844Sandreas.sandberg@arm.com             * @param _blocksize Size used for transactions injected
34510844Sandreas.sandberg@arm.com             * @param min_period Lower limit of random inter-transaction time
34610844Sandreas.sandberg@arm.com             * @param max_period Upper limit of random inter-transaction time
34710844Sandreas.sandberg@arm.com             * @param read_percent Percent of transactions that are reads
34810844Sandreas.sandberg@arm.com             * @param data_limit Upper limit on how much data to read/write
34910844Sandreas.sandberg@arm.com             */
35010844Sandreas.sandberg@arm.com            RandomGen(QueuedMasterPort& _port, MasterID master_id,
35110844Sandreas.sandberg@arm.com                      Tick _duration, Addr start_addr, Addr end_addr,
35210844Sandreas.sandberg@arm.com                      Addr _blocksize, Tick min_period, Tick max_period,
35310845Sandreas.sandberg@arm.com                      uint8_t read_percent, Addr data_limit)
35410845Sandreas.sandberg@arm.com                : BaseGen(_port, master_id, _duration),
35510845Sandreas.sandberg@arm.com                  startAddr(start_addr), endAddr(end_addr),
35610844Sandreas.sandberg@arm.com                  blocksize(_blocksize), minPeriod(min_period),
35710844Sandreas.sandberg@arm.com                  maxPeriod(max_period), readPercent(read_percent),
35810845Sandreas.sandberg@arm.com                  dataLimit(data_limit)
35910845Sandreas.sandberg@arm.com            { }
36010845Sandreas.sandberg@arm.com
36110844Sandreas.sandberg@arm.com            void enter();
36210844Sandreas.sandberg@arm.com
36310845Sandreas.sandberg@arm.com            void execute();
36410845Sandreas.sandberg@arm.com
36510845Sandreas.sandberg@arm.com            Tick nextExecuteTick();
36610844Sandreas.sandberg@arm.com
36710844Sandreas.sandberg@arm.com          private:
36810845Sandreas.sandberg@arm.com
36910845Sandreas.sandberg@arm.com            /** Start of address range */
37010844Sandreas.sandberg@arm.com            const Addr startAddr;
37110844Sandreas.sandberg@arm.com
37210844Sandreas.sandberg@arm.com            /** End of address range */
37310844Sandreas.sandberg@arm.com            const Addr endAddr;
37410844Sandreas.sandberg@arm.com
37510844Sandreas.sandberg@arm.com            /** Block size */
37610844Sandreas.sandberg@arm.com            const Addr blocksize;
37710844Sandreas.sandberg@arm.com
37810844Sandreas.sandberg@arm.com            /** Request generation period */
37910844Sandreas.sandberg@arm.com            const Tick minPeriod;
38010844Sandreas.sandberg@arm.com            const Tick maxPeriod;
38110844Sandreas.sandberg@arm.com
38210844Sandreas.sandberg@arm.com            /**
38310844Sandreas.sandberg@arm.com             * Percent of generated transactions that should be reads
38410844Sandreas.sandberg@arm.com             */
38510844Sandreas.sandberg@arm.com            const uint8_t readPercent;
38610844Sandreas.sandberg@arm.com
38710844Sandreas.sandberg@arm.com            /** Maximum amount of data to manipulate */
38810844Sandreas.sandberg@arm.com            const Addr dataLimit;
38910844Sandreas.sandberg@arm.com
39010844Sandreas.sandberg@arm.com            /**
39110844Sandreas.sandberg@arm.com             * Counter to determine the amount of data
39210844Sandreas.sandberg@arm.com             * manipulated. Used to determine if we should continue
39310844Sandreas.sandberg@arm.com             * generating requests.
39410844Sandreas.sandberg@arm.com             */
39510844Sandreas.sandberg@arm.com            Addr dataManipulated;
39610844Sandreas.sandberg@arm.com        };
39710844Sandreas.sandberg@arm.com
39810844Sandreas.sandberg@arm.com        /**
39910844Sandreas.sandberg@arm.com         * The trace replay generator reads a trace file and plays
40010844Sandreas.sandberg@arm.com         * back the transactions. The trace is offset with respect to
40110844Sandreas.sandberg@arm.com         * the time when the state was entered.
40210844Sandreas.sandberg@arm.com         */
40310844Sandreas.sandberg@arm.com        class TraceGen : public BaseGen
40410844Sandreas.sandberg@arm.com        {
40510844Sandreas.sandberg@arm.com
40610844Sandreas.sandberg@arm.com          private:
40710844Sandreas.sandberg@arm.com
40810844Sandreas.sandberg@arm.com            /**
40910844Sandreas.sandberg@arm.com             * This struct stores a line in the trace file.
41010844Sandreas.sandberg@arm.com             */
41110844Sandreas.sandberg@arm.com            struct TraceElement {
41210844Sandreas.sandberg@arm.com
41310844Sandreas.sandberg@arm.com                /** Specifies if the request is to be a read or a write */
41410844Sandreas.sandberg@arm.com                MemCmd cmd;
41510844Sandreas.sandberg@arm.com
41610844Sandreas.sandberg@arm.com                /** The address for the request */
41710844Sandreas.sandberg@arm.com                Addr addr;
41810844Sandreas.sandberg@arm.com
41910844Sandreas.sandberg@arm.com                /** The size of the access for the request */
42010844Sandreas.sandberg@arm.com                Addr blocksize;
42110844Sandreas.sandberg@arm.com
42210844Sandreas.sandberg@arm.com                /** The time at which the request should be sent */
42310844Sandreas.sandberg@arm.com                Tick tick;
42410844Sandreas.sandberg@arm.com
42510844Sandreas.sandberg@arm.com                /**
42610844Sandreas.sandberg@arm.com                 * Check validity of this element.
42710844Sandreas.sandberg@arm.com                 *
42810844Sandreas.sandberg@arm.com                 * @return if this element is valid
42910844Sandreas.sandberg@arm.com                 */
43010844Sandreas.sandberg@arm.com                bool isValid() const {
43110844Sandreas.sandberg@arm.com                    return cmd != MemCmd::InvalidCmd;
43210844Sandreas.sandberg@arm.com                }
43310844Sandreas.sandberg@arm.com
43410845Sandreas.sandberg@arm.com                /**
43510844Sandreas.sandberg@arm.com                 * Make this element invalid.
43610844Sandreas.sandberg@arm.com                 */
43710844Sandreas.sandberg@arm.com                void clear() {
43810845Sandreas.sandberg@arm.com                    cmd = MemCmd::InvalidCmd;
43910845Sandreas.sandberg@arm.com                }
44010844Sandreas.sandberg@arm.com            };
44110844Sandreas.sandberg@arm.com
44210845Sandreas.sandberg@arm.com          public:
44310845Sandreas.sandberg@arm.com
44410844Sandreas.sandberg@arm.com           /**
44510844Sandreas.sandberg@arm.com             * Create a trace generator.
44610845Sandreas.sandberg@arm.com             *
44710845Sandreas.sandberg@arm.com             * @param _port port used to send requests
44810844Sandreas.sandberg@arm.com             * @param master_id MasterID set on each request
44910844Sandreas.sandberg@arm.com             * @param _duration duration of this state before transitioning
45010845Sandreas.sandberg@arm.com             * @param trace_file File to read the transactions from
45110844Sandreas.sandberg@arm.com             * @param addr_offset Positive offset to add to trace address
45210844Sandreas.sandberg@arm.com             */
45310844Sandreas.sandberg@arm.com            TraceGen(QueuedMasterPort& _port, MasterID master_id,
45410844Sandreas.sandberg@arm.com                     Tick _duration, const std::string& trace_file,
45510844Sandreas.sandberg@arm.com                     Addr addr_offset)
45610844Sandreas.sandberg@arm.com                : BaseGen(_port, master_id, _duration),
45710844Sandreas.sandberg@arm.com                  traceFile(trace_file),
45810844Sandreas.sandberg@arm.com                  addrOffset(addr_offset),
45910844Sandreas.sandberg@arm.com                  traceComplete(false)
46010844Sandreas.sandberg@arm.com            {
46110844Sandreas.sandberg@arm.com                /**
46210844Sandreas.sandberg@arm.com                 * Create a 4MB read buffer for the input trace
46310844Sandreas.sandberg@arm.com                 * file. This is to reduce the number of disk accesses
46410844Sandreas.sandberg@arm.com                 * and thereby speed up the execution of the code.
46510844Sandreas.sandberg@arm.com                 */
46610844Sandreas.sandberg@arm.com                readBuffer = new char[4 * 1024 * 1024];
46710844Sandreas.sandberg@arm.com                trace.rdbuf()->pubsetbuf(readBuffer, 4 * 1024 * 1024);
46810844Sandreas.sandberg@arm.com                trace.open(traceFile.c_str(), std::ifstream::in);
46910844Sandreas.sandberg@arm.com
47010844Sandreas.sandberg@arm.com                if (!trace.is_open()) {
47110844Sandreas.sandberg@arm.com                    fatal("Traffic generator %s trace file could not be"
47210844Sandreas.sandberg@arm.com                          " opened: %s\n", name(), traceFile);
47310844Sandreas.sandberg@arm.com                }
47410844Sandreas.sandberg@arm.com            }
47510844Sandreas.sandberg@arm.com
47610844Sandreas.sandberg@arm.com            ~TraceGen() {
47710844Sandreas.sandberg@arm.com                // free the memory used by the readBuffer
47810844Sandreas.sandberg@arm.com                delete[] readBuffer;
47910844Sandreas.sandberg@arm.com            }
48010847Sandreas.sandberg@arm.com
48110847Sandreas.sandberg@arm.com            void enter();
48210847Sandreas.sandberg@arm.com
48310847Sandreas.sandberg@arm.com            void execute();
48410847Sandreas.sandberg@arm.com
48510847Sandreas.sandberg@arm.com            void exit();
48610847Sandreas.sandberg@arm.com
48710847Sandreas.sandberg@arm.com            /**
48810847Sandreas.sandberg@arm.com             * Read a line of the trace file. Returns the raw tick
48910847Sandreas.sandberg@arm.com             * when the next request should be generated. If the end
49010847Sandreas.sandberg@arm.com             * of the file has been reached, it returns MaxTick to
49110847Sandreas.sandberg@arm.com             * indicate that there will be no more requests.
49210847Sandreas.sandberg@arm.com             */
49310847Sandreas.sandberg@arm.com            Tick nextExecuteTick();
49410847Sandreas.sandberg@arm.com
49510847Sandreas.sandberg@arm.com          private:
49610847Sandreas.sandberg@arm.com
49710905Sandreas.sandberg@arm.com            /** Path to the trace file */
49810847Sandreas.sandberg@arm.com            std::string traceFile;
49910905Sandreas.sandberg@arm.com
50010847Sandreas.sandberg@arm.com            /** Input stream used for reading the input trace file */
50110905Sandreas.sandberg@arm.com            std::ifstream trace;
50210847Sandreas.sandberg@arm.com
50310905Sandreas.sandberg@arm.com            /** Larger buffer used for reading from the stream */
50410905Sandreas.sandberg@arm.com            char* readBuffer;
50510847Sandreas.sandberg@arm.com
50610847Sandreas.sandberg@arm.com            /** Store the current and next element in the trace */
50710847Sandreas.sandberg@arm.com            TraceElement currElement;
50810905Sandreas.sandberg@arm.com            TraceElement nextElement;
50910847Sandreas.sandberg@arm.com
51010905Sandreas.sandberg@arm.com            /**
51110847Sandreas.sandberg@arm.com             * Stores the time when the state was entered. This is to add an
51210847Sandreas.sandberg@arm.com             * offset to the times stored in the trace file.
51310847Sandreas.sandberg@arm.com             */
51410847Sandreas.sandberg@arm.com            Tick tickOffset;
51510847Sandreas.sandberg@arm.com
51610847Sandreas.sandberg@arm.com            /**
51710847Sandreas.sandberg@arm.com             * Offset for memory requests. Used to shift the trace
51810847Sandreas.sandberg@arm.com             * away from the CPU address space.
51910905Sandreas.sandberg@arm.com             */
52010905Sandreas.sandberg@arm.com            Addr addrOffset;
52110847Sandreas.sandberg@arm.com
52210847Sandreas.sandberg@arm.com            /**
52310847Sandreas.sandberg@arm.com             * Set to true when the trace replay for one instance of
52410847Sandreas.sandberg@arm.com             * state is complete.
52510847Sandreas.sandberg@arm.com             */
52610847Sandreas.sandberg@arm.com            bool traceComplete;
52710847Sandreas.sandberg@arm.com
52810847Sandreas.sandberg@arm.com            /**
52910847Sandreas.sandberg@arm.com             * Used to store the Tick when the next generate should
53010847Sandreas.sandberg@arm.com             * occur. It is to remove a transaction as soon as we
53110847Sandreas.sandberg@arm.com             * enter the state.
53210847Sandreas.sandberg@arm.com             */
53310847Sandreas.sandberg@arm.com            Tick oldEmitTime;
53410847Sandreas.sandberg@arm.com        };
53510847Sandreas.sandberg@arm.com
53610847Sandreas.sandberg@arm.com        /** Pointer to owner of request handler */
53710847Sandreas.sandberg@arm.com        TrafficGen& owner;
53810847Sandreas.sandberg@arm.com
53910847Sandreas.sandberg@arm.com        /** Pointer to request handler */
54010847Sandreas.sandberg@arm.com        QueuedMasterPort& port;
54110847Sandreas.sandberg@arm.com
54210847Sandreas.sandberg@arm.com        /** State transition matrix */
54310847Sandreas.sandberg@arm.com        std::vector<std::vector<double> > transitionMatrix;
54410847Sandreas.sandberg@arm.com
54510847Sandreas.sandberg@arm.com      public:
54610847Sandreas.sandberg@arm.com
54710847Sandreas.sandberg@arm.com        /** Index of the current state */
54810847Sandreas.sandberg@arm.com        uint32_t currState;
54910847Sandreas.sandberg@arm.com
55010847Sandreas.sandberg@arm.com        /** Map of states */
55110847Sandreas.sandberg@arm.com        m5::hash_map<uint32_t, BaseGen*> states;
55210847Sandreas.sandberg@arm.com    };
55310847Sandreas.sandberg@arm.com
55410847Sandreas.sandberg@arm.com
55510847Sandreas.sandberg@arm.com    /** Queued handler */
55610847Sandreas.sandberg@arm.com    class TrafficGenPort : public QueuedMasterPort
55710847Sandreas.sandberg@arm.com    {
55810847Sandreas.sandberg@arm.com      public:
55910847Sandreas.sandberg@arm.com
56010847Sandreas.sandberg@arm.com        TrafficGenPort(const std::string& name, TrafficGen& _owner)
56110847Sandreas.sandberg@arm.com            : QueuedMasterPort(name, &_owner, queue), queue(_owner, *this),
56210847Sandreas.sandberg@arm.com              owner(_owner)
56310847Sandreas.sandberg@arm.com        { }
56410847Sandreas.sandberg@arm.com
56510847Sandreas.sandberg@arm.com      protected:
56610847Sandreas.sandberg@arm.com
56710847Sandreas.sandberg@arm.com        bool recvTimingResp(PacketPtr pkt);
56810847Sandreas.sandberg@arm.com
56910847Sandreas.sandberg@arm.com      private:
57010847Sandreas.sandberg@arm.com
57110847Sandreas.sandberg@arm.com        MasterPacketQueue queue;
57210847Sandreas.sandberg@arm.com
57310847Sandreas.sandberg@arm.com        // Owner of the port
57410847Sandreas.sandberg@arm.com        TrafficGen& owner;
57510847Sandreas.sandberg@arm.com
57610847Sandreas.sandberg@arm.com    };
57710847Sandreas.sandberg@arm.com
57810847Sandreas.sandberg@arm.com    TrafficGenPort port;
57910847Sandreas.sandberg@arm.com
58010847Sandreas.sandberg@arm.com    /** Request generator state graph */
58110847Sandreas.sandberg@arm.com    StateGraph stateGraph;
58210847Sandreas.sandberg@arm.com
58310847Sandreas.sandberg@arm.com    /**
58410847Sandreas.sandberg@arm.com     * Schedules event for next update and executes an update on the
58510847Sandreas.sandberg@arm.com     * state graph.
58610847Sandreas.sandberg@arm.com     */
58710847Sandreas.sandberg@arm.com    void updateStateGraph();
58810847Sandreas.sandberg@arm.com
58910847Sandreas.sandberg@arm.com    /** Event for updating the state graph */
59010847Sandreas.sandberg@arm.com    EventWrapper<TrafficGen,
59110847Sandreas.sandberg@arm.com                 &TrafficGen::updateStateGraph> updateStateGraphEvent;
59210847Sandreas.sandberg@arm.com
59310847Sandreas.sandberg@arm.com
59410847Sandreas.sandberg@arm.com  public:
59510847Sandreas.sandberg@arm.com
59610847Sandreas.sandberg@arm.com    TrafficGen(const TrafficGenParams* p);
59710847Sandreas.sandberg@arm.com
59810847Sandreas.sandberg@arm.com    ~TrafficGen() {}
59910847Sandreas.sandberg@arm.com
60010847Sandreas.sandberg@arm.com    virtual BaseMasterPort& getMasterPort(const std::string &if_name,
60110847Sandreas.sandberg@arm.com                                          PortID idx = InvalidPortID);
60210847Sandreas.sandberg@arm.com
60310847Sandreas.sandberg@arm.com    void init();
60410847Sandreas.sandberg@arm.com
60510847Sandreas.sandberg@arm.com    void initState();
60610847Sandreas.sandberg@arm.com
60710847Sandreas.sandberg@arm.com    unsigned int drain(Event *drain_event);
60810847Sandreas.sandberg@arm.com
60910847Sandreas.sandberg@arm.com    void serialize(std::ostream &os);
61010847Sandreas.sandberg@arm.com
61110847Sandreas.sandberg@arm.com    void unserialize(Checkpoint* cp, const std::string& section);
61210847Sandreas.sandberg@arm.com
61310847Sandreas.sandberg@arm.com};
61410847Sandreas.sandberg@arm.com
61510847Sandreas.sandberg@arm.com#endif //__MEM_TRAFFIC_GEN_HH__
61610847Sandreas.sandberg@arm.com