From ab6d02361b04a18b7823aef0ff1cb0ff2a215ec2 Mon Sep 17 00:00:00 2001 From: bd Date: Thu, 27 Mar 2025 20:30:18 -0400 Subject: Instr, InstrDTO gets/sets, other structures required for decode --- inc/accessor.h | 3 +++ src/utils/accessor.cc | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/inc/accessor.h b/inc/accessor.h index fb4999d..eb56785 100644 --- a/inc/accessor.h +++ b/inc/accessor.h @@ -4,7 +4,10 @@ enum Accessor { IDLE, + WRITE, MEM, + EXEC, + DCDE, FETCH, L1CACHE, SIDE, diff --git a/src/utils/accessor.cc b/src/utils/accessor.cc index 86484c5..99347ed 100644 --- a/src/utils/accessor.cc +++ b/src/utils/accessor.cc @@ -3,6 +3,8 @@ std::ostream &operator<<(std::ostream &os, Accessor a) { - const std::string nameA[] = {"IDLE", "MEM", "FETCH", "L1CACHE", "SIDE"}; + const std::string nameA[] = { + "IDLE", "WRITE", "MEM", "EXEC", "DCDE", "FETCH", "L1CACHE", "SIDE", + }; return os << nameA[a]; } -- cgit v1.2.3 From 136417edd709f0e2d30931d222b658ff7dd9a5a8 Mon Sep 17 00:00:00 2001 From: bd Date: Fri, 28 Mar 2025 18:10:14 -0400 Subject: add get_instr_fields func to parse instruction fields from raw bits --- inc/definitions.h | 27 +++++++++++- inc/utils.h | 20 ++++++++- src/storage/cache.cc | 4 +- src/utils/utils.cc | 59 +++++++++++++++++++++++--- tests/utils.cc | 116 +++++++++++++++++++++++++++++++++++++++++++++++++-- 5 files changed, 213 insertions(+), 13 deletions(-) diff --git a/inc/definitions.h b/inc/definitions.h index ff2f7c6..c9367ff 100644 --- a/inc/definitions.h +++ b/inc/definitions.h @@ -11,6 +11,10 @@ * The total number of words in a line */ #define LINE_SIZE static_cast(pow(2, 2)) +/** + * Number of bits in a word + */ +#define WORD_SPEC 32 /** * The number of bits to specify a memory word @@ -28,7 +32,8 @@ * The total number of lines in l1 cache */ #define L1_CACHE_WORD_SPEC 7 -#define L1_CACHE_LINE_SPEC static_cast(L1_CACHE_WORD_SPEC - LINE_SPEC) +#define L1_CACHE_LINE_SPEC \ + static_cast(L1_CACHE_WORD_SPEC - LINE_SPEC) #define L1_CACHE_LINES static_cast(pow(2, L1_CACHE_LINE_SPEC)) /** @@ -46,6 +51,26 @@ */ #define GPR_NUM 16 +/** + * The number of bits to specify an instruction type + */ +#define TYPE_SIZE 2 + +/** + * The number of bits to specify a register + */ +#define REG_SIZE 5 + +/** + * The number of bits to specify an R-Type opcode. + */ +#define R_OPCODE_SIZE 5 + +/** + * The number of bits to specify an opcode. + */ +#define OPCODE_SIZE 4 + /** * Return the N least-significant bits from integer K using a bit mask * @param the integer to be parsed diff --git a/inc/utils.h b/inc/utils.h index df8d374..7fed157 100644 --- a/inc/utils.h +++ b/inc/utils.h @@ -10,7 +10,25 @@ * @param the resulting index * @param the resulting offset */ -void get_bit_fields(int address, int *tag, int *index, int *offset); +void get_cache_fields(int address, int *tag, int *index, int *offset); + +/** + * Parse an instruction into a type, opcode, and fields. If the type is invalid, + * only the type field will be set. + * @param the resulting first field, which varies per type. To call this + * function properly, this field must contain the full instruction bytes on + * function entry. + * @param the resulting second field, which varies per type. + * @param the resulting third field, which varies per type. + * @param the resulting type. + * @param the resulting opcode. + */ +void get_instr_fields( + signed int &s1, + signed int &s2, + signed int &s3, + unsigned int &type, + unsigned int &opcode); /** * Formats a string using snprintf. diff --git a/src/storage/cache.cc b/src/storage/cache.cc index dccab47..80f59ef 100644 --- a/src/storage/cache.cc +++ b/src/storage/cache.cc @@ -69,7 +69,7 @@ Response Cache::process( Response r = this->is_access_cleared(accessor, address); if (r == OK) { int tag, index, offset; - get_bit_fields(address, &tag, &index, &offset); + get_cache_fields(address, &tag, &index, &offset); request_handler(index, offset); } return r; @@ -104,7 +104,7 @@ void Cache::handle_miss(int expected) std::array *actual; std::array *meta; - get_bit_fields(expected, &tag, &index, &offset); + get_cache_fields(expected, &tag, &index, &offset); r = OK; meta = &this->meta.at(index); actual = &this->data->at(index); diff --git a/src/utils/utils.cc b/src/utils/utils.cc index 3a11c2c..3b140e0 100644 --- a/src/utils/utils.cc +++ b/src/utils/utils.cc @@ -4,14 +4,62 @@ #include #include -void get_bit_fields(int address, int *tag, int *index, int *offset) +static Logger *global_log = Logger::getInstance(); + +void get_cache_fields(int address, int *tag, int *index, int *offset) { - *tag = GET_MID_BITS( - address, L1_CACHE_LINE_SPEC + LINE_SPEC, MEM_WORD_SPEC); + *tag = GET_MID_BITS(address, L1_CACHE_LINE_SPEC + LINE_SPEC, MEM_WORD_SPEC); *index = GET_MID_BITS(address, LINE_SPEC, L1_CACHE_LINE_SPEC + LINE_SPEC); *offset = GET_LS_BITS(address, LINE_SPEC); } +void get_instr_fields( + signed int &s1, + signed int &s2, + signed int &s3, + unsigned int &type, + unsigned int &opcode) +{ + type = GET_LS_BITS(s1, TYPE_SIZE); + switch (type) { + case 0: + // R-TYPE + opcode = GET_MID_BITS(s1, TYPE_SIZE, TYPE_SIZE + R_OPCODE_SIZE); + s3 = GET_MID_BITS( + s1, TYPE_SIZE + R_OPCODE_SIZE + (REG_SIZE * 2), + TYPE_SIZE + R_OPCODE_SIZE + (REG_SIZE * 3)); + s2 = GET_MID_BITS( + s1, TYPE_SIZE + R_OPCODE_SIZE + REG_SIZE, + TYPE_SIZE + R_OPCODE_SIZE + (REG_SIZE * 2)); + s1 = GET_MID_BITS( + s1, TYPE_SIZE + R_OPCODE_SIZE, + TYPE_SIZE + R_OPCODE_SIZE + REG_SIZE); + break; + case 1: + // I-TYPE + opcode = GET_MID_BITS(s1, TYPE_SIZE, TYPE_SIZE + OPCODE_SIZE); + s3 = GET_MID_BITS( + s1, TYPE_SIZE + OPCODE_SIZE + (REG_SIZE * 2), WORD_SPEC); + s2 = GET_MID_BITS( + s1, TYPE_SIZE + OPCODE_SIZE + REG_SIZE, + TYPE_SIZE + OPCODE_SIZE + (REG_SIZE * 2)); + s1 = GET_MID_BITS( + s1, TYPE_SIZE + OPCODE_SIZE, TYPE_SIZE + OPCODE_SIZE + REG_SIZE); + break; + case 2: + // J-TYPE + opcode = GET_MID_BITS(s1, TYPE_SIZE, TYPE_SIZE + OPCODE_SIZE); + s2 = GET_MID_BITS(s1, TYPE_SIZE + OPCODE_SIZE + REG_SIZE, WORD_SPEC); + s1 = GET_MID_BITS( + s1, TYPE_SIZE + OPCODE_SIZE, TYPE_SIZE + OPCODE_SIZE + REG_SIZE); + break; + default: + global_log->log( + DEBUG, + string_format("%s returning invalid type: %d", __FUNCTION__, type)); + } +} + const std::string string_format(const char *const zcFormat, ...) { va_list vaArgs; @@ -28,8 +76,9 @@ const std::string string_format(const char *const zcFormat, ...) return std::string(zc.data(), iLen); } -int wrap_address(int address) { - if (address < 0){ +int wrap_address(int address) +{ + if (address < 0) { return ((address % MEM_WORDS) + MEM_WORDS) % MEM_WORDS; } return address % MEM_WORDS; diff --git a/tests/utils.cc b/tests/utils.cc index ea1a1ed..6c72694 100644 --- a/tests/utils.cc +++ b/tests/utils.cc @@ -2,26 +2,134 @@ #include "definitions.h" #include -TEST_CASE("Parse arbitrary fields # one", "[cache]") +TEST_CASE("Parse arbitrary fields # one", "[utils]") { int tag, index, offset; int address = 0b0001010101; - get_bit_fields(address, &tag, &index, &offset); + get_cache_fields(address, &tag, &index, &offset); CHECK(tag == 0b000); CHECK(index == 0b10101); CHECK(offset == 0b01); } -TEST_CASE("Parse arbitrary fields # two", "[cache]") +TEST_CASE("Parse arbitrary fields # two", "[utils]") { int tag, index, offset; int address = 0b0100111011; - get_bit_fields(address, &tag, &index, &offset); + get_cache_fields(address, &tag, &index, &offset); CHECK(tag == 0b010); CHECK(index == 0b01110); CHECK(offset == 0b11); } +TEST_CASE("Parse invalid type", "[utils]") +{ + signed int s1 = 0, s2 = 0, s3 = 0; + unsigned int type = 0, opcode = 0; + + s1 = 0x00FF00FF; + get_instr_fields(s1, s2, s3, type, opcode); + + REQUIRE(type == 0b11); + // behavior does nothing + CHECK(s1 == 0x00FF00FF); + CHECK(s2 == 0b0); + CHECK(s3 == 0b0); + CHECK(opcode == 0b0); +} + +TEST_CASE("Parse arbitrary r-type # one", "[utils]") +{ + signed int s1 = 0, s2 = 0, s3 = 0; + unsigned int type = 0, opcode = 0; + + s1 = 0xCCCCCCCC; + get_instr_fields(s1, s2, s3, type, opcode); + + REQUIRE(type == 0b00); + CHECK(s1 == 0b11001); + CHECK(s2 == 0b01100); + CHECK(s3 == 0b00110); + CHECK(opcode == 0b10011); +} + +TEST_CASE("Parse arbitrary r-type # two", "[utils]") +{ + signed int s1 = 0, s2 = 0, s3 = 0; + unsigned int type = 0, opcode = 0; + + s1 = 0x99AABBCC; + get_instr_fields(s1, s2, s3, type, opcode); + + REQUIRE(type == 0b00); + CHECK(s1 == 0b10111); + CHECK(s2 == 0b01011); + CHECK(s3 == 0b10101); + CHECK(opcode == 0b10011); +} + +TEST_CASE("Parse arbitrary i-type # one", "[utils]") +{ + signed int s1 = 0, s2 = 0, s3 = 0; + unsigned int type = 0, opcode = 0; + + s1 = 0xDDDDDDDD; + get_instr_fields(s1, s2, s3, type, opcode); + + REQUIRE(type == 0b01); + CHECK(s1 == 0b10111); + CHECK(s2 == 0b11011); + CHECK(s3 == 0xDDDD); + CHECK(opcode == 0b0111); +} + +TEST_CASE("Parse arbitrary i-type # two", "[utils]") +{ + signed int s1 = 0, s2 = 0, s3 = 0; + unsigned int type = 0, opcode = 0; + + s1 = 0xAABBCCDD; + get_instr_fields(s1, s2, s3, type, opcode); + + REQUIRE(type == 0b01); + CHECK(s1 == 0b10011); + CHECK(s2 == 0b11001); + CHECK(s3 == 0xAABB); + CHECK(opcode == 0b0111); +} + +TEST_CASE("Parse arbitrary j-type # one", "[utils]") +{ + signed int s1 = 0, s2 = 0, s3 = 0; + unsigned int type = 0, opcode = 0; + + s1 = 0xEEEEEEEE; + get_instr_fields(s1, s2, s3, type, opcode); + + REQUIRE(type == 0b10); + CHECK(s1 == 0b11011); + CHECK(s2 == 0b111011101110111011101); + CHECK(opcode == 0b1011); + // behavior does nothing + CHECK(s3 == 0b0); +} + +TEST_CASE("Parse arbitrary j-type # two", "[utils]") +{ + signed int s1 = 0, s2 = 0, s3 = 0; + unsigned int type = 0, opcode = 0; + + s1 = 0xBBCCDDEE; + get_instr_fields(s1, s2, s3, type, opcode); + + REQUIRE(type == 0b10); + CHECK(s1 == 0b10111); + CHECK(s2 == 0b101110111100110011011); + CHECK(opcode == 0b1011); + // behavior does nothing + CHECK(s3 == 0b0); +} + TEST_CASE("wrap address outside upper bound", "[utils]") { int address = MEM_WORDS + 25; -- cgit v1.2.3 From 579538d8c3240dcec1fd007a67b5ae4aaa832d3b Mon Sep 17 00:00:00 2001 From: bd Date: Fri, 28 Mar 2025 19:55:04 -0400 Subject: Move get_instr_fields, add all instruction mnemonics --- inc/storage.h | 2 +- inc/utils.h | 18 --------- src/utils/utils.cc | 49 ------------------------ tests/utils.cc | 108 ----------------------------------------------------- 4 files changed, 1 insertion(+), 176 deletions(-) diff --git a/inc/storage.h b/inc/storage.h index ff1fbcb..d6fa094 100644 --- a/inc/storage.h +++ b/inc/storage.h @@ -80,7 +80,7 @@ class Storage /** * The accessor currently being serviced. */ - enum Accessor requester; + Accessor requester; /** * The number of cycles until the current request is completed. */ diff --git a/inc/utils.h b/inc/utils.h index 7fed157..a375b68 100644 --- a/inc/utils.h +++ b/inc/utils.h @@ -12,24 +12,6 @@ */ void get_cache_fields(int address, int *tag, int *index, int *offset); -/** - * Parse an instruction into a type, opcode, and fields. If the type is invalid, - * only the type field will be set. - * @param the resulting first field, which varies per type. To call this - * function properly, this field must contain the full instruction bytes on - * function entry. - * @param the resulting second field, which varies per type. - * @param the resulting third field, which varies per type. - * @param the resulting type. - * @param the resulting opcode. - */ -void get_instr_fields( - signed int &s1, - signed int &s2, - signed int &s3, - unsigned int &type, - unsigned int &opcode); - /** * Formats a string using snprintf. * @param an object that represents the format string diff --git a/src/utils/utils.cc b/src/utils/utils.cc index 3b140e0..e12a0e0 100644 --- a/src/utils/utils.cc +++ b/src/utils/utils.cc @@ -4,8 +4,6 @@ #include #include -static Logger *global_log = Logger::getInstance(); - void get_cache_fields(int address, int *tag, int *index, int *offset) { *tag = GET_MID_BITS(address, L1_CACHE_LINE_SPEC + LINE_SPEC, MEM_WORD_SPEC); @@ -13,53 +11,6 @@ void get_cache_fields(int address, int *tag, int *index, int *offset) *offset = GET_LS_BITS(address, LINE_SPEC); } -void get_instr_fields( - signed int &s1, - signed int &s2, - signed int &s3, - unsigned int &type, - unsigned int &opcode) -{ - type = GET_LS_BITS(s1, TYPE_SIZE); - switch (type) { - case 0: - // R-TYPE - opcode = GET_MID_BITS(s1, TYPE_SIZE, TYPE_SIZE + R_OPCODE_SIZE); - s3 = GET_MID_BITS( - s1, TYPE_SIZE + R_OPCODE_SIZE + (REG_SIZE * 2), - TYPE_SIZE + R_OPCODE_SIZE + (REG_SIZE * 3)); - s2 = GET_MID_BITS( - s1, TYPE_SIZE + R_OPCODE_SIZE + REG_SIZE, - TYPE_SIZE + R_OPCODE_SIZE + (REG_SIZE * 2)); - s1 = GET_MID_BITS( - s1, TYPE_SIZE + R_OPCODE_SIZE, - TYPE_SIZE + R_OPCODE_SIZE + REG_SIZE); - break; - case 1: - // I-TYPE - opcode = GET_MID_BITS(s1, TYPE_SIZE, TYPE_SIZE + OPCODE_SIZE); - s3 = GET_MID_BITS( - s1, TYPE_SIZE + OPCODE_SIZE + (REG_SIZE * 2), WORD_SPEC); - s2 = GET_MID_BITS( - s1, TYPE_SIZE + OPCODE_SIZE + REG_SIZE, - TYPE_SIZE + OPCODE_SIZE + (REG_SIZE * 2)); - s1 = GET_MID_BITS( - s1, TYPE_SIZE + OPCODE_SIZE, TYPE_SIZE + OPCODE_SIZE + REG_SIZE); - break; - case 2: - // J-TYPE - opcode = GET_MID_BITS(s1, TYPE_SIZE, TYPE_SIZE + OPCODE_SIZE); - s2 = GET_MID_BITS(s1, TYPE_SIZE + OPCODE_SIZE + REG_SIZE, WORD_SPEC); - s1 = GET_MID_BITS( - s1, TYPE_SIZE + OPCODE_SIZE, TYPE_SIZE + OPCODE_SIZE + REG_SIZE); - break; - default: - global_log->log( - DEBUG, - string_format("%s returning invalid type: %d", __FUNCTION__, type)); - } -} - const std::string string_format(const char *const zcFormat, ...) { va_list vaArgs; diff --git a/tests/utils.cc b/tests/utils.cc index 6c72694..2e0e934 100644 --- a/tests/utils.cc +++ b/tests/utils.cc @@ -22,114 +22,6 @@ TEST_CASE("Parse arbitrary fields # two", "[utils]") CHECK(offset == 0b11); } -TEST_CASE("Parse invalid type", "[utils]") -{ - signed int s1 = 0, s2 = 0, s3 = 0; - unsigned int type = 0, opcode = 0; - - s1 = 0x00FF00FF; - get_instr_fields(s1, s2, s3, type, opcode); - - REQUIRE(type == 0b11); - // behavior does nothing - CHECK(s1 == 0x00FF00FF); - CHECK(s2 == 0b0); - CHECK(s3 == 0b0); - CHECK(opcode == 0b0); -} - -TEST_CASE("Parse arbitrary r-type # one", "[utils]") -{ - signed int s1 = 0, s2 = 0, s3 = 0; - unsigned int type = 0, opcode = 0; - - s1 = 0xCCCCCCCC; - get_instr_fields(s1, s2, s3, type, opcode); - - REQUIRE(type == 0b00); - CHECK(s1 == 0b11001); - CHECK(s2 == 0b01100); - CHECK(s3 == 0b00110); - CHECK(opcode == 0b10011); -} - -TEST_CASE("Parse arbitrary r-type # two", "[utils]") -{ - signed int s1 = 0, s2 = 0, s3 = 0; - unsigned int type = 0, opcode = 0; - - s1 = 0x99AABBCC; - get_instr_fields(s1, s2, s3, type, opcode); - - REQUIRE(type == 0b00); - CHECK(s1 == 0b10111); - CHECK(s2 == 0b01011); - CHECK(s3 == 0b10101); - CHECK(opcode == 0b10011); -} - -TEST_CASE("Parse arbitrary i-type # one", "[utils]") -{ - signed int s1 = 0, s2 = 0, s3 = 0; - unsigned int type = 0, opcode = 0; - - s1 = 0xDDDDDDDD; - get_instr_fields(s1, s2, s3, type, opcode); - - REQUIRE(type == 0b01); - CHECK(s1 == 0b10111); - CHECK(s2 == 0b11011); - CHECK(s3 == 0xDDDD); - CHECK(opcode == 0b0111); -} - -TEST_CASE("Parse arbitrary i-type # two", "[utils]") -{ - signed int s1 = 0, s2 = 0, s3 = 0; - unsigned int type = 0, opcode = 0; - - s1 = 0xAABBCCDD; - get_instr_fields(s1, s2, s3, type, opcode); - - REQUIRE(type == 0b01); - CHECK(s1 == 0b10011); - CHECK(s2 == 0b11001); - CHECK(s3 == 0xAABB); - CHECK(opcode == 0b0111); -} - -TEST_CASE("Parse arbitrary j-type # one", "[utils]") -{ - signed int s1 = 0, s2 = 0, s3 = 0; - unsigned int type = 0, opcode = 0; - - s1 = 0xEEEEEEEE; - get_instr_fields(s1, s2, s3, type, opcode); - - REQUIRE(type == 0b10); - CHECK(s1 == 0b11011); - CHECK(s2 == 0b111011101110111011101); - CHECK(opcode == 0b1011); - // behavior does nothing - CHECK(s3 == 0b0); -} - -TEST_CASE("Parse arbitrary j-type # two", "[utils]") -{ - signed int s1 = 0, s2 = 0, s3 = 0; - unsigned int type = 0, opcode = 0; - - s1 = 0xBBCCDDEE; - get_instr_fields(s1, s2, s3, type, opcode); - - REQUIRE(type == 0b10); - CHECK(s1 == 0b10111); - CHECK(s2 == 0b101110111100110011011); - CHECK(opcode == 0b1011); - // behavior does nothing - CHECK(s3 == 0b0); -} - TEST_CASE("wrap address outside upper bound", "[utils]") { int address = MEM_WORDS + 25; -- cgit v1.2.3 From b29311f0140c615c005f5d076adc921d98842ec6 Mon Sep 17 00:00:00 2001 From: bd Date: Sat, 29 Mar 2025 02:36:38 -0400 Subject: get_instr_fields return mnemonic rather than opcode and type --- inc/definitions.h | 5 +++++ src/cli/cli.cc | 3 +++ 2 files changed, 8 insertions(+) diff --git a/inc/definitions.h b/inc/definitions.h index c9367ff..3238a8b 100644 --- a/inc/definitions.h +++ b/inc/definitions.h @@ -51,6 +51,11 @@ */ #define GPR_NUM 16 +/** + * The number of vector registers + */ +#define V_NUM 8 + /** * The number of bits to specify an instruction type */ diff --git a/src/cli/cli.cc b/src/cli/cli.cc index 022b266..58575cb 100644 --- a/src/cli/cli.cc +++ b/src/cli/cli.cc @@ -3,6 +3,7 @@ #include "definitions.h" #include "dram.h" #include "response.h" +#include "accessor.h" #include "utils.h" #include @@ -43,6 +44,7 @@ Cli::Cli() }; commands['r'] = [this](std::vector args) { + (void)args; reset(); return; }; @@ -61,6 +63,7 @@ Cli::Cli() }; commands['h'] = [this](std::vector args) { + (void)args; help(); return; }; -- cgit v1.2.3 From d8e33f871bfb8dbfbad3fa0d7e1e13af5bcde830 Mon Sep 17 00:00:00 2001 From: bd Date: Sat, 29 Mar 2025 12:30:54 -0400 Subject: Add implementation functions for checking out a register. --- inc/response.h | 1 + src/utils/response.cc | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/inc/response.h b/inc/response.h index 6cd6678..05e9352 100644 --- a/inc/response.h +++ b/inc/response.h @@ -6,6 +6,7 @@ enum Response { OK, WAIT, BLOCKED, + STALLED, }; std::ostream &operator<<(std::ostream &os, Response r); diff --git a/src/utils/response.cc b/src/utils/response.cc index def6578..3d6e439 100644 --- a/src/utils/response.cc +++ b/src/utils/response.cc @@ -3,6 +3,6 @@ std::ostream &operator<<(std::ostream &os, Response r) { - const std::string nameR[] = {"OK", "WAIT", "BLOCKED"}; + const std::string nameR[] = {"OK", "WAIT", "BLOCKED", "STALLED"}; return os << nameR[r]; } -- cgit v1.2.3