Mahyar Samani has submitted this change. (
https://gem5-review.googlesource.com/c/public/gem5/+/47439 )
Change subject: cpu: Adding GUPSGen ClockedObject.
......................................................................
cpu: Adding GUPSGen ClockedObject.
This patch adds the code base to implement GUPSGen which is a
ClockedObject that creates read/write requests to the memory
to update elements in an array. The choosing of elements in
the array follow a random distribution. Each element is read
from and return as GUPSGen implements a key-value store program.
Specifications are found in HPCC website from RandomAccess
benchmark. link below.
https://icl.cs.utk.edu/projectsfiles/hpcc/RandomAccess/
Change-Id: I5c07f230bee317fff2cceec04d15d0218e8ede9a
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/47439
Reviewed-by: Jason Lowe-Power <[email protected]>
Reviewed-by: Bobby R. Bruce <[email protected]>
Maintainer: Jason Lowe-Power <[email protected]>
Tested-by: kokoro <[email protected]>
---
A src/cpu/testers/traffic_gen/GUPSGen.py
A src/cpu/testers/traffic_gen/gups_gen.cc
A src/cpu/testers/traffic_gen/gups_gen.hh
M src/cpu/testers/traffic_gen/SConscript
4 files changed, 795 insertions(+), 0 deletions(-)
Approvals:
Jason Lowe-Power: Looks good to me, but someone else must approve; Looks
good to me, approved
Bobby R. Bruce: Looks good to me, approved
kokoro: Regressions pass
diff --git a/src/cpu/testers/traffic_gen/GUPSGen.py
b/src/cpu/testers/traffic_gen/GUPSGen.py
new file mode 100644
index 0000000..dafc86d
--- /dev/null
+++ b/src/cpu/testers/traffic_gen/GUPSGen.py
@@ -0,0 +1,60 @@
+# 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.
+#
+
+from m5.params import *
+from m5.proxy import *
+from m5.objects.ClockedObject import ClockedObject
+
+class GUPSGen(ClockedObject):
+ """
+ This ClockedObject implements the RandomAccess benchmark specified by
HPCC
+ benchmarks in https://icl.utk.edu/projectsfiles/hpcc/RandomAccess.
+ """
+ type = 'GUPSGen'
+ cxx_header = "cpu/testers/traffic_gen/gups_gen.hh"
+ cxx_class = "gem5::GUPSGen"
+
+ system = Param.System(Parent.any, 'System this generator is a part of')
+
+ port = RequestPort('Port that should be connected to other components')
+
+ start_addr = Param.Addr(0, 'Start address for allocating update table,'
+ ' should be a multiple of block_size')
+
+ mem_size = Param.MemorySize('Size for allocating update table, based
on'
+ ' randomAccess benchmark specification, this'
+ ' should be equal to half of total system
memory'
+ ' ,also should be a power of 2')
+
+ update_limit = Param.Int(0, 'The number of updates to issue before the'
+ ' simulation is over')
+
+ request_queue_size = Param.Int(1024, 'Maximum number of parallel'
+ ' outstanding requests')
+
+ init_memory = Param.Bool(False, 'Whether or not to initialize the
memory,'
+ ' it does not effect the performance')
diff --git a/src/cpu/testers/traffic_gen/SConscript
b/src/cpu/testers/traffic_gen/SConscript
index 640d81a..a2670e7 100644
--- a/src/cpu/testers/traffic_gen/SConscript
+++ b/src/cpu/testers/traffic_gen/SConscript
@@ -43,6 +43,7 @@
Source('dram_gen.cc')
Source('dram_rot_gen.cc')
Source('exit_gen.cc')
+Source('gups_gen.cc')
Source('hybrid_gen.cc')
Source('idle_gen.cc')
Source('linear_gen.cc')
@@ -54,6 +55,9 @@
DebugFlag('TrafficGen')
SimObject('BaseTrafficGen.py')
+DebugFlag('GUPSGen')
+SimObject('GUPSGen.py')
+
if env['USE_PYTHON']:
Source('pygen.cc', add_tags='python')
SimObject('PyTrafficGen.py')
diff --git a/src/cpu/testers/traffic_gen/gups_gen.cc
b/src/cpu/testers/traffic_gen/gups_gen.cc
new file mode 100644
index 0000000..837b234
--- /dev/null
+++ b/src/cpu/testers/traffic_gen/gups_gen.cc
@@ -0,0 +1,373 @@
+/*
+ * 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.
+ */
+
+#include "cpu/testers/traffic_gen/gups_gen.hh"
+
+#include <cstring>
+#include <string>
+
+#include "base/random.hh"
+#include "debug/GUPSGen.hh"
+#include "sim/sim_exit.hh"
+
+namespace gem5
+{
+
+GUPSGen::GUPSGen(const GUPSGenParams& params):
+ ClockedObject(params),
+ nextCreateEvent([this]{ createNextReq(); }, name()),
+ nextSendEvent([this]{ sendNextReq(); }, name()),
+ system(params.system),
+ requestorId(system->getRequestorId(this)),
+ port(name() + ".port", this),
+ startAddr(params.start_addr),
+ memSize(params.mem_size),
+ updateLimit(params.update_limit),
+ elementSize(sizeof(uint64_t)), // every element in the table is a
uint64_t
+ reqQueueSize(params.request_queue_size),
+ initMemory(params.init_memory),
+ stats(this)
+{}
+
+Port&
+GUPSGen::getPort(const std::string &if_name, PortID idx)
+{
+ if (if_name != "port") {
+ return ClockedObject::getPort(if_name, idx);
+ } else {
+ return port;
+ }
+}
+
+void
+GUPSGen::init()
+{
+ doneReading = false;
+ onTheFlyRequests = 0;
+ readRequests = 0;
+
+ tableSize = memSize / elementSize;
+ numUpdates = 4 * tableSize;
+}
+
+void
+GUPSGen::startup()
+{
+ int block_size = 64; // Write the initial values in 64 byte blocks.
+ uint64_t stride_size = block_size / elementSize;
+ if (initMemory) {
+ for (uint64_t start_index = 0; start_index < tableSize;
+ start_index += stride_size) {
+ uint8_t write_data[block_size];
+ for (uint64_t offset = 0; offset < stride_size; offset++) {
+ uint64_t value = start_index + offset;
+ std::memcpy(write_data + offset * elementSize,
+ &value, elementSize);
+ }
+ Addr addr = indexToAddr(start_index);
+ PacketPtr pkt = getWritePacket(addr, block_size, write_data);
+ port.sendFunctionalPacket(pkt);
+ delete pkt;
+ }
+ }
+ schedule(nextCreateEvent, nextCycle());
+}
+
+Addr
+GUPSGen::indexToAddr (uint64_t index)
+{
+ Addr ret = index * elementSize + startAddr;
+ return ret;
+}
+
+PacketPtr
+GUPSGen::getReadPacket(Addr addr, unsigned int size)
+{
+ RequestPtr req = std::make_shared<Request>(addr, size, 0, requestorId);
+ // Dummy PC to have PC-based prefetchers latch on; get entropy into
higher
+ // bits
+ req->setPC(((Addr)requestorId) << 2);
+
+ // Embed it in a packet
+ PacketPtr pkt = new Packet(req, MemCmd::ReadReq);
+ pkt->allocate();
+
+ return pkt;
+}
+
+PacketPtr
+GUPSGen::getWritePacket(Addr addr, unsigned int size, uint8_t *data)
+{
+ RequestPtr req = std::make_shared<Request>(addr, size, 0,
+ requestorId);
+ // Dummy PC to have PC-based prefetchers latch on; get entropy into
higher
+ // bits
+ req->setPC(((Addr)requestorId) << 2);
+
+ PacketPtr pkt = new Packet(req, MemCmd::WriteReq);
+ pkt->allocate();
+ pkt->setData(data);
+
+ return pkt;
+}
+
+void
+GUPSGen::handleResponse(PacketPtr pkt)
+{
+ onTheFlyRequests--;
+ DPRINTF(GUPSGen, "%s: onTheFlyRequests: %d.\n",
+ __func__, onTheFlyRequests);
+ if (pkt->isWrite()) {
+ DPRINTF(GUPSGen, "%s: received a write resp. pkt->addr_range: %s,"
+ " pkt->data: %d\n", __func__,
+ pkt->getAddrRange().to_string(),
+ *pkt->getPtr<uint64_t>());
+ stats.totalUpdates++;
+ stats.totalWrites++;
+ stats.totalBytesWritten += elementSize;
+ stats.totalWriteLat += curTick() - exitTimes[pkt->req];
+
+ exitTimes.erase(pkt->req);
+ delete pkt;
+ } else {
+ DPRINTF(GUPSGen, "%s: received a read resp. pkt->addr_range: %s\n",
+ __func__, pkt->getAddrRange().to_string());
+
+ stats.totalReads++;
+ stats.totalBytesRead += elementSize;
+ stats.totalReadLat += curTick() - exitTimes[pkt->req];
+
+ exitTimes.erase(pkt->req);
+
+ responsePool.push(pkt);
+ }
+ if (doneReading && requestPool.empty() && onTheFlyRequests == 0) {
+ exitSimLoop(name() + " is finished updating the memory.\n");
+ return;
+ }
+
+ if ((requestPool.size() < reqQueueSize) &&
+ (!doneReading || !responsePool.empty()) &&
+ !nextCreateEvent.scheduled())
+ {
+ schedule(nextCreateEvent, nextCycle());
+ }
+}
+
+void
+GUPSGen::wakeUp()
+{
+ if (!nextSendEvent.scheduled() && !requestPool.empty()) {
+ schedule(nextSendEvent, nextCycle());
+ }
+}
+
+void
+GUPSGen::createNextReq()
+{
+ // Prioritize pending writes over reads
+ // Write as soon as the data is read
+ if (!responsePool.empty()) {
+ PacketPtr pkt = responsePool.front();
+ responsePool.pop();
+
+ uint64_t *updated_value = pkt->getPtr<uint64_t>();
+ DPRINTF(GUPSGen, "%s: Read value %lu from address %s", __func__,
+ *updated_value,
pkt->getAddrRange().to_string());
+ *updated_value ^= updateTable[pkt->req];
+ updateTable.erase(pkt->req);
+ Addr addr = pkt->getAddr();
+ PacketPtr new_pkt = getWritePacket(addr,
+ elementSize, (uint8_t*) updated_value);
+ delete pkt;
+ requestPool.push(new_pkt);
+ } else if (!doneReading) {
+ // If no writes then read
+ // Check to make sure we're not reading more than we should.
+ assert (readRequests < numUpdates);
+
+ uint64_t value = readRequests;
+ uint64_t index = random_mt.random((int64_t) 0, tableSize);
+ Addr addr = indexToAddr(index);
+ PacketPtr pkt = getReadPacket(addr, elementSize);
+ updateTable[pkt->req] = value;
+ requestPool.push(pkt);
+ readRequests++;
+
+ if (readRequests >= numUpdates) {
+ DPRINTF(GUPSGen, "%s: Done creating reads.\n", __func__);
+ doneReading = true;
+ }
+ else if (readRequests == updateLimit && updateLimit != 0) {
+ DPRINTF(GUPSGen, "%s: Update limit reached.\n", __func__);
+ doneReading = true;
+ }
+ }
+
+ if (!nextCreateEvent.scheduled() &&
+ (requestPool.size() < reqQueueSize) &&
+ (!doneReading || !responsePool.empty()))
+ {
+ schedule(nextCreateEvent, nextCycle());
+ }
+
+ if (!nextSendEvent.scheduled() && !requestPool.empty()) {
+ schedule(nextSendEvent, nextCycle());
+ }
+}
+
+void
+GUPSGen::sendNextReq()
+{
+ if (!port.blocked()) {
+ PacketPtr pkt = requestPool.front();
+
+ exitTimes[pkt->req] = curTick();
+ if (pkt->isWrite()) {
+ DPRINTF(GUPSGen, "%s: Sent write pkt, pkt->addr_range: "
+ "%s, pkt->data: %lu.\n", __func__,
+ pkt->getAddrRange().to_string(),
+ *pkt->getPtr<uint64_t>());
+ } else {
+ DPRINTF(GUPSGen, "%s: Sent read pkt, pkt->addr_range: %s.\n",
+ __func__, pkt->getAddrRange().to_string());
+ }
+ port.sendTimingPacket(pkt);
+ onTheFlyRequests++;
+ DPRINTF(GUPSGen, "%s: onTheFlyRequests: %d.\n",
+ __func__, onTheFlyRequests);
+ requestPool.pop();
+ }
+
+ if (!nextCreateEvent.scheduled() &&
+ (requestPool.size() < reqQueueSize) &&
+ (!doneReading || !responsePool.empty()))
+ {
+ schedule(nextCreateEvent, nextCycle());
+ }
+
+ if (!nextSendEvent.scheduled()) {
+ if (!requestPool.empty()) {
+ schedule(nextSendEvent, nextCycle());
+ }
+ }
+}
+
+
+void
+GUPSGen::GenPort::sendTimingPacket(PacketPtr pkt)
+{
+ panic_if(_blocked, "Should never try to send if blocked MemSide!");
+
+ // If we can't send the packet across the port, store it for later.
+ if (!sendTimingReq(pkt)) {
+ DPRINTF(GUPSGen, "GenPort::%s: Packet blocked\n", __func__);
+ blockedPacket = pkt;
+ _blocked = true;
+ } else {
+ DPRINTF(GUPSGen, "GenPort::%s: Packet sent\n", __func__);
+ }
+}
+
+void
+GUPSGen::GenPort::sendFunctionalPacket(PacketPtr pkt)
+{
+ sendFunctional(pkt);
+}
+
+void
+GUPSGen::GenPort::recvReqRetry()
+{
+ // We should have a blocked packet if this function is called.
+ DPRINTF(GUPSGen, "GenPort::%s: Received a retry.\n", __func__);
+
+ assert(_blocked && (blockedPacket != nullptr));
+ // Try to resend it. It's possible that it fails again.
+ _blocked = false;
+ sendTimingPacket(blockedPacket);
+ if (!_blocked){
+ blockedPacket = nullptr;
+ }
+
+ owner->wakeUp();
+}
+
+bool
+GUPSGen::GenPort::recvTimingResp(PacketPtr pkt)
+{
+ owner->handleResponse(pkt);
+ return true;
+}
+
+GUPSGen::GUPSGenStat::GUPSGenStat(GUPSGen* parent):
+ Stats::Group(parent),
+ ADD_STAT(totalUpdates, UNIT_COUNT,
+ "Total number of updates the generator made in the memory"),
+ ADD_STAT(GUPS, UNIT_RATE(Stats::Units::Count, Stats::Units::Second),
+ "Rate of billion updates per second"),
+ ADD_STAT(totalReads, UNIT_COUNT,
+ "Total number of read requests"),
+ ADD_STAT(totalBytesRead, UNIT_BYTE,
+ "Total number of bytes read"),
+ ADD_STAT(avgReadBW, UNIT_RATE(Stats::Units::Byte,
Stats::Units::Second),
+ "Average read bandwidth received from memory"),
+ ADD_STAT(totalReadLat, UNIT_TICK,
+ "Total latency of read requests."),
+ ADD_STAT(avgReadLat, UNIT_TICK,
+ "Average latency for read requests"),
+ ADD_STAT(totalWrites, UNIT_COUNT,
+ "Total number of write requests"),
+ ADD_STAT(totalBytesWritten, UNIT_BYTE,
+ "Total number of bytes written"),
+ ADD_STAT(avgWriteBW, UNIT_RATE(Stats::Units::Byte,
Stats::Units::Second),
+ "Average write bandwidth received from memory"),
+ ADD_STAT(totalWriteLat, UNIT_TICK,
+ "Total latency of write requests."),
+ ADD_STAT(avgWriteLat, UNIT_TICK,
+ "Average latency for write requests")
+{}
+
+void
+GUPSGen::GUPSGenStat::regStats()
+{
+ GUPS.precision(8);
+ avgReadBW.precision(2);
+ avgReadLat.precision(2);
+ avgWriteBW.precision(2);
+ avgWriteLat.precision(2);
+
+ GUPS = (totalUpdates / 1e9) / simSeconds;
+
+ avgReadBW = totalBytesRead / simSeconds;
+ avgReadLat = (totalReadLat) / totalReads;
+
+ avgWriteBW = totalBytesWritten / simSeconds;
+ avgWriteLat = (totalWriteLat) / totalWrites;
+}
+
+}
diff --git a/src/cpu/testers/traffic_gen/gups_gen.hh
b/src/cpu/testers/traffic_gen/gups_gen.hh
new file mode 100644
index 0000000..04c0bb0
--- /dev/null
+++ b/src/cpu/testers/traffic_gen/gups_gen.hh
@@ -0,0 +1,335 @@
+/*
+ * 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 uint32_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 Stats::Group
+ {
+ GUPSGenStat(GUPSGen* parent);
+ void regStats() override;
+
+ Stats::Scalar totalUpdates;
+ Stats::Formula GUPS;
+
+ Stats::Scalar totalReads;
+ Stats::Scalar totalBytesRead;
+ Stats::Formula avgReadBW;
+ Stats::Scalar totalReadLat;
+ Stats::Formula avgReadLat;
+
+ Stats::Scalar totalWrites;
+ Stats::Scalar totalBytesWritten;
+ Stats::Formula avgWriteBW;
+ Stats::Scalar totalWriteLat;
+ Stats::Formula avgWriteLat;
+ } stats;
+
+ public:
+
+ GUPSGen(const GUPSGenParams ¶ms);
+
+ Port &getPort(const std::string &if_name,
+ PortID idx=InvalidPortID) override;
+};
+
+}
+
+#endif // __CPU_TESTERS_TRAFFIC_GEN_GUPS_GEN_HH__
--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/47439
To unsubscribe, or for help writing mail filters, visit
https://gem5-review.googlesource.com/settings
Gerrit-Project: public/gem5
Gerrit-Branch: develop
Gerrit-Change-Id: I5c07f230bee317fff2cceec04d15d0218e8ede9a
Gerrit-Change-Number: 47439
Gerrit-PatchSet: 3
Gerrit-Owner: Mahyar Samani <[email protected]>
Gerrit-Reviewer: Bobby R. Bruce <[email protected]>
Gerrit-Reviewer: Gabe Black <[email protected]>
Gerrit-Reviewer: Jason Lowe-Power <[email protected]>
Gerrit-Reviewer: Jason Lowe-Power <[email protected]>
Gerrit-Reviewer: Mahyar Samani <[email protected]>
Gerrit-Reviewer: kokoro <[email protected]>
Gerrit-MessageType: merged
_______________________________________________
gem5-dev mailing list -- [email protected]
To unsubscribe send an email to [email protected]
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s