gem5  v21.0.1.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 
47  const HtmFailedInCacheReason ruby_ret_code)
48 {
49  switch (ruby_ret_code) {
50  case HtmFailedInCacheReason_NO_FAIL:
52  case HtmFailedInCacheReason_FAIL_SELF:
54  case HtmFailedInCacheReason_FAIL_REMOTE:
56  case HtmFailedInCacheReason_FAIL_OTHER:
58  default:
59  panic("Invalid htm return code\n");
60  }
61 }
62 
63 HTMSequencer::HTMSequencer(const RubyHTMSequencerParams &p)
64  : Sequencer(p),
65  ADD_STAT(m_htm_transaction_cycles, "number of cycles spent in an outer "
66  "transaction"),
67  ADD_STAT(m_htm_transaction_instructions, "number of instructions spent "
68  "in an outer transaction"),
69  ADD_STAT(m_htm_transaction_abort_cause, "cause of htm transaction abort")
70 {
71  m_htmstart_tick = 0;
73 
74  // hardware transactional memory
76  .init(10)
78  ;
80  .init(10)
82  ;
83  auto num_causes = static_cast<int>(HtmFailureFaultCause::NUM_CAUSES);
85  .init(num_causes)
87  ;
88 
89  for (unsigned cause_idx = 0; cause_idx < num_causes; ++cause_idx) {
91  cause_idx,
93  }
94 
95 }
96 
98 {
99 }
100 
101 void
103  const HtmCallbackMode mode,
104  const HtmFailedInCacheReason htm_return_code)
105 {
106  // mode=0: HTM command
107  // mode=1: transaction failed - inform via LD
108  // mode=2: transaction failed - inform via ST
109 
110  if (mode == HtmCallbackMode_HTM_CMD) {
111  SequencerRequest* request = nullptr;
112 
113  assert(m_htmCmdRequestTable.size() > 0);
114 
115  request = m_htmCmdRequestTable.front();
116  m_htmCmdRequestTable.pop_front();
117 
118  assert(isHtmCmdRequest(request->m_type));
119 
120  PacketPtr pkt = request->pkt;
121  delete request;
122 
123  // valid responses have zero as the payload
124  uint8_t* dataptr = pkt->getPtr<uint8_t>();
125  memset(dataptr, 0, pkt->getSize());
126  *dataptr = (uint8_t) htm_return_code;
127 
128  // record stats
129  if (htm_return_code == HtmFailedInCacheReason_NO_FAIL) {
130  if (pkt->req->isHTMStart()) {
131  m_htmstart_tick = pkt->req->time();
132  m_htmstart_instruction = pkt->req->getInstCount();
133  DPRINTF(HtmMem, "htmStart - htmUid=%u\n",
134  pkt->getHtmTransactionUid());
135  } else if (pkt->req->isHTMCommit()) {
136  Tick transaction_ticks = pkt->req->time() - m_htmstart_tick;
137  Cycles transaction_cycles = ticksToCycles(transaction_ticks);
138  m_htm_transaction_cycles.sample(transaction_cycles);
139  m_htmstart_tick = 0;
140  Counter transaction_instructions =
141  pkt->req->getInstCount() - m_htmstart_instruction;
143  transaction_instructions);
145  DPRINTF(HtmMem, "htmCommit - htmUid=%u\n",
146  pkt->getHtmTransactionUid());
147  } else if (pkt->req->isHTMAbort()) {
148  HtmFailureFaultCause cause = pkt->req->getHtmAbortCause();
149  assert(cause != HtmFailureFaultCause::INVALID);
150  auto cause_idx = static_cast<int>(cause);
151  m_htm_transaction_abort_cause[cause_idx]++;
152  DPRINTF(HtmMem, "htmAbort - reason=%s - htmUid=%u\n",
153  htmFailureToStr(cause),
154  pkt->getHtmTransactionUid());
155  }
156  } else {
157  DPRINTF(HtmMem, "HTM_CMD: fail - htmUid=%u\n",
158  pkt->getHtmTransactionUid());
159  }
160 
161  rubyHtmCallback(pkt, htm_return_code);
163  } else if (mode == HtmCallbackMode_LD_FAIL ||
164  mode == HtmCallbackMode_ST_FAIL) {
165  // transaction failed
166  assert(address == makeLineAddress(address));
167  assert(m_RequestTable.find(address) != m_RequestTable.end());
168 
169  auto &seq_req_list = m_RequestTable[address];
170  while (!seq_req_list.empty()) {
171  SequencerRequest &request = seq_req_list.front();
172 
173  PacketPtr pkt = request.pkt;
174  markRemoved();
175 
176  // TODO - atomics
177 
178  // store conditionals should indicate failure
179  if (request.m_type == RubyRequestType_Store_Conditional) {
180  pkt->req->setExtraData(0);
181  }
182 
183  DPRINTF(HtmMem, "%s_FAIL: size=%d - "
184  "addr=0x%lx - htmUid=%d\n",
185  (mode == HtmCallbackMode_LD_FAIL) ? "LD" : "ST",
186  pkt->getSize(),
187  address, pkt->getHtmTransactionUid());
188 
189  rubyHtmCallback(pkt, htm_return_code);
191  pkt = nullptr;
192  seq_req_list.pop_front();
193  }
194  // free all outstanding requests corresponding to this address
195  if (seq_req_list.empty()) {
196  m_RequestTable.erase(address);
197  }
198  } else {
199  panic("unrecognised HTM callback mode\n");
200  }
201 }
202 
203 void
205 {
206  // hardware transactional memory
208  .init(10)
209  .name(name() + ".htm_transaction_cycles")
210  .desc("number of cycles spent in an outer transaction")
212  ;
214  .init(10)
215  .name(name() + ".htm_transaction_instructions")
216  .desc("number of instructions spent in an outer transaction")
218  ;
219  auto num_causes = static_cast<int>(HtmFailureFaultCause::NUM_CAUSES);
221  .init(num_causes)
222  .name(name() + ".htm_transaction_abort_cause")
223  .desc("cause of htm transaction abort")
225  ;
226 
227  for (unsigned cause_idx = 0; cause_idx < num_causes; ++cause_idx) {
229  cause_idx,
231  }
232 }
233 
234 void
236  const HtmFailedInCacheReason htm_return_code)
237 {
238  // The packet was destined for memory and has not yet been turned
239  // into a response
240  assert(system->isMemAddr(pkt->getAddr()) || system->isDeviceMemAddr(pkt));
241  assert(pkt->isRequest());
242 
243  // First retrieve the request port from the sender State
244  RubyPort::SenderState *senderState =
245  safe_cast<RubyPort::SenderState *>(pkt->popSenderState());
246 
247  MemResponsePort *port = safe_cast<MemResponsePort*>(senderState->port);
248  assert(port != nullptr);
249  delete senderState;
250 
251  //port->htmCallback(pkt, htm_return_code);
252  DPRINTF(HtmMem, "HTM callback: start=%d, commit=%d, "
253  "cancel=%d, rc=%d\n",
254  pkt->req->isHTMStart(), pkt->req->isHTMCommit(),
255  pkt->req->isHTMCancel(), htm_return_code);
256 
257  // turn packet around to go back to requestor if response expected
258  if (pkt->needsResponse()) {
259  DPRINTF(RubyPort, "Sending packet back over port\n");
261  htmRetCodeConversion(htm_return_code));
262  port->schedTimingResp(pkt, curTick());
263  } else {
264  delete pkt;
265  }
266 
267  trySendRetries();
268 }
269 
270 void
272 {
274 
275  // Check for deadlock of any of the requests
276  Cycles current_time = curCycle();
277 
278  // hardware transactional memory commands
280  m_htmCmdRequestTable.begin();
282  m_htmCmdRequestTable.end();
283 
284  for (; htm != htm_end; ++htm) {
285  SequencerRequest* request = *htm;
286  if (current_time - request->issue_time < m_deadlock_threshold)
287  continue;
288 
289  panic("Possible Deadlock detected. Aborting!\n"
290  "version: %d m_htmCmdRequestTable: %d "
291  "current time: %u issue_time: %d difference: %d\n",
293  current_time * clockPeriod(),
294  request->issue_time * clockPeriod(),
295  (current_time * clockPeriod()) -
296  (request->issue_time * clockPeriod()));
297  }
298 }
299 
300 bool
302 {
303  return Sequencer::empty() && m_htmCmdRequestTable.empty();
304 }
305 
306 template <class VALUE>
307 std::ostream &
308 operator<<(std::ostream &out, const std::deque<VALUE> &queue)
309 {
310  auto i = queue.begin();
311  auto end = queue.end();
312 
313  out << "[";
314  for (; i != end; ++i)
315  out << " " << *i;
316  out << " ]";
317 
318  return out;
319 }
320 
321 void
322 HTMSequencer::print(std::ostream& out) const
323 {
324  Sequencer::print(out);
325 
326  out << "+ [HTMSequencer: " << m_version
327  << ", htm cmd request table: " << m_htmCmdRequestTable
328  << "]";
329 }
330 
331 // Insert the request in the request table. Return RequestStatus_Aliased
332 // if the entry was already present.
333 RequestStatus
334 HTMSequencer::insertRequest(PacketPtr pkt, RubyRequestType primary_type,
335  RubyRequestType secondary_type)
336 {
337  if (isHtmCmdRequest(primary_type)) {
338  // for the moment, allow just one HTM cmd into the cache controller.
339  // Later this can be adjusted for optimization, e.g.
340  // back-to-back HTM_Starts.
341  if ((m_htmCmdRequestTable.size() > 0) && !pkt->req->isHTMAbort())
342  return RequestStatus_BufferFull;
343 
344  // insert request into HtmCmd queue
345  SequencerRequest* htmReq =
346  new SequencerRequest(pkt, primary_type, secondary_type,
347  curCycle());
348  assert(htmReq);
349  m_htmCmdRequestTable.push_back(htmReq);
350  return RequestStatus_Ready;
351  } else {
352  return Sequencer::insertRequest(pkt, primary_type, secondary_type);
353  }
354 }
HtmFailureFaultCause::NUM_CAUSES
@ NUM_CAUSES
HTMSequencer::print
void print(std::ostream &out) const override
Definition: HTMSequencer.cc:322
HTMSequencer.hh
system.hh
SequencerRequest::pkt
PacketPtr pkt
Definition: Sequencer.hh:58
Sequencer::empty
virtual bool empty() const
Definition: Sequencer.cc:640
HTMSequencer::htmCallback
void htmCallback(Addr, const HtmCallbackMode, const HtmFailedInCacheReason)
Definition: HTMSequencer.cc:102
HTMSequencer::m_htmstart_instruction
Counter m_htmstart_instruction
Definition: HTMSequencer.hh:95
Packet::getAddr
Addr getAddr() const
Definition: packet.hh:755
makeLineAddress
Addr makeLineAddress(Addr addr)
Definition: Address.cc:54
Sequencer
Definition: Sequencer.hh:80
HtmCacheFailure::FAIL_OTHER
@ FAIL_OTHER
HTMSequencer::HTMSequencer
HTMSequencer(const RubyHTMSequencerParams &p)
Definition: HTMSequencer.cc:63
ArmISA::i
Bitfield< 7 > i
Definition: miscregs_types.hh:63
RubyPort::testDrainComplete
void testDrainComplete()
Definition: RubyPort.cc:483
HtmCacheFailure::NO_FAIL
@ NO_FAIL
SequencerRequest::m_type
RubyRequestType m_type
Definition: Sequencer.hh:59
HTMSequencer::m_htm_transaction_instructions
Stats::Histogram m_htm_transaction_instructions
Histogram of instruction lengths of HTM transactions.
Definition: HTMSequencer.hh:100
Tick
uint64_t Tick
Tick count type.
Definition: types.hh:59
Sequencer::wakeup
virtual void wakeup()
Definition: Sequencer.cc:210
Packet::req
RequestPtr req
A pointer to the original request.
Definition: packet.hh:341
Packet::getSize
unsigned getSize() const
Definition: packet.hh:765
HtmFailureFaultCause
HtmFailureFaultCause
Definition: htm.hh:44
HtmCacheFailure::FAIL_REMOTE
@ FAIL_REMOTE
Packet::isRequest
bool isRequest() const
Definition: packet.hh:560
QueuedResponsePort::schedTimingResp
void schedTimingResp(PacketPtr pkt, Tick when)
Schedule the sending of a timing response.
Definition: qport.hh:90
Sequencer::m_RequestTable
std::unordered_map< Addr, std::list< SequencerRequest > > m_RequestTable
Definition: Sequencer.hh:211
HTMSequencer::m_htm_transaction_abort_cause
Stats::Vector m_htm_transaction_abort_cause
Causes for HTM transaction aborts.
Definition: HTMSequencer.hh:102
Stats::DataWrap::flags
Derived & flags(Flags _flags)
Set the flags and marks this stat to print at the end of simulation.
Definition: statistics.hh:339
SequencerRequest::issue_time
Cycles issue_time
Definition: Sequencer.hh:61
Sequencer::print
virtual void print(std::ostream &out) const
Definition: Sequencer.cc:821
Counter
int64_t Counter
Statistics counter type.
Definition: types.hh:54
RubyPort::MemResponsePort
Definition: RubyPort.hh:75
Sequencer::insertRequest
virtual RequestStatus insertRequest(PacketPtr pkt, RubyRequestType primary_type, RubyRequestType secondary_type)
Definition: Sequencer.cc:291
operator<<
std::ostream & operator<<(std::ostream &out, const std::deque< VALUE > &queue)
Definition: HTMSequencer.cc:308
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:237
ADD_STAT
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
Definition: group.hh:71
RubyPort
Definition: RubyPort.hh:58
Sequencer::markRemoved
void markRemoved()
Definition: Sequencer.cc:318
Packet::needsResponse
bool needsResponse() const
Definition: packet.hh:571
Clocked::curCycle
Cycles curCycle() const
Determine the current cycle, corresponding to a tick aligned to a clock edge.
Definition: clocked_object.hh:192
ArmISA::mode
Bitfield< 4, 0 > mode
Definition: miscregs_types.hh:70
HTMSequencer::htmRetCodeConversion
HtmCacheFailure htmRetCodeConversion(const HtmFailedInCacheReason rc)
Htm return code conversion.
Definition: HTMSequencer.cc:46
RubySlicc_Util.hh
HTMSequencer::m_htmstart_tick
Tick m_htmstart_tick
Definition: HTMSequencer.hh:94
RubyPort::system
System * system
Definition: RubyPort.hh:193
HTMSequencer::regStats
void regStats() override
Callback to set stat parameters.
Definition: HTMSequencer.cc:204
HTMSequencer::rubyHtmCallback
void rubyHtmCallback(PacketPtr pkt, const HtmFailedInCacheReason fail_r)
Definition: HTMSequencer.cc:235
Addr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:148
HTMSequencer::wakeup
void wakeup() override
Definition: HTMSequencer.cc:271
Stats::DataWrap::name
Derived & name(const std::string &name)
Set the name and marks this stat to print at the end of simulation.
Definition: statistics.hh:270
HTMSequencer::insertRequest
RequestStatus insertRequest(PacketPtr pkt, RubyRequestType primary_type, RubyRequestType secondary_type) override
Definition: HTMSequencer.cc:334
Stats::dist
const FlagsType dist
Print the distribution.
Definition: info.hh:56
Stats::VectorBase::init
Derived & init(size_type size)
Set this vector to have the given size.
Definition: statistics.hh:1028
HtmCacheFailure
HtmCacheFailure
Definition: htm.hh:56
Clocked::clockPeriod
Tick clockPeriod() const
Definition: clocked_object.hh:214
Stats::nozero
const FlagsType nozero
Don't print if this is zero.
Definition: info.hh:58
HTMSequencer::~HTMSequencer
~HTMSequencer()
Definition: HTMSequencer.cc:97
Packet::getHtmTransactionUid
uint64_t getHtmTransactionUid() const
If a packet/request originates in a CPU executing in transactional mode, i.e.
Definition: packet.cc:550
HTMSequencer::m_htm_transaction_cycles
Stats::Histogram m_htm_transaction_cycles
Histogram of cycle latencies of HTM transactions.
Definition: HTMSequencer.hh:98
SimObject::name
virtual const std::string name() const
Definition: sim_object.hh:182
System::isDeviceMemAddr
bool isDeviceMemAddr(PacketPtr pkt) const
Similar to isMemAddr but for devices.
Definition: system.cc:421
Sequencer::m_deadlock_threshold
Cycles m_deadlock_threshold
Definition: Sequencer.hh:213
Clocked::ticksToCycles
Cycles ticksToCycles(Tick t) const
Definition: clocked_object.hh:219
Stats::pdf
const FlagsType pdf
Print the percent of the total that this entry represents.
Definition: info.hh:52
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:498
Packet
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:258
std::deque
STL deque class.
Definition: stl.hh:44
Packet::popSenderState
SenderState * popSenderState()
Pop the top of the state stack and return a pointer to it.
Definition: packet.cc:340
RubyPort::SenderState::port
MemResponsePort * port
Definition: RubyPort.hh:141
HTMSequencer::empty
bool empty() const override
Definition: HTMSequencer.cc:301
htmFailureToStr
std::string htmFailureToStr(HtmFailureFaultCause cause)
Convert enum into string to be used for debug purposes.
Definition: htm.cc:41
Stats::DistBase::sample
void sample(const U &v, int n=1)
Add a value to the distribtion n times.
Definition: statistics.hh:1323
Cycles
Cycles is a wrapper class for representing cycle counts, i.e.
Definition: types.hh:79
Packet::getPtr
T * getPtr()
get a pointer to the data ptr.
Definition: packet.hh:1158
SequencerRequest
Definition: Sequencer.hh:56
Stats::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:383
HTMSequencer::m_htmCmdRequestTable
std::deque< SequencerRequest * > m_htmCmdRequestTable
Definition: HTMSequencer.hh:92
curTick
Tick curTick()
The universal simulation clock.
Definition: cur_tick.hh:43
Stats::Histogram::init
Histogram & init(size_type size)
Set the parameters of this histogram.
Definition: statistics.hh:2153
HtmFailureFaultCause::INVALID
@ INVALID
MipsISA::p
Bitfield< 0 > p
Definition: pra_constants.hh:323
RubyPort::trySendRetries
void trySendRetries()
Definition: RubyPort.cc:457
Stats::total
const FlagsType total
Print the total.
Definition: info.hh:50
Stats::DataWrap::desc
Derived & desc(const std::string &_desc)
Set the description and marks this stat to print at the end of simulation.
Definition: statistics.hh:315
RubyPort::m_version
uint32_t m_version
Definition: RubyPort.hh:189
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:407
HtmCacheFailure::FAIL_SELF
@ FAIL_SELF
RubyPort::SenderState
Definition: RubyPort.hh:139
Stats::nonan
const FlagsType nonan
Don't print if this is NAN.
Definition: info.hh:60
panic
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:171
isHtmCmdRequest
bool isHtmCmdRequest(RubyRequestType type)
Definition: RubySlicc_Util.hh:146

Generated on Tue Jun 22 2021 15:28:30 for gem5 by doxygen 1.8.17