mc2lib
armv7.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_ARMv7_HPP_
35 #define MC2LIB_CODEGEN_OPS_ARMv7_HPP_
36 
37 #include <algorithm>
38 #include <random>
39 #include <stdexcept>
40 
41 #include "../cats.hpp"
42 #include "../compiler.hpp"
43 
44 namespace mc2lib {
45 namespace codegen {
46 
53 namespace armv7 {
54 
55 #define ASM_PRELUDE char *cnext__ = static_cast<char *>(code);
56 #define ASM_LEN (static_cast<std::size_t>(cnext__ - static_cast<char *>(code)))
57 #define ASM_AT (start + ASM_LEN)
58 
59 #define ASM16(v) \
60  do { \
61  assert(ASM_LEN + 2 <= len); \
62  *reinterpret_cast<std::uint16_t *>(cnext__) = (v); \
63  cnext__ += 2; \
64  } while (0)
65 
66 #define ASM_PROLOGUE return ASM_LEN;
67 
68 // Thumb
69 class Backend {
70  public:
71  void Reset() {}
72 
73  // Currently supports single byte operations only; to test for single-copy
74  // atomicity, implement multi-byte operations support.
75  static_assert(sizeof(types::WriteID) == 1, "Unsupported read/write size!");
76 
77  enum Reg {
78  r0 = 0,
79  r1,
80  r2,
81  r3,
82  r4,
83 
84  // reserved
88  };
89 
90  std::size_t Return(void *code, std::size_t len) const {
92  ASM16(0x4770); // bx lr
94  }
95 
96  std::size_t Delay(std::size_t length, void *code, std::size_t len) const {
98  for (std::size_t i = 0; i < length; ++i) {
99  ASM16(0xbf00); // nop
100  }
101  ASM_PROLOGUE;
102  }
103 
104  std::size_t DMB_ST(void *code, std::size_t len) const {
105  ASM_PRELUDE;
106  // dmb st
107  ASM16(0xf3bf);
108  ASM16(0x8f5e);
109  ASM_PROLOGUE;
110  }
111 
112  std::size_t Read(types::Addr addr, Reg out, types::InstPtr start, void *code,
113  std::size_t len, types::InstPtr *at) const {
114  ASM_PRELUDE;
115 
116  Helper h(cnext__, code, len);
117  h.MovImm32(r6__, addr);
118 
119  // ldrb out, [r6, #0]
120  *at = ASM_AT;
121  ASM16(0x7830 | out);
122 
123  ASM_PROLOGUE;
124  }
125 
126  std::size_t ReadAddrDp(types::Addr addr, Reg out, Reg dp,
127  types::InstPtr start, void *code, std::size_t len,
128  types::InstPtr *at) const {
129  ASM_PRELUDE;
130 
131  Helper h(cnext__, code, len);
132  h.MovImm32(r6__, addr);
133 
134  // eor dp, dp
135  ASM16(0x4040 | (dp << 3) | dp);
136 
137  // ldrb out, [r6, dp]
138  *at = ASM_AT;
139  ASM16(0x5c30 | (dp << 6) | out);
140 
141  ASM_PROLOGUE;
142  }
143 
144  std::size_t Write(types::Addr addr, types::WriteID write_id,
145  types::InstPtr start, void *code, std::size_t len,
146  types::InstPtr *at) const {
147  ASM_PRELUDE;
148 
149  Helper h(cnext__, code, len);
150  h.MovImm32(r6__, addr);
151 
152  // movs r7, #write_id
153  ASM16(0x2700 | write_id);
154 
155  // strb r7, [r6, #0]
156  *at = ASM_AT;
157  ASM16(0x7037);
158 
159  ASM_PROLOGUE;
160  }
161 
162  protected:
163  class Helper {
164  public:
165  Helper(char *&cnext, void *&code, std::size_t len)
166  : cnext__(cnext), code(code), len(len) {}
167 
168  void MovImm32(Reg reg, std::uint32_t imm32) {
169  // movw reg, #(imm32 & 0xffff)
170  std::uint16_t imm32_w = imm32 & 0xffff;
171  ASM16(0xf240
172  // [10:10]
173  | ((imm32_w & 0x0800) >> 1)
174  // [3:0]
175  | ((imm32_w & 0xf000) >> 12));
176  ASM16( // [14:12]
177  ((imm32_w & 0x0700) << 4)
178  // [11:8]
179  | (reg << 8)
180  // [7:0]
181  | (imm32_w & 0x00ff));
182 
183  // movt reg, #((imm32 & 0xffff0000) >> 16)
184  std::uint16_t imm32_t = (imm32 & 0xffff0000) >> 16;
185  ASM16(0xf2c0
186  // [10:10]
187  | ((imm32_t & 0x0800) >> 1)
188  // [3:0]
189  | ((imm32_t & 0xf000) >> 12));
190  ASM16( // [14:12]
191  ((imm32_t & 0x0700) << 4)
192  // [11:8]
193  | (reg << 8)
194  // [7:0]
195  | (imm32_t & 0x00ff));
196  }
197 
198  protected:
199  char *&cnext__;
200  void *&code;
201  const std::size_t len;
202  };
203 };
204 
205 #undef ASM_PRELUDE
206 #undef ASM_LEN
207 #undef ASM_AT
208 #undef ASM16
209 #undef ASM_PROLOGUE
210 
214 
215 class Return : public Operation {
216  public:
217  explicit Return(types::Pid pid = -1) : Operation(pid) {}
218 
219  Operation::Ptr Clone() const override {
220  return std::make_shared<Return>(*this);
221  }
222 
223  void Reset() override {}
224 
225  bool EnableEmit(EvtStateCats *evts) override { return true; }
226 
227  void InsertPo(Operation::ThreadConstIt before, EvtStateCats *evts) override {}
228 
229  std::size_t Emit(types::InstPtr start, Backend *backend, EvtStateCats *evts,
230  void *code, std::size_t len) override {
231  return backend->Return(code, len);
232  }
233 
234  const mc::Event *LastEvent(const mc::Event *next_event,
235  EvtStateCats *evts) const override {
236  return nullptr;
237  }
238 
239  const mc::Event *FirstEvent(const mc::Event *prev_event,
240  EvtStateCats *evts) const override {
241  return nullptr;
242  }
243 
244  bool UpdateObs(types::InstPtr ip, int part, types::Addr addr,
245  const types::WriteID *from_id, std::size_t size,
246  EvtStateCats *evts) override {
247  return true;
248  }
249 };
250 
251 class Delay : public Operation {
252  public:
253  explicit Delay(std::size_t length, types::Pid pid = -1)
254  : Operation(pid), length_(length), before_(nullptr) {}
255 
256  Operation::Ptr Clone() const override {
257  return std::make_shared<Delay>(*this);
258  }
259 
260  void Reset() override { before_ = nullptr; }
261 
262  bool EnableEmit(EvtStateCats *evts) override { return true; }
263 
264  void InsertPo(Operation::ThreadConstIt before, EvtStateCats *evts) override {
265  before_ = *before;
266  }
267 
268  std::size_t Emit(types::InstPtr start, Backend *backend, EvtStateCats *evts,
269  void *code, std::size_t len) override {
270  return backend->Delay(length_, code, len);
271  }
272 
273  const mc::Event *LastEvent(const mc::Event *next_event,
274  EvtStateCats *evts) const override {
275  // Forward
276  if (before_ != nullptr) {
277  return before_->LastEvent(next_event, evts);
278  }
279 
280  return nullptr;
281  }
282 
283  const mc::Event *FirstEvent(const mc::Event *prev_event,
284  EvtStateCats *evts) const override {
285  // Forward
286  if (before_ != nullptr) {
287  return before_->FirstEvent(prev_event, evts);
288  }
289 
290  return nullptr;
291  }
292 
293  bool UpdateObs(types::InstPtr ip, int part, types::Addr addr,
294  const types::WriteID *from_id, std::size_t size,
295  EvtStateCats *evts) override {
296  throw std::logic_error("Unexpected UpdateObs");
297  return false;
298  }
299 
300  protected:
301  std::size_t length_;
302  const Operation *before_;
303 };
304 
305 class Read : public MemOperation {
306  public:
307  explicit Read(types::Addr addr, Backend::Reg out, types::Pid pid = -1)
308  : MemOperation(pid),
309  addr_(addr),
310  out_(out),
311  event_(nullptr),
312  from_(nullptr) {}
313 
314  Operation::Ptr Clone() const override {
315  return std::make_shared<Read>(*this);
316  }
317 
318  void Reset() override {
319  event_ = nullptr;
320  from_ = nullptr;
321  }
322 
323  bool EnableEmit(EvtStateCats *evts) override { return !evts->Exhausted(); }
324 
325  void InsertPo(Operation::ThreadConstIt before, EvtStateCats *evts) override {
326  event_ = evts->MakeRead(pid(), mc::Event::kRead, addr_)[0];
327 
328  if (*before != nullptr) {
329  auto event_before = (*before)->LastEvent(event_, evts);
330  if (event_before != nullptr) {
331  evts->ew()->po.Insert(*event_before, *event_);
332  }
333  }
334  }
335 
336  std::size_t Emit(types::InstPtr start, Backend *backend, EvtStateCats *evts,
337  void *code, std::size_t len) override {
338  return backend->Read(addr_, out(), start, code, len, &at_);
339  }
340 
341  bool UpdateObs(types::InstPtr ip, int part, types::Addr addr,
342  const types::WriteID *from_id, std::size_t size,
343  EvtStateCats *evts) override {
344  assert(event_ != nullptr);
345  assert(ip == at_);
346  assert(addr == addr_);
347  assert(size == sizeof(types::WriteID));
348 
349  const mc::Event *from =
350  evts->GetWrite(MakeEventPtrs(event_), addr_, from_id)[0];
351 
352  if (from_ != nullptr) {
353  // If from_ == from, we still need to continue to try to erase and
354  // insert, in case the from-relation has been cleared.
355 
356  evts->ew()->rf.Erase(*from_, *event_);
357  }
358 
359  from_ = from;
360  evts->ew()->rf.Insert(*from_, *event_, true);
361 
362  return true;
363  }
364 
365  const mc::Event *LastEvent(const mc::Event *next_event,
366  EvtStateCats *evts) const override {
367  return event_;
368  }
369 
370  const mc::Event *FirstEvent(const mc::Event *prev_event,
371  EvtStateCats *evts) const override {
372  return event_;
373  }
374 
375  types::Addr addr() const override { return addr_; }
376 
377  Backend::Reg out() const { return out_; }
378 
379  protected:
383  const mc::Event *from_;
385 };
386 
387 class ReadAddrDp : public Read {
388  public:
390  types::Pid pid = -1)
391  : Read(addr, reg, pid), dp_(dp) {}
392 
393  Operation::Ptr Clone() const override {
394  return std::make_shared<ReadAddrDp>(*this);
395  }
396 
397  void InsertPo(Operation::ThreadConstIt before, EvtStateCats *evts) override {
398  event_ = evts->MakeRead(pid(), mc::Event::kRead | mc::Event::kRegInAddr,
399  addr_)[0];
400 
401  if (*before != nullptr) {
402  auto event_before = (*before)->LastEvent(event_, evts);
403  if (event_before != nullptr) {
404  evts->ew()->po.Insert(*event_before, *event_);
405 
406  // Find read dependency.
407  auto arch = dynamic_cast<mc::cats::Arch_ARMv7 *>(evts->arch());
408  if (arch != nullptr) {
409  do {
410  auto potential_dp_read = dynamic_cast<const Read *>(*before);
411  if (potential_dp_read != nullptr) {
412  if (potential_dp_read->out() == dp_) {
413  auto event_dp = potential_dp_read->LastEvent(event_, evts);
414  arch->dd_reg.Insert(*event_dp, *event_);
415  break;
416  }
417  }
418  } while (*(--before) != nullptr);
419  }
420  }
421  }
422  }
423 
424  std::size_t Emit(types::InstPtr start, Backend *backend, EvtStateCats *evts,
425  void *code, std::size_t len) override {
426  return backend->ReadAddrDp(addr_, out(), dp_, start, code, len, &at_);
427  }
428 
429  protected:
431 };
432 
433 class Write : public MemOperation {
434  public:
435  explicit Write(types::Addr addr, types::Pid pid = -1)
436  : MemOperation(pid), addr_(addr), write_id_(0) {}
437 
438  Operation::Ptr Clone() const override {
439  return std::make_shared<Write>(*this);
440  }
441 
442  void Reset() override {
443  event_ = nullptr;
444  from_ = nullptr;
445  write_id_ = 0;
446  }
447 
448  bool EnableEmit(EvtStateCats *evts) override { return !evts->Exhausted(); }
449 
450  void InsertPo(Operation::ThreadConstIt before, EvtStateCats *evts) override {
451  event_ = evts->MakeWrite(pid(), mc::Event::kWrite, addr_, &write_id_)[0];
452 
453  if (*before != nullptr) {
454  auto event_before = (*before)->LastEvent(event_, evts);
455  if (event_before != nullptr) {
456  evts->ew()->po.Insert(*event_before, *event_);
457  }
458  }
459  }
460 
461  std::size_t Emit(types::InstPtr start, Backend *backend, EvtStateCats *evts,
462  void *code, std::size_t len) override {
463  return backend->Write(addr_, write_id_, start, code, len, &at_);
464  }
465 
466  bool UpdateObs(types::InstPtr ip, int part, types::Addr addr,
467  const types::WriteID *from_id, std::size_t size,
468  EvtStateCats *evts) override {
469  assert(event_ != nullptr);
470  assert(ip == at_);
471  assert(addr == addr_);
472  assert(size == sizeof(types::WriteID));
473 
474  const mc::Event *from =
475  evts->GetWrite(MakeEventPtrs(event_), addr_, from_id)[0];
476 
477  if (from_ != nullptr) {
478  // If from_ == from, we still need to continue to try to erase and
479  // insert, in case the from-relation has been cleared.
480 
481  evts->ew()->co.Erase(*from_, *event_);
482  }
483 
484  from_ = from;
485  evts->ew()->co.Insert(*from_, *event_, true);
486 
487  return true;
488  }
489 
490  const mc::Event *LastEvent(const mc::Event *next_event,
491  EvtStateCats *evts) const override {
492  return event_;
493  }
494 
495  const mc::Event *FirstEvent(const mc::Event *prev_event,
496  EvtStateCats *evts) const override {
497  return event_;
498  }
499 
500  types::Addr addr() const override { return addr_; }
501 
502  protected:
506  const mc::Event *from_;
508 };
509 
510 class DMB_ST : public Operation {
511  public:
512  explicit DMB_ST(types::Pid pid = -1)
513  : Operation(pid), before_(nullptr), first_write_before_(nullptr) {}
514 
515  Operation::Ptr Clone() const override {
516  return std::make_shared<DMB_ST>(*this);
517  }
518 
519  void Reset() override {
520  before_ = nullptr;
521  first_write_before_ = nullptr;
522  }
523 
524  bool EnableEmit(EvtStateCats *evts) override { return true; }
525 
526  void InsertPo(Operation::ThreadConstIt before, EvtStateCats *evts) override {
527  before_ = *before;
528 
529  while (*before != nullptr) {
530  auto potential_write = dynamic_cast<const Write *>(*before);
531  if (potential_write != nullptr) {
532  first_write_before_ = potential_write;
533  break;
534  }
535  --before;
536  }
537  }
538 
539  void RegisterCallback(Operation::CallbackStack *callback_stack) override {
540  callback_stack->push_back([this](Operation *after, types::InstPtr start,
541  Backend *backend, EvtStateCats *evts,
542  void *code, std::size_t len) {
543  if (first_write_before_ != nullptr) {
544  auto potential_write = dynamic_cast<const Write *>(after);
545  if (potential_write != nullptr) {
546  auto arch = dynamic_cast<mc::cats::Arch_ARMv7 *>(evts->arch());
547  if (arch != nullptr) {
548  auto event_before = first_write_before_->LastEvent(nullptr, evts);
549  auto event_after = potential_write->FirstEvent(nullptr, evts);
550  assert(event_before != nullptr);
551  assert(event_after != nullptr);
552 
553  arch->dmb_st.Insert(*event_before, *event_after);
554  // cats::ARMv7 takes care of transitivity.
555  }
556  first_write_before_ = nullptr;
557  }
558  }
559  return 0;
560  });
561  }
562 
563  std::size_t Emit(types::InstPtr start, Backend *backend, EvtStateCats *evts,
564  void *code, std::size_t len) override {
565  return backend->DMB_ST(code, len);
566  }
567 
568  const mc::Event *LastEvent(const mc::Event *next_event,
569  EvtStateCats *evts) const override {
570  // Forward
571  if (before_ != nullptr) {
572  return before_->LastEvent(next_event, evts);
573  }
574 
575  return nullptr;
576  }
577 
578  const mc::Event *FirstEvent(const mc::Event *prev_event,
579  EvtStateCats *evts) const override {
580  // Forward
581  if (before_ != nullptr) {
582  return before_->FirstEvent(prev_event, evts);
583  }
584 
585  return nullptr;
586  }
587 
588  bool UpdateObs(types::InstPtr ip, int part, types::Addr addr,
589  const types::WriteID *from_id, std::size_t size,
590  EvtStateCats *evts) override {
591  throw std::logic_error("Unexpected UpdateObs");
592  return false;
593  }
594 
595  protected:
596  const Operation *before_;
597  const Operation *first_write_before_;
598 };
599 
604  typedef Operation ResultType;
605 
606  explicit RandomFactory(types::Pid min_pid, types::Pid max_pid,
607  types::Addr min_addr, types::Addr max_addr,
608  std::size_t stride = sizeof(types::WriteID),
609  std::size_t max_sequence = 50)
610  : min_pid_(min_pid),
611  max_pid_(max_pid),
612  min_addr_(min_addr),
613  max_addr_(max_addr),
614  stride_(stride),
615  max_sequence_(max_sequence) {
616  assert(this->stride() >= sizeof(types::WriteID));
617  assert(this->stride() % sizeof(types::WriteID) == 0);
618  }
619 
620  void Reset(types::Pid min_pid, types::Pid max_pid, types::Addr min_addr,
621  types::Addr max_addr,
622  std::size_t stride = sizeof(types::WriteID)) {
623  min_pid_ = min_pid;
624  max_pid_ = max_pid;
625  min_addr_ = min_addr;
626  max_addr_ = max_addr;
627  stride_ = stride;
628  }
629 
630  template <class URNG, class AddrFilterFunc>
631  Operation::Ptr operator()(URNG &urng, AddrFilterFunc addr_filter_func,
632  std::size_t max_fails = 0) const {
633  // Choice distribution
634  std::uniform_int_distribution<std::size_t> dist_choice(0, 1000 - 1);
635 
636  // Pid distribution
637  std::uniform_int_distribution<types::Pid> dist_pid(min_pid_, max_pid_);
638 
639  // Addr distribution
640  auto chunk_min_addr = min_addr_;
641  auto chunk_max_addr = max_addr_;
642 
643  if (ChunkSize() > 1 && HoleSize() > 1) {
644  std::size_t chunk_cnt =
645  for_each_AddrRange([](types::Addr a, types::Addr b) {});
646  std::size_t select_chunk =
647  std::uniform_int_distribution<std::size_t>(0, chunk_cnt - 1)(urng);
648 
649  chunk_min_addr = min_addr_ + (select_chunk * HoleSize());
650  chunk_max_addr = chunk_min_addr + ChunkSize() - 1;
651 
652  assert(chunk_min_addr >= min_addr_);
653  assert(chunk_max_addr <= max_addr_);
654  }
655 
656  std::uniform_int_distribution<types::Addr> dist_addr(
657  chunk_min_addr, chunk_max_addr - EvtStateCats::kMaxOpSize);
658 
659  // Sequence distribution
660  std::uniform_int_distribution<std::size_t> dist_sequence(1, max_sequence_);
661 
662  // Register distribution
663  std::uniform_int_distribution<int> dist_reg(Backend::r0, Backend::r4);
664 
665  // select op
666  const auto choice = dist_choice(urng);
667 
668  // pid
669  const auto pid = dist_pid(urng);
670 
671  // addr (lazy)
672  auto addr = [&]() {
673  types::Addr result = 0;
674 
675  for (std::size_t tries = 0; tries < max_fails + 1; ++tries) {
676  result = dist_addr(urng);
677  result -= result % stride();
678  if (result < chunk_min_addr) result += stride();
679  assert(result >= chunk_min_addr);
680  assert(result <= chunk_max_addr - EvtStateCats::kMaxOpSize);
681 
682  if (addr_filter_func(result)) {
683  return result;
684  }
685  }
686 
687  return result;
688  };
689 
690  // sequence (lazy)
691  auto sequence = [&dist_sequence, &urng]() { return dist_sequence(urng); };
692 
693  // sequence (lazy)
694  auto reg = [&dist_reg, &urng]() {
695  return static_cast<Backend::Reg>(dist_reg(urng));
696  };
697 
698  if (choice < 320) { // 32%
699  return std::make_shared<Read>(addr(), reg(), pid);
700  } else if (choice < 560) { // 24%
701  return std::make_shared<ReadAddrDp>(addr(), reg(), reg(), pid);
702  } else if (choice < 980) { // 42%
703  return std::make_shared<Write>(addr(), pid);
704  } else if (choice < 990) { // 1%
705  return std::make_shared<DMB_ST>(pid);
706  } else if (choice < 1000) { // 1%
707  return std::make_shared<Delay>(sequence(), pid);
708  }
709 
710  // should never get here
711  throw std::logic_error("Not exhaustive");
712  return nullptr;
713  }
714 
715  template <class URNG>
716  Operation::Ptr operator()(URNG &urng) const {
717  return (*this)(urng, [](types::Addr addr) { return true; });
718  }
719 
720  types::Pid min_pid() const { return min_pid_; }
721 
722  types::Pid max_pid() const { return max_pid_; }
723 
724  types::Addr min_addr() const { return min_addr_; }
725 
726  types::Addr max_addr() const { return max_addr_; }
727 
728  std::size_t stride() const { return stride_ & ((1ULL << 16) - 1); }
729 
730  std::size_t ChunkSize() const {
731  return 1ULL << ((stride_ & (0xffULL << 24)) >> 24);
732  }
733 
734  std::size_t HoleSize() const {
735  return 1ULL << ((stride_ & (0xffULL << 16)) >> 16);
736  }
737 
738  template <class Func>
739  std::size_t for_each_AddrRange(Func func) const {
740  if (ChunkSize() > 1 && HoleSize() > 1) {
741  assert(HoleSize() >= ChunkSize());
742  assert(ChunkSize() <= (max_addr_ - min_addr_ + 1));
743 
744  std::size_t chunk_cnt = 0;
745 
746  for (;; ++chunk_cnt) {
747  types::Addr min = min_addr_ + (chunk_cnt * HoleSize());
748  types::Addr max = min + ChunkSize() - 1;
749  if (max > max_addr_) break;
750 
751  func(min, max);
752  }
753 
754  return chunk_cnt;
755  }
756 
757  func(min_addr_, max_addr_);
758  return 1;
759  }
760 
761  std::size_t max_sequence() const { return max_sequence_; }
762 
763  void set_max_sequence(std::size_t val) { max_sequence_ = val; }
764 
765  private:
770  std::size_t stride_;
771  std::size_t max_sequence_;
772 };
773 
774 } // namespace armv7
775 } // namespace codegen
776 } // namespace mc2lib
777 
778 #endif /* MC2LIB_CODEGEN_OPS_ARMv7_HPP_ */
779 
780 /* vim: set ts=2 sts=2 sw=2 et : */
Backend::Reg out_
Definition: armv7.hpp:381
std::size_t Read(types::Addr addr, Reg out, types::InstPtr start, void *code, std::size_t len, types::InstPtr *at) const
Definition: armv7.hpp:112
static constexpr std::size_t kMaxOpSize
Definition: cats.hpp:81
std::size_t Emit(types::InstPtr start, Backend *backend, EvtStateCats *evts, void *code, std::size_t len) override
Definition: armv7.hpp:336
const mc::Event * from_
Definition: armv7.hpp:506
void InsertPo(Operation::ThreadConstIt before, EvtStateCats *evts) override
Definition: armv7.hpp:325
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: armv7.hpp:620
types::Addr min_addr() const
Definition: armv7.hpp:724
Helper(char *&cnext, void *&code, std::size_t len)
Definition: armv7.hpp:165
std::size_t Emit(types::InstPtr start, Backend *backend, EvtStateCats *evts, void *code, std::size_t len) override
Definition: armv7.hpp:461
Definition: armv7.hpp:215
void InsertPo(Operation::ThreadConstIt before, EvtStateCats *evts) override
Definition: armv7.hpp:450
void MovImm32(Reg reg, std::uint32_t imm32)
Definition: armv7.hpp:168
Operation::Ptr Clone() const override
Definition: armv7.hpp:438
void RegisterCallback(Operation::CallbackStack *callback_stack) override
Definition: armv7.hpp:539
bool UpdateObs(types::InstPtr ip, int part, types::Addr addr, const types::WriteID *from_id, std::size_t size, EvtStateCats *evts) override
Definition: armv7.hpp:341
auto MakeEventPtrs(const mc::Event *e1, Ts... en) -> EventPtrs<(1+sizeof...(Ts)) *sizeof(types::WriteID)>
Definition: compiler.hpp:67
Read(types::Addr addr, Backend::Reg out, types::Pid pid=-1)
Definition: armv7.hpp:307
std::size_t ChunkSize() const
Definition: armv7.hpp:730
std::size_t Emit(types::InstPtr start, Backend *backend, EvtStateCats *evts, void *code, std::size_t len) override
Definition: armv7.hpp:424
const mc::Event * FirstEvent(const mc::Event *prev_event, EvtStateCats *evts) const override
Definition: armv7.hpp:495
Definition: armv7.hpp:82
DMB_ST(types::Pid pid=-1)
Definition: armv7.hpp:512
Definition: armv7.hpp:69
Operation::Ptr operator()(URNG &urng) const
Definition: armv7.hpp:716
void Reset() override
Definition: armv7.hpp:260
const Operation * before_
Definition: armv7.hpp:302
Definition: armv7.hpp:80
Interface to memconsistency::cats data structures.
Definition: cats.hpp:78
Delay(std::size_t length, types::Pid pid=-1)
Definition: armv7.hpp:253
Definition: cats.hpp:47
Definition: armv7.hpp:433
Definition: compiler.hpp:77
std::vector< Callback > CallbackStack
Definition: compiler.hpp:97
Write(types::Addr addr, types::Pid pid=-1)
Definition: armv7.hpp:435
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
const mc::Event * from_
Definition: armv7.hpp:383
const mc::Event * FirstEvent(const mc::Event *prev_event, EvtStateCats *evts) const override
Definition: armv7.hpp:283
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
std::size_t stride_
Definition: armv7.hpp:770
types::Addr addr() const override
Definition: armv7.hpp:500
void InsertPo(Operation::ThreadConstIt before, EvtStateCats *evts) override
Definition: armv7.hpp:264
void InsertPo(Operation::ThreadConstIt before, EvtStateCats *evts) override
Definition: armv7.hpp:526
mc::cats::ExecWitness * ew()
Definition: cats.hpp:238
Types< true >::InstPtr InstPtr
Instruction pointer type.
Definition: types.hpp:81
Operation::Ptr Clone() const override
Definition: armv7.hpp:219
#define ASM_PROLOGUE
Definition: armv7.hpp:66
void InsertPo(Operation::ThreadConstIt before, EvtStateCats *evts) override
Definition: armv7.hpp:227
types::Pid max_pid_
Definition: armv7.hpp:767
types::Pid max_pid() const
Definition: armv7.hpp:722
std::size_t ReadAddrDp(types::Addr addr, Reg out, Reg dp, types::InstPtr start, void *code, std::size_t len, types::InstPtr *at) const
Definition: armv7.hpp:126
MemOp< Backend, EvtStateCats > MemOperation
Definition: armv7.hpp:212
const Operation * first_write_before_
Definition: armv7.hpp:597
const mc::Event * LastEvent(const mc::Event *next_event, EvtStateCats *evts) const override
Definition: armv7.hpp:568
void InsertPo(Operation::ThreadConstIt before, EvtStateCats *evts) override
Definition: armv7.hpp:397
const mc::Event * FirstEvent(const mc::Event *prev_event, EvtStateCats *evts) const override
Definition: armv7.hpp:578
void Reset() override
Definition: armv7.hpp:318
Definition: armv7.hpp:603
Backend::Reg out() const
Definition: armv7.hpp:377
Definition: eventsets.hpp:103
bool UpdateObs(types::InstPtr ip, int part, types::Addr addr, const types::WriteID *from_id, std::size_t size, EvtStateCats *evts) override
Definition: armv7.hpp:293
void Reset() override
Definition: armv7.hpp:223
void Reset() override
Definition: armv7.hpp:519
ThreadConst::const_iterator ThreadConstIt
Definition: compiler.hpp:90
types::Addr max_addr_
Definition: armv7.hpp:769
const mc::Event * LastEvent(const mc::Event *next_event, EvtStateCats *evts) const override
Definition: armv7.hpp:490
std::size_t max_sequence() const
Definition: armv7.hpp:761
#define ASM_AT
Definition: armv7.hpp:57
Operation::Ptr Clone() const override
Definition: armv7.hpp:256
Definition: armv7.hpp:305
#define ASM16(v)
Definition: armv7.hpp:59
bool EnableEmit(EvtStateCats *evts) override
Definition: armv7.hpp:524
std::size_t Emit(types::InstPtr start, Backend *backend, EvtStateCats *evts, void *code, std::size_t len) override
Definition: armv7.hpp:229
Definition: compiler.hpp:245
bool EnableEmit(EvtStateCats *evts) override
Definition: armv7.hpp:225
Definition: armv7.hpp:251
types::Addr max_addr() const
Definition: armv7.hpp:726
Op< Backend, EvtStateCats > Operation
Definition: armv7.hpp:211
bool UpdateObs(types::InstPtr ip, int part, types::Addr addr, const types::WriteID *from_id, std::size_t size, EvtStateCats *evts) override
Definition: armv7.hpp:466
Reg
Definition: armv7.hpp:77
void set_max_sequence(std::size_t val)
Definition: armv7.hpp:763
Definition: compiler.hpp:253
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)
Definition: armv7.hpp:606
const mc::Event * event_
Definition: armv7.hpp:505
#define ASM_PRELUDE
Definition: armv7.hpp:55
NullOp< Backend, EvtStateCats > NullOperation
Definition: armv7.hpp:213
types::Pid min_pid_
Definition: armv7.hpp:766
Definition: armv7.hpp:79
mc::cats::Architecture * arch()
Definition: cats.hpp:242
const mc::Event * LastEvent(const mc::Event *next_event, EvtStateCats *evts) const override
Definition: armv7.hpp:234
bool EnableEmit(EvtStateCats *evts) override
Definition: armv7.hpp:262
std::size_t stride() const
Definition: armv7.hpp:728
Return(types::Pid pid=-1)
Definition: armv7.hpp:217
types::Addr addr_
Definition: armv7.hpp:380
types::Pid min_pid() const
Definition: armv7.hpp:720
void Reset()
Definition: armv7.hpp:71
Types< true >::WriteID WriteID
Write ID type.
Definition: types.hpp:86
std::size_t max_sequence_
Definition: armv7.hpp:771
types::WriteID write_id_
Definition: armv7.hpp:504
Operation::Ptr Clone() const override
Definition: armv7.hpp:393
void *& code
Definition: armv7.hpp:200
bool EnableEmit(EvtStateCats *evts) override
Definition: armv7.hpp:323
Operation ResultType
Definition: armv7.hpp:604
Definition: armv7.hpp:510
std::size_t HoleSize() const
Definition: armv7.hpp:734
bool UpdateObs(types::InstPtr ip, int part, types::Addr addr, const types::WriteID *from_id, std::size_t size, EvtStateCats *evts) override
Definition: armv7.hpp:244
std::size_t Write(types::Addr addr, types::WriteID write_id, types::InstPtr start, void *code, std::size_t len, types::InstPtr *at) const
Definition: armv7.hpp:144
const mc::Event * event_
Definition: armv7.hpp:382
types::Addr min_addr_
Definition: armv7.hpp:768
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
ReadAddrDp(types::Addr addr, Backend::Reg reg, Backend::Reg dp, types::Pid pid=-1)
Definition: armv7.hpp:389
types::Addr addr() const override
Definition: armv7.hpp:375
void Reset() override
Definition: armv7.hpp:442
std::size_t for_each_AddrRange(Func func) const
Definition: armv7.hpp:739
const mc::Event * FirstEvent(const mc::Event *prev_event, EvtStateCats *evts) const override
Definition: armv7.hpp:239
const Operation * before_
Definition: armv7.hpp:596
const std::size_t len
Definition: armv7.hpp:201
std::shared_ptr< Op > Ptr
Definition: compiler.hpp:82
Types< true >::Pid Pid
Processor/thread ID type.
Definition: types.hpp:71
std::size_t DMB_ST(void *code, std::size_t len) const
Definition: armv7.hpp:104
char *& cnext__
Definition: armv7.hpp:199
Definition: armv7.hpp:387
types::InstPtr at_
Definition: armv7.hpp:384
Definition: armv7.hpp:81
Operation::Ptr Clone() const override
Definition: armv7.hpp:515
Operation::Ptr Clone() const override
Definition: armv7.hpp:314
bool EnableEmit(EvtStateCats *evts) override
Definition: armv7.hpp:448
const mc::Event * LastEvent(const mc::Event *next_event, EvtStateCats *evts) const override
Definition: armv7.hpp:365
std::size_t Delay(std::size_t length, void *code, std::size_t len) const
Definition: armv7.hpp:96
bool UpdateObs(types::InstPtr ip, int part, types::Addr addr, const types::WriteID *from_id, std::size_t size, EvtStateCats *evts) override
Definition: armv7.hpp:588
const mc::Event * FirstEvent(const mc::Event *prev_event, EvtStateCats *evts) const override
Definition: armv7.hpp:370
Backend::Reg dp_
Definition: armv7.hpp:430
types::InstPtr at_
Definition: armv7.hpp:507
std::size_t Emit(types::InstPtr start, Backend *backend, EvtStateCats *evts, void *code, std::size_t len) override
Definition: armv7.hpp:268
std::size_t Return(void *code, std::size_t len) const
Definition: armv7.hpp:90
const mc::Event * LastEvent(const mc::Event *next_event, EvtStateCats *evts) const override
Definition: armv7.hpp:273
std::size_t length_
Definition: armv7.hpp:301
types::Addr addr_
Definition: armv7.hpp:503
Operation::Ptr operator()(URNG &urng, AddrFilterFunc addr_filter_func, std::size_t max_fails=0) const
Definition: armv7.hpp:631
std::size_t Emit(types::InstPtr start, Backend *backend, EvtStateCats *evts, void *code, std::size_t len) override
Definition: armv7.hpp:563
Definition: armv7.hpp:78
bool Exhausted() const
Definition: cats.hpp:114