34 #ifndef MC2LIB_CODEGEN_OPS_ARMv7_HPP_ 35 #define MC2LIB_CODEGEN_OPS_ARMv7_HPP_ 41 #include "../cats.hpp" 42 #include "../compiler.hpp" 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) 61 assert(ASM_LEN + 2 <= len); \ 62 *reinterpret_cast<std::uint16_t *>(cnext__) = (v); \ 66 #define ASM_PROLOGUE return ASM_LEN; 75 static_assert(
sizeof(
types::WriteID) == 1,
"Unsupported read/write size!");
90 std::size_t
Return(
void *code, std::size_t len)
const {
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) {
104 std::size_t
DMB_ST(
void *code, std::size_t len)
const {
116 Helper h(cnext__, code, len);
131 Helper h(cnext__, code, len);
135 ASM16(0x4040 | (dp << 3) | dp);
139 ASM16(0x5c30 | (dp << 6) | out);
149 Helper h(cnext__, code, len);
153 ASM16(0x2700 | write_id);
166 :
cnext__(cnext), code(code), len(len) {}
170 std::uint16_t imm32_w = imm32 & 0xffff;
173 | ((imm32_w & 0x0800) >> 1)
175 | ((imm32_w & 0xf000) >> 12));
177 ((imm32_w & 0x0700) << 4)
181 | (imm32_w & 0x00ff));
184 std::uint16_t imm32_t = (imm32 & 0xffff0000) >> 16;
187 | ((imm32_t & 0x0800) >> 1)
189 | ((imm32_t & 0xf000) >> 12));
191 ((imm32_t & 0x0700) << 4)
195 | (imm32_t & 0x00ff));
220 return std::make_shared<Return>(*this);
230 void *
code, std::size_t
len)
override {
231 return backend->
Return(code, len);
254 : Operation(pid), length_(length), before_(nullptr) {}
257 return std::make_shared<Delay>(*this);
260 void Reset()
override { before_ =
nullptr; }
269 void *
code, std::size_t
len)
override {
270 return backend->
Delay(length_, code, len);
276 if (before_ !=
nullptr) {
277 return before_->LastEvent(next_event, evts);
286 if (before_ !=
nullptr) {
287 return before_->FirstEvent(prev_event, evts);
296 throw std::logic_error(
"Unexpected UpdateObs");
305 class Read :
public MemOperation {
315 return std::make_shared<Read>(*this);
326 event_ = evts->
MakeRead(pid(), mc::Event::kRead, addr_)[0];
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_);
337 void *
code, std::size_t
len)
override {
338 return backend->
Read(addr_, out(), start, code, len, &at_);
344 assert(event_ !=
nullptr);
346 assert(addr == addr_);
352 if (from_ !=
nullptr) {
356 evts->
ew()->rf.Erase(*from_, *event_);
360 evts->
ew()->rf.Insert(*from_, *event_,
true);
391 :
Read(addr, reg, pid), dp_(dp) {}
394 return std::make_shared<ReadAddrDp>(*this);
398 event_ = evts->
MakeRead(pid(), mc::Event::kRead | mc::Event::kRegInAddr,
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_);
407 auto arch =
dynamic_cast<mc::cats::Arch_ARMv7 *
>(evts->
arch());
408 if (arch !=
nullptr) {
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_);
418 }
while (*(--before) !=
nullptr);
425 void *
code, std::size_t
len)
override {
426 return backend->
ReadAddrDp(addr_, out(), dp_, start, code, len, &at_);
436 : MemOperation(pid), addr_(addr), write_id_(0) {}
439 return std::make_shared<Write>(*this);
451 event_ = evts->
MakeWrite(pid(), mc::Event::kWrite, addr_, &write_id_)[0];
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_);
462 void *
code, std::size_t
len)
override {
463 return backend->
Write(addr_, write_id_, start, code, len, &at_);
469 assert(event_ !=
nullptr);
471 assert(addr == addr_);
477 if (from_ !=
nullptr) {
481 evts->
ew()->co.Erase(*from_, *event_);
485 evts->
ew()->co.Insert(*from_, *event_,
true);
513 : Operation(pid), before_(nullptr), first_write_before_(nullptr) {}
516 return std::make_shared<DMB_ST>(*this);
521 first_write_before_ =
nullptr;
529 while (*before !=
nullptr) {
530 auto potential_write =
dynamic_cast<const Write *
>(*before);
531 if (potential_write !=
nullptr) {
532 first_write_before_ = potential_write;
540 callback_stack->push_back([
this](Operation *after,
types::InstPtr start,
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);
553 arch->dmb_st.Insert(*event_before, *event_after);
556 first_write_before_ =
nullptr;
564 void *
code, std::size_t
len)
override {
565 return backend->
DMB_ST(code, len);
571 if (before_ !=
nullptr) {
572 return before_->LastEvent(next_event, evts);
581 if (before_ !=
nullptr) {
582 return before_->FirstEvent(prev_event, evts);
591 throw std::logic_error(
"Unexpected UpdateObs");
609 std::size_t max_sequence = 50)
615 max_sequence_(max_sequence) {
625 min_addr_ = min_addr;
626 max_addr_ = max_addr;
630 template <
class URNG,
class AddrFilterFunc>
632 std::size_t max_fails = 0)
const {
634 std::uniform_int_distribution<std::size_t> dist_choice(0, 1000 - 1);
637 std::uniform_int_distribution<types::Pid> dist_pid(min_pid_, max_pid_);
640 auto chunk_min_addr = min_addr_;
641 auto chunk_max_addr = max_addr_;
643 if (ChunkSize() > 1 && HoleSize() > 1) {
644 std::size_t chunk_cnt =
646 std::size_t select_chunk =
647 std::uniform_int_distribution<std::size_t>(0, chunk_cnt - 1)(urng);
649 chunk_min_addr = min_addr_ + (select_chunk * HoleSize());
650 chunk_max_addr = chunk_min_addr + ChunkSize() - 1;
652 assert(chunk_min_addr >= min_addr_);
653 assert(chunk_max_addr <= max_addr_);
656 std::uniform_int_distribution<types::Addr> dist_addr(
660 std::uniform_int_distribution<std::size_t> dist_sequence(1, max_sequence_);
666 const auto choice = dist_choice(urng);
669 const auto pid = dist_pid(urng);
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);
682 if (addr_filter_func(result)) {
691 auto sequence = [&dist_sequence, &urng]() {
return dist_sequence(urng); };
694 auto reg = [&dist_reg, &urng]() {
699 return std::make_shared<Read>(addr(), reg(), pid);
700 }
else if (choice < 560) {
701 return std::make_shared<ReadAddrDp>(addr(), reg(), reg(), pid);
702 }
else if (choice < 980) {
703 return std::make_shared<Write>(addr(), pid);
704 }
else if (choice < 990) {
705 return std::make_shared<DMB_ST>(pid);
706 }
else if (choice < 1000) {
707 return std::make_shared<Delay>(sequence(), pid);
711 throw std::logic_error(
"Not exhaustive");
715 template <
class URNG>
717 return (*
this)(urng, [](
types::Addr addr) {
return true; });
728 std::size_t
stride()
const {
return stride_ & ((1ULL << 16) - 1); }
731 return 1ULL << ((stride_ & (0xffULL << 24)) >> 24);
735 return 1ULL << ((stride_ & (0xffULL << 16)) >> 16);
738 template <
class Func>
740 if (ChunkSize() > 1 && HoleSize() > 1) {
741 assert(HoleSize() >= ChunkSize());
742 assert(ChunkSize() <= (max_addr_ - min_addr_ + 1));
744 std::size_t chunk_cnt = 0;
746 for (;; ++chunk_cnt) {
747 types::Addr min = min_addr_ + (chunk_cnt * HoleSize());
749 if (max > max_addr_)
break;
757 func(min_addr_, max_addr_);
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
DMB_ST(types::Pid pid=-1)
Definition: armv7.hpp:512
Operation::Ptr operator()(URNG &urng) const
Definition: armv7.hpp:716
void Reset() override
Definition: armv7.hpp:260
const Operation * before_
Definition: armv7.hpp:302
Interface to memconsistency::cats data structures.
Definition: cats.hpp:78
Delay(std::size_t length, types::Pid pid=-1)
Definition: armv7.hpp:253
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
Definition: armv7.hpp:163
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
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
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
bool Exhausted() const
Definition: cats.hpp:114