112810Sandreas.sandberg@arm.com/*
214054Stiago.muck@arm.com * Copyright (c) 2012-2013, 2016-2019 ARM Limited
312810Sandreas.sandberg@arm.com * All rights reserved
412810Sandreas.sandberg@arm.com *
512810Sandreas.sandberg@arm.com * The license below extends only to copyright in the software and shall
612810Sandreas.sandberg@arm.com * not be construed as granting a license to any other intellectual
712810Sandreas.sandberg@arm.com * property including but not limited to intellectual property relating
812810Sandreas.sandberg@arm.com * to a hardware implementation of the functionality of the software
912810Sandreas.sandberg@arm.com * licensed hereunder.  You may use the software subject to the license
1012810Sandreas.sandberg@arm.com * terms below provided that you ensure that this notice is replicated
1112810Sandreas.sandberg@arm.com * unmodified and in its entirety in all distributions of the software,
1212810Sandreas.sandberg@arm.com * modified or unmodified, in source code or in binary form.
1312810Sandreas.sandberg@arm.com *
1412810Sandreas.sandberg@arm.com * Redistribution and use in source and binary forms, with or without
1512810Sandreas.sandberg@arm.com * modification, are permitted provided that the following conditions are
1612810Sandreas.sandberg@arm.com * met: redistributions of source code must retain the above copyright
1712810Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer;
1812810Sandreas.sandberg@arm.com * redistributions in binary form must reproduce the above copyright
1912810Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer in the
2012810Sandreas.sandberg@arm.com * documentation and/or other materials provided with the distribution;
2112810Sandreas.sandberg@arm.com * neither the name of the copyright holders nor the names of its
2212810Sandreas.sandberg@arm.com * contributors may be used to endorse or promote products derived from
2312810Sandreas.sandberg@arm.com * this software without specific prior written permission.
2412810Sandreas.sandberg@arm.com *
2512810Sandreas.sandberg@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2612810Sandreas.sandberg@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2712810Sandreas.sandberg@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2812810Sandreas.sandberg@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2912810Sandreas.sandberg@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3012810Sandreas.sandberg@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3112810Sandreas.sandberg@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3212810Sandreas.sandberg@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3312810Sandreas.sandberg@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3412810Sandreas.sandberg@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3512810Sandreas.sandberg@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3612810Sandreas.sandberg@arm.com *
3712810Sandreas.sandberg@arm.com * Authors: Thomas Grass
3812810Sandreas.sandberg@arm.com *          Andreas Hansson
3912810Sandreas.sandberg@arm.com *          Sascha Bischoff
4012810Sandreas.sandberg@arm.com */
4112810Sandreas.sandberg@arm.com
4212810Sandreas.sandberg@arm.com#ifndef __CPU_TRAFFIC_GEN_BASE_HH__
4312810Sandreas.sandberg@arm.com#define __CPU_TRAFFIC_GEN_BASE_HH__
4412810Sandreas.sandberg@arm.com
4512810Sandreas.sandberg@arm.com#include <memory>
4612810Sandreas.sandberg@arm.com#include <tuple>
4714054Stiago.muck@arm.com#include <unordered_map>
4812810Sandreas.sandberg@arm.com
4912810Sandreas.sandberg@arm.com#include "base/statistics.hh"
5012810Sandreas.sandberg@arm.com#include "mem/qport.hh"
5113892Sgabeblack@google.com#include "sim/clocked_object.hh"
5212810Sandreas.sandberg@arm.com
5312810Sandreas.sandberg@arm.comclass BaseGen;
5412919Sgiacomo.travaglini@arm.comclass StreamGen;
5512810Sandreas.sandberg@arm.comclass System;
5612810Sandreas.sandberg@arm.comstruct BaseTrafficGenParams;
5712810Sandreas.sandberg@arm.com
5812810Sandreas.sandberg@arm.com/**
5912810Sandreas.sandberg@arm.com * The traffic generator is a master module that generates stimuli for
6012810Sandreas.sandberg@arm.com * the memory system, based on a collection of simple generator
6112810Sandreas.sandberg@arm.com * behaviours that are either probabilistic or based on traces. It can
6212810Sandreas.sandberg@arm.com * be used stand alone for creating test cases for interconnect and
6312810Sandreas.sandberg@arm.com * memory controllers, or function as a black box replacement for
6412810Sandreas.sandberg@arm.com * system components that are not yet modelled in detail, e.g. a video
6512810Sandreas.sandberg@arm.com * engine or baseband subsystem.
6612810Sandreas.sandberg@arm.com */
6713892Sgabeblack@google.comclass BaseTrafficGen : public ClockedObject
6812810Sandreas.sandberg@arm.com{
6912811Sandreas.sandberg@arm.com    friend class BaseGen;
7012811Sandreas.sandberg@arm.com
7112810Sandreas.sandberg@arm.com  protected: // Params
7212810Sandreas.sandberg@arm.com    /**
7312810Sandreas.sandberg@arm.com     * The system used to determine which mode we are currently operating
7412810Sandreas.sandberg@arm.com     * in.
7512810Sandreas.sandberg@arm.com     */
7612810Sandreas.sandberg@arm.com    System *const system;
7712810Sandreas.sandberg@arm.com
7812810Sandreas.sandberg@arm.com    /**
7912810Sandreas.sandberg@arm.com     * Determine whether to add elasticity in the request injection,
8012810Sandreas.sandberg@arm.com     * thus responding to backpressure by slowing things down.
8112810Sandreas.sandberg@arm.com     */
8212810Sandreas.sandberg@arm.com    const bool elasticReq;
8312810Sandreas.sandberg@arm.com
8412810Sandreas.sandberg@arm.com    /**
8512810Sandreas.sandberg@arm.com     * Time to tolerate waiting for retries (not making progress),
8612810Sandreas.sandberg@arm.com     * until we declare things broken.
8712810Sandreas.sandberg@arm.com     */
8812810Sandreas.sandberg@arm.com    const Tick progressCheck;
8912810Sandreas.sandberg@arm.com
9012810Sandreas.sandberg@arm.com  private:
9112810Sandreas.sandberg@arm.com    /**
9212810Sandreas.sandberg@arm.com     * Receive a retry from the neighbouring port and attempt to
9312810Sandreas.sandberg@arm.com     * resend the waiting packet.
9412810Sandreas.sandberg@arm.com     */
9512810Sandreas.sandberg@arm.com    void recvReqRetry();
9612810Sandreas.sandberg@arm.com
9714054Stiago.muck@arm.com    void retryReq();
9814054Stiago.muck@arm.com
9914054Stiago.muck@arm.com    bool recvTimingResp(PacketPtr pkt);
10014054Stiago.muck@arm.com
10112810Sandreas.sandberg@arm.com    /** Transition to the next generator */
10212810Sandreas.sandberg@arm.com    void transition();
10312810Sandreas.sandberg@arm.com
10412810Sandreas.sandberg@arm.com    /**
10512810Sandreas.sandberg@arm.com     * Schedule the update event based on nextPacketTick and
10612810Sandreas.sandberg@arm.com     * nextTransitionTick.
10712810Sandreas.sandberg@arm.com     */
10812810Sandreas.sandberg@arm.com    void scheduleUpdate();
10912810Sandreas.sandberg@arm.com
11012810Sandreas.sandberg@arm.com    /**
11112810Sandreas.sandberg@arm.com     * Method to inform the user we have made no progress.
11212810Sandreas.sandberg@arm.com     */
11312810Sandreas.sandberg@arm.com    void noProgress();
11412810Sandreas.sandberg@arm.com
11512810Sandreas.sandberg@arm.com    /**
11612810Sandreas.sandberg@arm.com     * Event to keep track of our progress, or lack thereof.
11712810Sandreas.sandberg@arm.com     */
11812810Sandreas.sandberg@arm.com    EventFunctionWrapper noProgressEvent;
11912810Sandreas.sandberg@arm.com
12012810Sandreas.sandberg@arm.com    /** Time of next transition */
12112810Sandreas.sandberg@arm.com    Tick nextTransitionTick;
12212810Sandreas.sandberg@arm.com
12312810Sandreas.sandberg@arm.com    /** Time of the next packet. */
12412810Sandreas.sandberg@arm.com    Tick nextPacketTick;
12512810Sandreas.sandberg@arm.com
12614054Stiago.muck@arm.com    const int maxOutstandingReqs;
12714054Stiago.muck@arm.com
12812810Sandreas.sandberg@arm.com
12912810Sandreas.sandberg@arm.com    /** Master port specialisation for the traffic generator */
13012810Sandreas.sandberg@arm.com    class TrafficGenPort : public MasterPort
13112810Sandreas.sandberg@arm.com    {
13212810Sandreas.sandberg@arm.com      public:
13312810Sandreas.sandberg@arm.com
13412810Sandreas.sandberg@arm.com        TrafficGenPort(const std::string& name, BaseTrafficGen& traffic_gen)
13512810Sandreas.sandberg@arm.com            : MasterPort(name, &traffic_gen), trafficGen(traffic_gen)
13612810Sandreas.sandberg@arm.com        { }
13712810Sandreas.sandberg@arm.com
13812810Sandreas.sandberg@arm.com      protected:
13912810Sandreas.sandberg@arm.com
14012810Sandreas.sandberg@arm.com        void recvReqRetry() { trafficGen.recvReqRetry(); }
14112810Sandreas.sandberg@arm.com
14214054Stiago.muck@arm.com        bool recvTimingResp(PacketPtr pkt)
14314054Stiago.muck@arm.com        { return trafficGen.recvTimingResp(pkt); }
14412810Sandreas.sandberg@arm.com
14512810Sandreas.sandberg@arm.com        void recvTimingSnoopReq(PacketPtr pkt) { }
14612810Sandreas.sandberg@arm.com
14712810Sandreas.sandberg@arm.com        void recvFunctionalSnoop(PacketPtr pkt) { }
14812810Sandreas.sandberg@arm.com
14912810Sandreas.sandberg@arm.com        Tick recvAtomicSnoop(PacketPtr pkt) { return 0; }
15012810Sandreas.sandberg@arm.com
15112810Sandreas.sandberg@arm.com      private:
15212810Sandreas.sandberg@arm.com
15312810Sandreas.sandberg@arm.com        BaseTrafficGen& trafficGen;
15412810Sandreas.sandberg@arm.com
15512810Sandreas.sandberg@arm.com    };
15612810Sandreas.sandberg@arm.com
15712810Sandreas.sandberg@arm.com    /**
15812810Sandreas.sandberg@arm.com     * Schedules event for next update and generates a new packet or
15912810Sandreas.sandberg@arm.com     * requests a new generatoir depending on the current time.
16012810Sandreas.sandberg@arm.com     */
16112810Sandreas.sandberg@arm.com    void update();
16212810Sandreas.sandberg@arm.com
16312810Sandreas.sandberg@arm.com    /** The instance of master port used by the traffic generator. */
16412810Sandreas.sandberg@arm.com    TrafficGenPort port;
16512810Sandreas.sandberg@arm.com
16612810Sandreas.sandberg@arm.com    /** Packet waiting to be sent. */
16712810Sandreas.sandberg@arm.com    PacketPtr retryPkt;
16812810Sandreas.sandberg@arm.com
16912810Sandreas.sandberg@arm.com    /** Tick when the stalled packet was meant to be sent. */
17012810Sandreas.sandberg@arm.com    Tick retryPktTick;
17112810Sandreas.sandberg@arm.com
17214054Stiago.muck@arm.com    /** Set when we blocked waiting for outstanding reqs */
17314054Stiago.muck@arm.com    bool blockedWaitingResp;
17414054Stiago.muck@arm.com
17514054Stiago.muck@arm.com    /**
17614054Stiago.muck@arm.com     * Puts this packet in the waitingResp list and returns true if
17714054Stiago.muck@arm.com     * we are above the maximum number of oustanding requests.
17814054Stiago.muck@arm.com     */
17914054Stiago.muck@arm.com    bool allocateWaitingRespSlot(PacketPtr pkt)
18014054Stiago.muck@arm.com    {
18114054Stiago.muck@arm.com        assert(waitingResp.find(pkt->req) == waitingResp.end());
18214054Stiago.muck@arm.com        assert(pkt->needsResponse());
18314054Stiago.muck@arm.com
18414054Stiago.muck@arm.com        waitingResp[pkt->req] = curTick();
18514054Stiago.muck@arm.com
18614054Stiago.muck@arm.com        return (maxOutstandingReqs > 0) &&
18714054Stiago.muck@arm.com               (waitingResp.size() > maxOutstandingReqs);
18814054Stiago.muck@arm.com    }
18914054Stiago.muck@arm.com
19012810Sandreas.sandberg@arm.com    /** Event for scheduling updates */
19112810Sandreas.sandberg@arm.com    EventFunctionWrapper updateEvent;
19212810Sandreas.sandberg@arm.com
19314207Sandreas.sandberg@arm.com  protected: // Stats
19414054Stiago.muck@arm.com    /** Reqs waiting for response **/
19514054Stiago.muck@arm.com    std::unordered_map<RequestPtr,Tick> waitingResp;
19614054Stiago.muck@arm.com
19714207Sandreas.sandberg@arm.com    struct StatGroup : public Stats::Group {
19814207Sandreas.sandberg@arm.com        StatGroup(Stats::Group *parent);
19914055Stiago.muck@arm.com
20014207Sandreas.sandberg@arm.com        /** Count the number of dropped requests. */
20114207Sandreas.sandberg@arm.com        Stats::Scalar numSuppressed;
20214055Stiago.muck@arm.com
20314207Sandreas.sandberg@arm.com        /** Count the number of generated packets. */
20414207Sandreas.sandberg@arm.com        Stats::Scalar numPackets;
20514055Stiago.muck@arm.com
20614207Sandreas.sandberg@arm.com        /** Count the number of retries. */
20714207Sandreas.sandberg@arm.com        Stats::Scalar numRetries;
20814055Stiago.muck@arm.com
20914207Sandreas.sandberg@arm.com        /** Count the time incurred from back-pressure. */
21014207Sandreas.sandberg@arm.com        Stats::Scalar retryTicks;
21114055Stiago.muck@arm.com
21214207Sandreas.sandberg@arm.com        /** Count the number of bytes read. */
21314207Sandreas.sandberg@arm.com        Stats::Scalar bytesRead;
21414055Stiago.muck@arm.com
21514207Sandreas.sandberg@arm.com        /** Count the number of bytes written. */
21614207Sandreas.sandberg@arm.com        Stats::Scalar bytesWritten;
21714055Stiago.muck@arm.com
21814207Sandreas.sandberg@arm.com        /** Total num of ticks read reqs took to complete  */
21914207Sandreas.sandberg@arm.com        Stats::Scalar totalReadLatency;
22014055Stiago.muck@arm.com
22114207Sandreas.sandberg@arm.com        /** Total num of ticks write reqs took to complete  */
22214207Sandreas.sandberg@arm.com        Stats::Scalar totalWriteLatency;
22314055Stiago.muck@arm.com
22414207Sandreas.sandberg@arm.com        /** Count the number reads. */
22514207Sandreas.sandberg@arm.com        Stats::Scalar totalReads;
22614207Sandreas.sandberg@arm.com
22714207Sandreas.sandberg@arm.com        /** Count the number writes. */
22814207Sandreas.sandberg@arm.com        Stats::Scalar totalWrites;
22914207Sandreas.sandberg@arm.com
23014207Sandreas.sandberg@arm.com        /** Avg num of ticks each read req took to complete  */
23114207Sandreas.sandberg@arm.com        Stats::Formula avgReadLatency;
23214207Sandreas.sandberg@arm.com
23314207Sandreas.sandberg@arm.com        /** Avg num of ticks each write reqs took to complete  */
23414207Sandreas.sandberg@arm.com        Stats::Formula avgWriteLatency;
23514207Sandreas.sandberg@arm.com
23614207Sandreas.sandberg@arm.com        /** Read bandwidth in bytes/s  */
23714207Sandreas.sandberg@arm.com        Stats::Formula readBW;
23814207Sandreas.sandberg@arm.com
23914207Sandreas.sandberg@arm.com        /** Write bandwidth in bytes/s  */
24014207Sandreas.sandberg@arm.com        Stats::Formula writeBW;
24114207Sandreas.sandberg@arm.com    } stats;
24214055Stiago.muck@arm.com
24312810Sandreas.sandberg@arm.com  public:
24412810Sandreas.sandberg@arm.com    BaseTrafficGen(const BaseTrafficGenParams* p);
24512810Sandreas.sandberg@arm.com
24612919Sgiacomo.travaglini@arm.com    ~BaseTrafficGen();
24712810Sandreas.sandberg@arm.com
24813784Sgabeblack@google.com    Port &getPort(const std::string &if_name,
24913784Sgabeblack@google.com                  PortID idx=InvalidPortID) override;
25012810Sandreas.sandberg@arm.com
25112810Sandreas.sandberg@arm.com    void init() override;
25212810Sandreas.sandberg@arm.com
25312810Sandreas.sandberg@arm.com    DrainState drain() override;
25412810Sandreas.sandberg@arm.com
25512810Sandreas.sandberg@arm.com    void serialize(CheckpointOut &cp) const override;
25612810Sandreas.sandberg@arm.com    void unserialize(CheckpointIn &cp) override;
25712810Sandreas.sandberg@arm.com
25812811Sandreas.sandberg@arm.com  public: // Generator factory methods
25912811Sandreas.sandberg@arm.com    std::shared_ptr<BaseGen> createIdle(Tick duration);
26012811Sandreas.sandberg@arm.com    std::shared_ptr<BaseGen> createExit(Tick duration);
26112811Sandreas.sandberg@arm.com
26212811Sandreas.sandberg@arm.com    std::shared_ptr<BaseGen> createLinear(
26312811Sandreas.sandberg@arm.com        Tick duration,
26412811Sandreas.sandberg@arm.com        Addr start_addr, Addr end_addr, Addr blocksize,
26512811Sandreas.sandberg@arm.com        Tick min_period, Tick max_period,
26612811Sandreas.sandberg@arm.com        uint8_t read_percent, Addr data_limit);
26712811Sandreas.sandberg@arm.com
26812811Sandreas.sandberg@arm.com    std::shared_ptr<BaseGen> createRandom(
26912811Sandreas.sandberg@arm.com        Tick duration,
27012811Sandreas.sandberg@arm.com        Addr start_addr, Addr end_addr, Addr blocksize,
27112811Sandreas.sandberg@arm.com        Tick min_period, Tick max_period,
27212811Sandreas.sandberg@arm.com        uint8_t read_percent, Addr data_limit);
27312811Sandreas.sandberg@arm.com
27412811Sandreas.sandberg@arm.com    std::shared_ptr<BaseGen> createDram(
27512811Sandreas.sandberg@arm.com        Tick duration,
27612811Sandreas.sandberg@arm.com        Addr start_addr, Addr end_addr, Addr blocksize,
27712811Sandreas.sandberg@arm.com        Tick min_period, Tick max_period,
27812811Sandreas.sandberg@arm.com        uint8_t read_percent, Addr data_limit,
27912811Sandreas.sandberg@arm.com        unsigned int num_seq_pkts, unsigned int page_size,
28012811Sandreas.sandberg@arm.com        unsigned int nbr_of_banks_DRAM, unsigned int nbr_of_banks_util,
28112811Sandreas.sandberg@arm.com        unsigned int addr_mapping,
28212811Sandreas.sandberg@arm.com        unsigned int nbr_of_ranks);
28312811Sandreas.sandberg@arm.com
28412811Sandreas.sandberg@arm.com    std::shared_ptr<BaseGen> createDramRot(
28512811Sandreas.sandberg@arm.com        Tick duration,
28612811Sandreas.sandberg@arm.com        Addr start_addr, Addr end_addr, Addr blocksize,
28712811Sandreas.sandberg@arm.com        Tick min_period, Tick max_period,
28812811Sandreas.sandberg@arm.com        uint8_t read_percent, Addr data_limit,
28912811Sandreas.sandberg@arm.com        unsigned int num_seq_pkts, unsigned int page_size,
29012811Sandreas.sandberg@arm.com        unsigned int nbr_of_banks_DRAM, unsigned int nbr_of_banks_util,
29112811Sandreas.sandberg@arm.com        unsigned int addr_mapping,
29212811Sandreas.sandberg@arm.com        unsigned int nbr_of_ranks,
29312811Sandreas.sandberg@arm.com        unsigned int max_seq_count_per_rank);
29412811Sandreas.sandberg@arm.com
29512811Sandreas.sandberg@arm.com    std::shared_ptr<BaseGen> createTrace(
29612811Sandreas.sandberg@arm.com        Tick duration,
29712811Sandreas.sandberg@arm.com        const std::string& trace_file, Addr addr_offset);
29812811Sandreas.sandberg@arm.com
29912810Sandreas.sandberg@arm.com  protected:
30012810Sandreas.sandberg@arm.com    void start();
30112810Sandreas.sandberg@arm.com
30212810Sandreas.sandberg@arm.com    virtual std::shared_ptr<BaseGen> nextGenerator() = 0;
30312810Sandreas.sandberg@arm.com
30412810Sandreas.sandberg@arm.com    /**
30512810Sandreas.sandberg@arm.com     * MasterID used in generated requests.
30612810Sandreas.sandberg@arm.com     */
30712810Sandreas.sandberg@arm.com    const MasterID masterID;
30812810Sandreas.sandberg@arm.com
30912810Sandreas.sandberg@arm.com    /** Currently active generator */
31012810Sandreas.sandberg@arm.com    std::shared_ptr<BaseGen> activeGenerator;
31112919Sgiacomo.travaglini@arm.com
31212919Sgiacomo.travaglini@arm.com    /** Stream/SubStreamID Generator */
31312919Sgiacomo.travaglini@arm.com    std::unique_ptr<StreamGen> streamGenerator;
31412810Sandreas.sandberg@arm.com};
31512810Sandreas.sandberg@arm.com
31612810Sandreas.sandberg@arm.com#endif //__CPU_TRAFFIC_GEN_BASE_HH__
317