diff options
author | bd <bdunahu@operationnull.com> | 2025-04-01 15:57:14 -0400 |
---|---|---|
committer | bd <bdunahu@operationnull.com> | 2025-04-01 15:57:14 -0400 |
commit | 25ce77db5f0dbfe6064eb0553591f1b956bad24a (patch) | |
tree | 5a1c347f05f14496d2d3a2f1befd88be9020cad3 | |
parent | 6579f7272905d1e25b43ef051da6c2180e60ca2b (diff) |
Fix a lot of pipeline bugs
-rw-r--r-- | inc/stage.h | 6 | ||||
-rw-r--r-- | inc/wb.h | 20 | ||||
-rw-r--r-- | src/sim/ex.cc | 14 | ||||
-rw-r--r-- | src/sim/id.cc | 20 | ||||
-rw-r--r-- | src/sim/instrDTO.cc | 2 | ||||
-rw-r--r-- | src/sim/mm.cc | 1 | ||||
-rw-r--r-- | src/sim/stage.cc | 25 | ||||
-rw-r--r-- | src/sim/wb.cc | 75 | ||||
-rw-r--r-- | tests/controller.cc | 111 | ||||
-rw-r--r-- | tests/id.cc | 320 |
10 files changed, 371 insertions, 223 deletions
diff --git a/inc/stage.h b/inc/stage.h index 2f9812f..87ee9c1 100644 --- a/inc/stage.h +++ b/inc/stage.h @@ -81,6 +81,12 @@ class Stage */ bool is_checked_out(signed int r); /** + * Stores `d` into the register indexed `v`. + * @param the register number. + * @param the value to store. + */ + void store_register(signed int v, signed int d); + /** * Returns the value of the register corresponding to `v`. * @param the register number. * @return the value in the associated register. @@ -14,9 +14,27 @@ class WB : public Stage */ WB(Stage *next); using Stage::advance; - + private: void advance_helper() override; + /** + * Performs the actual work of storing into a register. + */ + void write_handler(); + /** + * Performs the actual work of processing a jump instruction. + */ + void jump_handler(); + /** + * @return true if the current instruction is an R or I type and is not a + * STORE. + */ + bool should_write(); + /** + * @return true if the current instruction is a J type and is not a push. + * STORE. + */ + bool should_jump(); }; #endif /* WB_H_INCLUDED */ diff --git a/src/sim/ex.cc b/src/sim/ex.cc index 3d95917..ec4c47f 100644 --- a/src/sim/ex.cc +++ b/src/sim/ex.cc @@ -4,6 +4,7 @@ #include "instrDTO.h" #include "response.h" #include "stage.h" +#include "utils.h" #include <unordered_map> // clang-format off @@ -185,6 +186,7 @@ EX::EX(Stage *stage) : Stage(stage) ADDI, { s1 = s1 + s3; + std::cout << "= " << s2 << std::endl; (void)s2; (void)this; }), @@ -282,28 +284,32 @@ EX::EX(Stage *stage) : Stage(stage) INIT_INSTRUCTION( BEQ, { - (this->get_condition(EQ)) ? s1 = this->pc + s2 : s1 = this->pc; + (this->get_condition(EQ)) ? s1 = wrap_address(this->pc + s2) + : s1 = -1; (void)s3; }), INIT_INSTRUCTION( BGT, { - (this->get_condition(GT)) ? s1 = this->pc + s2 : s1 = this->pc; + (this->get_condition(GT)) ? s1 = wrap_address(this->pc + s2) + : s1 = -1; (void)s3; }), INIT_INSTRUCTION( BUF, { - (this->get_condition(UF)) ? s1 = this->pc + s2 : s1 = this->pc; + (this->get_condition(UF)) ? s1 = wrap_address(this->pc) + s2 + : s1 = -1; (void)s3; }), INIT_INSTRUCTION( BOF, { - (this->get_condition(OF)) ? s1 = this->pc + s2 : s1 = this->pc; + (this->get_condition(OF)) ? s1 = wrap_address(this->pc + s2) + : s1 = -1; (void)s3; }), diff --git a/src/sim/id.cc b/src/sim/id.cc index 4a55d04..ddac35b 100644 --- a/src/sim/id.cc +++ b/src/sim/id.cc @@ -48,14 +48,18 @@ void ID::advance_helper() Mnemonic m; Type t; - s1 = curr_instr->get_instr_bits(); - get_instr_fields(s1, s2, s3, m, t); - if (this->status == OK) { - curr_instr->set_s1(s1); - curr_instr->set_s2(s2); - curr_instr->set_s3(s3); - curr_instr->set_mnemonic(m); - curr_instr->set_type(t); + if (curr_instr->get_mnemonic() == NOP) + this->status = OK; + else { + s1 = curr_instr->get_instr_bits(); + get_instr_fields(s1, s2, s3, m, t); + if (this->status == OK) { + curr_instr->set_s1(s1); + curr_instr->set_s2(s2); + curr_instr->set_s3(s3); + curr_instr->set_mnemonic(m); + curr_instr->set_type(t); + } } } diff --git a/src/sim/instrDTO.cc b/src/sim/instrDTO.cc index 28364b7..7324ba9 100644 --- a/src/sim/instrDTO.cc +++ b/src/sim/instrDTO.cc @@ -7,7 +7,7 @@ InstrDTO::InstrDTO() this->s1 = 0; this->s2 = 0; this->s3 = 0; - this->mnemonic = NOP; + this->mnemonic = ADD; this->type = INV; } diff --git a/src/sim/mm.cc b/src/sim/mm.cc index c83ae7d..e29bf90 100644 --- a/src/sim/mm.cc +++ b/src/sim/mm.cc @@ -10,6 +10,7 @@ void MM::advance_helper() { signed int data; + std::cout << "mem" << this->curr_instr->get_s2() << std::endl; switch (this->curr_instr->get_mnemonic()) { case LOAD: this->status = this->storage->read_word( diff --git a/src/sim/stage.cc b/src/sim/stage.cc index 31d7d0d..b10a206 100644 --- a/src/sim/stage.cc +++ b/src/sim/stage.cc @@ -2,7 +2,6 @@ #include "utils.h" #include <array> #include <deque> -#include <iostream> Stage::Stage(Stage *next) { @@ -28,10 +27,12 @@ void Stage::set_pc(unsigned int pc) { this->pc = pc; } InstrDTO *Stage::advance(Response p) { InstrDTO *r = nullptr; + InstrDTO *s = nullptr; Response n; - if (this->curr_instr && this->status != OK) + if (this->curr_instr && this->status != OK) { this->advance_helper(); + } if (this->status == OK && p == WAIT && this->curr_instr) { // mutual consent this->curr_instr->set_time_of(this->id, this->clock_cycle); @@ -42,8 +43,9 @@ InstrDTO *Stage::advance(Response p) } n = (p != WAIT || this->status != WAIT) ? STALLED : WAIT; - // the power of consent - this->curr_instr = this->next->advance(n); + s = this->next->advance(n); + if (s) + this->curr_instr = s; return r; } @@ -70,6 +72,21 @@ signed int Stage::dereference_register(signed int v) return r; } +void Stage::store_register(signed int v, signed int d) +{ + if (v < 0 || v >= GPR_NUM + V_NUM) { + throw std::out_of_range(string_format( + "instruction tried to access register %d, which does " + "not exist", + v)); + } + + if (v >= GPR_NUM) + this->vrs[v % GPR_NUM] = d; + else + this->gprs[v] = d; +} + bool Stage::is_checked_out(signed int r) { return std::find(this->checked_out.begin(), this->checked_out.end(), r) != diff --git a/src/sim/wb.cc b/src/sim/wb.cc index 276d1d0..01768e8 100644 --- a/src/sim/wb.cc +++ b/src/sim/wb.cc @@ -8,33 +8,54 @@ WB::WB(Stage *stage) : Stage(stage) { this->id = WRITE; } void WB::advance_helper() { - if (this->curr_instr->get_type() == R || - this->curr_instr->get_type() == I) { - if (this->checked_out.size() > 0) { - signed int reg = this->checked_out.front(); - this->checked_out.pop_front(); - if (reg >= GPR_NUM) { - // TODO: handle vector instructions - } else { - if (this->curr_instr->get_mnemonic() != STORE && - this->curr_instr->get_mnemonic() != STOREV) { - this->gprs[reg] = this->curr_instr->get_s1(); - } - } - } - } else if (this->curr_instr->get_type() == J) { - // TODO:handle push pop - // branch taken - if (this->pc != this->curr_instr->get_s1()) { - if (this->curr_instr->get_mnemonic() == JAL) { - // set link register to next instruction - this->gprs[1] = this->pc + 1; - } - this->pc = this->curr_instr->get_s1(); - // clear pending registers and squash pipeline - this->checked_out = {}; - this->next->squash(); - } + if (this->curr_instr->get_mnemonic() != NOP && + this->curr_instr->get_type() != INV) { + if (this->should_write()) + this->write_handler(); + else if (this->should_jump()) + this->jump_handler(); } this->status = OK; } + +void WB::write_handler() +{ + signed int reg; + + if (this->checked_out.size() < 1) + throw std::runtime_error("instruction tried to pop a register out of " + "an empty queue during writeback."); + + reg = this->checked_out.front(); + this->checked_out.pop_front(); + this->store_register(reg, this->curr_instr->get_s1()); +} + +void WB::jump_handler() +{ + if (this->curr_instr->get_s1() > 0) { + if (this->curr_instr->get_mnemonic() == JAL) + this->gprs[1] = this->pc + 1; + this->pc = this->curr_instr->get_s1(); + this->checked_out = {}; + this->next->squash(); + } +} + +bool WB::should_jump() +{ + Type t; + + t = this->curr_instr->get_type(); + return t == J; +} + +bool WB::should_write() +{ + Mnemonic m; + Type t; + + m = this->curr_instr->get_mnemonic(); + t = this->curr_instr->get_type(); + return (t == R || t == I) && (m != STORE && m != STOREV); +} diff --git a/tests/controller.cc b/tests/controller.cc index f6d9b25..f2ef3de 100644 --- a/tests/controller.cc +++ b/tests/controller.cc @@ -21,15 +21,27 @@ class ControllerPipeFixture IF *f = new IF(nullptr); ID *d = new ID(f); EX *e = new EX(d); + MM *m = new MM(e); + WB *w = new WB(m); + this->stage_num = 5; - this->ct = new Controller(e, this->c, true); + this->ct = new Controller(w, this->c, true); } ~ControllerPipeFixture() { delete this->ct; delete this->c; }; - + void fill_pipe() + { + InstrDTO *i = nullptr; + int j; + for (j = 0; j < this->stage_num + 1; ++j) { + i = this->ct->advance(WAIT); + REQUIRE(i == nullptr); + } + } + int stage_num; Cache *c; Dram *d; Controller *ct; @@ -51,40 +63,103 @@ TEST_CASE_METHOD( CHECK(this->ct->get_pc() == 0); } -TEST_CASE_METHOD(ControllerPipeFixture, "Add until exec", "[tmp]") +TEST_CASE_METHOD(ControllerPipeFixture, "two num adder", "[full pipe]") { - signed int b; + signed int b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11; std::vector<signed int> p; InstrDTO *i; - b = 0b1010100000000001001101; - p = {b}; + // I-TYPE / / / / + b0 = 0b00000010000000000001000000001101; // ADDI $sp $0 0x200; + b1 = 0b00000000000000010010100000001101; // ADDI $5 $0 0x1; + b2 = 0b00000000000000000001000101101101; // STORE $5 0($sp); (RAW HAZARD)! + // I-TYPE / / / / + b3 = 0b00000000000000100010100000001101; // ADDI $5 $0 0x2; (RAW HAZARD)! + b4 = 0b00000000000000010001000101101101; // STORE $5 1($sp); (RAW HAZARD)! + // // I-TYPE / / / / + // b9 = 0b00000000000000000010100000001101; // ADDI $5 $0 0x0; + // // I-TYPE / / / / + // b10 = 0b00000000000000110011000000001101; // ADDI $6 $0 0x3; + // // J-TYPE / / / + // b11 = 0b00000000000000000011100000001010; // jrl CHECK + + p = {b0, b1, b2, b3}; this->d->load(p); - // dram + this->fill_pipe(); + i = this->ct->advance(WAIT); + REQUIRE(i != nullptr); + + CHECK(i->get_time_of(FETCH) == 3); + CHECK(i->get_time_of(DCDE) == 4); + CHECK(i->get_time_of(EXEC) == 5); + CHECK(i->get_time_of(MEM) == 6); + CHECK(i->get_time_of(WRITE) == 7); + CHECK(i->get_s1() == 0x200); + CHECK(i->get_s2() == 0x0); + CHECK(i->get_s3() == 0x200); + CHECK(this->ct->get_gprs().at(2) == 0x200); + CHECK(i->get_mnemonic() == ADDI); + CHECK(i->get_instr_bits() == b0); + + delete i; + i = this->ct->advance(WAIT); + REQUIRE(i != nullptr); + + CHECK(i->get_time_of(FETCH) == 4); + CHECK(i->get_time_of(DCDE) == 5); + CHECK(i->get_time_of(EXEC) == 6); + CHECK(i->get_time_of(MEM) == 7); + CHECK(i->get_time_of(WRITE) == 8); + CHECK(i->get_s1() == 0x1); + CHECK(i->get_s2() == 0x0); + CHECK(i->get_s3() == 0x1); + CHECK(this->ct->get_gprs().at(5) == 0x1); + CHECK(i->get_mnemonic() == ADDI); + CHECK(i->get_instr_bits() == b1); + + delete i; i = this->ct->advance(WAIT); REQUIRE(i == nullptr); - // fetch i = this->ct->advance(WAIT); REQUIRE(i == nullptr); - // decode i = this->ct->advance(WAIT); REQUIRE(i == nullptr); - // exec i = this->ct->advance(WAIT); REQUIRE(i == nullptr); - // done i = this->ct->advance(WAIT); REQUIRE(i != nullptr); - CHECK(i->get_time_of(FETCH) == 3); - CHECK(i->get_time_of(DCDE) == 4); - CHECK(i->get_time_of(EXEC) == 5); - CHECK(i->get_s1() == 42); - CHECK(i->get_s2() == 0); - CHECK(i->get_s3() == 42); + CHECK(i->get_time_of(FETCH) == 5); + CHECK(i->get_time_of(DCDE) == 8); // the previous conflicting instruction wrote here! + CHECK(i->get_time_of(EXEC) == 9); + CHECK(i->get_time_of(MEM) == 12); // waited for fetch + 2 dram + CHECK(i->get_time_of(WRITE) == 13); + CHECK(i->get_s1() == 0x1); + CHECK(i->get_s2() == 0x200); + CHECK(i->get_s3() == 0x0); + // NO STORE + CHECK(this->ct->get_gprs().at(2) == 0x200); + CHECK(this->ct->get_gprs().at(5) == 0x1); + CHECK(i->get_mnemonic() == STORE); + CHECK(i->get_instr_bits() == b2); + + delete i; + i = this->ct->advance(WAIT); + REQUIRE(i != nullptr); + + CHECK(i->get_time_of(FETCH) == 8); + CHECK(i->get_time_of(DCDE) == 9); + CHECK(i->get_time_of(EXEC) == 12); + CHECK(i->get_time_of(MEM) == 13); + CHECK(i->get_time_of(WRITE) == 14); + CHECK(i->get_s1() == 0x2); + CHECK(i->get_s2() == 0x0); + CHECK(i->get_s3() == 0x2); + // NO STORE + CHECK(this->ct->get_gprs().at(5) == 0x2); CHECK(i->get_mnemonic() == ADDI); - CHECK(i->get_instr_bits() == b); + CHECK(i->get_instr_bits() == b3); delete i; } diff --git a/tests/id.cc b/tests/id.cc index 7d5e05d..77a7cd9 100644 --- a/tests/id.cc +++ b/tests/id.cc @@ -84,18 +84,18 @@ class IDFixture Controller *ct; }; -// TEST_CASE_METHOD(IDFixture, "Parse invalid type", "[id]") -// { -// signed int t; -// InstrDTO *i; +TEST_CASE_METHOD(IDFixture, "Parse invalid type", "[id]") +{ + signed int t; + InstrDTO *i; -// t = this->encode_R_type(0b0, 0b1, 0b10, 0b11, 0b11); -// i = this->decode_bits(t); + t = this->encode_R_type(0b0, 0b1, 0b10, 0b11, 0b11); + i = this->decode_bits(t); -// CHECK(i->get_mnemonic() == NOP); + CHECK(i->get_mnemonic() == NOP); -// delete i; -// } + delete i; +} TEST_CASE_METHOD(IDFixture, "Parse arbitrary r-type # one", "[id]") { @@ -113,164 +113,164 @@ TEST_CASE_METHOD(IDFixture, "Parse arbitrary r-type # one", "[id]") delete i; } -// TEST_CASE_METHOD(IDFixture, "Parse arbitrary r-type # two", "[id]") -// { -// signed int t; -// InstrDTO *i; +TEST_CASE_METHOD(IDFixture, "Parse arbitrary r-type # two", "[id]") +{ + signed int t; + InstrDTO *i; -// t = this->encode_R_type(0b10000, 0b01000, 0b00100, 0b10, 0b0); -// i = this->decode_bits(t); + t = this->encode_R_type(0b10000, 0b01000, 0b00100, 0b10, 0b0); + i = this->decode_bits(t); -// CHECK(i->get_s1() == 0x00000000); // registers are empty -// CHECK(i->get_s2() == 0x00000000); -// CHECK(i->get_s3() == 0x00000000); -// CHECK(i->get_mnemonic() == SUB); + CHECK(i->get_s1() == 0x00000000); // registers are empty + CHECK(i->get_s2() == 0x00000000); + CHECK(i->get_s3() == 0x00000000); + CHECK(i->get_mnemonic() == SUB); -// delete i; -// } + delete i; +} -// TEST_CASE_METHOD(IDFixture, "Parse arbitrary i-type # one", "[id]") -// { -// signed int t; -// InstrDTO *i; +TEST_CASE_METHOD(IDFixture, "Parse arbitrary i-type # one", "[id]") +{ + signed int t; + InstrDTO *i; -// t = this->encode_I_type(0xF, 0b1, 0b10, 0b0111, 0b1); -// i = this->decode_bits(t); + t = this->encode_I_type(0xF, 0b1, 0b10, 0b0111, 0b1); + i = this->decode_bits(t); -// CHECK(i->get_s1() == 0x00000000); // registers are empty -// CHECK(i->get_s2() == 0x00000000); -// CHECK(i->get_s3() == 0xF); -// CHECK(i->get_mnemonic() == SFTLI); + CHECK(i->get_s1() == 0x00000000); // registers are empty + CHECK(i->get_s2() == 0x00000000); + CHECK(i->get_s3() == 0xF); + CHECK(i->get_mnemonic() == SFTLI); -// delete i; -// } + delete i; +} -// TEST_CASE_METHOD(IDFixture, "Parse arbitrary i-type # two", "[id]") -// { -// signed int t; -// InstrDTO *i; +TEST_CASE_METHOD(IDFixture, "Parse arbitrary i-type # two", "[id]") +{ + signed int t; + InstrDTO *i; -// t = this->encode_I_type(0xCC, 0b010, 0b101, 0b1011, 0b1); -// i = this->decode_bits(t); + t = this->encode_I_type(0xCC, 0b010, 0b101, 0b1011, 0b1); + i = this->decode_bits(t); -// CHECK(i->get_s1() == 0x00000000); // registers are empty -// CHECK(i->get_s2() == 0x00000000); -// CHECK(i->get_s3() == 0xCC); -// CHECK(i->get_mnemonic() == STORE); - -// delete i; -// } - -// TEST_CASE_METHOD(IDFixture, "Parse arbitrary j-type # one", "[id]") -// { -// signed int t; -// InstrDTO *i; - -// t = this->encode_J_type(0x3456, 0b10101, 0b0111, 0b10); -// i = this->decode_bits(t); - -// CHECK(i->get_s1() == 0x00000000); // registers are empty -// CHECK(i->get_s2() == 0x3456); -// CHECK(i->get_mnemonic() == BOF); - -// delete i; -// } - -// TEST_CASE_METHOD(IDFixture, "Parse arbitrary j-type # two", "[id]") -// { -// signed int t; -// InstrDTO *i; - -// t = this->encode_J_type(0xBBCCF, 0b10101, 0b0011, 0b10); -// i = this->decode_bits(t); - -// CHECK(i->get_s1() == 0x00000000); // registers are empty -// CHECK(i->get_s2() == 0xBBCCF); -// CHECK(i->get_mnemonic() == JAL); - -// delete i; -// } - -// TEST_CASE_METHOD(IDFixture, "read does not conflict with read", "[id]") -// { -// signed int v; -// Response r; - -// v = 0b1; -// r = this->d->read_guard(v); -// CHECK(v == 0b0); -// REQUIRE(r == OK); - -// v = 0b1; -// this->d->read_guard(v); -// REQUIRE(v == 0b0); -// } - -// TEST_CASE_METHOD(IDFixture, "write does not conflict with write", "[id]") -// { -// signed int v; - -// v = 0b1; -// this->d->write_guard(v); -// REQUIRE(v == 0b0); - -// v = 0b1; -// this->d->write_guard(v); -// REQUIRE(v == 0b0); -// } - -// TEST_CASE_METHOD(IDFixture, "write does not conflict with read", "[id]") -// { -// signed int v; -// Response r; - -// v = 0b1; -// r = this->d->read_guard(v); -// CHECK(v == 0b0); -// REQUIRE(r == OK); - -// v = 0b1; -// this->d->write_guard(v); -// REQUIRE(v == 0b0); -// } - -// TEST_CASE_METHOD(IDFixture, "read does conflict with write", "[id]") -// { -// signed int v; -// Response r; - -// v = 0b1; -// this->d->write_guard(v); -// REQUIRE(v == 0b0); - -// v = 0b1; -// r = this->d->read_guard(v); -// CHECK(v == 0b01); -// REQUIRE(r == STALLED); -// } - -// TEST_CASE_METHOD(IDFixture, "stores indefinite conflicts", "[id]") -// { -// signed int v, ov; -// Response r; - -// v = 0b0; -// ov = v; -// while (v < 0b110) { -// this->d->write_guard(v); -// REQUIRE(v == 0b0); -// v = ++ov; -// } -// this->d->write_guard(v); -// REQUIRE(v == 0b0); - -// v = 0b110; -// r = this->d->read_guard(v); -// CHECK(v == 0b110); -// REQUIRE(r == STALLED); - -// v = 0b0; -// r = this->d->read_guard(v); -// CHECK(v == 0b0); -// REQUIRE(r == STALLED); -// } + CHECK(i->get_s1() == 0x00000000); // registers are empty + CHECK(i->get_s2() == 0x00000000); + CHECK(i->get_s3() == 0xCC); + CHECK(i->get_mnemonic() == STORE); + + delete i; +} + +TEST_CASE_METHOD(IDFixture, "Parse arbitrary j-type # one", "[id]") +{ + signed int t; + InstrDTO *i; + + t = this->encode_J_type(0x3456, 0b10101, 0b0111, 0b10); + i = this->decode_bits(t); + + CHECK(i->get_s1() == 0x00000000); // registers are empty + CHECK(i->get_s2() == 0x3456); + CHECK(i->get_mnemonic() == BOF); + + delete i; +} + +TEST_CASE_METHOD(IDFixture, "Parse arbitrary j-type # two", "[id]") +{ + signed int t; + InstrDTO *i; + + t = this->encode_J_type(0xBBCCF, 0b10101, 0b0011, 0b10); + i = this->decode_bits(t); + + CHECK(i->get_s1() == 0x00000000); // registers are empty + CHECK(i->get_s2() == 0xBBCCF); + CHECK(i->get_mnemonic() == JAL); + + delete i; +} + +TEST_CASE_METHOD(IDFixture, "read does not conflict with read", "[id]") +{ + signed int v; + Response r; + + v = 0b1; + r = this->d->read_guard(v); + CHECK(v == 0b0); + REQUIRE(r == OK); + + v = 0b1; + this->d->read_guard(v); + REQUIRE(v == 0b0); +} + +TEST_CASE_METHOD(IDFixture, "write does not conflict with write", "[id]") +{ + signed int v; + + v = 0b1; + this->d->write_guard(v); + REQUIRE(v == 0b0); + + v = 0b1; + this->d->write_guard(v); + REQUIRE(v == 0b0); +} + +TEST_CASE_METHOD(IDFixture, "write does not conflict with read", "[id]") +{ + signed int v; + Response r; + + v = 0b1; + r = this->d->read_guard(v); + CHECK(v == 0b0); + REQUIRE(r == OK); + + v = 0b1; + this->d->write_guard(v); + REQUIRE(v == 0b0); +} + +TEST_CASE_METHOD(IDFixture, "read does conflict with write", "[id]") +{ + signed int v; + Response r; + + v = 0b1; + this->d->write_guard(v); + REQUIRE(v == 0b0); + + v = 0b1; + r = this->d->read_guard(v); + CHECK(v == 0b01); + REQUIRE(r == STALLED); +} + +TEST_CASE_METHOD(IDFixture, "stores indefinite conflicts", "[id]") +{ + signed int v, ov; + Response r; + + v = 0b0; + ov = v; + while (v < 0b110) { + this->d->write_guard(v); + REQUIRE(v == 0b0); + v = ++ov; + } + this->d->write_guard(v); + REQUIRE(v == 0b0); + + v = 0b110; + r = this->d->read_guard(v); + CHECK(v == 0b110); + REQUIRE(r == STALLED); + + v = 0b0; + r = this->d->read_guard(v); + CHECK(v == 0b0); + REQUIRE(r == STALLED); +} |