mem: Add HTM fields to the Packet object
authorTimothy Hayes <timothy.hayes@arm.com>
Mon, 6 Apr 2020 14:37:25 +0000 (15:37 +0100)
committerGiacomo Travaglini <giacomo.travaglini@arm.com>
Tue, 8 Sep 2020 09:13:30 +0000 (09:13 +0000)
JIRA: https://gem5.atlassian.net/browse/GEM5-587

Change-Id: I39268825327f2387ca7e622093fdb42c24a6c82c
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/30318
Reviewed-by: Jason Lowe-Power <power.jg@gmail.com>
Maintainer: Jason Lowe-Power <power.jg@gmail.com>
Tested-by: kokoro <noreply+kokoro@google.com>
src/mem/SConscript
src/mem/packet.cc
src/mem/packet.hh

index 07e197b9ed767380032e57b5be79885a6e74556e..2fe179d37c1354a175b50f7ea4eac5dc124511a4 100644 (file)
@@ -114,6 +114,7 @@ DebugFlag('DRAM')
 DebugFlag('DRAMPower')
 DebugFlag('DRAMState')
 DebugFlag('ExternalPort')
+DebugFlag('HtmMem', 'Hardware Transactional Memory (Mem side)')
 DebugFlag('LLSC')
 DebugFlag('MMU')
 DebugFlag('MemoryAccess')
index b009cc5f695c315e178c162d67e06c2c663916f4..0783e0f2484ed856a62fee264b0460ed99306138 100644 (file)
@@ -230,7 +230,11 @@ MemCmd::commandInfo[] =
       InvalidateResp, "InvalidateReq" },
     /* Invalidation Response */
     { SET2(IsInvalidate, IsResponse),
-      InvalidCmd, "InvalidateResp" }
+      InvalidCmd, "InvalidateResp" },
+      // hardware transactional memory
+    { SET3(IsRead, IsRequest, NeedsResponse), HTMReqResp, "HTMReq" },
+    { SET2(IsRead, IsResponse), InvalidCmd, "HTMReqResp" },
+    { SET2(IsRead, IsRequest), InvalidCmd, "HTMAbort" },
 };
 
 AddrRange
@@ -489,3 +493,62 @@ Packet::PrintReqState::printObj(Printable *obj)
     printLabels();
     obj->print(os, verbosity, curPrefix());
 }
+
+void
+Packet::makeHtmTransactionalReqResponse(
+    const HtmCacheFailure htm_return_code)
+{
+    assert(needsResponse());
+    assert(isRequest());
+
+    cmd = cmd.responseCommand();
+
+    setHtmTransactionFailedInCache(htm_return_code);
+
+    // responses are never express, even if the snoop that
+    // triggered them was
+    flags.clear(EXPRESS_SNOOP);
+}
+
+void
+Packet::setHtmTransactionFailedInCache(
+    const HtmCacheFailure htm_return_code)
+{
+    if (htm_return_code != HtmCacheFailure::NO_FAIL)
+        flags.set(FAILS_TRANSACTION);
+
+    htmReturnReason = htm_return_code;
+}
+
+bool
+Packet::htmTransactionFailedInCache() const
+{
+    return flags.isSet(FAILS_TRANSACTION);
+}
+
+HtmCacheFailure
+Packet::getHtmTransactionFailedInCacheRC() const
+{
+    assert(htmTransactionFailedInCache());
+    return htmReturnReason;
+}
+
+void
+Packet::setHtmTransactional(uint64_t htm_uid)
+{
+    flags.set(FROM_TRANSACTION);
+    htmTransactionUid = htm_uid;
+}
+
+bool
+Packet::isHtmTransactional() const
+{
+    return flags.isSet(FROM_TRANSACTION);
+}
+
+uint64_t
+Packet::getHtmTransactionUid() const
+{
+    assert(flags.isSet(FROM_TRANSACTION));
+    return htmTransactionUid;
+}
index 4af0d0b1c5772c4f42e6aabb29e8bb86237cd131..4ded3b360154455992ce324f3ab3765fff2479ff 100644 (file)
@@ -58,6 +58,7 @@
 #include "base/logging.hh"
 #include "base/printable.hh"
 #include "base/types.hh"
