Tuan Ta has uploaded this change for review. ( https://gem5-review.googlesource.com/c/public/gem5/+/16769

Change subject: ruby,protocol,configs: Ensure lr/sc forward progress on MESI_Two_Level
......................................................................

ruby,protocol,configs: Ensure lr/sc forward progress on MESI_Two_Level

This commit addresses LL/SC livelock issue in ruby MESI_Two_Level protocol. As
per RISC-V ISA, restricted lr/sc sequences are guaranteed to have forward
progress. We implement this property by "locking" a cacheline obtained by LL
instruction for bounded amount of cycles.

Change-Id: I243d9f00789cc398753b2b42a802fbc349c29e73
---
M configs/ruby/MESI_Two_Level.py
M src/mem/protocol/MESI_Two_Level-L1cache.sm
M src/mem/protocol/MESI_Two_Level-msg.sm
M src/mem/protocol/RubySlicc_Types.sm
M src/mem/ruby/slicc_interface/RubyRequest.hh
M src/mem/ruby/system/Sequencer.cc
M src/mem/ruby/system/Sequencer.hh
7 files changed, 216 insertions(+), 43 deletions(-)



diff --git a/configs/ruby/MESI_Two_Level.py b/configs/ruby/MESI_Two_Level.py
index 27ef9c8..2adf271 100644
--- a/configs/ruby/MESI_Two_Level.py
+++ b/configs/ruby/MESI_Two_Level.py
@@ -132,6 +132,7 @@
         l1_cntrl.responseToL1Cache = MessageBuffer()
         l1_cntrl.responseToL1Cache.slave = ruby_system.network.master

+        l1_cntrl.triggerQueue = MessageBuffer()

     l2_index_start = block_size_bits + l2_bits

diff --git a/src/mem/protocol/MESI_Two_Level-L1cache.sm b/src/mem/protocol/MESI_Two_Level-L1cache.sm
index 87684ce..57eeef6 100644
--- a/src/mem/protocol/MESI_Two_Level-L1cache.sm
+++ b/src/mem/protocol/MESI_Two_Level-L1cache.sm
@@ -37,6 +37,7 @@
    Cycles to_l2_latency := 1;
    bool send_evictions;
    bool enable_prefetch := "False";
+   Cycles llsc_locked_duration := 128;

    // Message Queues
    // From this node's L1 cache TO the network
@@ -67,6 +68,9 @@

   // Buffer for requests generated by the processor core.
   MessageBuffer * mandatoryQueue;
+
+  // Buffer for unlock
+  MessageBuffer * triggerQueue;
 {
   // STATES
state_declaration(State, desc="Cache states", default="L1Cache_State_I") {
@@ -76,11 +80,14 @@
     S, AccessPermission:Read_Only, desc="a L1 cache entry Shared";
     E, AccessPermission:Read_Only, desc="a L1 cache entry Exclusive";
M, AccessPermission:Read_Write, desc="a L1 cache entry Modified", format="!b"; + L, AccessPermission:Read_Write, desc="a L1 cache entry Modified and locked";

     // Transient States
IS, AccessPermission:Busy, desc="L1 idle, issued GETS, have not seen response yet"; IM, AccessPermission:Busy, desc="L1 idle, issued GETX, have not seen response yet"; + IL, AccessPermission:Busy, desc="L1 idle, issued GETX, have not seen response yet, will be locked"; SM, AccessPermission:Read_Only, desc="L1 idle, issued GETX, have not seen response yet"; + SL, AccessPermission:Read_Only, desc="L1 idle, issued GETX, have not seen response yet, will be locked"; IS_I, AccessPermission:Busy, desc="L1 idle, issued GETS, saw Inv before data because directory doesn't block on GETS hit";

     M_I, AccessPermission:Busy, desc="L1 replacing, waiting for ACK";
@@ -99,6 +106,7 @@
     Load,            desc="Load request from the home processor";
     Ifetch,          desc="I-fetch request from the home processor";
     Store,           desc="Store request from the home processor";
+    LL,              desc="Load-Linked";

     Inv,           desc="Invalidate request from L2 bank";

@@ -124,6 +132,9 @@
     PF_Load,    desc="load request from prefetcher";
     PF_Ifetch,  desc="instruction fetch request from prefetcher";
     PF_Store,   desc="exclusive load request from prefetcher";
+
+    // unlock
+    Unlock,     desc="Unlock locked cacheline";
   }

   // TYPES
@@ -164,6 +175,7 @@
   void set_tbe(TBE a);
   void unset_tbe();
   void wakeUpBuffers(Addr a);
+  void wakeUpAllBuffers();
   void profileMsgDelay(int virtualNetworkType, Cycles c);

   // inclusive cache returns L1 entries only
@@ -258,13 +270,20 @@
     }
   }

