diff options
| -rw-r--r-- | inc/cache.h | 56 | ||||
| -rw-r--r-- | inc/definitions.h | 31 | ||||
| -rw-r--r-- | inc/dram.h | 9 | ||||
| -rw-r--r-- | src/cache.cc | 24 | ||||
| -rw-r--r-- | src/dram.cc | 1 | ||||
| -rw-r--r-- | tests/c11.h | 11 | ||||
| -rw-r--r-- | tests/cache_2_1.cc | 21 | 
7 files changed, 79 insertions, 74 deletions
| diff --git a/inc/cache.h b/inc/cache.h index 0f15536..325d46f 100644 --- a/inc/cache.h +++ b/inc/cache.h @@ -3,40 +3,45 @@  #include "definitions.h"  #include "storage.h"  #include <array> +#include <cmath>  #include <functional>  #include <ostream> +/** + * Parse an address into a tag, index into the cache table, and a line + * offset. + * @param the address to be parsed + * @param the resulting tag + * @param the resulting index + * @param the resulting offset + */ +// clang-format off +#define GET_FIELDS(a, t, i, o) \ +    *(t) = GET_MID_BITS(a, this->size + LINE_SPEC, MEM_WORD_SPEC); \ +    *(i) = GET_MID_BITS(a, LINE_SPEC, this->size + LINE_SPEC); \ +    *(o) = GET_LS_BITS(a, LINE_SPEC) +// clang-format on +  class Cache : public Storage  {    public:  	/** -	 * Constructor. +nn	 * Constructor.  	 * @param The number of `lines` contained in memory. The total number of  	 * words is this number multiplied by LINE_SIZE.  	 * @param The next lowest level in storage. Methods from this object are  	 * called in case of a cache miss. +	 * @param The number of bits required to specify a line in this level of cache.  	 * @param The number of clock cycles each access takes.  	 * @return A new cache object.  	 */ -	Cache(Storage *lower, int delay); +	Cache(Storage *lower, unsigned int size, int delay);  	~Cache(); -	int -	write_word(void *, signed int, int) override; -	int -	write_line(void *, std::array<signed int, LINE_SIZE>, int) override; -	int -	read_line(void *, int, std::array<signed int, LINE_SIZE> &) override; -	int -	read_word(void *, int, signed int &) override; - -	/** -	 * Getter for the meta attribute. -	 * TODO this doesn't seem like good object-oriented practice. -	 * @return this->meta -	 */ -	std::array<std::array<int, 2>, L1_CACHE_LINES> -	get_meta() const; +	int write_word(void *, signed int, int) override; +	int write_line(void *, std::array<signed int, LINE_SIZE>, int) override; +	int read_line(void *, int, std::array<signed int, LINE_SIZE> &) override; +	int read_word(void *, int, signed int &) override;    private:  	/** @@ -47,8 +52,7 @@ class Cache : public Storage  	 * @param the address to write to  	 * @param the function to call when an access should be completed  	 */ -	int -	process(void *id, int address, std::function<void(int index, int offset)> request_handler); +	int process(void *id, int address, std::function<void(int index, int offset)> request_handler);  	/**  	 * Returns OK if `id` is allowed to complete its request this cycle.  	 * Handles cache misses, wait times, and setting the current id this @@ -56,8 +60,7 @@ class Cache : public Storage  	 * @param the id asking for a resource  	 * @return 1 if the access can be carried out this function call, 0 otherwise.  	 */ -	int -	is_access_cleared(void *id, int address); +	int is_access_cleared(void *id, int address);  	/**  	 * Helper for is_access_cleared.  	 * Fetches `address` from a lower level of storage if it is not already @@ -65,15 +68,18 @@ class Cache : public Storage  	 * @param the address that must be present in cache.  	 * @param 0 if the address is currently in cache, 1 if it is being fetched.  	 */ -	int -	is_address_missing(int address); +	int is_address_missing(int address); +	/** +	 * The number of bits required to specify a line in this level of cache. +	 */ +	unsigned int size;  	/**  	 * An array of metadata about elements in `data`.  	 * If the first value of an element is negative, the corresponding  	 * element in `data` is invalid. If the most second value of an element  	 * is nonzero, the corresponding element in `data` is dirty.  	 */ -	std::array<std::array<int, 2>, L1_CACHE_LINES> meta; +	std::vector<std::array<signed int, 2>> meta;  };  #endif /* CACHE_H_INCLUDED */ diff --git a/inc/definitions.h b/inc/definitions.h index 113c6e4..db43426 100644 --- a/inc/definitions.h +++ b/inc/definitions.h @@ -26,15 +26,6 @@  #define MEM_LINES static_cast<int>(pow(2, MEM_LINE_SPEC))  /** - * The number of bits to specify a l1 cache word - * The number of bits to specify a l1 cache line - * The total number of lines in l1 cache - */ -#define L1_CACHE_WORD_SPEC 7 -#define L1_CACHE_LINE_SPEC static_cast<unsigned int>(L1_CACHE_WORD_SPEC - LINE_SPEC) -#define L1_CACHE_LINES static_cast<int>(pow(2, L1_CACHE_LINE_SPEC)) - -/**   * The total number of cycles a memory access takes   */  #define MEM_DELAY 3 @@ -61,26 +52,4 @@   */  #define GET_MID_BITS(k, m, n) GET_LS_BITS((k) >> (m), ((n) - (m))) -/** - * Parse an address into a tag, index into the cache table, and a line - * offset. - * @param the address to be parsed - * @param the resulting tag - * @param the resulting index - * @param the resulting offset - */ -// clang-format off -#define GET_FIELDS(a, t, i, o) \ -    *(t) = GET_MID_BITS(a, L1_CACHE_LINE_SPEC + LINE_SPEC, MEM_WORD_SPEC); \ -    *(i) = GET_MID_BITS(a, LINE_SPEC, L1_CACHE_LINE_SPEC + LINE_SPEC); \ -    *(o) = GET_LS_BITS(a, LINE_SPEC) - -/** - * Ensures address is within the current memory size using a clean wrap. - * @param an address - */ -#define WRAP_ADDRESS(a) \ -  ((a < 0) ? ((a % MEM_WORDS) + MEM_WORDS) % MEM_WORDS : a % MEM_WORDS) -// clang-format on -  #endif /* DEFINITIONS_H_INCLUDED */ @@ -5,6 +5,15 @@  #include <functional>  #include <ostream> +// clang-format off +/** + * Ensures address is within the current memory size using a clean wrap. + * @param an address + */ +#define WRAP_ADDRESS(a) \ +  ((a < 0) ? ((a % MEM_WORDS) + MEM_WORDS) % MEM_WORDS : a % MEM_WORDS) +// clang-format on +  class Dram : public Storage  {    public: diff --git a/src/cache.cc b/src/cache.cc index acbabcf..307d6d0 100644 --- a/src/cache.cc +++ b/src/cache.cc @@ -1,13 +1,17 @@  #include "cache.h"  #include "definitions.h" -#include <bits/stdc++.h> +#include <iostream>  #include <iterator> -Cache::Cache(Storage *lower, int delay) : Storage(delay) +Cache::Cache(Storage *lower, unsigned int size, 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, 2>>(true_size, {-1, -1}); +	this->size = size;  	this->lower = lower; -	this->meta.fill({-1, -1});  }  Cache::~Cache() @@ -35,7 +39,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)  { @@ -103,8 +106,7 @@ Cache::is_address_missing(int expected)  		r = 1;  		if (meta->at(1) >= 0) {  			q = this->lower->write_line( -				this, *actual, -				((index << LINE_SPEC) + (meta->at(0) << (L1_CACHE_LINE_SPEC + LINE_SPEC)))); +				this, *actual, ((index << LINE_SPEC) + (meta->at(0) << (this->size + LINE_SPEC))));  			if (q) {  				meta->at(1) = -1;  			} @@ -118,11 +120,3 @@ Cache::is_address_missing(int expected)  	return r;  } - -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; -} diff --git a/src/dram.cc b/src/dram.cc index 2fd8a91..18c1a3e 100644 --- a/src/dram.cc +++ b/src/dram.cc @@ -24,7 +24,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)  { diff --git a/tests/c11.h b/tests/c11.h index eb59cc0..6d63c77 100644 --- a/tests/c11.h +++ b/tests/c11.h @@ -6,12 +6,19 @@  #include <catch2/catch_test_macros.hpp>  #include <functional> +/** + * one way associative, single level + */  class C11  {    public: -	C11() : m_delay(4), c_delay(2), mem(new int), fetch(new int) +	C11()  	{ -		this->c = new Cache(new Dram(this->m_delay), this->c_delay); +		this->m_delay = 4; +		this->c_delay = 2; +		this->mem = new int(); +		this->fetch = new int(); +		this->c = new Cache(new Dram(this->m_delay), 5, this->c_delay);  		this->expected = {0, 0, 0, 0};  		this->actual = this->c->view(0, 1)[0];  	} diff --git a/tests/cache_2_1.cc b/tests/cache_2_1.cc new file mode 100644 index 0000000..101c6c3 --- /dev/null +++ b/tests/cache_2_1.cc @@ -0,0 +1,21 @@ +#include "c11.h" +#include "cache.h" +#include "dram.h" +#include "storage.h" +#include <catch2/catch_test_macros.hpp> + +/** + * one way associative, two level + */ +class C21 : public C11 +{ +  public: +	C21() : C11() +	{ +		Storage *s; + +		s = new Dram(this->m_delay); +		s = new Cache(s, 5, this->c_delay); +		this->c = new Cache(s, 7, this->c_delay); +	} +}; | 