+#include "mem/htm.hh"
 #include "mem/request.hh"
 #include "sim/core.hh"
 
@@ -131,6 +132,10 @@ class MemCmd
         FlushReq,      //request for a cache flush
         InvalidateReq,   // request for address to be invalidated
         InvalidateResp,
+        // hardware transactional memory
+        HTMReq,
+        HTMReqResp,
+        HTMAbort,
         NUM_MEM_CMDS
     };
 
@@ -259,7 +264,7 @@ class Packet : public Printable
 
     enum : FlagsType {
         // Flags to transfer across when copying a packet
-        COPY_FLAGS             = 0x0000003F,
+        COPY_FLAGS             = 0x000000FF,
 
         // Flags that are used to create reponse packets
         RESPONDER_FLAGS        = 0x00000009,
@@ -289,6 +294,17 @@ class Packet : public Printable
         // operations
         SATISFIED              = 0x00000020,
 
+        // hardware transactional memory
+
+        // Indicates that this packet/request has returned from the
+        // cache hierarchy in a failed transaction. The core is
+        // notified like this.
+        FAILS_TRANSACTION      = 0x00000040,
+
+        // Indicates that this packet/request originates in the CPU executing
+        // in transactional mode, i.e. in a transaction.
+        FROM_TRANSACTION       = 0x00000080,
+
         /// Are the 'addr' and 'size' fields valid?
         VALID_ADDR             = 0x00000100,
         VALID_SIZE             = 0x00000200,
@@ -351,6 +367,21 @@ class Packet : public Printable
     // Quality of Service priority value
     uint8_t _qosValue;
 
+    // hardware transactional memory
+
+    /**
+     * Holds the return status of the transaction.
+     * The default case will be NO_FAIL, otherwise this will specify the
+     * reason for the transaction's failure in the memory subsystem.
+     */
+    HtmCacheFailure htmReturnReason;
+
+    /**
+     * A global unique identifier of the transaction.
+     * This is used for correctness/debugging only.
+     */
+    uint64_t htmTransactionUid;
+
   public:
 
     /**
@@ -793,14 +824,33 @@ class Packet : public Printable
     Packet(const RequestPtr &_req, MemCmd _cmd)
         :  cmd(_cmd), id((PacketId)_req.get()), req(_req),
            data(nullptr), addr(0), _isSecure(false), size(0),
-           _qosValue(0), headerDelay(0), snoopDelay(0),
+           _qosValue(0),
+           htmReturnReason(HtmCacheFailure::NO_FAIL),
+           htmTransactionUid(0),
+           headerDelay(0), snoopDelay(0),
            payloadDelay(0), senderState(NULL)
     {
+        flags.clear();
         if (req->hasPaddr()) {
             addr = req->getPaddr();
             flags.set(VALID_ADDR);
             _isSecure = req->isSecure();
         }
+
+        /**
+         * hardware transactional memory
+         *
+         * This is a bit of a hack!
+         * Technically the address of a HTM command is set to zero
+         * but is not valid. The reason that we pretend it's valid is
+         * to void the getAddr() function from failing. It would be
+         * cumbersome to add control flow in many places to check if the
+         * packet represents a HTM command before calling getAddr().
+         */
+        if (req->isHTMCmd()) {
+            flags.set(VALID_ADDR);
+            assert(addr == 0x0);
+        }
         if (req->hasSize()) {
             size = req->getSize();
             flags.set(VALID_SIZE);
@@ -815,9 +865,13 @@ class Packet : public Printable
     Packet(const RequestPtr &_req, MemCmd _cmd, int _blkSize, PacketId _id = 0)
         :  cmd(_cmd), id(_id ? _id : (PacketId)_req.get()), req(_req),
            data(nullptr), addr(0), _isSecure(false),
-           _qosValue(0), headerDelay(0),
+           _qosValue(0),
+           htmReturnReason(HtmCacheFailure::NO_FAIL),
+           htmTransactionUid(0),
+           headerDelay(0),
            snoopDelay(0), payloadDelay(0), senderState(NULL)
     {
+        flags.clear();
         if (req->hasPaddr()) {
             addr = req->getPaddr() & ~(_blkSize - 1);
             flags.set(VALID_ADDR);
@@ -840,6 +894,8 @@ class Packet : public Printable
            addr(pkt->addr), _isSecure(pkt->_isSecure), size(pkt->size),
            bytesValid(pkt->bytesValid),
            _qosValue(pkt->qosValue()),
+           htmReturnReason(HtmCacheFailure::NO_FAIL),
+           htmTransactionUid(0),
            headerDelay(pkt->headerDelay),
            snoopDelay(0),
            payloadDelay(pkt->payloadDelay),
@@ -850,6 +906,15 @@ class Packet : public Printable
 
         flags.set(pkt->flags & (VALID_ADDR|VALID_SIZE));
 
+        if (pkt->isHtmTransactional())
+            setHtmTransactional(pkt->getHtmTransactionUid());
+
+        if (pkt->htmTransactionFailedInCache()) {
+            setHtmTransactionFailedInCache(
+                pkt->getHtmTransactionFailedInCacheRC()
+            );
+        }
+
         // should we allocate space for data, or not, the express
         // snoops do not need to carry any data as they only serve to
         // co-ordinate state changes
@@ -873,7 +938,12 @@ class Packet : public Printable
     static MemCmd
     makeReadCmd(const RequestPtr &req)
     {
-        if (req->isLLSC())
+        if (req->isHTMCmd()) {
+            if (req->isHTMAbort())
+                return MemCmd::HTMAbort;
+            else
+                return MemCmd::HTMReq;
+        } else if (req->isLLSC())
             return MemCmd::LoadLockedReq;
         else if (req->isPrefetchEx())
             return MemCmd::SoftPFExReq;
@@ -1346,6 +1416,58 @@ class Packet : public Printable
      * @return string with the request's type and start<->end addresses
      */
     std::string print() const;
+
+    // hardware transactional memory
+
+    /**
+     * Communicates to the core that a packet was processed by the memory
+     * subsystem while running in transactional mode.
+     * It may happen that the transaction has failed at the memory subsystem
+     * and this needs to be communicated to the core somehow.
+     * This function decorates the response packet with flags to indicate
+     * such a situation has occurred.
+     */
+    void makeHtmTransactionalReqResponse(const HtmCacheFailure ret_code);
+
+    /**
+     * Stipulates that this packet/request originates in the CPU executing
+     * in transactional mode, i.e. within a transaction.
+     */
+    void setHtmTransactional(uint64_t val);
+
+    /**
+     * Returns whether or not this packet/request originates in the CPU
+     * executing in transactional mode, i.e. within a transaction.
+     */
+    bool isHtmTransactional() const;
+
+    /**
+     * If a packet/request originates in a CPU executing in transactional
+     * mode, i.e. within a transaction, this function returns the unique ID
+     * of the transaction. This is used for verifying correctness
+     * and debugging.
+     */
+    uint64_t getHtmTransactionUid() const;
+
+    /**
+     * Stipulates that this packet/request has returned from the
+     * cache hierarchy in a failed transaction. The core is
+     * notified like this.
+     */
+    void setHtmTransactionFailedInCache(const HtmCacheFailure ret_code);
+
+    /**
+     * Returns whether or not this packet/request has returned from the
+     * cache hierarchy in a failed transaction. The core is
+     * notified liked this.
+     */
+    bool htmTransactionFailedInCache() const;
+
+    /**
+     * If a packet/request has returned from the cache hierarchy in a
+     * failed transaction, this function returns the failure reason.
+     */
+    HtmCacheFailure getHtmTransactionFailedInCacheRC() const;
 };
 
 #endif //__MEM_PACKET_HH