diff options
Diffstat (limited to 'src/cache.cc')
-rw-r--r-- | src/cache.cc | 138 |
1 files changed, 80 insertions, 58 deletions
diff --git a/src/cache.cc b/src/cache.cc index bbb90b4..90bffd6 100644 --- a/src/cache.cc +++ b/src/cache.cc @@ -1,14 +1,38 @@ +// Memory subsystem for the RISC-V[ECTOR] mini-ISA +// Copyright (C) 2025 Siddarth Suresh +// Copyright (C) 2025 bdunahu + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <https://www.gnu.org/licenses/>. + #include "cache.h" #include "definitions.h" -#include "utils.h" -#include <bits/stdc++.h> +#include <cstdlib> +#include <iostream> #include <iterator> -Cache::Cache(Storage *lower, int delay) : Storage(delay) +Cache::Cache(Storage *lower, unsigned int size, unsigned int ways, int delay) : Storage(delay) { - this->data->resize(L1_CACHE_LINES); + int true_size; + + true_size = 1 << size; + this->data->resize(true_size); + this->meta = std::vector<std::array<signed int, 3>>(true_size, {-1, -1, -1}); this->lower = lower; - this->meta.fill({-1, -1}); + + this->size = size; + // store the number of bits which are moved into the tag field + this->ways = ways; } Cache::~Cache() @@ -36,7 +60,6 @@ Cache::write_line(void *id, std::array<signed int, LINE_SIZE> data_line, int add }); } -// TODO: tests for multi level cache int Cache::read_line(void *id, int address, std::array<signed int, LINE_SIZE> &data_line) { @@ -56,74 +79,73 @@ Cache::read_word(void *id, int address, signed int &data) int Cache::process(void *id, int address, std::function<void(int index, int offset)> request_handler) { - int r; - r = this->is_access_cleared(id, address); - if (r) { - int tag, index, offset; - get_cache_fields(address, &tag, &index, &offset); - request_handler(index, offset); - } - return r; -} + address = WRAP_ADDRESS(address); + if (!preprocess(id) || priming_address(address) || !this->is_data_ready()) + return 0; -int -Cache::is_access_cleared(void *id, int address) -{ - /* Do this first--then process the first cycle immediately. */ - if (id == nullptr) - throw std::invalid_argument("Accessor cannot be nullptr."); - if (this->current_request == nullptr) - this->current_request = id; - if (this->current_request == id) { - if (is_address_missing(address)) - return 0; - else if (this->wait_time == 0) { - this->current_request = nullptr; - this->wait_time = delay; - return 1; - } else { - --this->wait_time; - } - } - return 0; + int tag, index, offset; + GET_FIELDS(address, &tag, &index, &offset); + index = this->get_true_index(index); + request_handler(index, offset); + + return 1; } int -Cache::is_address_missing(int expected) +Cache::priming_address(int address) { - int r, q, tag, index, offset; - std::array<signed int, LINE_SIZE> *actual; - std::array<int, 2> *meta; + int tag, index, offset; + int r1, r2; + std::array<signed int, LINE_SIZE> *evict; + std::array<int, 3> *meta; - get_cache_fields(expected, &tag, &index, &offset); - r = 0; - meta = &this->meta.at(index); - actual = &this->data->at(index); + r1 = 0; + GET_FIELDS(address, &tag, &index, &offset); + index = this->get_true_index(index); - if (meta->at(0) != tag) { - r = 1; + if (this->is_address_missing(index, tag)) { + r1 = 1; + + index = this->get_replacement_index(index); + meta = &this->meta.at(index); + evict = &this->data->at(index); + + // handle eviction of dirty cache lines if (meta->at(1) >= 0) { - q = this->lower->write_line( - this, *actual, - ((index << LINE_SPEC) + (meta->at(0) << (L1_CACHE_LINE_SPEC + LINE_SPEC)))); - if (q) { + r2 = this->lower->write_line( + this, *evict, ((index << LINE_SPEC) + (meta->at(0) << (this->size + LINE_SPEC)))); + if (r2) meta->at(1) = -1; - } } else { - q = this->lower->read_line(this, expected, *actual); - if (q) { + r2 = this->lower->read_line(this, address, *evict); + if (r2) { meta->at(0) = tag; } } } - return r; + return r1; } -std::array<std::array<int, 2>, L1_CACHE_LINES> -Cache::get_meta() const +int +Cache::is_address_missing(int index, int tag) +{ + int i; + + for (i = 0; i < (1 << this->ways); ++i) + if (this->meta.at(index + i).at(0) == tag) + return i; + return -1; +} + +int +Cache::get_true_index(int index) +{ + return index * (1 << this->ways); +} + +int +Cache::get_replacement_index(int index) { - 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; + return index + (rand() % (1 << this->ways)); } |