diff options
author | Siddarth Suresh <155843085+SiddarthSuresh98@users.noreply.github.com> | 2025-04-12 13:04:10 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-04-12 13:04:10 -0400 |
commit | 561f7a6e6c24b05383b6db86b48125ee80a8355f (patch) | |
tree | 6acbfd27652c2b83686df93c21918a877a0451e8 /src | |
parent | c9e35a8f3aa2047701e87a50f12b4bed23d5e7db (diff) | |
parent | 3ae113c7d6f1b6f46d8960b284837a44fbeb2e77 (diff) |
Merge pull request #50 from bdunahu/bdunahu
Move storage to a separate git repository.
Diffstat (limited to 'src')
-rw-r--r-- | src/cli/cli.cc | 214 | ||||
-rw-r--r-- | src/sim/ex.cc | 2 | ||||
-rw-r--r-- | src/sim/if.cc | 4 | ||||
-rw-r--r-- | src/sim/mm.cc | 10 | ||||
-rw-r--r-- | src/storage/cache.cc | 180 | ||||
-rw-r--r-- | src/storage/dram.cc | 130 | ||||
-rw-r--r-- | src/storage/storage.cc | 16 | ||||
-rw-r--r-- | src/utils/utils.cc | 42 |
8 files changed, 10 insertions, 588 deletions
diff --git a/src/cli/cli.cc b/src/cli/cli.cc deleted file mode 100644 index 58575cb..0000000 --- a/src/cli/cli.cc +++ /dev/null @@ -1,214 +0,0 @@ -#include "cli.h" -#include "cache.h" -#include "definitions.h" -#include "dram.h" -#include "response.h" -#include "accessor.h" -#include "utils.h" -#include <iostream> - -Cli::Cli() -{ - this->cache = nullptr; - this->cycle = 0; - this->initialize(); - - commands['l'] = [this](std::vector<std::string> args) { - Accessor a; - if (args.size() >= 2) { - try { - a = match_accessor_or_die(args[0]); - load(a, std::stoi(args[1])); - } catch (const std::invalid_argument &e) { - std::cerr << "Invalid input: " << e.what() << std::endl; - } - } else { - std::cout << "Usage: l <memory-address>\n"; - } - return; - }; - - commands['s'] = [this](std::vector<std::string> args) { - Accessor a; - if (args.size() >= 3) { - try { - a = match_accessor_or_die(args[0]); - store(a, std::stoi(args[1]), std::stoi(args[2])); - } catch (const std::invalid_argument &e) { - std::cerr << "Invalid input: " << e.what() << std::endl; - } - } else { - std::cout << "Usage: s <memory-address> <data>\n"; - } - return; - }; - - commands['r'] = [this](std::vector<std::string> args) { - (void)args; - reset(); - return; - }; - - commands['p'] = [this](std::vector<std::string> args) { - if (args.size() >= 1) { - try { - peek(std::stoi(args[0])); - } catch (const std::invalid_argument &e) { - std::cerr << "Invalid input: " << e.what() << std::endl; - } - } else { - std::cout << "Usage: v <storage-level> <base> <lines>\n"; - } - return; - }; - - commands['h'] = [this](std::vector<std::string> args) { - (void)args; - help(); - return; - }; -} - -Cli::~Cli() { delete this->cache; } - -void Cli::help() -{ - std::cout - << "Available commands:" << std::endl - << " [l]oad <address> - Load data from memory at the specified " - "address" - << std::endl - << " [s]tore <accessor> <data> <address> - Stores data into memory at " - "specified address. Acessor must be one of: [f]etch, [m]em" - << " [p]eek <storage-level> <base> <lines> - side door function that " - "peeks the current status of the entire memory subsystem" - << std::endl - << " [r]eset - side door function that resets the memory " - "configuration and " - "cycles" - << std::endl - << " [h]elp - prints this help text" << std::endl - << " [q]uit - quits the program" << std::endl; -} - -void Cli::load(Accessor accessor, int address) -{ - address = wrap_address(address); - const auto default_flags = std::cout.flags(); - const auto default_fill = std::cout.fill(); - - signed int data; - Response r = this->cache->read_word(accessor, address, data); - std::cout << r << " to " << accessor << " reading " << address << std::endl; - if (r == OK) - std::cout << " Got: " << std::hex << data << std::endl; - - std::cout.flags(default_flags); - std::cout.fill(default_fill); -} - -void Cli::store(Accessor accessor, int data, int address) -{ - address = wrap_address(address); - Response r = this->cache->write_word(accessor, data, address); - std::cout << r << " to " << accessor << " storing " << data << " in " - << address << std::endl; -} - -void Cli::reset() -{ - this->initialize(); - std::cout << "Done." << std::endl; -} - -void Cli::peek(int level) -{ - Storage *curr = this->cache; - for (int i = 0; i < level; ++i) { - if (!curr) { - std::cerr << "Level " << level << " of storage does not exist." - << std::endl; - return; - } - curr = curr->get_lower(); - } - - Cache *c = dynamic_cast<Cache *>(curr); - if (c) { - std::cout << *c << std::endl; - } else { - std::cout << *dynamic_cast<Dram *>(curr) << std::endl; - ; - } -} - -void Cli::run() -{ - std::cout << "Memory Command Processor Started. Type 'h' for a list of " - "commands." - << std::endl; - std::string input; - - bool run = true; - while (run) { - std::cout << this->cycle << "> "; - std::getline(std::cin, input); - - std::istringstream iss1(input); - std::vector<std::string> words; - std::string sentence; - std::string word; - - while (std::getline(iss1, sentence, ';')) { - words.clear(); - std::istringstream iss2(sentence); - - while (iss2 >> word) { - words.push_back(word); - } - if (words.empty()) - continue; - - std::string command = words[0]; - words.erase(words.begin()); - - if (command == "q") { - run = false; - break; - } - - auto it = commands.find(tolower(command[0])); - if (it != commands.end()) { - it->second(words); - } else { - std::cout << "Unknown command: '" << command - << "'. Type 'help' for available commands." - << std::endl; - } - } - } -} - -void Cli::initialize() -{ - Logger *global_log = Logger::getInstance(); - - global_log->log(INFO, "Resetting memory configuration and cycle."); - - if (this->cache != nullptr) - delete this->cache; - - Dram *d = new Dram(MEM_DELAY); - this->cache = new Cache(d, L1_CACHE_DELAY); - this->cycle = 1; -} - -Accessor Cli::match_accessor_or_die(std::string s) -{ - if (tolower(s[0]) == 'f') - return FETCH; - else if (tolower(s[0]) == 'm') - return MEM; - else - throw std::invalid_argument(s); -} diff --git a/src/sim/ex.cc b/src/sim/ex.cc index b6f8a1d..50f00a8 100644 --- a/src/sim/ex.cc +++ b/src/sim/ex.cc @@ -1,6 +1,6 @@ #include "ex.h" #include "accessor.h" -#include "definitions.h" +#include "pipe_spec.h" #include "instrDTO.h" #include "response.h" #include "stage.h" diff --git a/src/sim/if.cc b/src/sim/if.cc index 85fb27f..4ab7f3e 100644 --- a/src/sim/if.cc +++ b/src/sim/if.cc @@ -26,10 +26,12 @@ InstrDTO *IF::advance(Response p) void IF::advance_helper() { Response r; + int i; signed int bits; if (this->curr_instr == nullptr) { - r = this->storage->read_word(this->id, this->pc, bits); + i = this->storage->read_word(this, this->pc, bits); + r = i ? OK : STALLED; if (r == OK) { this->curr_instr = new InstrDTO(); this->curr_instr->set_instr_bits(bits); diff --git a/src/sim/mm.cc b/src/sim/mm.cc index 07a362b..a9a60c2 100644 --- a/src/sim/mm.cc +++ b/src/sim/mm.cc @@ -9,11 +9,12 @@ MM::MM(Stage *stage) : Stage(stage) { this->id = MEM; } void MM::advance_helper() { signed int data; + int i; switch (this->curr_instr->get_mnemonic()) { case LOAD: - this->status = this->storage->read_word( - this->id, this->curr_instr->get_s1(), data); + i = this->storage->read_word(this, this->curr_instr->get_s1(), data); + this->status = i ? OK : STALLED; if (this->status == OK) { this->curr_instr->set_s1(data); } else @@ -22,8 +23,9 @@ void MM::advance_helper() case STORE: // TODO signed issues, we aren't wrapping addresses - this->status = this->storage->write_word( - this->id, this->curr_instr->get_s2(), this->curr_instr->get_s1()); + i = this->storage->write_word( + this, this->curr_instr->get_s2(), this->curr_instr->get_s1()); + this->status = i ? OK : STALLED; if (this->status != OK) { this->status = STALLED; } diff --git a/src/storage/cache.cc b/src/storage/cache.cc deleted file mode 100644 index 80f59ef..0000000 --- a/src/storage/cache.cc +++ /dev/null @@ -1,180 +0,0 @@ -#include "cache.h" -#include "definitions.h" -#include "response.h" -#include "utils.h" -#include <bits/stdc++.h> -#include <iostream> -#include <iterator> - -Cache::Cache(Storage *lower, int delay) -{ - this->data = new std::vector<std::array<signed int, LINE_SIZE>>; - this->data->resize(L1_CACHE_LINES); - this->delay = delay; - this->is_waiting = false; - this->lower = lower; - this->meta.fill({-1, -1}); - this->requester = IDLE; - this->wait_time = this->delay; -} - -Cache::~Cache() -{ - delete this->lower; - delete this->data; -} - -Response Cache::write_word(Accessor accessor, signed int data, int address) -{ - return process(accessor, address, [&](int index, int offset) { - this->data->at(index).at(offset) = data; - this->meta[index].at(1) = 1; - }); -} - -Response Cache::write_line( - Accessor accessor, std::array<signed int, LINE_SIZE> data_line, int address) -{ - return process(accessor, address, [&](int index, int offset) { - (void)offset; - this->data->at(index) = data_line; - this->meta[index].at(1) = 1; - }); -} - -// TODO: tests for multi level cache -Response Cache::read_line( - Accessor accessor, - int address, - std::array<signed int, LINE_SIZE> &data_line) -{ - return process(accessor, address, [&](int index, int offset) { - (void)offset; - data_line = this->data->at(index); - }); -} - -Response Cache::read_word(Accessor accessor, int address, signed int &data) -{ - return process(accessor, address, [&](int index, int offset) { - data = this->data->at(index).at(offset); - }); -} - -Response Cache::process( - Accessor accessor, - int address, - std::function<void(int index, int offset)> request_handler) -{ - Response r = this->is_access_cleared(accessor, address); - if (r == OK) { - int tag, index, offset; - get_cache_fields(address, &tag, &index, &offset); - request_handler(index, offset); - } - return r; -} - -Response Cache::is_access_cleared(Accessor accessor, int address) -{ - Response r; - r = WAIT; - /* Do this first--then process the first cycle immediately. */ - if (this->requester == IDLE) - this->requester = accessor; - if (this->requester == accessor) { - handle_miss(address); - if (this->is_waiting) - r = BLOCKED; - else if (this->wait_time == 0) { - this->requester = IDLE; - this->wait_time = delay; - r = OK; - } else { - --this->wait_time; - } - } - return r; -} - -void Cache::handle_miss(int expected) -{ - Response r, q; - int tag, index, offset; - std::array<signed int, LINE_SIZE> *actual; - std::array<int, 2> *meta; - - get_cache_fields(expected, &tag, &index, &offset); - r = OK; - meta = &this->meta.at(index); - actual = &this->data->at(index); - - if (meta->at(0) != tag) { - r = WAIT; - // address not in cache - if (meta->at(1) >= 0) { - // occupant is dirty - // writing line to DRam in case of dirty cache eviction - q = this->lower->write_line( - L1CACHE, *actual, - ((index << LINE_SPEC) + - (meta->at(0) << (L1_CACHE_LINE_SPEC + LINE_SPEC)))); - if (q == OK) { - meta->at(1) = -1; - } - } else { - q = this->lower->read_line(L1CACHE, expected, *actual); - if (q == OK) { - meta->at(0) = tag; - } - } - } - - this->is_waiting = (r == OK) ? false : true; -} - -std::array<std::array<int, 2>, L1_CACHE_LINES> Cache::get_meta() const -{ - std::array<std::array<int, 2>, L1_CACHE_LINES> ret; - std::copy(std::begin(this->meta), std::end(this->meta), std::begin(ret)); - return ret; -} - -std::ostream &operator<<(std::ostream &os, const Cache &c) -{ - const auto default_flags = std::cout.flags(); - const auto default_fill = std::cout.fill(); - - std::vector<std::array<signed int, LINE_SIZE>> data = - c.view(0, L1_CACHE_LINES); - std::array<std::array<int, 2>, L1_CACHE_LINES> meta = c.get_meta(); - - os << " " << std::setfill(' ') << std::setw(L1_CACHE_LINE_SPEC + 2) - << "INDEX" - << " | " << std::setfill(' ') << std::setw((8 + 3) * 4 - 1) << "DATA" - << " | " << std::setfill(' ') - << std::setw(MEM_LINE_SPEC - L1_CACHE_LINE_SPEC + 2) << "TAG" - << " | D" << std::endl; - for (int i = 0; i < L1_CACHE_LINES; ++i) { - os << " 0b" << std::setw(L1_CACHE_LINE_SPEC) - << std::bitset<L1_CACHE_LINE_SPEC>(i) << " | "; - for (int j = 0; j < LINE_SIZE; ++j) { - os << "0x" << std::setfill('0') << std::setw(8) << std::hex - << data.at(i).at(j) << " "; - } - os << "| 0b" << std::setfill(' '); - - if (meta.at(i)[0] < 0) - os << std::setfill('?') - << std::setw(MEM_LINE_SPEC - L1_CACHE_LINE_SPEC) << ""; - else - os << std::bitset<MEM_LINE_SPEC - L1_CACHE_LINE_SPEC>( - meta.at(i)[0]); - - os << " | " << (int)(meta.at(i)[0] >= 0) << std::endl; - } - - std::cout.flags(default_flags); - std::cout.fill(default_fill); - return os; -} diff --git a/src/storage/dram.cc b/src/storage/dram.cc deleted file mode 100644 index f90f8db..0000000 --- a/src/storage/dram.cc +++ /dev/null @@ -1,130 +0,0 @@ -#include "dram.h" -#include "definitions.h" -#include "response.h" -#include <algorithm> -#include <bits/stdc++.h> -#include <bitset> -#include <iostream> -#include <iterator> -#include <utils.h> - -Dram::Dram(int delay) -{ - this->data = new std::vector<std::array<signed int, LINE_SIZE>>; - this->data->resize(MEM_LINES); - this->delay = delay; - this->is_waiting = false; - this->lower = nullptr; - this->requester = IDLE; - this->wait_time = this->delay; -} - -Dram::~Dram() { delete this->data; } - -Response Dram::write_line( - Accessor accessor, std::array<signed int, LINE_SIZE> data_line, int address) -{ - return process(accessor, address, [&](int line, int word) { - (void)word; - this->data->at(line) = data_line; - }); -} - -Response Dram::write_word(Accessor accessor, signed int data, int address) -{ - return process(accessor, address, [&](int line, int word) { - this->data->at(line).at(word) = data; - }); -} - -// TODO requires testing -Response Dram::read_line( - Accessor accessor, - int address, - std::array<signed int, LINE_SIZE> &data_line) -{ - return process(accessor, address, [&](int line, int word) { - (void)word; - data_line = this->data->at(line); - }); -} - -Response Dram::read_word(Accessor accessor, int address, signed int &data) -{ - return process(accessor, address, [&](int line, int word) { - data = this->data->at(line).at(word); - }); -} - -// TODO load a file instead and test this method -void Dram::load(std::vector<signed int> program) { - unsigned long i; - for (i = 0; i < program.size(); ++i) { - int line, word; - get_memory_index(i, line, word); - this->data->at(line).at(word) = program[i]; - } -} - -Response Dram::process( - Accessor accessor, - int address, - std::function<void(int line, int word)> request_handler) -{ - Response r = this->is_access_cleared(accessor); - if (r == OK) { - int line, word; - get_memory_index(address, line, word); - request_handler(line, word); - } - return r; -} - -Response Dram::is_access_cleared(Accessor accessor) -{ - Response r; - r = WAIT; - /* Do this first--then process the first cycle immediately. */ - if (accessor == SIDE) - r = OK; - else { - if (this->requester == IDLE) - this->requester = accessor; - if (this->requester == accessor) { - if (this->wait_time == 0) { - this->requester = IDLE; - this->wait_time = delay; - r = OK; - } else { - --this->wait_time; - } - } - } - return r; -} - -std::ostream &operator<<(std::ostream &os, const Dram &d) -{ - const auto default_flags = std::cout.flags(); - const auto default_fill = std::cout.fill(); - - std::vector<std::array<signed int, LINE_SIZE>> data = d.view(0, MEM_LINES); - - os << " " << std::setfill(' ') << std::setw(MEM_LINE_SPEC + 2 + LINE_SPEC) - << "ADDRESS" - << " | " << std::setfill(' ') << std::setw((8 + 3) * 4 - 1) << "DATA" - << std::endl; - for (int i = 0; i < MEM_LINES; ++i) { - os << " 0b" << std::setw(MEM_LINE_SPEC + LINE_SPEC) << left - << std::bitset<MEM_LINE_SPEC>(i) << " | "; - for (int j = 0; j < LINE_SIZE; ++j) { - os << "0x" << std::setfill('0') << std::setw(8) << std::hex - << data.at(i).at(j) << ' '; - } - os << std::endl; - } - - std::cout.flags(default_flags); - std::cout.fill(default_fill); - return os; -} diff --git a/src/storage/storage.cc b/src/storage/storage.cc deleted file mode 100644 index fed607b..0000000 --- a/src/storage/storage.cc +++ /dev/null @@ -1,16 +0,0 @@ -#include "storage.h" -#include "definitions.h" -#include <algorithm> - -std::vector<std::array<signed int, LINE_SIZE>> -Storage::view(int base, int lines) const -{ - base = (base / LINE_SIZE) * LINE_SIZE; - std::vector<std::array<signed int, LINE_SIZE>> ret(lines + 1); - std::copy( - this->data->begin() + base, this->data->begin() + base + lines, - ret.begin()); - return ret; -} - -Storage *Storage::get_lower() { return this->lower; } diff --git a/src/utils/utils.cc b/src/utils/utils.cc deleted file mode 100644 index e12a0e0..0000000 --- a/src/utils/utils.cc +++ /dev/null @@ -1,42 +0,0 @@ -#include "utils.h" -#include "definitions.h" -#include <cstdarg> -#include <string> -#include <vector> - -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); - *index = GET_MID_BITS(address, LINE_SPEC, L1_CACHE_LINE_SPEC + LINE_SPEC); - *offset = GET_LS_BITS(address, LINE_SPEC); -} - -const std::string string_format(const char *const zcFormat, ...) -{ - va_list vaArgs; - va_start(vaArgs, zcFormat); - - va_list vaArgsCopy; - va_copy(vaArgsCopy, vaArgs); - const int iLen = std::vsnprintf(NULL, 0, zcFormat, vaArgsCopy); - va_end(vaArgsCopy); - - std::vector<char> zc(iLen + 1); - std::vsnprintf(zc.data(), zc.size(), zcFormat, vaArgs); - va_end(vaArgs); - return std::string(zc.data(), iLen); -} - -int wrap_address(int address) -{ - if (address < 0) { - return ((address % MEM_WORDS) + MEM_WORDS) % MEM_WORDS; - } - return address % MEM_WORDS; -} - -void get_memory_index(int address, int &line, int &word) -{ - line = wrap_address(address) / LINE_SIZE; - word = address % LINE_SIZE; -} |