mem: Add HTM fields to Request

This starts the support of Hardware Transactional Memory on the mem side

* The following flags have been added:

HTM_START: The request starts a HTM transaction
HTM_COMMIT: The request commits a HTM transaction
HTM_CANCEL: The request cancels a HTM transaction
HTM_ABORT: The request aborts a HTM transaction

* The following fields have been added:

_instCount: The instruction count at the time this request is created
_htmAbortCause: The cause for HTM transaction abort

https://gem5.atlassian.net/browse/GEM5-587

Change-Id: Ic582a6566fdd23f30eb92723e629d0c4d4ca10e5
Signed-off-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/30316
Reviewed-by: Jason Lowe-Power <power.jg@gmail.com>
Maintainer: Jason Lowe-Power <power.jg@gmail.com>
Tested-by: kokoro <noreply+kokoro@google.com>
diff --git a/src/mem/request.hh b/src/mem/request.hh
index 7b324dc..7f0ddcb 100644
--- a/src/mem/request.hh
+++ b/src/mem/request.hh
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2013,2017-2019 ARM Limited
+ * Copyright (c) 2012-2013,2017-2020 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
@@ -56,6 +56,7 @@
 #include "base/logging.hh"
 #include "base/types.hh"
 #include "cpu/inst_seq.hh"
+#include "mem/htm.hh"
 #include "sim/core.hh"
 
 /**
@@ -187,6 +188,42 @@
         /** Bits to define the destination of a request */
         DST_BITS                    = 0x0000003000000000,
 
+        /** hardware transactional memory **/
+
+        /** The request starts a HTM transaction */
+        HTM_START                   = 0x0000010000000000,
+
+        /** The request commits a HTM transaction */
+        HTM_COMMIT                  = 0x0000020000000000,
+
+        /** The request cancels a HTM transaction */
+        HTM_CANCEL                  = 0x0000040000000000,
+
+        /** The request aborts a HTM transaction */
+        HTM_ABORT                   = 0x0000080000000000,
+
+        // What is the different between HTM cancel and abort?
+        //
+        // HTM_CANCEL will originate from a user instruction, e.g.
+        // Arm's TCANCEL or x86's XABORT. This is an explicit request
+        // to end a transaction and restore from the last checkpoint.
+        //
+        // HTM_ABORT is an internally generated request used to synchronize
+        // a transaction's failure between the core and memory subsystem.
+        // If a transaction fails in the core, e.g. because an instruction
+        // within the transaction generates an exception, the core will prepare
+        // itself to stop fetching/executing more instructions and send an
+        // HTM_ABORT to the memory subsystem before restoring the checkpoint.
+        // Similarly, the transaction could fail in the memory subsystem and
+        // this will be communicated to the core via the Packet object.
+        // Once the core notices, it will do the same as the above and send
+        // a HTM_ABORT to the memory subsystem.
+        // A HTM_CANCEL sent to the memory subsystem will ultimately return
+        // to the core which in turn will send a HTM_ABORT.
+        //
+        // This separation is necessary to ensure the disjoint components
+        // of the system work correctly together.
+
         /**
          * These flags are *not* cleared when a Request object is
          * reused (assigned a new address).
@@ -196,6 +233,9 @@
     static const FlagsType STORE_NO_DATA = CACHE_BLOCK_ZERO |
         CLEAN | INVALIDATE;
 
+    static const FlagsType HTM_CMD = HTM_START | HTM_COMMIT |
+        HTM_CANCEL | HTM_ABORT;
+
     /** Master Ids that are statically allocated
      * @{*/
     enum : MasterID {
@@ -274,6 +314,11 @@
         /** Whether or not the stream ID and substream ID is valid. */
         VALID_STREAM_ID      = 0x00000100,
         VALID_SUBSTREAM_ID   = 0x00000200,
+        // hardware transactional memory
+        /** Whether or not the abort cause is valid. */
+        VALID_HTM_ABORT_CAUSE = 0x00000400,
+        /** Whether or not the instruction count is valid. */
+        VALID_INST_COUNT      = 0x00000800,
         /**
          * These flags are *not* cleared when a Request object is reused
          * (assigned a new address).
@@ -362,6 +407,12 @@
 
     LocalAccessor _localAccessor;
 
+    /** The instruction count at the time this request is created */
+    Counter _instCount = 0;
+
+    /** The cause for HTM transaction abort */
+    HtmFailureFaultCause _htmAbortCause = HtmFailureFaultCause::INVALID;
+
   public:
 
     /**
@@ -517,6 +568,21 @@
     }
 
     /**
+     * Accessor for instruction count.
+     */
+    Counter getInstCount() const
+    {
+        assert(privateFlags.isSet(VALID_INST_COUNT));
+        return _instCount;
+    }
+
+    void setInstCount(Counter val)
+    {
+        privateFlags.set(VALID_INST_COUNT);
+        _instCount = val;
+    }
+
+    /**
      * Time for the TLB/table walker to successfully translate this request.
      */
     Tick translateDelta = 0;
@@ -611,6 +677,24 @@
         return atomicOpFunctor.get();
     }
 
+    /**
+     * Accessor for hardware transactional memory abort cause.
+     */
+    HtmFailureFaultCause
+    getHtmAbortCause() const
+    {
+        assert(privateFlags.isSet(VALID_HTM_ABORT_CAUSE));
+        return _htmAbortCause;
+    }
+
+    void
+    setHtmAbortCause(HtmFailureFaultCause val)
+    {
+        assert(isHTMAbort());
+        privateFlags.set(VALID_HTM_ABORT_CAUSE);
+        _htmAbortCause = val;
+    }
+
     /** Accessor for flags. */
     Flags
     getFlags()
@@ -819,6 +903,17 @@
     bool isKernel() const { return _flags.isSet(KERNEL); }
     bool isAtomicReturn() const { return _flags.isSet(ATOMIC_RETURN_OP); }
     bool isAtomicNoReturn() const { return _flags.isSet(ATOMIC_NO_RETURN_OP); }
+    // hardware transactional memory
+    bool isHTMStart() const { return _flags.isSet(HTM_START); }
+    bool isHTMCommit() const { return _flags.isSet(HTM_COMMIT); }
+    bool isHTMCancel() const { return _flags.isSet(HTM_CANCEL); }
+    bool isHTMAbort() const { return _flags.isSet(HTM_ABORT); }
+    bool
+    isHTMCmd() const
+    {
+        return (isHTMStart() || isHTMCommit() ||
+                isHTMCancel() || isHTMAbort());
+    }
 
     bool
     isAtomic() const