diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/cache.cc | 138 | ||||
| -rw-r--r-- | src/dram.cc | 55 | ||||
| -rw-r--r-- | src/storage.cc | 50 | ||||
| -rw-r--r-- | src/utils.cc | 42 | 
4 files changed, 157 insertions, 128 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));  } diff --git a/src/dram.cc b/src/dram.cc index d81e2d2..9d94280 100644 --- a/src/dram.cc +++ b/src/dram.cc @@ -1,10 +1,26 @@ +// 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 "dram.h"  #include "definitions.h"  #include <algorithm>  #include <bits/stdc++.h>  #include <bitset>  #include <iterator> -#include <utils.h>  Dram::Dram(int delay) : Storage(delay) { this->data->resize(MEM_LINES); } @@ -25,7 +41,6 @@ Dram::write_word(void *id, signed int data, int address)  	return process(id, address, [&](int line, int word) { this->data->at(line).at(word) = data; });  } -// TODO requires testing  int  Dram::read_line(void *id, int address, std::array<signed int, LINE_SIZE> &data_line)  { @@ -56,32 +71,18 @@ Dram::load(std::vector<signed int> program)  int  Dram::process(void *id, int address, std::function<void(int line, int word)> request_handler)  { -	int r; -	r = this->is_access_cleared(id); -	if (r) { -		int line, word; -		get_memory_index(address, line, word); -		request_handler(line, word); -	} -	return r; +	if (!preprocess(id) || !this->is_data_ready()) +		return 0; + +	int line, word; +	get_memory_index(address, line, word); +	request_handler(line, word); +	return 1;  } -int -Dram::is_access_cleared(void *id) +void +Dram::get_memory_index(int address, int &line, int &word)  { -	/* 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 (this->wait_time == 0) { -			this->current_request = nullptr; -			this->wait_time = delay; -			return 1; -		} else { -			--this->wait_time; -		} -	} -	return 0; +	line = WRAP_ADDRESS(address) / LINE_SIZE; +	word = address % LINE_SIZE;  } diff --git a/src/storage.cc b/src/storage.cc index 4ad916b..c13b9db 100644 --- a/src/storage.cc +++ b/src/storage.cc @@ -1,8 +1,27 @@ +// 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 "storage.h"  #include "definitions.h"  #include <algorithm> +#include <stdexcept> -Storage::Storage(int delay) { +Storage::Storage(int delay) +{  	this->data = new std::vector<std::array<signed int, LINE_SIZE>>;  	this->delay = delay;  	this->lower = nullptr; @@ -18,3 +37,32 @@ Storage::view(int base, int lines) const  	std::copy(this->data->begin() + base, this->data->begin() + base + lines, ret.begin());  	return ret;  } + +int +Storage::preprocess(void *id) +{ +	if (id == nullptr) +		throw std::invalid_argument("Accessor cannot be nullptr."); + +	if (this->current_request == nullptr) +		this->current_request = id; + +	return this->current_request == id; +} + +int +Storage::is_data_ready() +{ +	int r; + +	r = 0; +	if (this->wait_time == 0) { +		this->current_request = nullptr; +		this->wait_time = delay; +		r = 1; +	} else { +		--this->wait_time; +	} + +	return r; +} diff --git a/src/utils.cc b/src/utils.cc deleted file mode 100644 index e12a0e0..0000000 --- a/src/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; -} | 
