gem5  [DEVELOP-FOR-23.0]
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
HTMSequencer.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 ARM Limited
3  * All rights reserved
4  *
5  * The license below extends only to copyright in the software and shall
6  * not be construed as granting a license to any other intellectual
7  * property including but not limited to intellectual property relating
8  * to a hardware implementation of the functionality of the software
9  * licensed hereunder. You may use the software subject to the license
10  * terms below provided that you ensure that this notice is replicated
11  * unmodified and in its entirety in all distributions of the software,
12  * modified or unmodified, in source code or in binary form.
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions are
16  * met: redistributions of source code must retain the above copyright
17  * notice, this list of conditions and the following disclaimer;
18  * redistributions in binary form must reproduce the above copyright
19  * notice, this list of conditions and the following disclaimer in the
20  * documentation and/or other materials provided with the distribution;
21  * neither the name of the copyright holders nor the names of its
22  * contributors may be used to endorse or promote products derived from
23  * this software without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36  */
37 
39 
40 #include "debug/HtmMem.hh"
41 #include "debug/RubyPort.hh"
43 #include "sim/system.hh"
44 
45 namespace gem5
46 {
47 
48 namespace ruby
49 {
50 
53  const HtmFailedInCacheReason ruby_ret_code)
54 {
55  switch (ruby_ret_code) {
56  case HtmFailedInCacheReason_NO_FAIL:
58  case HtmFailedInCacheReason_FAIL_SELF:
60  case HtmFailedInCacheReason_FAIL_REMOTE:
62  case HtmFailedInCacheReason_FAIL_OTHER:
64  default:
65  panic("Invalid htm return code\n");
66  }
67 }
68 
69 HTMSequencer::HTMSequencer(const RubyHTMSequencerParams &p)
70  : Sequencer(p),
71  ADD_STAT(m_htm_transaction_cycles, "number of cycles spent in an outer "
72  "transaction"),
73  ADD_STAT(m_htm_transaction_instructions, "number of instructions spent "
74  "in an outer transaction"),
75  ADD_STAT(m_htm_transaction_abort_cause, "cause of htm transaction abort")
76 {
77  m_htmstart_tick = 0;
79 
80  // hardware transactional memory
82  .init(10)
85  ;
87  .init(10)
90  ;
91  auto num_causes = static_cast<int>(HtmFailureFaultCause::NUM_CAUSES);
93  .init(num_causes)
96  ;
97 
98  for (unsigned cause_idx = 0; cause_idx < num_causes; ++cause_idx) {
100  cause_idx,
102  }
103 
104 }
105 
107 {
108 }
109 
110 void
112  const HtmCallbackMode mode,
113  const HtmFailedInCacheReason htm_return_code)
114 {
115  // mode=0: HTM command
116  // mode=1: transaction failed - inform via LD
117  // mode=2: transaction failed - inform via ST
118 
119  if (mode == HtmCallbackMode_HTM_CMD) {
120  SequencerRequest* request = nullptr;
121 
122  assert(m_htmCmdRequestTable.size() > 0);
123 
124  request = m_htmCmdRequestTable.front();
125  m_htmCmdRequestTable.pop_front();
126 
127  assert(isHtmCmdRequest(request->m_type));
128 
129  PacketPtr pkt = request->pkt;
130  delete request;
131 
132  // valid responses have zero as the payload
133  uint8_t* dataptr = pkt->getPtr<uint8_t>();
134  memset(dataptr, 0, pkt->getSize());
135  *dataptr = (uint8_t) htm_return_code;
136 
137  // record stats
138  if (htm_return_code == HtmFailedInCacheReason_NO_FAIL) {
139  if (pkt->req->isHTMStart()) {
140  m_htmstart_tick = pkt->req->time();
141  m_htmstart_instruction = pkt->req->getInstCount();
142  DPRINTF(HtmMem, "htmStart - htmUid=%u\n",
143  pkt->getHtmTransactionUid());
144  } else if (pkt->req->isHTMCommit()) {
145  Tick transaction_ticks = pkt->req->time() - m_htmstart_tick;
146  Cycles transaction_cycles = ticksToCycles(transaction_ticks);
147  m_htm_transaction_cycles.sample(transaction_cycles);
148  m_htmstart_tick = 0;
149  Counter transaction_instructions =
150  pkt->req->getInstCount() - m_htmstart_instruction;
152  transaction_instructions);
154  DPRINTF(HtmMem, "htmCommit - htmUid=%u\n",
155  pkt->getHtmTransactionUid());
156  } else if (pkt->req->isHTMAbort()) {
157  HtmFailureFaultCause cause = pkt->req->getHtmAbortCause();
158  assert(cause != HtmFailureFaultCause::INVALID);
159  auto cause_idx = static_cast<int>(cause);
160  m_htm_transaction_abort_cause[cause_idx]++;
161  DPRINTF(HtmMem, "htmAbort - reason=%s - htmUid=%u\n",
162  htmFailureToStr(cause),
163  pkt->getHtmTransactionUid());
164  }
165  } else {
166  DPRINTF(HtmMem, "HTM_CMD: fail - htmUid=%u\n",
167  pkt->getHtmTransactionUid());
168  }
169 
170  rubyHtmCallback(pkt, htm_return_code);
172  } else if (mode == HtmCallbackMode_LD_FAIL ||
173  mode == HtmCallbackMode_ST_FAIL) {
174  // transaction failed
175  assert(address == makeLineAddress(address));
176  assert(m_RequestTable.find(address) != m_RequestTable.end());
177 
178  auto &seq_req_list = m_RequestTable[address];
179  while (!seq_req_list.empty()) {
180  SequencerRequest &request = seq_req_list.front();
181 
182  PacketPtr pkt = request.pkt;
183  markRemoved();
184 
185  // TODO - atomics
186 
187  // store conditionals should indicate failure
188  if (request.m_type == RubyRequestType_Store_Conditional) {
189  pkt->req->setExtraData(0);
190  }
191 
192  DPRINTF(HtmMem, "%s_FAIL: size=%d - "
193  "addr=0x%lx - htmUid=%d\n",
194  (mode == HtmCallbackMode_LD_FAIL) ? "LD" : "ST",
195  pkt->getSize(),
196  address, pkt->getHtmTransactionUid());
197 
198  rubyHtmCallback(pkt, htm_return_code);
200  pkt = nullptr;
201  seq_req_list.pop_front();
202  }
203  // free all outstanding requests corresponding to this address
204  if (seq_req_list.empty()) {
205  m_RequestTable.erase(address);
206  }
207  } else {
208  panic("unrecognised HTM callback mode\n");
209  }
210 }
211 
212 void
214  const HtmFailedInCacheReason htm_return_code)
215 {
216  // The packet was destined for memory and has not yet been turned
217  // into a response
218  assert(system->isMemAddr(pkt->getAddr()) || system->isDeviceMemAddr(pkt));
219  assert(pkt->isRequest());
220 
221  // First retrieve the request port from the sender State
222  RubyPort::SenderState *senderState =
223  safe_cast<RubyPort::SenderState *>(pkt->popSenderState());
224 
225  MemResponsePort *port = safe_cast<MemResponsePort*>(senderState->port);
226  assert(port != nullptr);
227  delete senderState;
228 
229  //port->htmCallback(pkt, htm_return_code);
230  DPRINTF(HtmMem, "HTM callback: start=%d, commit=%d, "
231  "cancel=%d, rc=%d\n",
232  pkt->req->isHTMStart(), pkt->req->isHTMCommit(),
233  pkt->req->isHTMCancel(), htm_return_code);
234 
235  // turn packet around to go back to requestor if response expected
236  if (pkt->needsResponse()) {
237  DPRINTF(RubyPort, "Sending packet back over port\n");
239  htmRetCodeConversion(htm_return_code));
240  port->schedTimingResp(pkt, curTick());
241  } else {
242  delete pkt;
243  }
244 
245  trySendRetries();
246 }
247 
248 void
250 {
252 
253  // Check for deadlock of any of the requests
254  Cycles current_time = curCycle();
255 
256  // hardware transactional memory commands
258  m_htmCmdRequestTable.begin();
260  m_htmCmdRequestTable.end();
261 
262  for (; htm != htm_end; ++htm) {
263  SequencerRequest* request = *htm;
264  if (current_time - request->issue_time < m_deadlock_threshold)
265  continue;
266 
267  panic("Possible Deadlock detected. Aborting!\n"
268  "version: %d m_htmCmdRequestTable: %d "
269  "current time: %u issue_time: %d difference: %d\n",
271  current_time * clockPeriod(),
272  request->issue_time * clockPeriod(),
273  (current_time * clockPeriod()) -
274  (request->issue_time * clockPeriod()));
275  }
276 }
277 
278 bool
280 {
281  return Sequencer::empty() && m_htmCmdRequestTable.empty();
282 }
283 
284 template <class VALUE>
285 std::ostream &
286 operator<<(std::ostream &out, const std::deque<VALUE> &queue)
287 {
288  auto i = queue.begin();
289  auto end = queue.end();
290 
291  out << "[";
292  for (; i != end; ++i)
293  out << " " << *i;
294  out << " ]";
295 
296  return out;
297 }
298 
299 void
300 HTMSequencer::print(std::ostream& out) const
301 {
302  Sequencer::print(out);
303 
304  out << "+ [HTMSequencer: " << m_version
305  << ", htm cmd request table: " << m_htmCmdRequestTable
306  << "]";
307 }
308 
309 // Insert the request in the request table. Return RequestStatus_Aliased
310 // if the entry was already present.
311 RequestStatus
312 HTMSequencer::insertRequest(PacketPtr pkt, RubyRequestType primary_type,
313  RubyRequestType secondary_type)
314 {
315  if (isHtmCmdRequest(primary_type)) {
316  // for the moment, allow just one HTM cmd into the cache controller.
317  // Later this can be adjusted for optimization, e.g.
318  // back-to-back HTM_Starts.
319  if ((m_htmCmdRequestTable.size() > 0) && !pkt->req->isHTMAbort())
320  return RequestStatus_BufferFull;
321 
322  // insert request into HtmCmd queue
323  SequencerRequest* htmReq =
324  new SequencerRequest(pkt, primary_type, secondary_type,
325  curCycle());
326  assert(htmReq);
327  m_htmCmdRequestTable.push_back(htmReq);
328  return RequestStatus_Ready;
329  } else {
330  return Sequencer::insertRequest(pkt, primary_type, secondary_type);
331  }
332 }
333 
334 } // namespace ruby
335 } // namespace gem5
gem5::curTick
Tick curTick()
The universal simulation clock.
Definition: cur_tick.hh:46
gem5::HtmCacheFailure::FAIL_OTHER
@ FAIL_OTHER
gem5::ruby::Sequencer::m_RequestTable
std::unordered_map< Addr, std::list< SequencerRequest > > m_RequestTable
Definition: Sequencer.hh:224
gem5::ruby::HTMSequencer::~HTMSequencer
~HTMSequencer()
Definition: HTMSequencer.cc:106
gem5::ruby::Sequencer
Definition: Sequencer.hh:86
gem5::ruby::RubyPort::m_version
uint32_t m_version
Definition: RubyPort.hh:203
gem5::ruby::RubyPort::SenderState::port
MemResponsePort * port
Definition: RubyPort.hh:153
gem5::Packet::isRequest
bool isRequest() const
Definition: packet.hh:597
HTMSequencer.hh
gem5::ruby::Sequencer::m_deadlock_threshold
Cycles m_deadlock_threshold
Definition: Sequencer.hh:229
system.hh
gem5::Clocked::curCycle
Cycles curCycle() const
Determine the current cycle, corresponding to a tick aligned to a clock edge.
Definition: clocked_object.hh:195
gem5::ruby::HTMSequencer::print
void print(std::ostream &out) const override
Definition: HTMSequencer.cc:300
gem5::HtmFailureFaultCause
HtmFailureFaultCause
Definition: htm.hh:47
gem5::ruby::operator<<
std::ostream & operator<<(std::ostream &os, const BoolVec &myvector)
Definition: BoolVec.cc:49
gem5::HtmCacheFailure::NO_FAIL
@ NO_FAIL
gem5::Packet::req
RequestPtr req
A pointer to the original request.
Definition: packet.hh:377
gem5::ruby::RubyPort::system
System * system
Definition: RubyPort.hh:207
gem5::ruby::RubyPort::MemResponsePort
Definition: RubyPort.hh:82
gem5::statistics::nozero
const FlagsType nozero
Don't print if this is zero.
Definition: info.hh:67
gem5::HtmCacheFailure
HtmCacheFailure
Definition: htm.hh:59
gem5::ruby::Sequencer::insertRequest
virtual RequestStatus insertRequest(PacketPtr pkt, RubyRequestType primary_type, RubyRequestType secondary_type)
Definition: Sequencer.cc:306
gem5::statistics::DataWrapVec::subname
Derived & subname(off_type index, const std::string &name)
Set the subfield name for the given index, and marks this stat to print at the end of simulation.
Definition: statistics.hh:401
gem5::statistics::nonan
const FlagsType nonan
Don't print if this is NAN.
Definition: info.hh:69
gem5::ruby::RubyPort::trySendRetries
void trySendRetries()
Definition: RubyPort.cc:523
gem5::ruby::HTMSequencer::htmRetCodeConversion
HtmCacheFailure htmRetCodeConversion(const HtmFailedInCacheReason rc)
Htm return code conversion.
Definition: HTMSequencer.cc:52
gem5::ArmISA::i
Bitfield< 7 > i
Definition: misc_types.hh:67
gem5::ruby::makeLineAddress
Addr makeLineAddress(Addr addr)
Definition: Address.cc:60
gem5::ruby::HTMSequencer::m_htmstart_instruction
Counter m_htmstart_instruction
Definition: HTMSequencer.hh:100
gem5::ruby::HTMSequencer::m_htm_transaction_cycles
statistics::Histogram m_htm_transaction_cycles
Histogram of cycle latencies of HTM transactions.
Definition: HTMSequencer.hh:103
gem5::ruby::RubyPort::SenderState
Definition: RubyPort.hh:151
gem5::statistics::DistBase::sample
void sample(const U &v, int n=1)
Add a value to the distribtion n times.
Definition: statistics.hh:1327
gem5::statistics::dist
const FlagsType dist
Print the distribution.
Definition: info.hh:65
gem5::HtmCacheFailure::FAIL_SELF
@ FAIL_SELF
gem5::Cycles
Cycles is a wrapper class for representing cycle counts, i.e.
Definition: types.hh:78
gem5::statistics::pdf
const FlagsType pdf
Print the percent of the total that this entry represents.
Definition: info.hh:61
gem5::ruby::HTMSequencer::insertRequest
RequestStatus insertRequest(PacketPtr pkt, RubyRequestType primary_type, RubyRequestType secondary_type) override
Definition: HTMSequencer.cc:312
gem5::ruby::HTMSequencer::m_htmstart_tick
Tick m_htmstart_tick
Definition: HTMSequencer.hh:99
gem5::HtmCacheFailure::FAIL_REMOTE
@ FAIL_REMOTE
gem5::System::isMemAddr
bool isMemAddr(Addr addr) const
Check if a physical address is within a range of a memory that is part of the global address map.
Definition: system.cc:288
gem5::VegaISA::p
Bitfield< 54 > p
Definition: pagetable.hh:70
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:210
ADD_STAT
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
Definition: group.hh:75
gem5::Packet
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:294
gem5::ruby::HTMSequencer::htmCallback
void htmCallback(Addr, const HtmCallbackMode, const HtmFailedInCacheReason)
Definition: HTMSequencer.cc:111
gem5::Tick
uint64_t Tick
Tick count type.
Definition: types.hh:58
gem5::ruby::SequencerRequest
Definition: Sequencer.hh:62
gem5::Packet::getHtmTransactionUid
uint64_t getHtmTransactionUid() const
If a packet/request originates in a CPU executing in transactional mode, i.e.
Definition: packet.cc:529
gem5::HtmFailureFaultCause::NUM_CAUSES
@ NUM_CAUSES
RubySlicc_Util.hh
gem5::ruby::HTMSequencer::empty
bool empty() const override
Definition: HTMSequencer.cc:279
gem5::Packet::makeHtmTransactionalReqResponse
void makeHtmTransactionalReqResponse(const HtmCacheFailure ret_code)
Communicates to the core that a packet was processed by the memory subsystem while running in transac...
Definition: packet.cc:477
gem5::HtmFailureFaultCause::INVALID
@ INVALID
gem5::ruby::HTMSequencer::m_htmCmdRequestTable
std::deque< SequencerRequest * > m_htmCmdRequestTable
Definition: HTMSequencer.hh:97
gem5::ruby::Sequencer::empty
virtual bool empty() const
Definition: Sequencer.cc:747
gem5::Packet::needsResponse
bool needsResponse() const
Definition: packet.hh:608
gem5::ruby::RubyPort::testDrainComplete
void testDrainComplete()
Definition: RubyPort.cc:549
gem5::Addr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:147
gem5::statistics::Histogram::init
Histogram & init(size_type size)
Set the parameters of this histogram.
Definition: statistics.hh:2153
gem5::ruby::HTMSequencer::m_htm_transaction_instructions
statistics::Histogram m_htm_transaction_instructions
Histogram of instruction lengths of HTM transactions.
Definition: HTMSequencer.hh:105
gem5::Packet::popSenderState
SenderState * popSenderState()
Pop the top of the state stack and return a pointer to it.
Definition: packet.cc:342
gem5::ruby::Sequencer::print
virtual void print(std::ostream &out) const
Definition: Sequencer.cc:955
gem5::ruby::Sequencer::wakeup
virtual void wakeup()
Definition: Sequencer.cc:225
gem5::System::isDeviceMemAddr
bool isDeviceMemAddr(const PacketPtr &pkt) const
Similar to isMemAddr but for devices.
Definition: system.cc:301
gem5::ruby::Sequencer::markRemoved
void markRemoved()
Definition: Sequencer.cc:369
gem5::ruby::HTMSequencer::HTMSequencer
HTMSequencer(const RubyHTMSequencerParams &p)
Definition: HTMSequencer.cc:69
gem5::htmFailureToStr
std::string htmFailureToStr(HtmFailureFaultCause cause)
Convert enum into string to be used for debug purposes.
Definition: htm.cc:44
gem5::ruby::HTMSequencer::rubyHtmCallback
void rubyHtmCallback(PacketPtr pkt, const HtmFailedInCacheReason fail_r)
Definition: HTMSequencer.cc:213
gem5::ruby::HTMSequencer::wakeup
void wakeup() override
Definition: HTMSequencer.cc:249
gem5::ruby::isHtmCmdRequest
bool isHtmCmdRequest(RubyRequestType type)
Definition: RubySlicc_Util.hh:153
std::deque
STL deque class.
Definition: stl.hh:44
gem5::statistics::Counter
double Counter
All counters are of 64-bit values.
Definition: types.hh:46
gem5::ruby::SequencerRequest::m_type
RubyRequestType m_type
Definition: Sequencer.hh:65
gem5::ruby::SequencerRequest::issue_time
Cycles issue_time
Definition: Sequencer.hh:67
gem5::ruby::HTMSequencer::m_htm_transaction_abort_cause
statistics::Vector m_htm_transaction_abort_cause
Causes for HTM transaction aborts.
Definition: HTMSequencer.hh:107
gem5::statistics::DataWrap::flags
Derived & flags(Flags _flags)
Set the flags and marks this stat to print at the end of simulation.
Definition: statistics.hh:357
gem5::Clocked::ticksToCycles
Cycles ticksToCycles(Tick t) const
Definition: clocked_object.hh:222
gem5::Packet::getAddr
Addr getAddr() const
Definition: packet.hh:807
gem5::QueuedResponsePort::schedTimingResp
void schedTimingResp(PacketPtr pkt, Tick when)
Schedule the sending of a timing response.
Definition: qport.hh:94
gem5
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
Definition: gpu_translation_state.hh:37
gem5::statistics::total
const FlagsType total
Print the total.
Definition: info.hh:59
gem5::statistics::VectorBase::init
Derived & init(size_type size)
Set this vector to have the given size.
Definition: statistics.hh:1039
gem5::ruby::RubyPort
Definition: RubyPort.hh:64
gem5::Packet::getSize
unsigned getSize() const
Definition: packet.hh:817
panic
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:188
gem5::Clocked::clockPeriod
Tick clockPeriod() const
Definition: clocked_object.hh:217
gem5::ArmISA::mode
Bitfield< 4, 0 > mode
Definition: misc_types.hh:74
gem5::Packet::getPtr
T * getPtr()
get a pointer to the data ptr.
Definition: packet.hh:1225
gem5::ruby::SequencerRequest::pkt
PacketPtr pkt
Definition: Sequencer.hh:64

Generated on Sun Jul 30 2023 01:56:59 for gem5 by doxygen 1.8.17