blob: f33f7dae1e8613559a6bd1db1e1a03f21e256531 [file] [log] [blame]
/*
* Copyright (c) 2021 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __CPU_TESTERS_TRAFFIC_GEN_GUPS_GEN_HH__
#define __CPU_TESTERS_TRAFFIC_GEN_GUPS_GEN_HH__
/**
* @file gups_gen.hh
* Contatins the description of the class GUPSGen. GUPSGen is a simobject
* that will generate a memory access pattern to that of RandomAccess benchmark
* specified by HPCC benchmarks.
* Find more details: [https://icl.cs.utk.edu/projectsfiles/hpcc/RandomAccess/]
*/
#include <queue>
#include <unordered_map>
#include <vector>
#include "base/statistics.hh"
#include "mem/port.hh"
#include "params/GUPSGen.hh"
#include "sim/clocked_object.hh"
#include "sim/system.hh"
namespace gem5
{
class GUPSGen : public ClockedObject
{
private:
/**
* @brief definition of the GenPort class which is of the type RequestPort.
* It defines the functionalities required for outside communication of
* memory packets from the GUPSGen simobject. It also implements
* functionalities of receiving responses from outside.
*/
class GenPort : public RequestPort
{
private:
/**
* @brief Pointer to the GUPSGen this port belongs to
*/
GUPSGen *owner;
/**
* @brief Boolean value to remember if the port is previously blocked
* and is occupied by a previous request, it should not accept new
* requests if it is blocked, instead, it will be freed by a
* recvReqRetry call from outside.
*/
bool _blocked;
/**
* @brief Pointer to the blocked packet in the port. It is initialized
* as nullptr and will be set to the address of the packet which is
* blocked. It will reset upon recvReqRetry call.
*/
PacketPtr blockedPacket;
public:
GenPort(const std::string& name, GUPSGen *owner) :
RequestPort(name, owner), owner(owner), _blocked(false),
blockedPacket(nullptr)
{}
/**
* @brief Return whether the port is blocked.
*
* @return true if the port is blocked.
* @return false if the port is free.
*/
bool blocked(){
return _blocked;
}
/**
* @brief This function send a timing request to the port's peer
* responsePort
* @param pkt Pointer to the packet for the timing request
*/
void sendTimingPacket(PacketPtr pkt);
/**
* @brief This function send a functional request to the port's peer
* responsePort
* @param pkt Pointer to the packet for the timing request
*/
void sendFunctionalPacket(PacketPtr pkt);
protected:
bool recvTimingResp(PacketPtr pkt) override;
void recvReqRetry() override;
};
virtual void init() override;
virtual void startup() override;
/**
* @brief Convert and index from array to its physical address
* in the memory
* @param index Index of the element in the array
* @return Addr Physical address corresponding to the index.
*/
Addr indexToAddr (uint64_t index);
/**
* @brief Generate a read request to be sent to the outside.
*
* @param addr Physical address to which the request is sent to
* @param size The number of bytes to be read by the request.
* @return Pointer to the generated packet. This packet includes
* the request to the outside.
*/
PacketPtr getReadPacket(Addr addr, unsigned int size);
/**
* @brief Generate a write request to be sent to the outside.
*
* @param addr Physical address to which the request is sent to
* @param size The number of bytes to be written by the request.
* @param data Pointer to the data that should be written.
* @return Pointer to the generated packet. This packet includes
* the request to the outside.
*/
PacketPtr getWritePacket(Addr addr, unsigned int size, uint8_t* data);
/**
* @brief Handles the incoming responses from the outside.
* @param pkt Pointer to the packet that includes the response.
*/
void handleResponse(PacketPtr pkt);
/**
* @brief This function allows the port to wake its owner GUPSGen object
* in case it has stopped working due to back pressure, it will wake up
* as soon as back pressure is resolved.
*/
void wakeUp();
/**
* @brief Create the next request and store in the requestPool.
*/
void createNextReq();
/**
* @brief Corresponding event to the createNextReq function. Scheduled
* whenever a request needs to and can be created.
*/
EventFunctionWrapper nextCreateEvent;
/**
* @brief Send outstanding requests from requestPool to the port.
*/
void sendNextReq();
/**
* @brief Corresponding event to the sendNextReq function. Scheduled
* whenever a request needs to and can be sent.
*/
EventFunctionWrapper nextSendEvent;
/**
* @brief Use an unordered map to store future updates on current reads
* as the updated value depends on the index which is know when a read
* request is created. The respective write will use the value stored to
* update the value.
*/
std::unordered_map<RequestPtr, uint64_t> updateTable;
/**
* @brief Use an unordered map to track the time at which each request
* exits the GUPSGen. This is useful when we need to compute request
* latency.
*/
std::unordered_map<RequestPtr, Tick> exitTimes;
/**
* @brief A queue to store the outstanding requests whether read or write.
* The element at the front of the queue is sent to outside everytime
* nextSendEvent is scheduled.
*/
std::queue<PacketPtr> requestPool;
/**
* @brief A queue to store response packets from reads. each response in
* the response pool will generate a write request. The write request
* updates the value of data in the response packet with its corresponding
* value in the update table.
*/
std::queue<PacketPtr> responsePool;
/**
* @brief The total number of updates (one read and one write) to do for
* running the benchmark to completion.
*/
int64_t numUpdates;
/**
* @brief Number of elements in the allocated array.
*/
int64_t tableSize;
/**
* @brief Pointer to the system object this GUPSGen belongs to, the system
* object is used to acquire a requestorId.
*/
System *const system;
/**
* @brief Used to identify each requestor in a system object. Every GUPSGen
* has its own unique requestorId.
*/
const RequestorID requestorId;
/**
* @brief An instance of GenPort to communicate with the outside.
*/
GenPort port;
/**
* @brief The beginning address for allocating the array.
*/
Addr startAddr;
/**
* @brief Size of the memory in bytes that will be allocated for the array.
*/
const uint64_t memSize;
/**
* @brief The number of updates to do before creating an exit event.
*/
int updateLimit;
/**
* @brief size of each element in the array (in bytes). Every element
* should be uint64_t, therefore this is equal to size_of(uint64_t) = 8
*/
const int elementSize;
/**
* @brief The maximum number of outstanding requests (i.e. maximum length
* of the requestPool), specified as 1024 by the HPCC benchmark.
*/
int reqQueueSize;
/**
* @brief Boolean value to determine whether we need to initialize the
* array with the right values, as we don't care about the values, this
* is defaulted to false in python wrapper for this simobject.
*/
bool initMemory;
/**
* @brief Boolean to indicate whether the generator is done creating read
* requests, which means number of reads equal either updateLimit or
* numUpdates.
*/
bool doneReading;
/**
* @brief The number of requests that have existed this GUPSGen and have
* no corresponding response (they are being serviced some where in the
* system).
*/
int onTheFlyRequests;
/**
* @brief The number of read requests currently created.
*/
int readRequests;
struct GUPSGenStat : public statistics::Group
{
GUPSGenStat(GUPSGen* parent);
void regStats() override;
statistics::Scalar totalUpdates;
statistics::Formula GUPS;
statistics::Scalar totalReads;
statistics::Scalar totalBytesRead;
statistics::Formula avgReadBW;
statistics::Scalar totalReadLat;
statistics::Formula avgReadLat;
statistics::Scalar totalWrites;
statistics::Scalar totalBytesWritten;
statistics::Formula avgWriteBW;
statistics::Scalar totalWriteLat;
statistics::Formula avgWriteLat;
} stats;
public:
GUPSGen(const GUPSGenParams &params);
Port &getPort(const std::string &if_name,
PortID idx=InvalidPortID) override;
};
}
#endif // __CPU_TESTERS_TRAFFIC_GEN_GUPS_GEN_HH__