base.hh revision 14054
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
19312918SMichiel.VanTol@arm.com    /** Count the number of dropped requests. */
19412918SMichiel.VanTol@arm.com    Stats::Scalar numSuppressed;
19512810Sandreas.sandberg@arm.com
19612810Sandreas.sandberg@arm.com  private: // Stats
19712810Sandreas.sandberg@arm.com    /** Count the number of generated packets. */
19812810Sandreas.sandberg@arm.com    Stats::Scalar numPackets;
19912810Sandreas.sandberg@arm.com
20012810Sandreas.sandberg@arm.com    /** Count the number of retries. */
20112810Sandreas.sandberg@arm.com    Stats::Scalar numRetries;
20212810Sandreas.sandberg@arm.com
20312810Sandreas.sandberg@arm.com    /** Count the time incurred from back-pressure. */
20412810Sandreas.sandberg@arm.com    Stats::Scalar retryTicks;
20512810Sandreas.sandberg@arm.com
20614054Stiago.muck@arm.com    /** Reqs waiting for response **/
20714054Stiago.muck@arm.com    std::unordered_map<RequestPtr,Tick> waitingResp;
20814054Stiago.muck@arm.com
20912810Sandreas.sandberg@arm.com  public:
21012810Sandreas.sandberg@arm.com    BaseTrafficGen(const BaseTrafficGenParams* p);
21112810Sandreas.sandberg@arm.com
21212919Sgiacomo.travaglini@arm.com    ~BaseTrafficGen();
21312810Sandreas.sandberg@arm.com
21413784Sgabeblack@google.com    Port &getPort(const std::string &if_name,
21513784Sgabeblack@google.com                  PortID idx=InvalidPortID) override;
21612810Sandreas.sandberg@arm.com
21712810Sandreas.sandberg@arm.com    void init() override;
21812810Sandreas.sandberg@arm.com
21912810Sandreas.sandberg@arm.com    DrainState drain() override;
22012810Sandreas.sandberg@arm.com
22112810Sandreas.sandberg@arm.com    void serialize(CheckpointOut &cp) const override;
22212810Sandreas.sandberg@arm.com    void unserialize(CheckpointIn &cp) override;
22312810Sandreas.sandberg@arm.com
22412810Sandreas.sandberg@arm.com    /** Register statistics */
22512810Sandreas.sandberg@arm.com    void regStats() override;
22612810Sandreas.sandberg@arm.com
22712811Sandreas.sandberg@arm.com  public: // Generator factory methods
22812811Sandreas.sandberg@arm.com    std::shared_ptr<BaseGen> createIdle(Tick duration);
22912811Sandreas.sandberg@arm.com    std::shared_ptr<BaseGen> createExit(Tick duration);
23012811Sandreas.sandberg@arm.com
23112811Sandreas.sandberg@arm.com    std::shared_ptr<BaseGen> createLinear(
23212811Sandreas.sandberg@arm.com        Tick duration,
23312811Sandreas.sandberg@arm.com        Addr start_addr, Addr end_addr, Addr blocksize,
23412811Sandreas.sandberg@arm.com        Tick min_period, Tick max_period,
23512811Sandreas.sandberg@arm.com        uint8_t read_percent, Addr data_limit);
23612811Sandreas.sandberg@arm.com
23712811Sandreas.sandberg@arm.com    std::shared_ptr<BaseGen> createRandom(
23812811Sandreas.sandberg@arm.com        Tick duration,
23912811Sandreas.sandberg@arm.com        Addr start_addr, Addr end_addr, Addr blocksize,
24012811Sandreas.sandberg@arm.com        Tick min_period, Tick max_period,
24112811Sandreas.sandberg@arm.com        uint8_t read_percent, Addr data_limit);
24212811Sandreas.sandberg@arm.com
24312811Sandreas.sandberg@arm.com    std::shared_ptr<BaseGen> createDram(
24412811Sandreas.sandberg@arm.com        Tick duration,
24512811Sandreas.sandberg@arm.com        Addr start_addr, Addr end_addr, Addr blocksize,
24612811Sandreas.sandberg@arm.com        Tick min_period, Tick max_period,
24712811Sandreas.sandberg@arm.com        uint8_t read_percent, Addr data_limit,
24812811Sandreas.sandberg@arm.com        unsigned int num_seq_pkts, unsigned int page_size,
24912811Sandreas.sandberg@arm.com        unsigned int nbr_of_banks_DRAM, unsigned int nbr_of_banks_util,
25012811Sandreas.sandberg@arm.com        unsigned int addr_mapping,
25112811Sandreas.sandberg@arm.com        unsigned int nbr_of_ranks);
25212811Sandreas.sandberg@arm.com
25312811Sandreas.sandberg@arm.com    std::shared_ptr<BaseGen> createDramRot(
25412811Sandreas.sandberg@arm.com        Tick duration,
25512811Sandreas.sandberg@arm.com        Addr start_addr, Addr end_addr, Addr blocksize,
25612811Sandreas.sandberg@arm.com        Tick min_period, Tick max_period,
25712811Sandreas.sandberg@arm.com        uint8_t read_percent, Addr data_limit,
25812811Sandreas.sandberg@arm.com        unsigned int num_seq_pkts, unsigned int page_size,
25912811Sandreas.sandberg@arm.com        unsigned int nbr_of_banks_DRAM, unsigned int nbr_of_banks_util,
26012811Sandreas.sandberg@arm.com        unsigned int addr_mapping,
26112811Sandreas.sandberg@arm.com        unsigned int nbr_of_ranks,
26212811Sandreas.sandberg@arm.com        unsigned int max_seq_count_per_rank);
26312811Sandreas.sandberg@arm.com
26412811Sandreas.sandberg@arm.com    std::shared_ptr<BaseGen> createTrace(
26512811Sandreas.sandberg@arm.com        Tick duration,
26612811Sandreas.sandberg@arm.com        const std::string& trace_file, Addr addr_offset);
26712811Sandreas.sandberg@arm.com
26812810Sandreas.sandberg@arm.com  protected:
26912810Sandreas.sandberg@arm.com    void start();
27012810Sandreas.sandberg@arm.com
27112810Sandreas.sandberg@arm.com    virtual std::shared_ptr<BaseGen> nextGenerator() = 0;
27212810Sandreas.sandberg@arm.com
27312810Sandreas.sandberg@arm.com    /**
27412810Sandreas.sandberg@arm.com     * MasterID used in generated requests.
27512810Sandreas.sandberg@arm.com     */
27612810Sandreas.sandberg@arm.com    const MasterID masterID;
27712810Sandreas.sandberg@arm.com
27812810Sandreas.sandberg@arm.com    /** Currently active generator */
27912810Sandreas.sandberg@arm.com    std::shared_ptr<BaseGen> activeGenerator;
28012919Sgiacomo.travaglini@arm.com
28112919Sgiacomo.travaglini@arm.com    /** Stream/SubStreamID Generator */
28212919Sgiacomo.travaglini@arm.com    std::unique_ptr<StreamGen> streamGenerator;
28312810Sandreas.sandberg@arm.com};
28412810Sandreas.sandberg@arm.com
28512810Sandreas.sandberg@arm.com#endif //__CPU_TRAFFIC_GEN_BASE_HH__
286