gem5  v20.1.0.0
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 using namespace std;
46 
49  const HtmFailedInCacheReason ruby_ret_code)
50 {
51  switch (ruby_ret_code) {
52  case HtmFailedInCacheReason_NO_FAIL:
54  case HtmFailedInCacheReason_FAIL_SELF:
56  case HtmFailedInCacheReason_FAIL_REMOTE:
58  case HtmFailedInCacheReason_FAIL_OTHER:
60  default:
61  panic("Invalid htm return code\n");
62  }
63 }
64 
66 RubyHTMSequencerParams::create()
67 {
68  return new HTMSequencer(this);
69 }
70 
71 HTMSequencer::HTMSequencer(const RubyHTMSequencerParams *p)
72  : Sequencer(p)
73 {
74  m_htmstart_tick = 0;
76 }
77 
79 {
80 }
81 
82 void
84  const HtmCallbackMode mode,
85  const HtmFailedInCacheReason htm_return_code)
86 {
87  // mode=0: HTM command
88  // mode=1: transaction failed - inform via LD
89  // mode=2: transaction failed - inform via ST
90 
91  if (mode == HtmCallbackMode_HTM_CMD) {
92  SequencerRequest* request = nullptr;
93 
94  assert(m_htmCmdRequestTable.size() > 0);
95 
96  request = m_htmCmdRequestTable.front();
97  m_htmCmdRequestTable.pop_front();
98 
99  assert(isHtmCmdRequest(request->m_type));
100 
101  PacketPtr pkt = request->pkt;
102  delete request;
103 
104  // valid responses have zero as the payload
105  uint8_t* dataptr = pkt->getPtr<uint8_t>();
106  memset(dataptr, 0, pkt->getSize());
107  *dataptr = (uint8_t) htm_return_code;
108 
109  // record stats
110  if (htm_return_code == HtmFailedInCacheReason_NO_FAIL) {
111  if (pkt->req->isHTMStart()) {
112  m_htmstart_tick = pkt->req->time();
113  m_htmstart_instruction = pkt->req->getInstCount();
114  DPRINTF(HtmMem, "htmStart - htmUid=%u\n",
115  pkt->getHtmTransactionUid());
116  } else if (pkt->req->isHTMCommit()) {
117  Tick transaction_ticks = pkt->req->time() - m_htmstart_tick;
118  Cycles transaction_cycles = ticksToCycles(transaction_ticks);
119  m_htm_transaction_cycles.sample(transaction_cycles);
120  m_htmstart_tick = 0;
121  Counter transaction_instructions =
122  pkt->req->getInstCount() - m_htmstart_instruction;
124  transaction_instructions);
126  DPRINTF(HtmMem, "htmCommit - htmUid=%u\n",
127  pkt->getHtmTransactionUid());
128  } else if (pkt->req->isHTMAbort()) {
129  HtmFailureFaultCause cause = pkt->req->getHtmAbortCause();
130  assert(cause != HtmFailureFaultCause::INVALID);
131  auto cause_idx = static_cast<int>(cause);
132  m_htm_transaction_abort_cause[cause_idx]++;
133  DPRINTF(HtmMem, "htmAbort - reason=%s - htmUid=%u\n",
134  htmFailureToStr(cause),
135  pkt->getHtmTransactionUid());
136  }
137  } else {
138  DPRINTF(HtmMem, "HTM_CMD: fail - htmUid=%u\n",
139  pkt->getHtmTransactionUid());
140  }
141 
142  rubyHtmCallback(pkt, htm_return_code);
144  } else if (mode == HtmCallbackMode_LD_FAIL ||
145  mode == HtmCallbackMode_ST_FAIL) {
146  // transaction failed
147  assert(address == makeLineAddress(address));
148  assert(m_RequestTable.find(address) != m_RequestTable.end());
149 
150  auto &seq_req_list = m_RequestTable[address];
151  while (!seq_req_list.empty()) {
152  SequencerRequest &request = seq_req_list.front();
153 
154  PacketPtr pkt = request.pkt;
155  markRemoved();
156 
157  // TODO - atomics
158 
159  // store conditionals should indicate failure
160  if (request.m_type == RubyRequestType_Store_Conditional) {
161  pkt->req->setExtraData(0);
162  }
163 
164  DPRINTF(HtmMem, "%s_FAIL: size=%d - "
165  "addr=0x%lx - htmUid=%d\n",
166  (mode == HtmCallbackMode_LD_FAIL) ? "LD" : "ST",
167  pkt->getSize(),
168  address, pkt->getHtmTransactionUid());
169 
170  rubyHtmCallback(pkt, htm_return_code);
172  pkt = nullptr;
173  seq_req_list.pop_front();
174  }
175  // free all outstanding requests corresponding to this address
176  if (seq_req_list.empty()) {
177  m_RequestTable.erase(address);
178  }
179  } else {
180  panic("unrecognised HTM callback mode\n");
181  }
182 }
183 
184 void
186 {
188 
189  // hardware transactional memory
191  .init(10)
192  .name(name() + ".htm_transaction_cycles")
193  .desc("number of cycles spent in an outer transaction")
195  ;
197  .init(10)
198  .name(name() + ".htm_transaction_instructions")
199  .desc("number of instructions spent in an outer transaction")
201  ;
202  auto num_causes = static_cast<int>(HtmFailureFaultCause::NUM_CAUSES);
204  .init(num_causes)
205  .name(name() + ".htm_transaction_abort_cause")
206  .desc("cause of htm transaction abort")
208  ;
209 
210  for (unsigned cause_idx = 0; cause_idx < num_causes; ++cause_idx) {
212  cause_idx,
214  }
215 }
216 
217 void
219  const HtmFailedInCacheReason htm_return_code)
220 {
221  // The packet was destined for memory and has not yet been turned
222  // into a response
223  assert(system->isMemAddr(pkt->getAddr()) || system->isDeviceMemAddr(pkt));
224  assert(pkt->isRequest());
225 
226  // First retrieve the request port from the sender State
227  RubyPort::SenderState *senderState =
228  safe_cast<RubyPort::SenderState *>(pkt->popSenderState());
229 
230  MemResponsePort *port = safe_cast<MemResponsePort*>(senderState->port);
231  assert(port != nullptr);
232  delete senderState;
233 
234  //port->htmCallback(pkt, htm_return_code);
235  DPRINTF(HtmMem, "HTM callback: start=%d, commit=%d, "
236  "cancel=%d, rc=%d\n",
237  pkt->req->isHTMStart(), pkt->req->isHTMCommit(),
238  pkt->req->isHTMCancel(), htm_return_code);
239 
240  // turn packet around to go back to requestor if response expected
241  if (pkt->needsResponse()) {
242  DPRINTF(RubyPort, "Sending packet back over port\n");
244  htmRetCodeConversion(htm_return_code));
245  port->schedTimingResp(pkt, curTick());
246  } else {
247  delete pkt;
248  }
249 
250  trySendRetries();
251 }
252 
253 void
255 {
257 
258  // Check for deadlock of any of the requests
259  Cycles current_time = curCycle();
260 
261  // hardware transactional memory commands
263  m_htmCmdRequestTable.begin();
265  m_htmCmdRequestTable.end();
266 
267  for (; htm != htm_end; ++htm) {
268  SequencerRequest* request = *htm;
269  if (current_time - request->issue_time < m_deadlock_threshold)
270  continue;
271 
272  panic("Possible Deadlock detected. Aborting!\n"
273  "version: %d m_htmCmdRequestTable: %d "
274  "current time: %u issue_time: %d difference: %d\n",
276  current_time * clockPeriod(),
277  request->issue_time * clockPeriod(),
278  (current_time * clockPeriod()) -
279  (request->issue_time * clockPeriod()));
280  }
281 }
282 
283 bool
285 {
286  return Sequencer::empty() && m_htmCmdRequestTable.empty();
287 }
288 
289 template <class VALUE>
290 std::ostream &
291 operator<<(ostream &out, const std::deque<VALUE> &queue)
292 {
293  auto i = queue.begin();
294  auto end = queue.end();
295 
296  out << "[";
297  for (; i != end; ++i)
298  out << " " << *i;
299  out << " ]";
300 
301  return out;
302 }
303 
304 void
305 HTMSequencer::print(ostream& out) const
306 {
307  Sequencer::print(out);
308 
309  out << "+ [HTMSequencer: " << m_version
310  << ", htm cmd request table: " << m_htmCmdRequestTable
311  << "]";
312 }
313 
314 // Insert the request in the request table. Return RequestStatus_Aliased
315 // if the entry was already present.
316 RequestStatus
317 HTMSequencer::insertRequest(PacketPtr pkt, RubyRequestType primary_type,
318  RubyRequestType secondary_type)
319 {
320  if (isHtmCmdRequest(primary_type)) {
321  // for the moment, allow just one HTM cmd into the cache controller.
322  // Later this can be adjusted for optimization, e.g.
323  // back-to-back HTM_Starts.
324  if ((m_htmCmdRequestTable.size() > 0) && !pkt->req->isHTMAbort())
325  return RequestStatus_BufferFull;
326 
327  // insert request into HtmCmd queue
328  SequencerRequest* htmReq =
329  new SequencerRequest(pkt, primary_type, secondary_type,
330  curCycle());
331  assert(htmReq);
332  m_htmCmdRequestTable.push_back(htmReq);
333  return RequestStatus_Ready;
334  } else {
335  return Sequencer::insertRequest(pkt, primary_type, secondary_type);
336  }
337 }
HtmFailureFaultCause::NUM_CAUSES
@ NUM_CAUSES
HTMSequencer::print
void print(std::ostream &out) const override
Definition: HTMSequencer.cc:305
HTMSequencer.hh
system.hh
SequencerRequest::pkt
PacketPtr pkt
Definition: Sequencer.hh:58
Sequencer::empty
virtual bool empty() const
Definition: Sequencer.cc:572
HTMSequencer::htmCallback
void htmCallback(Addr, const HtmCallbackMode, const HtmFailedInCacheReason)
Definition: HTMSequencer.cc:83
HTMSequencer::m_htmstart_instruction
Counter m_htmstart_instruction
Definition: HTMSequencer.hh:95
Packet::getAddr
Addr getAddr() const
Definition: packet.hh:754
makeLineAddress
Addr makeLineAddress(Addr addr)
Definition: Address.cc:54
Sequencer
Definition: Sequencer.hh:80
HtmCacheFailure::FAIL_OTHER
@ FAIL_OTHER
ArmISA::i
Bitfield< 7 > i
Definition: miscregs_types.hh:63
RubyPort::testDrainComplete
void testDrainComplete()
Definition: RubyPort.cc:481
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:63
Sequencer::wakeup
virtual void wakeup()
Definition: Sequencer.cc:159
Packet::req
RequestPtr req
A pointer to the original request.
Definition: packet.hh:340
Packet::getSize
unsigned getSize() const
Definition: packet.hh:764
HtmFailureFaultCause
HtmFailureFaultCause
Definition: htm.hh:44
HtmCacheFailure::FAIL_REMOTE
@ FAIL_REMOTE
Packet::isRequest
bool isRequest() const
Definition: packet.hh:559
QueuedResponsePort::schedTimingResp
void schedTimingResp(PacketPtr pkt, Tick when)
Schedule the sending of a timing response.
Definition: qport.hh:90
HTMSequencer
Definition: HTMSequencer.hh:51
Sequencer::m_RequestTable
std::unordered_map< Addr, std::list< SequencerRequest > > m_RequestTable
Definition: Sequencer.hh:203
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:331
SequencerRequest::issue_time
Cycles issue_time
Definition: Sequencer.hh:61
Sequencer::print
virtual void print(std::ostream &out) const
Definition: Sequencer.cc:755
Counter
int64_t Counter
Statistics counter type.
Definition: types.hh:58
RubyPort::MemResponsePort
Definition: RubyPort.hh:75
Sequencer::insertRequest
virtual RequestStatus insertRequest(PacketPtr pkt, RubyRequestType primary_type, RubyRequestType secondary_type)
Definition: Sequencer.cc:240
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:234
RubyPort
Definition: RubyPort.hh:58
Sequencer::markRemoved
void markRemoved()
Definition: Sequencer.cc:267
Packet::needsResponse
bool needsResponse() const
Definition: packet.hh:570
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:48
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:185
HTMSequencer::rubyHtmCallback
void rubyHtmCallback(PacketPtr pkt, const HtmFailedInCacheReason fail_r)
Definition: HTMSequencer.cc:218
Addr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
HTMSequencer::wakeup
void wakeup() override
Definition: HTMSequencer.cc:254
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:274
HTMSequencer::insertRequest
RequestStatus insertRequest(PacketPtr pkt, RubyRequestType primary_type, RubyRequestType secondary_type) override
Definition: HTMSequencer.cc:317
HTMSequencer::HTMSequencer
HTMSequencer(const RubyHTMSequencerParams *p)
Definition: HTMSequencer.cc:71
Stats::dist
const FlagsType dist
Print the distribution.
Definition: info.hh:55
Stats::VectorBase::init
Derived & init(size_type size)
Set this vector to have the given size.
Definition: statistics.hh:1177
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:57
HTMSequencer::~HTMSequencer
~HTMSequencer()
Definition: HTMSequencer.cc:78
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:133
Sequencer::regStats
void regStats() override
Callback to set stat parameters.
Definition: Sequencer.cc:777
System::isDeviceMemAddr
bool isDeviceMemAddr(PacketPtr pkt) const
Similar to isMemAddr but for devices.
Definition: system.cc:431
std
Overload hash function for BasicBlockRange type.
Definition: vec_reg.hh:587
Sequencer::m_deadlock_threshold
Cycles m_deadlock_threshold
Definition: Sequencer.hh:205
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:51
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:257
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:284
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:1924
Cycles
Cycles is a wrapper class for representing cycle counts, i.e.
Definition: types.hh:83
Packet::getPtr
T * getPtr()
get a pointer to the data ptr.
Definition: packet.hh:1157
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:374
HTMSequencer::m_htmCmdRequestTable
std::deque< SequencerRequest * > m_htmCmdRequestTable
Definition: HTMSequencer.hh:92
Stats::Histogram::init
Histogram & init(size_type size)
Set the parameters of this histogram.
Definition: statistics.hh:2669
HtmFailureFaultCause::INVALID
@ INVALID
MipsISA::p
Bitfield< 0 > p
Definition: pra_constants.hh:323
RubyPort::trySendRetries
void trySendRetries()
Definition: RubyPort.cc:455
Stats::total
const FlagsType total
Print the total.
Definition: info.hh:49
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:307
RubyPort::m_version
uint32_t m_version
Definition: RubyPort.hh:189
operator<<
std::ostream & operator<<(ostream &out, const std::deque< VALUE > &queue)
Definition: HTMSequencer.cc:291
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:417
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:59
panic
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:171
isHtmCmdRequest
bool isHtmCmdRequest(RubyRequestType type)
Definition: RubySlicc_Util.hh:140
curTick
Tick curTick()
The current simulated tick.
Definition: core.hh:45

Generated on Wed Sep 30 2020 14:02:13 for gem5 by doxygen 1.8.17