-  Event mandatory_request_type_to_event(RubyRequestType type) {
-    if (type == RubyRequestType:LD) {
+ Event mandatory_request_type_to_event(RubyRequestType stype, RubyRequestType ptype) {
+    if (stype == RubyRequestType:LD) {
       return Event:Load;
-    } else if (type == RubyRequestType:IFETCH) {
+    } else if (stype == RubyRequestType:IFETCH) {
       return Event:Ifetch;
- } else if ((type == RubyRequestType:ST) || (type == RubyRequestType:ATOMIC)) {
-      return Event:Store;
+    } else if ((stype == RubyRequestType:ST) ||
+               (stype == RubyRequestType:ATOMIC) ||
+               (stype == RubyRequestType:ATOMIC_NO_RETURN) ||
+               (stype == RubyRequestType:ATOMIC_RETURN)) {
+      if (ptype == RubyRequestType:Load_Linked) {
+        return Event:LL;
+      } else {
+        return Event:Store;
+      }
     } else {
       error("Invalid RubyRequestType");
     }
@@ -291,7 +310,18 @@
   out_port(responseL1Network_out, ResponseMsg, responseFromL1Cache);
   out_port(unblockNetwork_out, ResponseMsg, unblockFromL1Cache);
   out_port(optionalQueue_out, RubyRequest, optionalQueue);
+  out_port(triggerQueue_out, RequestMsg, triggerQueue);

+  // Trigger Queue for unlocking cachelines
+  in_port(triggerQueue_in, RequestMsg, triggerQueue) {
+    if (triggerQueue_in.isReady(clockEdge())) {
+      peek(triggerQueue_in, RequestMsg) {
+        Entry cache_entry := getCacheEntry(in_msg.addr);
+        TBE tbe := TBEs[in_msg.addr];
+        trigger(Event:Unlock, in_msg.addr, cache_entry, tbe);
+      }
+    }
+  }

   // Prefetch queue between the controller and the prefetcher
   // As per Spracklen et al. (HPCA 2005), the prefetch queue should be
@@ -453,8 +483,8 @@
           Entry L1Icache_entry := getL1ICacheEntry(in_msg.LineAddress);
           if (is_valid(L1Icache_entry)) {
             // The tag matches for the L1, so the L1 asks the L2 for it.
- trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress,
-                    L1Icache_entry, TBEs[in_msg.LineAddress]);
+ trigger(mandatory_request_type_to_event(in_msg.Type, in_msg.PrimaryType), + in_msg.LineAddress, L1Icache_entry, TBEs[in_msg.LineAddress]);
           } else {

             // Check to see if it is in the OTHER L1
@@ -468,8 +498,8 @@
             if (L1Icache.cacheAvail(in_msg.LineAddress)) {
               // L1 does't have the line, but we have space for it
               // in the L1 so let's see if the L2 has it.
- trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress,
-                      L1Icache_entry, TBEs[in_msg.LineAddress]);
+ trigger(mandatory_request_type_to_event(in_msg.Type, in_msg.PrimaryType), + in_msg.LineAddress, L1Icache_entry, TBEs[in_msg.LineAddress]);
             } else {
               // No room in the L1, so we need to make room in the L1
trigger(Event:L1_Replacement, L1Icache.cacheProbe(in_msg.LineAddress),
@@ -483,8 +513,8 @@
           Entry L1Dcache_entry := getL1DCacheEntry(in_msg.LineAddress);
           if (is_valid(L1Dcache_entry)) {
             // The tag matches for the L1, so the L1 ask the L2 for it
- trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress,
-                    L1Dcache_entry, TBEs[in_msg.LineAddress]);
+ trigger(mandatory_request_type_to_event(in_msg.Type, in_msg.PrimaryType), + in_msg.LineAddress, L1Dcache_entry, TBEs[in_msg.LineAddress]);
           } else {

             // Check to see if it is in the OTHER L1
@@ -498,8 +528,8 @@
             if (L1Dcache.cacheAvail(in_msg.LineAddress)) {
               // L1 does't have the line, but we have space for it
               // in the L1 let's see if the L2 has it.
- trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress,
-                      L1Dcache_entry, TBEs[in_msg.LineAddress]);
+ trigger(mandatory_request_type_to_event(in_msg.Type, in_msg.PrimaryType), + in_msg.LineAddress, L1Dcache_entry, TBEs[in_msg.LineAddress]);
             } else {
               // No room in the L1, so we need to make room in the L1
trigger(Event:L1_Replacement, L1Dcache.cacheProbe(in_msg.LineAddress),
@@ -936,10 +966,22 @@
     stall_and_wait(optionalQueue_in, address);
   }

+ action(z_stallAndWaitRequestQueue, "\zr", desc="recycle L1 request queue") {
+    stall_and_wait(requestL1Network_in, address);
+  }
+
+  action(z_stall, "zs", desc="Stall the incoming request") {
+    // do nothing
+  }
+
   action(kd_wakeUpDependents, "kd", desc="wake-up dependents") {
     wakeUpBuffers(address);
   }

+  action(kd_wakeUpAllDependents, "kda", desc="wake-up all dependents") {
+    wakeUpAllBuffers();
+  }
+
   action(uu_profileInstMiss, "\uim", desc="Profile the demand miss") {
       ++L1Icache.demand_misses;
   }
@@ -989,17 +1031,31 @@
       cache_entry.isPrefetch := true;
   }

+  action(su_scheduleUnlock, "su", desc="Schdule an unlock event") {
+    assert(is_valid(cache_entry));
+    enqueue(triggerQueue_out, RequestMsg, llsc_locked_duration) {
+      out_msg.addr := address;
+      out_msg.Type := CoherenceRequestType:UNLOCK;
+      out_msg.MessageSize := MessageSizeType:Control;
+      DPRINTF(RubySlicc, "schedule to unlock line %#x at %s\n", address,
+              ticksToCycles(clockEdge()) + llsc_locked_duration);
+    }
+  }
+
+  action(pt_popTriggerQueue, "pT", desc="Pop the trigger queue") {
+    triggerQueue_in.dequeue(clockEdge());
+  }

   //*****************************************************
   // TRANSITIONS
   //*****************************************************

   // Transitions for Load/Store/Replacement/WriteBack from transient states
- transition({IS, IM, IS_I, M_I, SM, SINK_WB_ACK}, {Load, Ifetch, Store, L1_Replacement}) { + transition({IS, IM, IS_I, M_I, SM, SINK_WB_ACK}, {Load, Ifetch, Store, LL, L1_Replacement}) {
     z_stallAndWaitMandatoryQueue;
   }

-  transition({PF_IS, PF_IS_I}, {Store, L1_Replacement}) {
+  transition({PF_IS, PF_IS_I}, {Store, L1_Replacement, LL}) {
     z_stallAndWaitMandatoryQueue;
   }

@@ -1088,6 +1144,15 @@
     k_popMandatoryQueue;
   }

+  transition({NP,I}, LL, IL) {
+    oo_allocateL1DCacheBlock;
+    i_allocateTBE;
+    b_issueGETX;
+    uu_profileDataMiss;
+    po_observeMiss;
+    k_popMandatoryQueue;
+  }
+
   transition({NP,I}, PF_Store, PF_IM) {
     oo_allocateL1DCacheBlock;
     i_allocateTBE;
@@ -1101,26 +1166,38 @@
     k_popMandatoryQueue;
   }

+  transition(PF_IM, LL, IL) {
+    uu_profileDataMiss;
+    ppm_observePfMiss;
+    k_popMandatoryQueue;
+  }
+
   transition(PF_SM, Store, SM) {
     uu_profileDataMiss;
     ppm_observePfMiss;
     k_popMandatoryQueue;
   }

+  transition(PF_SM, LL, SL) {
+    uu_profileDataMiss;
+    ppm_observePfMiss;
+    k_popMandatoryQueue;
+  }
+
   transition({NP, I}, Inv) {
     fi_sendInvAck;
     l_popRequestQueue;
   }

   // Transitions from Shared
-  transition({S,E,M}, Load) {
+  transition({S,E,M,L}, Load) {
     h_load_hit;
     uu_profileDataHit;
     po_observeHit;
     k_popMandatoryQueue;
   }

-  transition({S,E,M}, Ifetch) {
+  transition({S,E,M,L}, Ifetch) {
     h_ifetch_hit;
     uu_profileInstHit;
     po_observeHit;
@@ -1134,6 +1211,13 @@
     k_popMandatoryQueue;
   }

+  transition(S, LL, SL) {
+    i_allocateTBE;
+    c_issueUPGRADE;
+    uu_profileDataMiss;
+    k_popMandatoryQueue;
+  }
+
   transition(S, {L1_Replacement, PF_L1_Replacement}, I) {
     forward_eviction_to_cpu;
     ff_deallocateL1CacheBlock;
@@ -1146,7 +1230,6 @@
   }

   // Transitions from Exclusive
-
   transition({E,M}, Store, M) {
     hh_store_hit;
     uu_profileDataHit;
@@ -1154,6 +1237,13 @@
     k_popMandatoryQueue;
   }

+  transition({E,M}, LL, L) {
+    su_scheduleUnlock;
+    hh_store_hit;
+    uu_profileDataHit;
+    k_popMandatoryQueue;
+  }
+
   transition(E, {L1_Replacement, PF_L1_Replacement}, M_I) {
     // silent E replacement??
     forward_eviction_to_cpu;
@@ -1182,7 +1272,6 @@
   }

   // Transitions from Modified
-
   transition(M, {L1_Replacement, PF_L1_Replacement}, M_I) {
     forward_eviction_to_cpu;
     i_allocateTBE;
@@ -1230,6 +1319,26 @@
     l_popRequestQueue;
   }

+  // Transitions from Locked
+  transition(L, {Store, LL}) {
+    hh_store_hit;
+    uu_profileDataHit;
+    k_popMandatoryQueue;
+  }
+
+  transition(L, Unlock, M) {
+    pt_popTriggerQueue;
+    kd_wakeUpAllDependents;
+  }
+
+  transition(L, {Fwd_GETX, Fwd_GETS, Fwd_GET_INSTR, Inv}) {
+    z_stallAndWaitRequestQueue;
+  }
+
+  transition(L, L1_Replacement) {
+    z_stall;
+  }
+
   // Transitions from IS
   transition({IS, IS_I}, Inv, IS_I) {
     fi_sendInvAck;
@@ -1342,7 +1451,7 @@
   }

   // Transitions from IM
-  transition(IM, Inv, IM) {
+  transition({IM, IL}, Inv) {
     fi_sendInvAck;
     l_popRequestQueue;
   }
@@ -1382,7 +1491,24 @@
     kd_wakeUpDependents;
   }

-  // transitions from SM
+  // Transitions from IL
+  transition(IL, Data, SL) {
+    u_writeDataToL1Cache;
+    q_updateAckCount;
+    o_popIncomingResponseQueue;
+  }
+
+  transition(IL, Data_all_Acks, L) {
+    u_writeDataToL1Cache;
+    hhx_store_hit;
+    jj_sendExclusiveUnblock;
+    s_deallocateTBE;
+    o_popIncomingResponseQueue;
+    su_scheduleUnlock;
+    kd_wakeUpDependents;
+  }
+
+  // Transitions from SM
   transition(SM, Inv, IM) {
     forward_eviction_to_cpu;
     fi_sendInvAck;
@@ -1390,7 +1516,7 @@
     l_popRequestQueue;
   }

-  transition({SM, IM, PF_SM, PF_IM}, Ack) {
+  transition({SM, IM, PF_SM, PF_IM, SL, IL}, Ack) {
     q_updateAckCount;
     o_popIncomingResponseQueue;
   }
@@ -1411,6 +1537,24 @@
     kd_wakeUpDependents;
   }

+  // Transitions from SL
+  transition(SL, Inv, IL) {
+    forward_eviction_to_cpu;
+    fi_sendInvAck;
+    dg_invalidate_sc;
+    l_popRequestQueue;
+  }
+
+  transition(SL, Ack_all, L) {
+    jj_sendExclusiveUnblock;
+    hhx_store_hit;
+    s_deallocateTBE;
+    o_popIncomingResponseQueue;
+    su_scheduleUnlock;
+    kd_wakeUpDependents;
+  }
+
+  // Transitions from SINK_WB_ACK
   transition(SINK_WB_ACK, Inv){
     fi_sendInvAck;
     l_popRequestQueue;
diff --git a/src/mem/protocol/MESI_Two_Level-msg.sm b/src/mem/protocol/MESI_Two_Level-msg.sm
index 738019e..e14015d 100644
--- a/src/mem/protocol/MESI_Two_Level-msg.sm
+++ b/src/mem/protocol/MESI_Two_Level-msg.sm
@@ -39,8 +39,10 @@

   WB_ACK,    desc="Writeback ack";

-  DMA_READ, desc="DMA Read";
+  DMA_READ,  desc="DMA Read";
   DMA_WRITE, desc="DMA Write";
+
+  UNLOCK,    desc="Unlock cache line";
 }

 // CoherenceResponseType
diff --git a/src/mem/protocol/RubySlicc_Types.sm b/src/mem/protocol/RubySlicc_Types.sm
index 27a045d..6a699fb 100644
--- a/src/mem/protocol/RubySlicc_Types.sm
+++ b/src/mem/protocol/RubySlicc_Types.sm
@@ -158,20 +158,21 @@
 }

 structure(RubyRequest, desc="...", interface="Message", external="yes") {
-  Addr LineAddress,       desc="Line address for this request";
-  Addr PhysicalAddress,   desc="Physical address for this request";
-  RubyRequestType Type,      desc="Type of request (LD, ST, etc)";
- Addr ProgramCounter, desc="Program counter of the instruction that caused the miss";
-  RubyAccessMode AccessMode, desc="user/supervisor access type";
-  int Size,                  desc="size in bytes of access";
-  PrefetchBit Prefetch,      desc="Is this a prefetch request";
- int contextId, desc="this goes away but must be replace with Nilay";
-  WriteMask writeMask,       desc="Writethrough mask";
-  DataBlock WTData,          desc="Writethrough data block";
-  int wfid,                  desc="Writethrough wavefront";
-  HSAScope scope,            desc="HSA scope";
-  HSASegment segment,        desc="HSA segment";
-  PacketPtr pkt,             desc="Packet associated with this request";
+  Addr LineAddress,            desc="Line address for this request";
+  Addr PhysicalAddress,        desc="Physical address for this request";
+  RubyRequestType Type,        desc="Type of request (LD, ST, etc)";
+  RubyRequestType PrimaryType, desc="Type of primary request";
+ Addr ProgramCounter, desc="Program counter of the instruction that caused the miss";
+  RubyAccessMode AccessMode,   desc="user/supervisor access type";
+  int Size,                    desc="size in bytes of access";
+  PrefetchBit Prefetch,        desc="Is this a prefetch request";
+ int contextId, desc="this goes away but must be replace with Nilay";
+  WriteMask writeMask,         desc="Writethrough mask";
+  DataBlock WTData,            desc="Writethrough data block";
+  int wfid,                    desc="Writethrough wavefront";
+  HSAScope scope,              desc="HSA scope";
+  HSASegment segment,          desc="HSA segment";
+  PacketPtr pkt,               desc="Packet associated with this request";
 }

 structure(AbstractEntry, primitive="yes", external = "yes") {
diff --git a/src/mem/ruby/slicc_interface/RubyRequest.hh b/src/mem/ruby/slicc_interface/RubyRequest.hh
index 6c84f38..3894749 100644
--- a/src/mem/ruby/slicc_interface/RubyRequest.hh
+++ b/src/mem/ruby/slicc_interface/RubyRequest.hh
@@ -48,6 +48,7 @@
     Addr m_PhysicalAddress;
     Addr m_LineAddress;
     RubyRequestType m_Type;
+    RubyRequestType m_PrimaryType;
     Addr m_ProgramCounter;
     RubyAccessMode m_AccessMode;
     int m_Size;
@@ -61,7 +62,6 @@
     HSAScope m_scope;
     HSASegment m_segment;

-
     RubyRequest(Tick curTime, uint64_t _paddr, uint8_t* _data, int _len,
         uint64_t _pc, RubyRequestType _type, RubyAccessMode _access_mode,
         PacketPtr _pkt, PrefetchBit _pb = PrefetchBit_No,
@@ -85,6 +85,29 @@
     }

     RubyRequest(Tick curTime, uint64_t _paddr, uint8_t* _data, int _len,
+        uint64_t _pc, RubyRequestType _type, RubyRequestType _ptype,
+        RubyAccessMode _access_mode, PacketPtr _pkt,
+        PrefetchBit _pb = PrefetchBit_No, ContextID _proc_id = 100,
+        ContextID _core_id = 99, HSAScope _scope = HSAScope_UNSPECIFIED,
+        HSASegment _segment = HSASegment_GLOBAL)
+        : Message(curTime),
+          m_PhysicalAddress(_paddr),
+          m_Type(_type),
+          m_PrimaryType(_ptype),
+          m_ProgramCounter(_pc),
+          m_AccessMode(_access_mode),
+          m_Size(_len),
+          m_Prefetch(_pb),
+          data(_data),
+          m_pkt(_pkt),
+          m_contextId(_core_id),
+          m_scope(_scope),
+          m_segment(_segment)
+    {
+        m_LineAddress = makeLineAddress(m_PhysicalAddress);
+    }
+
+    RubyRequest(Tick curTime, uint64_t _paddr, uint8_t* _data, int _len,
         uint64_t _pc, RubyRequestType _type,
         RubyAccessMode _access_mode, PacketPtr _pkt, PrefetchBit _pb,
         unsigned _proc_id, unsigned _core_id,
diff --git a/src/mem/ruby/system/Sequencer.cc b/src/mem/ruby/system/Sequencer.cc
index a884981..d6830d9 100644
--- a/src/mem/ruby/system/Sequencer.cc
+++ b/src/mem/ruby/system/Sequencer.cc
@@ -640,14 +640,15 @@
     if (status != RequestStatus_Ready)
         return status;

-    issueRequest(pkt, secondary_type);
+    issueRequest(pkt, secondary_type, primary_type);

     // TODO: issue hardware prefetches here
     return RequestStatus_Issued;
 }

 void
-Sequencer::issueRequest(PacketPtr pkt, RubyRequestType secondary_type)
+Sequencer::issueRequest(PacketPtr pkt, RubyRequestType secondary_type,
+                        RubyRequestType primary_type)
 {
     assert(pkt != NULL);
     ContextID proc_id = pkt->req->hasContextId() ?
@@ -668,8 +669,8 @@
                                       pkt->isFlush() ?
                                       nullptr : pkt->getPtr<uint8_t>(),
                                       pkt->getSize(), pc, secondary_type,
-                                      RubyAccessMode_Supervisor, pkt,
-                                      PrefetchBit_No, proc_id, core_id);
+ primary_type, RubyAccessMode_Supervisor, + pkt, PrefetchBit_No, proc_id, core_id);

     DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %#x %s\n",
             curTick(), m_version, "Seq", "Begin", "", "",
diff --git a/src/mem/ruby/system/Sequencer.hh b/src/mem/ruby/system/Sequencer.hh
index fcfa8ad..4a5b9ea 100644
--- a/src/mem/ruby/system/Sequencer.hh
+++ b/src/mem/ruby/system/Sequencer.hh
@@ -149,7 +149,8 @@
     { return m_IncompleteTimes[t]; }

   private:
-    void issueRequest(PacketPtr pkt, RubyRequestType type);
+    void issueRequest(PacketPtr pkt, RubyRequestType secondary_type,
+                      RubyRequestType primary_type);

     void hitCallback(SequencerRequest* request, DataBlock& data,
                      bool llscSuccess,

--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/16769
To unsubscribe, or for help writing mail filters, visit https://gem5-review.googlesource.com/settings

Gerrit-Project: public/gem5
Gerrit-Branch: master
Gerrit-Change-Id: I243d9f00789cc398753b2b42a802fbc349c29e73
Gerrit-Change-Number: 16769
Gerrit-PatchSet: 1
Gerrit-Owner: Tuan Ta <[email protected]>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to