mc2lib
strong.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014-2016, Marco Elver
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *
12  * * Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the
15  * distribution.
16  *
17  * * Neither the name of the software nor the names of its contributors
18  * may be used to endorse or promote products derived from this
19  * software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33 
34 #ifndef MC2LIB_CODEGEN_OPS_STRONG_HPP_
35 #define MC2LIB_CODEGEN_OPS_STRONG_HPP_
36 
37 #include <algorithm>
38 #include <random>
39 #include <sstream>
40 #include <stdexcept>
41 
42 #include "../cats.hpp"
43 #include "../compiler.hpp"
44 
45 namespace mc2lib {
46 namespace codegen {
47 
52 namespace strong {
53 
54 struct Backend {
55  virtual ~Backend() {}
56 
57  virtual void Reset() {}
58 
59  virtual std::size_t Return(void *code, std::size_t len) const = 0;
60 
61  virtual std::size_t Delay(std::size_t length, void *code,
62  std::size_t len) const = 0;
63 
64  virtual std::size_t Read(types::Addr addr, types::InstPtr start, void *code,
65  std::size_t len, types::InstPtr *at) const = 0;
66 
67  virtual std::size_t ReadAddrDp(types::Addr addr, types::InstPtr start,
68  void *code, std::size_t len,
69  types::InstPtr *at) const = 0;
70 
71  virtual std::size_t Write(types::Addr addr, types::WriteID write_id,
72  types::InstPtr start, void *code, std::size_t len,
73  types::InstPtr *at) const = 0;
74 
75  virtual std::size_t ReadModifyWrite(types::Addr addr, types::WriteID write_id,
76  types::InstPtr start, void *code,
77  std::size_t len,
78  types::InstPtr *at) const = 0;
79 
80  virtual std::size_t CacheFlush(types::Addr addr, void *code,
81  std::size_t len) const = 0;
82 };
83 
87 
88 class Return : public Operation {
89  public:
90  explicit Return(types::Pid pid = -1) : Operation(pid) {}
91 
92  Operation::Ptr Clone() const override {
93  return std::make_shared<Return>(*this);
94  }
95 
96  void Reset() override {}
97 
98  bool EnableEmit(EvtStateCats *evts) override { return true; }
99 
100  void InsertPo(Operation::ThreadConstIt before, EvtStateCats *evts) override {}
101 
102  std::size_t Emit(types::InstPtr start, Backend *backend, EvtStateCats *evts,
103  void *code, std::size_t len) override {
104  return backend->Return(code, len);
105  }
106 
107  const mc::Event *LastEvent(const mc::Event *next_event,
108  EvtStateCats *evts) const override {
109  return nullptr;
110  }
111 
112  const mc::Event *FirstEvent(const mc::Event *prev_event,
113  EvtStateCats *evts) const override {
114  return nullptr;
115  }
116 
117  bool UpdateObs(types::InstPtr ip, int part, types::Addr addr,
118  const types::WriteID *from_id, std::size_t size,
119  EvtStateCats *evts) override {
120  return true;
121  }
122 };
123 
124 class Delay : public Operation {
125  public:
126  explicit Delay(std::size_t length, types::Pid pid = -1)
127  : Operation(pid), length_(length), before_(nullptr) {}
128 
129  Operation::Ptr Clone() const override {
130  return std::make_shared<Delay>(*this);
131  }
132 
133  void Reset() override { before_ = nullptr; }
134 
135  bool EnableEmit(EvtStateCats *evts) override { return true; }
136 
137  void InsertPo(Operation::ThreadConstIt before, EvtStateCats *evts) override {
138  before_ = *before;
139  }
140 
141  std::size_t Emit(types::InstPtr start, Backend *backend, EvtStateCats *evts,
142  void *code, std::size_t len) override {
143  return backend->Delay(length_, code, len);
144  }
145 
146  const mc::Event *LastEvent(const mc::Event *next_event,
147  EvtStateCats *evts) const override {
148  // Forward
149  if (before_ != nullptr) {
150  return before_->LastEvent(next_event, evts);
151  }
152 
153  return nullptr;
154  }
155 
156  const mc::Event *FirstEvent(const mc::Event *prev_event,
157  EvtStateCats *evts) const override {
158  // Forward
159  if (before_ != nullptr) {
160  return before_->FirstEvent(prev_event, evts);
161  }
162 
163  return nullptr;
164  }
165 
166  bool UpdateObs(types::InstPtr ip, int part, types::Addr addr,
167  const types::WriteID *from_id, std::size_t size,
168  EvtStateCats *evts) override {
169  throw std::logic_error("Unexpected UpdateObs");
170  return false;
171  }
172 
173  protected:
174  std::size_t length_;
175  const Operation *before_;
176 };
177 
178 class Read : public MemOperation {
179  public:
180  explicit Read(types::Addr addr, types::Pid pid = -1)
181  : MemOperation(pid), addr_(addr), event_(nullptr), from_(nullptr) {}
182 
183  Operation::Ptr Clone() const override {
184  return std::make_shared<Read>(*this);
185  }
186 
187  void Reset() override {
188  event_ = nullptr;
189  from_ = nullptr;
190  }
191 
192  bool EnableEmit(EvtStateCats *evts) override { return !evts->Exhausted(); }
193 
194  void InsertPo(Operation::ThreadConstIt before, EvtStateCats *evts) override {
195  event_ = evts->MakeRead(pid(), mc::Event::kRead, addr_)[0];
196 
197  if (*before != nullptr) {
198  auto event_before = (*before)->LastEvent(event_, evts);
199  if (event_before != nullptr) {
200  evts->ew()->po.Insert(*event_before, *event_);
201  }
202  }
203  }
204 
205  std::size_t Emit(types::InstPtr start, Backend *backend, EvtStateCats *evts,
206  void *code, std::size_t len) override {
207  return backend->Read(addr_, start, code, len, &at_);
208  }
209 
210  bool UpdateObs(types::InstPtr ip, int part, types::Addr addr,
211  const types::WriteID *from_id, std::size_t size,
212  EvtStateCats *evts) override {
213  assert(event_ != nullptr);
214  assert(ip == at_);
215  assert(addr == addr_);
216  assert(size == sizeof(types::WriteID));
217 
218  const mc::Event *from =
219  evts->GetWrite(MakeEventPtrs(event_), addr_, from_id)[0];
220 
221  if (from_ != nullptr) {
222  // If from_ == from, we still need to continue to try to erase and
223  // insert, in case the from-relation has been cleared.
224 
225  EraseObsHelper(from_, event_, evts->ew());
226  }
227 
228  from_ = from;
229  InsertObsHelper(from_, event_, evts->ew());
230 
231  return true;
232  }
233 
234  const mc::Event *LastEvent(const mc::Event *next_event,
235  EvtStateCats *evts) const override {
236  return event_;
237  }
238 
239  const mc::Event *FirstEvent(const mc::Event *prev_event,
240  EvtStateCats *evts) const override {
241  return event_;
242  }
243 
244  types::Addr addr() const override { return addr_; }
245 
246  protected:
247  virtual void InsertObsHelper(const mc::Event *e1, const mc::Event *e2,
248  mc::cats::ExecWitness *ew) {
249  ew->rf.Insert(*e1, *e2, true);
250  }
251 
252  virtual void EraseObsHelper(const mc::Event *e1, const mc::Event *e2,
253  mc::cats::ExecWitness *ew) {
254  ew->rf.Erase(*e1, *e2);
255  }
256 
259  const mc::Event *from_;
261 };
262 
263 class ReadAddrDp : public Read {
264  public:
265  explicit ReadAddrDp(types::Addr addr, types::Pid pid = -1)
266  : Read(addr, pid) {}
267 
268  Operation::Ptr Clone() const override {
269  return std::make_shared<ReadAddrDp>(*this);
270  }
271 
272  // TODO(melver): InsertPo: if we start supporting an Arch which does not
273  // order Read->Read, add a dependency-hb between this and the last Read --
274  // this assumes all Reads are reading into the same register, and this read
275  // computes the address with this one register.
276  // NOTE: before can be used to traverse operations backwards before "before".
277 
278  std::size_t Emit(types::InstPtr start, Backend *backend, EvtStateCats *evts,
279  void *code, std::size_t len) override {
280  return backend->ReadAddrDp(addr_, start, code, len, &at_);
281  }
282 };
283 
284 class Write : public Read {
285  public:
286  explicit Write(types::Addr addr, types::Pid pid = -1)
287  : Read(addr, pid), write_id_(0) {}
288 
289  Operation::Ptr Clone() const override {
290  return std::make_shared<Write>(*this);
291  }
292 
293  void Reset() override {
294  event_ = nullptr;
295  from_ = nullptr;
296  write_id_ = 0;
297  }
298 
299  void InsertPo(Operation::ThreadConstIt before, EvtStateCats *evts) override {
300  event_ = evts->MakeWrite(pid(), mc::Event::kWrite, addr_, &write_id_)[0];
301 
302  if (*before != nullptr) {
303  auto event_before = (*before)->LastEvent(event_, evts);
304  if (event_before != nullptr) {
305  evts->ew()->po.Insert(*event_before, *event_);
306  }
307  }
308  }
309 
310  std::size_t Emit(types::InstPtr start, Backend *backend, EvtStateCats *evts,
311  void *code, std::size_t len) override {
312  return backend->Write(addr_, write_id_, start, code, len, &at_);
313  }
314 
315  protected:
316  void InsertObsHelper(const mc::Event *e1, const mc::Event *e2,
317  mc::cats::ExecWitness *ew) override {
318  ew->co.Insert(*e1, *e2);
319  }
320 
321  void EraseObsHelper(const mc::Event *e1, const mc::Event *e2,
322  mc::cats::ExecWitness *ew) override {
323  ew->co.Erase(*e1, *e2);
324  }
325 
327 };
328 
329 class ReadModifyWrite : public MemOperation {
330  public:
331  explicit ReadModifyWrite(types::Addr addr, types::Pid pid = -1)
332  : MemOperation(pid), addr_(addr), last_part_(-1) {}
333 
334  Operation::Ptr Clone() const override {
335  return std::make_shared<ReadModifyWrite>(*this);
336  }
337 
338  void Reset() override {
339  last_part_ = -1;
340  event_r_ = nullptr;
341  event_w_ = nullptr;
342  from_ = nullptr;
343  write_id_ = 0;
344  }
345 
346  bool EnableEmit(EvtStateCats *evts) override { return !evts->Exhausted(); }
347 
348  void InsertPo(Operation::ThreadConstIt before, EvtStateCats *evts) override {
349  event_r_ = evts->MakeRead(pid(), mc::Event::kRead, addr_)[0];
350  event_w_ = evts->MakeWrite(pid(), mc::Event::kWrite, addr_, &write_id_)[0];
351 
352  if (*before != nullptr) {
353  auto event_before = (*before)->LastEvent(event_r_, evts);
354  if (event_before != nullptr) {
355  evts->ew()->po.Insert(*event_before, *event_r_);
356 
357  if (dynamic_cast<mc::cats::Arch_TSO *>(evts->arch()) != nullptr) {
358  // Implied fence before atomic
359  auto arch_tso = dynamic_cast<mc::cats::Arch_TSO *>(evts->arch());
360  arch_tso->mfence.Insert(*event_before, *event_r_);
361  }
362  }
363  }
364 
365  evts->ew()->po.Insert(*event_r_, *event_w_);
366  }
367 
368  std::size_t Emit(types::InstPtr start, Backend *backend, EvtStateCats *evts,
369  void *code, std::size_t len) override {
370  return backend->ReadModifyWrite(addr_, write_id_, start, code, len, &at_);
371  }
372 
373  bool UpdateObs(types::InstPtr ip, int part, types::Addr addr,
374  const types::WriteID *from_id, std::size_t size,
375  EvtStateCats *evts) override {
376  assert(event_r_ != nullptr);
377  assert(event_w_ != nullptr);
378  assert(ip == at_);
379  assert(addr == addr_);
380  assert(size == sizeof(types::WriteID));
381 
382  // This also alerts us if the read would be seeing the write's data.
383  const mc::Event *from =
384  evts->GetWrite(MakeEventPtrs(event_w_), addr_, from_id)[0];
385 
386  auto part_event = event_r_;
387  auto obs_rel = &evts->ew()->rf;
388 
389  // TODO(melver): clean this up! Do we need ability to update squashed?
390 
391  if (last_part_ == -1 || part <= last_part_) {
392  // First part: read
393 
394  if (from_ != nullptr) {
395  // Restart
396  evts->ew()->rf.Erase(*from_, *event_r_);
397  evts->ew()->co.Erase(*from_, *event_w_);
398  }
399  } else {
400  // Second part: write
401  assert(part > last_part_);
402 
403  // Check atomicity.
404  if (*from != *from_) {
405  std::ostringstream oss;
406  oss << "RMW NOT ATOMIC: expected <" << static_cast<std::string>(*from_)
407  << ">, but overwriting <" << static_cast<std::string>(*from)
408  << ">!";
409  throw mc::Error(oss.str());
410  }
411 
412  part_event = event_w_;
413  obs_rel = &evts->ew()->co;
414  }
415 
416  obs_rel->Insert(*from, *part_event, true);
417 
418  from_ = from;
419  last_part_ = part;
420  return true;
421  }
422 
423  const mc::Event *LastEvent(const mc::Event *next_event,
424  EvtStateCats *evts) const override {
425  if (dynamic_cast<mc::cats::Arch_TSO *>(evts->arch()) != nullptr) {
426  // Implied fence after atomic
427  auto arch_tso = dynamic_cast<mc::cats::Arch_TSO *>(evts->arch());
428  arch_tso->mfence.Insert(*event_w_, *next_event);
429  }
430 
431  return event_w_;
432  }
433 
434  const mc::Event *FirstEvent(const mc::Event *prev_event,
435  EvtStateCats *evts) const override {
436  return event_r_;
437  }
438 
439  types::Addr addr() const override { return addr_; }
440 
441  protected:
446  const mc::Event *from_;
449 };
450 
451 class CacheFlush : public MemOperation {
452  public:
453  explicit CacheFlush(types::Addr addr, types::Pid pid = -1)
454  : MemOperation(pid), addr_(addr), before_(nullptr) {}
455 
456  Operation::Ptr Clone() const override {
457  return std::make_shared<CacheFlush>(*this);
458  }
459 
460  void Reset() override { before_ = nullptr; }
461 
462  bool EnableEmit(EvtStateCats *evts) override { return true; }
463 
464  void InsertPo(Operation::ThreadConstIt before, EvtStateCats *evts) override {
465  before_ = *before;
466  }
467 
468  std::size_t Emit(types::InstPtr start, Backend *backend, EvtStateCats *evts,
469  void *code, std::size_t len) override {
470  return backend->CacheFlush(addr_, code, len);
471  }
472 
473  const mc::Event *LastEvent(const mc::Event *next_event,
474  EvtStateCats *evts) const override {
475  // Forward
476  if (before_ != nullptr) {
477  return before_->LastEvent(next_event, evts);
478  }
479 
480  return nullptr;
481  }
482 
483  const mc::Event *FirstEvent(const mc::Event *prev_event,
484  EvtStateCats *evts) const override {
485  // Forward
486  if (before_ != nullptr) {
487  return before_->FirstEvent(prev_event, evts);
488  }
489 
490  return nullptr;
491  }
492 
493  bool UpdateObs(types::InstPtr ip, int part, types::Addr addr,
494  const types::WriteID *from_id, std::size_t size,
495  EvtStateCats *evts) override {
496  return true;
497  }
498 
499  types::Addr addr() const override { return addr_; }
500 
501  protected:
503  const Operation *before_;
504 };
505 
506 class ReadSequence : public NullOperation {
507  public:
508  explicit ReadSequence(types::Addr min_addr, types::Addr max_addr,
509  types::Pid pid = -1)
510  : NullOperation(pid), min_addr_(min_addr), max_addr_(max_addr) {
511  while (min_addr <= max_addr) {
512  sequence_.emplace_back(std::make_shared<Read>(min_addr, pid));
513  min_addr += 64;
514  }
515  }
516 
517  void AdvanceThread(Operation::ThreadItStack *it_stack) const override {
518  ++(it_stack->back().first);
519  it_stack->emplace_back(sequence_.begin(), sequence_.end());
520  }
521 
522  Operation::Ptr Clone() const override {
523  // Don't just copy, need deep clone
524  return std::make_shared<ReadSequence>(min_addr_, max_addr_, pid());
525  }
526 
527  void Reset() override {
528  for (const auto &op : sequence_) {
529  op->Reset();
530  }
531  }
532 
533  protected:
537 };
538 
543  typedef Operation ResultType;
544 
545  explicit RandomFactory(types::Pid min_pid, types::Pid max_pid,
546  types::Addr min_addr, types::Addr max_addr,
547  std::size_t stride = sizeof(types::WriteID),
548  std::size_t max_sequence = 50, bool extended = false)
549  : min_pid_(min_pid),
550  max_pid_(max_pid),
551  min_addr_(min_addr),
552  max_addr_(max_addr),
553  stride_(stride),
554  max_sequence_(max_sequence),
555  extended_(extended) {
556  assert(this->stride() >= sizeof(types::WriteID));
557  assert(this->stride() % sizeof(types::WriteID) == 0);
558  }
559 
560  void Reset(types::Pid min_pid, types::Pid max_pid, types::Addr min_addr,
561  types::Addr max_addr,
562  std::size_t stride = sizeof(types::WriteID)) {
563  min_pid_ = min_pid;
564  max_pid_ = max_pid;
565  min_addr_ = min_addr;
566  max_addr_ = max_addr;
567  stride_ = stride;
568  }
569 
570  template <class URNG, class AddrFilterFunc>
571  Operation::Ptr operator()(URNG &urng, AddrFilterFunc addr_filter_func,
572  std::size_t max_fails = 0) const {
573  // Choice distribution
574  const std::size_t max_choice = (extended_ ? 1005 : 1000) - 1;
575  std::uniform_int_distribution<std::size_t> dist_choice(0, max_choice);
576 
577  // Pid distribution
578  std::uniform_int_distribution<types::Pid> dist_pid(min_pid_, max_pid_);
579 
580  // Addr distribution
581  auto chunk_min_addr = min_addr_;
582  auto chunk_max_addr = max_addr_;
583 
584  if (ChunkSize() > 1 && HoleSize() > 1) {
585  std::size_t chunk_cnt =
586  for_each_AddrRange([](types::Addr a, types::Addr b) {});
587  std::size_t select_chunk =
588  std::uniform_int_distribution<std::size_t>(0, chunk_cnt - 1)(urng);
589 
590  chunk_min_addr = min_addr_ + (select_chunk * HoleSize());
591  chunk_max_addr = chunk_min_addr + ChunkSize() - 1;
592 
593  assert(chunk_min_addr >= min_addr_);
594  assert(chunk_max_addr <= max_addr_);
595  }
596 
597  std::uniform_int_distribution<types::Addr> dist_addr(
598  chunk_min_addr, chunk_max_addr - EvtStateCats::kMaxOpSize);
599 
600  // Sequence distribution
601  std::uniform_int_distribution<std::size_t> dist_sequence(1, max_sequence_);
602 
603  // select op
604  const auto choice = dist_choice(urng);
605 
606  // pid
607  const auto pid = dist_pid(urng);
608 
609  // addr (lazy)
610  auto addr = [&]() {
611  types::Addr result = 0;
612 
613  for (std::size_t tries = 0; tries < max_fails + 1; ++tries) {
614  result = dist_addr(urng);
615  result -= result % stride();
616  if (result < chunk_min_addr) result += stride();
617  assert(result >= chunk_min_addr);
618  assert(result <= chunk_max_addr - EvtStateCats::kMaxOpSize);
619 
620  if (addr_filter_func(result)) {
621  return result;
622  }
623  }
624 
625  return result;
626  };
627 
628  // sequence (lazy)
629  auto sequence = [&dist_sequence, &urng]() { return dist_sequence(urng); };
630 
631  if (choice < 500) { // 50%
632  return std::make_shared<Read>(addr(), pid);
633  } else if (choice < 550) { // 5%
634  return std::make_shared<ReadAddrDp>(addr(), pid);
635  } else if (choice < 970) { // 42%
636  return std::make_shared<Write>(addr(), pid);
637  } else if (choice < 980) { // 1%
638  return std::make_shared<ReadModifyWrite>(addr(), pid);
639  } else if (choice < 990) { // 1%
640  return std::make_shared<CacheFlush>(addr(), pid);
641  } else if (choice < 1000) { // 1%
642  return std::make_shared<Delay>(sequence(), pid);
643  } else if (extended_) {
644  // REAL_PERCENTAGE_OF_100 = PERC * (1000 / MAX_CHOICE)
645 
646  if (choice < 1005) { // 0.5%
647  auto min_a = addr();
648  // TODO(melver): do not hard-code stride
649  auto max_a = min_a + sequence() * 64;
650  if (max_a > max_addr()) {
651  max_a = max_addr();
652  }
653 
654  return std::make_shared<ReadSequence>(min_a, max_a, pid);
655  }
656  }
657 
658  // should never get here
659  throw std::logic_error("Not exhaustive");
660  return nullptr;
661  }
662 
663  template <class URNG>
664  Operation::Ptr operator()(URNG &urng) const {
665  return (*this)(urng, [](types::Addr addr) { return true; });
666  }
667 
668  types::Pid min_pid() const { return min_pid_; }
669 
670  types::Pid max_pid() const { return max_pid_; }
671 
672  types::Addr min_addr() const { return min_addr_; }
673 
674  types::Addr max_addr() const { return max_addr_; }
675 
676  std::size_t stride() const { return stride_ & ((1ULL << 16) - 1); }
677 
678  std::size_t ChunkSize() const {
679  return 1ULL << ((stride_ & (0xffULL << 24)) >> 24);
680  }
681 
682  std::size_t HoleSize() const {
683  return 1ULL << ((stride_ & (0xffULL << 16)) >> 16);
684  }
685 
686  template <class Func>
687  std::size_t for_each_AddrRange(Func func) const {
688  if (ChunkSize() > 1 && HoleSize() > 1) {
689  assert(HoleSize() >= ChunkSize());
690  assert(ChunkSize() <= (max_addr_ - min_addr_ + 1));
691 
692  std::size_t chunk_cnt = 0;
693 
694  for (;; ++chunk_cnt) {
695  types::Addr min = min_addr_ + (chunk_cnt * HoleSize());
696  types::Addr max = min + ChunkSize() - 1;
697  if (max > max_addr_) break;
698 
699  func(min, max);
700  }
701 
702  return chunk_cnt;
703  }
704 
705  func(min_addr_, max_addr_);
706  return 1;
707  }
708 
709  std::size_t max_sequence() const { return max_sequence_; }
710 
711  void set_max_sequence(std::size_t val) { max_sequence_ = val; }
712 
713  bool extended() const { return extended_; }
714 
715  void set_extended(bool val) { extended_ = val; }
716 
717  private:
722  std::size_t stride_;
723  std::size_t max_sequence_;
724  bool extended_;
725 };
726 
727 } // namespace strong
728 } // namespace codegen
729 } // namespace mc2lib
730 
731 #endif /* MC2LIB_CODEGEN_OPS_STRONG_HPP_ */
732 
733 /* vim: set ts=2 sts=2 sw=2 et : */
std::size_t stride_
Definition: strong.hpp:722
Definition: eventsets.hpp:227
static constexpr std::size_t kMaxOpSize
Definition: cats.hpp:81
bool UpdateObs(types::InstPtr ip, int part, types::Addr addr, const types::WriteID *from_id, std::size_t size, EvtStateCats *evts) override
Definition: strong.hpp:210
Operation::Ptr Clone() const override
Definition: strong.hpp:268
std::size_t max_sequence() const
Definition: strong.hpp:709
void InsertPo(Operation::ThreadConstIt before, EvtStateCats *evts) override
Definition: strong.hpp:464
void set_extended(bool val)
Definition: strong.hpp:715
auto MakeEventPtrs(const mc::Event *e1, Ts... en) -> EventPtrs<(1+sizeof...(Ts)) *sizeof(types::WriteID)>
Definition: compiler.hpp:67
bool EnableEmit(EvtStateCats *evts) override
Definition: strong.hpp:135
void InsertPo(Operation::ThreadConstIt before, EvtStateCats *evts) override
Definition: strong.hpp:100
ReadModifyWrite(types::Addr addr, types::Pid pid=-1)
Definition: strong.hpp:331
void Reset() override
Definition: strong.hpp:293
std::size_t ChunkSize() const
Definition: strong.hpp:678
Operation::Ptr Clone() const override
Definition: strong.hpp:92
void InsertPo(Operation::ThreadConstIt before, EvtStateCats *evts) override
Definition: strong.hpp:137
const mc::Event * FirstEvent(const mc::Event *prev_event, EvtStateCats *evts) const override
Definition: strong.hpp:483
ReadAddrDp(types::Addr addr, types::Pid pid=-1)
Definition: strong.hpp:265
types::Addr addr() const override
Definition: strong.hpp:499
std::size_t Emit(types::InstPtr start, Backend *backend, EvtStateCats *evts, void *code, std::size_t len) override
Definition: strong.hpp:205
const mc::Event * FirstEvent(const mc::Event *prev_event, EvtStateCats *evts) const override
Definition: strong.hpp:434
Operation::Thread sequence_
Definition: strong.hpp:536
Definition: strong.hpp:178
bool extended() const
Definition: strong.hpp:713
virtual std::size_t CacheFlush(types::Addr addr, void *code, std::size_t len) const =0
void InsertPo(Operation::ThreadConstIt before, EvtStateCats *evts) override
Definition: strong.hpp:194
virtual std::size_t ReadAddrDp(types::Addr addr, types::InstPtr start, void *code, std::size_t len, types::InstPtr *at) const =0
std::size_t stride() const
Definition: strong.hpp:676
void InsertPo(Operation::ThreadConstIt before, EvtStateCats *evts) override
Definition: strong.hpp:348
bool EnableEmit(EvtStateCats *evts) override
Definition: strong.hpp:192
Interface to memconsistency::cats data structures.
Definition: cats.hpp:78
void InsertPo(Operation::ThreadConstIt before, EvtStateCats *evts) override
Definition: strong.hpp:299
Definition: cats.hpp:47
std::size_t Emit(types::InstPtr start, Backend *backend, EvtStateCats *evts, void *code, std::size_t len) override
Definition: strong.hpp:141
types::WriteID write_id_
Definition: strong.hpp:447
Definition: compiler.hpp:77
bool UpdateObs(types::InstPtr ip, int part, types::Addr addr, const types::WriteID *from_id, std::size_t size, EvtStateCats *evts) override
Definition: strong.hpp:117
void set_max_sequence(std::size_t val)
Definition: strong.hpp:711
EventPtrs< max_size_bytes > MakeWrite(types::Pid pid, mc::Event::Type type, types::Addr addr, types::WriteID *data, std::size_t size=max_size_bytes)
Definition: cats.hpp:161
types::InstPtr at_
Definition: strong.hpp:448
MemOp< Backend, EvtStateCats > MemOperation
Definition: strong.hpp:85
virtual std::size_t Return(void *code, std::size_t len) const =0
bool EnableEmit(EvtStateCats *evts) override
Definition: strong.hpp:346
Definition: strong.hpp:451
virtual ~Backend()
Definition: strong.hpp:55
types::Addr addr() const override
Definition: strong.hpp:439
Delay(std::size_t length, types::Pid pid=-1)
Definition: strong.hpp:126
EventPtrs< max_size_bytes > MakeRead(types::Pid pid, mc::Event::Type type, types::Addr addr, std::size_t size=max_size_bytes)
Definition: cats.hpp:146
void Reset() override
Definition: strong.hpp:133
virtual void Reset()
Definition: strong.hpp:57
mc::cats::ExecWitness * ew()
Definition: cats.hpp:238
const mc::Event * FirstEvent(const mc::Event *prev_event, EvtStateCats *evts) const override
Definition: strong.hpp:239
Types< true >::InstPtr InstPtr
Instruction pointer type.
Definition: types.hpp:81
Operation::Ptr operator()(URNG &urng) const
Definition: strong.hpp:664
types::Addr max_addr_
Definition: strong.hpp:721
const Operation * before_
Definition: strong.hpp:503
Operation ResultType
Definition: strong.hpp:543
void Reset() override
Definition: strong.hpp:527
NullOp< Backend, EvtStateCats > NullOperation
Definition: strong.hpp:86
std::size_t Emit(types::InstPtr start, Backend *backend, EvtStateCats *evts, void *code, std::size_t len) override
Definition: strong.hpp:102
types::Addr addr_
Definition: strong.hpp:442
void Reset() override
Definition: strong.hpp:187
virtual std::size_t Read(types::Addr addr, types::InstPtr start, void *code, std::size_t len, types::InstPtr *at) const =0
void EraseObsHelper(const mc::Event *e1, const mc::Event *e2, mc::cats::ExecWitness *ew) override
Definition: strong.hpp:321
Definition: strong.hpp:506
Definition: strong.hpp:284
types::Addr min_addr() const
Definition: strong.hpp:672
const mc::Event * from_
Definition: strong.hpp:259
Definition: eventsets.hpp:103
ThreadConst::const_iterator ThreadConstIt
Definition: compiler.hpp:90
Definition: strong.hpp:542
bool EnableEmit(EvtStateCats *evts) override
Definition: strong.hpp:462
std::vector< Ptr > Thread
Definition: compiler.hpp:83
types::Addr addr_
Definition: strong.hpp:502
types::Addr min_addr_
Definition: strong.hpp:534
bool UpdateObs(types::InstPtr ip, int part, types::Addr addr, const types::WriteID *from_id, std::size_t size, EvtStateCats *evts) override
Definition: strong.hpp:166
std::vector< std::pair< ThreadIt, ThreadIt > > ThreadItStack
Definition: compiler.hpp:86
Read(types::Addr addr, types::Pid pid=-1)
Definition: strong.hpp:180
Operation::Ptr Clone() const override
Definition: strong.hpp:334
const mc::Event * LastEvent(const mc::Event *next_event, EvtStateCats *evts) const override
Definition: strong.hpp:107
const mc::Event * LastEvent(const mc::Event *next_event, EvtStateCats *evts) const override
Definition: strong.hpp:234
ReadSequence(types::Addr min_addr, types::Addr max_addr, types::Pid pid=-1)
Definition: strong.hpp:508
Definition: strong.hpp:54
std::size_t Emit(types::InstPtr start, Backend *backend, EvtStateCats *evts, void *code, std::size_t len) override
Definition: strong.hpp:310
Definition: compiler.hpp:245
virtual void EraseObsHelper(const mc::Event *e1, const mc::Event *e2, mc::cats::ExecWitness *ew)
Definition: strong.hpp:252
CacheFlush(types::Addr addr, types::Pid pid=-1)
Definition: strong.hpp:453
const mc::Event * LastEvent(const mc::Event *next_event, EvtStateCats *evts) const override
Definition: strong.hpp:146
types::Addr max_addr_
Definition: strong.hpp:535
std::size_t HoleSize() const
Definition: strong.hpp:682
const Operation * before_
Definition: strong.hpp:175
const mc::Event * FirstEvent(const mc::Event *prev_event, EvtStateCats *evts) const override
Definition: strong.hpp:156
void InsertObsHelper(const mc::Event *e1, const mc::Event *e2, mc::cats::ExecWitness *ew) override
Definition: strong.hpp:316
types::WriteID write_id_
Definition: strong.hpp:326
void Reset() override
Definition: strong.hpp:338
bool EnableEmit(EvtStateCats *evts) override
Definition: strong.hpp:98
Op< Backend, EvtStateCats > Operation
Definition: strong.hpp:84
Definition: strong.hpp:124
std::size_t length_
Definition: strong.hpp:174
const mc::Event * from_
Definition: strong.hpp:446
bool UpdateObs(types::InstPtr ip, int part, types::Addr addr, const types::WriteID *from_id, std::size_t size, EvtStateCats *evts) override
Definition: strong.hpp:373
RandomFactory(types::Pid min_pid, types::Pid max_pid, types::Addr min_addr, types::Addr max_addr, std::size_t stride=sizeof(types::WriteID), std::size_t max_sequence=50, bool extended=false)
Definition: strong.hpp:545
const mc::Event * FirstEvent(const mc::Event *prev_event, EvtStateCats *evts) const override
Definition: strong.hpp:112
Definition: compiler.hpp:253
types::Addr addr() const override
Definition: strong.hpp:244
Definition: strong.hpp:263
Return(types::Pid pid=-1)
Definition: strong.hpp:90
Operation::Ptr Clone() const override
Definition: strong.hpp:289
types::Addr addr_
Definition: strong.hpp:257
Operation::Ptr Clone() const override
Definition: strong.hpp:183
mc::cats::Architecture * arch()
Definition: cats.hpp:242
Operation::Ptr operator()(URNG &urng, AddrFilterFunc addr_filter_func, std::size_t max_fails=0) const
Definition: strong.hpp:571
types::Addr max_addr() const
Definition: strong.hpp:674
Operation::Ptr Clone() const override
Definition: strong.hpp:129
const mc::Event * LastEvent(const mc::Event *next_event, EvtStateCats *evts) const override
Definition: strong.hpp:423
Types< true >::WriteID WriteID
Write ID type.
Definition: types.hpp:86
virtual std::size_t ReadModifyWrite(types::Addr addr, types::WriteID write_id, types::InstPtr start, void *code, std::size_t len, types::InstPtr *at) const =0
bool extended_
Definition: strong.hpp:724
const mc::Event * event_
Definition: strong.hpp:258
virtual void InsertObsHelper(const mc::Event *e1, const mc::Event *e2, mc::cats::ExecWitness *ew)
Definition: strong.hpp:247
Definition: strong.hpp:88
bool UpdateObs(types::InstPtr ip, int part, types::Addr addr, const types::WriteID *from_id, std::size_t size, EvtStateCats *evts) override
Definition: strong.hpp:493
Write(types::Addr addr, types::Pid pid=-1)
Definition: strong.hpp:286
Types< true >::Addr Addr
Address type.
Definition: types.hpp:66
EventPtrs< max_size_bytes > GetWrite(const EventPtrs< max_size_bytes > &after, types::Addr addr, const types::WriteID *from_id, std::size_t size=max_size_bytes)
Definition: cats.hpp:179
void Reset(types::Pid min_pid, types::Pid max_pid, types::Addr min_addr, types::Addr max_addr, std::size_t stride=sizeof(types::WriteID))
Definition: strong.hpp:560
void Reset() override
Definition: strong.hpp:96
types::Pid max_pid_
Definition: strong.hpp:719
types::Addr min_addr_
Definition: strong.hpp:720
std::size_t max_sequence_
Definition: strong.hpp:723
std::shared_ptr< Op > Ptr
Definition: compiler.hpp:82
types::Pid min_pid_
Definition: strong.hpp:718
int last_part_
Definition: strong.hpp:443
const mc::Event * event_w_
Definition: strong.hpp:445
Types< true >::Pid Pid
Processor/thread ID type.
Definition: types.hpp:71
types::Pid min_pid() const
Definition: strong.hpp:668
void Reset() override
Definition: strong.hpp:460
std::size_t Emit(types::InstPtr start, Backend *backend, EvtStateCats *evts, void *code, std::size_t len) override
Definition: strong.hpp:468
virtual std::size_t Delay(std::size_t length, void *code, std::size_t len) const =0
std::size_t Emit(types::InstPtr start, Backend *backend, EvtStateCats *evts, void *code, std::size_t len) override
Definition: strong.hpp:278
Operation::Ptr Clone() const override
Definition: strong.hpp:456
Operation::Ptr Clone() const override
Definition: strong.hpp:522
virtual std::size_t Write(types::Addr addr, types::WriteID write_id, types::InstPtr start, void *code, std::size_t len, types::InstPtr *at) const =0
const mc::Event * event_r_
Definition: strong.hpp:444
std::size_t Emit(types::InstPtr start, Backend *backend, EvtStateCats *evts, void *code, std::size_t len) override
Definition: strong.hpp:368
const mc::Event * LastEvent(const mc::Event *next_event, EvtStateCats *evts) const override
Definition: strong.hpp:473
types::Pid max_pid() const
Definition: strong.hpp:670
void AdvanceThread(Operation::ThreadItStack *it_stack) const override
Definition: strong.hpp:517
std::size_t for_each_AddrRange(Func func) const
Definition: strong.hpp:687
types::InstPtr at_
Definition: strong.hpp:260
bool Exhausted() const
Definition: cats.hpp:114