34 #ifndef MC2LIB_CODEGEN_OPS_STRONG_HPP_ 35 #define MC2LIB_CODEGEN_OPS_STRONG_HPP_ 42 #include "../cats.hpp" 43 #include "../compiler.hpp" 59 virtual std::size_t
Return(
void *code, std::size_t len)
const = 0;
61 virtual std::size_t
Delay(std::size_t length,
void *code,
62 std::size_t len)
const = 0;
68 void *code, std::size_t len,
81 std::size_t len)
const = 0;
93 return std::make_shared<Return>(*this);
103 void *code, std::size_t len)
override {
104 return backend->
Return(code, len);
127 : Operation(pid), length_(length), before_(nullptr) {}
130 return std::make_shared<Delay>(*this);
133 void Reset()
override { before_ =
nullptr; }
142 void *code, std::size_t len)
override {
143 return backend->
Delay(length_, code, len);
149 if (before_ !=
nullptr) {
150 return before_->LastEvent(next_event, evts);
159 if (before_ !=
nullptr) {
160 return before_->FirstEvent(prev_event, evts);
169 throw std::logic_error(
"Unexpected UpdateObs");
178 class Read :
public MemOperation {
181 : MemOperation(pid), addr_(addr), event_(nullptr), from_(nullptr) {}
184 return std::make_shared<Read>(*this);
195 event_ = evts->
MakeRead(pid(), mc::Event::kRead, addr_)[0];
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_);
206 void *code, std::size_t len)
override {
207 return backend->
Read(addr_, start, code, len, &at_);
213 assert(event_ !=
nullptr);
215 assert(addr == addr_);
221 if (from_ !=
nullptr) {
225 EraseObsHelper(from_, event_, evts->
ew());
229 InsertObsHelper(from_, event_, evts->
ew());
248 mc::cats::ExecWitness *ew) {
249 ew->rf.Insert(*e1, *e2,
true);
253 mc::cats::ExecWitness *ew) {
254 ew->rf.Erase(*e1, *e2);
269 return std::make_shared<ReadAddrDp>(*this);
279 void *code, std::size_t len)
override {
280 return backend->
ReadAddrDp(addr_, start, code, len, &at_);
287 :
Read(addr, pid), write_id_(0) {}
290 return std::make_shared<Write>(*this);
300 event_ = evts->
MakeWrite(pid(), mc::Event::kWrite, addr_, &write_id_)[0];
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_);
311 void *code, std::size_t len)
override {
312 return backend->
Write(addr_, write_id_, start, code, len, &at_);
317 mc::cats::ExecWitness *ew)
override {
318 ew->co.Insert(*e1, *e2);
322 mc::cats::ExecWitness *ew)
override {
323 ew->co.Erase(*e1, *e2);
332 : MemOperation(pid), addr_(addr), last_part_(-1) {}
335 return std::make_shared<ReadModifyWrite>(*this);
349 event_r_ = evts->
MakeRead(pid(), mc::Event::kRead, addr_)[0];
350 event_w_ = evts->
MakeWrite(pid(), mc::Event::kWrite, addr_, &write_id_)[0];
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_);
357 if (dynamic_cast<mc::cats::Arch_TSO *>(evts->
arch()) !=
nullptr) {
359 auto arch_tso =
dynamic_cast<mc::cats::Arch_TSO *
>(evts->
arch());
360 arch_tso->mfence.Insert(*event_before, *event_r_);
365 evts->
ew()->po.Insert(*event_r_, *event_w_);
369 void *code, std::size_t len)
override {
370 return backend->
ReadModifyWrite(addr_, write_id_, start, code, len, &at_);
376 assert(event_r_ !=
nullptr);
377 assert(event_w_ !=
nullptr);
379 assert(addr == addr_);
386 auto part_event = event_r_;
387 auto obs_rel = &evts->
ew()->rf;
391 if (last_part_ == -1 || part <= last_part_) {
394 if (from_ !=
nullptr) {
396 evts->
ew()->rf.Erase(*from_, *event_r_);
397 evts->
ew()->co.Erase(*from_, *event_w_);
401 assert(part > last_part_);
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)
412 part_event = event_w_;
413 obs_rel = &evts->
ew()->co;
416 obs_rel->Insert(*from, *part_event,
true);
425 if (dynamic_cast<mc::cats::Arch_TSO *>(evts->
arch()) !=
nullptr) {
427 auto arch_tso =
dynamic_cast<mc::cats::Arch_TSO *
>(evts->
arch());
428 arch_tso->mfence.Insert(*event_w_, *next_event);
454 : MemOperation(pid), addr_(addr), before_(nullptr) {}
457 return std::make_shared<CacheFlush>(*this);
460 void Reset()
override { before_ =
nullptr; }
469 void *code, std::size_t len)
override {
476 if (before_ !=
nullptr) {
477 return before_->LastEvent(next_event, evts);
486 if (before_ !=
nullptr) {
487 return before_->FirstEvent(prev_event, evts);
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));
518 ++(it_stack->back().first);
519 it_stack->emplace_back(sequence_.begin(), sequence_.end());
524 return std::make_shared<ReadSequence>(min_addr_, max_addr_, pid());
528 for (
const auto &op : sequence_) {
548 std::size_t max_sequence = 50,
bool extended =
false)
554 max_sequence_(max_sequence),
555 extended_(extended) {
565 min_addr_ = min_addr;
566 max_addr_ = max_addr;
570 template <
class URNG,
class AddrFilterFunc>
572 std::size_t max_fails = 0)
const {
574 const std::size_t max_choice = (extended_ ? 1005 : 1000) - 1;
575 std::uniform_int_distribution<std::size_t> dist_choice(0, max_choice);
578 std::uniform_int_distribution<types::Pid> dist_pid(min_pid_, max_pid_);
581 auto chunk_min_addr = min_addr_;
582 auto chunk_max_addr = max_addr_;
584 if (ChunkSize() > 1 && HoleSize() > 1) {
585 std::size_t chunk_cnt =
587 std::size_t select_chunk =
588 std::uniform_int_distribution<std::size_t>(0, chunk_cnt - 1)(urng);
590 chunk_min_addr = min_addr_ + (select_chunk * HoleSize());
591 chunk_max_addr = chunk_min_addr + ChunkSize() - 1;
593 assert(chunk_min_addr >= min_addr_);
594 assert(chunk_max_addr <= max_addr_);
597 std::uniform_int_distribution<types::Addr> dist_addr(
601 std::uniform_int_distribution<std::size_t> dist_sequence(1, max_sequence_);
604 const auto choice = dist_choice(urng);
607 const auto pid = dist_pid(urng);
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);
620 if (addr_filter_func(result)) {
629 auto sequence = [&dist_sequence, &urng]() {
return dist_sequence(urng); };
632 return std::make_shared<Read>(addr(), pid);
633 }
else if (choice < 550) {
634 return std::make_shared<ReadAddrDp>(addr(), pid);
635 }
else if (choice < 970) {
636 return std::make_shared<Write>(addr(), pid);
637 }
else if (choice < 980) {
638 return std::make_shared<ReadModifyWrite>(addr(), pid);
639 }
else if (choice < 990) {
640 return std::make_shared<CacheFlush>(addr(), pid);
641 }
else if (choice < 1000) {
642 return std::make_shared<Delay>(sequence(), pid);
643 }
else if (extended_) {
649 auto max_a = min_a + sequence() * 64;
650 if (max_a > max_addr()) {
654 return std::make_shared<ReadSequence>(min_a, max_a, pid);
659 throw std::logic_error(
"Not exhaustive");
663 template <
class URNG>
665 return (*
this)(urng, [](
types::Addr addr) {
return true; });
676 std::size_t
stride()
const {
return stride_ & ((1ULL << 16) - 1); }
679 return 1ULL << ((stride_ & (0xffULL << 24)) >> 24);
683 return 1ULL << ((stride_ & (0xffULL << 16)) >> 16);
686 template <
class Func>
688 if (ChunkSize() > 1 && HoleSize() > 1) {
689 assert(HoleSize() >= ChunkSize());
690 assert(ChunkSize() <= (max_addr_ - min_addr_ + 1));
692 std::size_t chunk_cnt = 0;
694 for (;; ++chunk_cnt) {
695 types::Addr min = min_addr_ + (chunk_cnt * HoleSize());
697 if (max > max_addr_)
break;
705 func(min_addr_, max_addr_);
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
Definition: strong.hpp:329
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
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