From cdcaec3c1e62b47fcd270df651cd0e343e46f0e7 Mon Sep 17 00:00:00 2001 From: bd Date: Mon, 10 Mar 2025 14:53:59 -0400 Subject: Update cli method signatures, add some getters to cache and storage --- src/storage/storage.cc | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/storage/storage.cc') diff --git a/src/storage/storage.cc b/src/storage/storage.cc index 61531d1..16ad63f 100644 --- a/src/storage/storage.cc +++ b/src/storage/storage.cc @@ -13,6 +13,8 @@ Storage::view(int base, int lines) return ret; } +Storage *Storage::get_lower() { return this->lower; } + void Storage::resolve() { if (this->wait_time == 0) { -- cgit v1.2.3 From 9009d358f7959b1dd60b77fea181be04ae190ef3 Mon Sep 17 00:00:00 2001 From: bd Date: Mon, 10 Mar 2025 16:44:39 -0400 Subject: Add starter overloaded << operator for cache --- inc/cache.h | 5 ++++- inc/storage.h | 2 +- src/cli/cli.cc | 8 +++----- src/storage/cache.cc | 42 ++++++++++++++++++++++++++++++++++++++++-- src/storage/storage.cc | 2 +- 5 files changed, 49 insertions(+), 10 deletions(-) (limited to 'src/storage/storage.cc') diff --git a/inc/cache.h b/inc/cache.h index b7b72cf..0c9b3d7 100644 --- a/inc/cache.h +++ b/inc/cache.h @@ -3,6 +3,7 @@ #include "definitions.h" #include "storage.h" #include +#include class Cache : public Storage { @@ -30,7 +31,7 @@ class Cache : public Storage * TODO this doesn't seem like good object-oriented practice. * @return this->meta */ - std::array, L1_CACHE_SIZE> *get_meta(); + std::array, L1_CACHE_SIZE> get_meta() const; private: /** @@ -49,4 +50,6 @@ class Cache : public Storage std::array, L1_CACHE_SIZE> meta; }; +std::ostream &operator<<(std::ostream &os, const Cache &a); + #endif /* CACHE_H_INCLUDED */ diff --git a/inc/storage.h b/inc/storage.h index 0ab16e4..3f113d3 100644 --- a/inc/storage.h +++ b/inc/storage.h @@ -45,7 +45,7 @@ class Storage * @return A matrix of data values, where each row is a line and each column * is a word. */ - std::vector> view(int base, int lines); + std::vector> view(int base, int lines) const; /** * Advances to the next job if the current job is completed. */ diff --git a/src/cli/cli.cc b/src/cli/cli.cc index fea44d7..d1631b4 100644 --- a/src/cli/cli.cc +++ b/src/cli/cli.cc @@ -120,11 +120,9 @@ void Cli::view(int level, int base, int lines) curr = curr->get_lower(); } - std::vector> data = - curr->view(base, lines); - - if (dynamic_cast(curr)) { - + Cache *c = dynamic_cast(curr); + if (c) { + std::cout << *c; } else { std::cout << "dram"; } diff --git a/src/storage/cache.cc b/src/storage/cache.cc index 55c8cfa..45ef0ab 100644 --- a/src/storage/cache.cc +++ b/src/storage/cache.cc @@ -3,6 +3,9 @@ #include "response.h" #include "utils.h" #include +#include +#include +#include Cache::Cache(Storage *lower, int delay) { @@ -81,7 +84,42 @@ void Cache::fetch_resource(int expected) this->is_waiting = (r == OK) ? false : true; } -std::array, L1_CACHE_SIZE> *Cache::get_meta() +std::array, L1_CACHE_SIZE> Cache::get_meta() const { - return &(this->meta); + std::array, L1_CACHE_SIZE> 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> data = + c.view(0, L1_CACHE_SIZE); + std::array, L1_CACHE_SIZE> meta = c.get_meta(); + + os << std::setfill(' ') << std::setw(L1_CACHE_SPEC + 1) << " ADDRESS |" + << std::setfill(' ') << std::setw(11) << "0" << std::setfill(' ') + << std::setw(11) << "1" << std::setfill(' ') << std::setw(11) << "2" + << std::setfill(' ') << std::setw(11) << "3" + << " |" << std::setfill(' ') + << std::setw(MEM_SPEC - LINE_SPEC - L1_CACHE_SPEC + 4) << "TAG " + << "| D \n"; + for (int i = 0; i < L1_CACHE_SIZE; ++i) { + os << " 0b" << std::setw(L1_CACHE_SPEC) << std::bitset(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 << "| 0x" << std::setfill(' ') + << std::bitset(meta.at(i)[0]) + << " | " << (int)(meta.at(i)[0] < 0) << '\n'; + } + + std::cout.flags(default_flags); + std::cout.fill(default_fill); + return os; } diff --git a/src/storage/storage.cc b/src/storage/storage.cc index 16ad63f..62f3699 100644 --- a/src/storage/storage.cc +++ b/src/storage/storage.cc @@ -3,7 +3,7 @@ #include std::vector> -Storage::view(int base, int lines) +Storage::view(int base, int lines) const { base = (base / LINE_SIZE) * LINE_SIZE; std::vector> ret(lines + 1); -- cgit v1.2.3 From 4dbe50416eea0fecc2aa6f5ce3dc7032c95234c5 Mon Sep 17 00:00:00 2001 From: bd Date: Mon, 10 Mar 2025 19:42:01 -0400 Subject: CLI view, clock, store, program banner --- inc/accessor.h | 15 ++++++++++++ inc/cli.h | 9 ++++--- inc/response.h | 3 +++ inc/risc_vector.h | 12 ++++++++++ inc/storage.h | 15 ++++-------- src/cli/cli.cc | 65 ++++++++++++++++++++++++++++++-------------------- src/main.cc | 34 ++++++++++++++++++++++---- src/storage/cache.cc | 14 +++++------ src/storage/storage.cc | 2 ++ src/utils/accessor.cc | 8 +++++++ src/utils/response.cc | 8 +++++++ tests/cache.cc | 15 ------------ 12 files changed, 132 insertions(+), 68 deletions(-) create mode 100644 inc/accessor.h create mode 100644 inc/risc_vector.h create mode 100644 src/utils/accessor.cc create mode 100644 src/utils/response.cc (limited to 'src/storage/storage.cc') diff --git a/inc/accessor.h b/inc/accessor.h new file mode 100644 index 0000000..fb4999d --- /dev/null +++ b/inc/accessor.h @@ -0,0 +1,15 @@ +#ifndef ACCESSOR_H +#define ACCESSOR_H +#include + +enum Accessor { + IDLE, + MEM, + FETCH, + L1CACHE, + SIDE, +}; + +std::ostream &operator<<(std::ostream &os, Accessor a); + +#endif /* ACCESSOR_H_INCLUDED */ diff --git a/inc/cli.h b/inc/cli.h index 4a5726c..2194228 100644 --- a/inc/cli.h +++ b/inc/cli.h @@ -29,10 +29,11 @@ class Cli /** * Stores data into memory at the specified address. - * @param memory_address address of the memory where data needs to be stored + * @param accessor the pipline stage that is making this request * @param data data value to be written to the memory + * @param address address of the memory where data needs to be stored */ - void store(int memory_address, int data); + void store(Accessor accessor, int data, int address); /** * Resets the memory configuration and cycles to their initial state. @@ -64,10 +65,8 @@ class Cli * @param level the level specifying the storage device. The first level * one cache is level zero, with descending levels incrementing by a factor * of one. - * @param base the first index to be printed - * @param the number of lines to be printed */ - void view(int level, int base, int lines); + void peek(int level); /** * Runs the command line interface diff --git a/inc/response.h b/inc/response.h index d945e0f..6cd6678 100644 --- a/inc/response.h +++ b/inc/response.h @@ -1,5 +1,6 @@ #ifndef RESPONSE_H #define RESPONSE_H +#include enum Response { OK, @@ -7,4 +8,6 @@ enum Response { BLOCKED, }; +std::ostream &operator<<(std::ostream &os, Response r); + #endif /* RESPONSE_H_INCLUDED */ diff --git a/inc/risc_vector.h b/inc/risc_vector.h new file mode 100644 index 0000000..244adb6 --- /dev/null +++ b/inc/risc_vector.h @@ -0,0 +1,12 @@ +#ifndef RISC_VECTOR_H +#define RISC_VECTOR_H +#include + + + +/** + * Outputs the program version and banner. + */ +void print_version_number(); + +#endif /* RISC_VECTOR_H_INCLUDED */ diff --git a/inc/storage.h b/inc/storage.h index 3f113d3..a30e74d 100644 --- a/inc/storage.h +++ b/inc/storage.h @@ -1,19 +1,13 @@ #ifndef STORAGE_H #define STORAGE_H +#include "accessor.h" #include "definitions.h" #include "response.h" #include #include +#include #include -enum Accessor { - IDLE, - MEM, - FETCH, - L1CACHE, - SIDE, -}; - class Storage { public: @@ -45,9 +39,10 @@ class Storage * @return A matrix of data values, where each row is a line and each column * is a word. */ - std::vector> view(int base, int lines) const; + std::vector> + view(int base, int lines) const; /** - * Advances to the next job if the current job is completed. + * Refreshes the state of this storage device and lower. */ void resolve(); diff --git a/src/cli/cli.cc b/src/cli/cli.cc index d1631b4..a5706fb 100644 --- a/src/cli/cli.cc +++ b/src/cli/cli.cc @@ -2,20 +2,20 @@ #include "cache.h" #include "definitions.h" #include "dram.h" +#include "response.h" #include #include #include Cli::Cli() { - Dram *d = new Dram(MEM_SIZE, MEM_DELAY); - this->cache = new Cache(d, L1_CACHE_DELAY); + this->initialize(); commands["l"] = [this](std::vector args) { if (args.size() >= 1) { try { load(std::stoi(args[0])); - } catch (const std::exception &e) { + } catch (const std::invalid_argument &e) { std::cerr << "Invalid input: " << e.what() << std::endl; } } else { @@ -25,10 +25,17 @@ Cli::Cli() }; commands["s"] = [this](std::vector args) { - if (args.size() >= 2) { + Accessor a; + if (args.size() >= 3) { try { - store(std::stoi(args[0]), std::stoi(args[1])); - } catch (const std::exception &e) { + if (tolower(args[0][0]) == 'f') + a = FETCH; + else if (tolower(args[0][0]) == 'm') + a = MEM; + else + throw std::invalid_argument(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 { @@ -42,12 +49,11 @@ Cli::Cli() return; }; - commands["v"] = [this](std::vector args) { - if (args.size() >= 3) { + commands["p"] = [this](std::vector args) { + if (args.size() >= 1) { try { - view( - std::stoi(args[0]), std::stoi(args[1]), std::stoi(args[2])); - } catch (const std::exception &e) { + peek(std::stoi(args[0])); + } catch (const std::invalid_argument &e) { std::cerr << "Invalid input: " << e.what() << std::endl; } } else { @@ -56,6 +62,11 @@ Cli::Cli() return; }; + commands["c"] = [this](std::vector args) { + clock(); + return; + }; + commands["h"] = [this](std::vector args) { help(); return; @@ -68,16 +79,17 @@ void Cli::help() { std::cout << "Available commands:\n" - << " l - Load data from memory at the specified " + << " l
- Load data from memory at the specified " "address\n" - << " s - Stores data into " - "memory at specified address\n" + << " s
- Stores data into memory at " + "specified address. Accessor must be one of: \"MEM\", \"FETCH\", " + "\"L1CACHE\".\n" << " c - manually advances the clock\n" << " r - side door function that resets the memory configuration and " "cycles\n" - << " u - side door function that updates " + << " u
- side door function that updates " "the memory at the specified address with data provided\n" - << " v - side door function that views " + << " p - side door function that peeks " "the current status of the entire memory subsystem\n" << " h - Prints this help text\n" << " q - Quits the program\n"; @@ -88,10 +100,10 @@ void Cli::load(int memory_address) std::cout << "Loading data from memory address " << memory_address; } -void Cli::store(int memory_address, int data) +void Cli::store(Accessor accessor, int data, int address) { - std::cout << "Storing " << data << " into memory address " - << memory_address; + Response r = this->cache->write(accessor, data, address); + std::cout << r << " to " << accessor << " storing " << data << '\n'; } void Cli::update(int memory_address, int data) @@ -99,17 +111,15 @@ void Cli::update(int memory_address, int data) std::cout << "Resetting memory configuration and cycles.\n"; }; -void Cli::clock() -{ - std::cout << "Resetting memory configuration and cycles.\n"; -} +void Cli::clock() { this->cache->resolve(); } void Cli::reset() { - std::cout << "Resetting memory configuration and cycles.\n"; + this->initialize(); + std::cout << "Done.\n"; } -void Cli::view(int level, int base, int lines) +void Cli::peek(int level) { Storage *curr = this->cache; for (int i = 0; i < level; ++i) { @@ -166,6 +176,9 @@ void Cli::run() void Cli::initialize() { - if (this->cache) + std::cout << "Resetting memory configuration.\n"; + if (this->cache == nullptr) delete this->cache; + Dram *d = new Dram(MEM_SIZE, MEM_DELAY); + this->cache = new Cache(d, L1_CACHE_DELAY); } diff --git a/src/main.cc b/src/main.cc index 08cb89f..cc5fbb3 100644 --- a/src/main.cc +++ b/src/main.cc @@ -3,25 +3,47 @@ #include #include -void err() +static std::string version_number = "v0.1"; + +static std::string banner = + " _/_/_/ _/_/_/ _/_/_/ _/_/_/ \n" + " _/ _/ _/ _/ _/ \n" + " _/_/_/ _/ _/_/ _/ \n" + " _/ _/ _/ _/ _/ \n" + "_/ _/ _/_/_/ _/_/_/ _/_/_/ \n" + " \n" + " \n" + " _/_/ _/_/ \n" + " _/ _/ _/ _/_/_/_/ _/_/_/ _/_/_/_/_/ _/_/ _/_/_/ _/ \n" + " _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ \n" + "_/ _/ _/ _/_/_/ _/ _/ _/ _/ _/_/_/ _/ \n" + " _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ \n" + " _/ _/ _/_/_/_/ _/_/_/ _/ _/_/ _/ _/ _/ \n" + " _/_/ _/_/ \n"; + +static void print_version_number() { std::cout << banner << version_number << '\n'; } + +static void err() { std::cerr << "Usage:\n\trisc_vector [OPTIONS]\nOptions:\n\t--debug,\t-d: " - "turn on verbose output\n\t--no-python,\t-p: run without GUI\n" + "turn on verbose output\n\t--no-python,\t-p: run without " + "GUI\n\t--version,\t-v: print the version information and exit\n" << std::endl; } -void parseArguments(int argc, char **argv, Logger &logger, bool &python) +static void parseArguments(int argc, char **argv, Logger &logger, bool &python) { struct option long_options[] = { {"debug", no_argument, 0, 'd'}, {"no-python", no_argument, 0, 'p'}, + {"version", no_argument, 0, 'v'}, {0, 0, 0, 0}}; python = true; int opt; - while ((opt = getopt_long(argc, argv, "d:p", long_options, NULL)) != -1) { + while ((opt = getopt_long(argc, argv, "d:p:v", long_options, NULL)) != -1) { switch (opt) { case 'd': logger.setLevel(DEBUG); @@ -31,6 +53,9 @@ void parseArguments(int argc, char **argv, Logger &logger, bool &python) logger.log(INFO, "Python will NOT be started!"); python = false; break; + case 'v': + print_version_number(); + exit(EXIT_SUCCESS); default: err(); exit(EXIT_FAILURE); @@ -40,6 +65,7 @@ void parseArguments(int argc, char **argv, Logger &logger, bool &python) int main(int argc, char **argv) { + print_version_number(); Logger logger("vector.log"); Cli cli; logger.log(INFO, "Initializing..."); diff --git a/src/storage/cache.cc b/src/storage/cache.cc index 45ef0ab..d382c3d 100644 --- a/src/storage/cache.cc +++ b/src/storage/cache.cc @@ -100,13 +100,11 @@ std::ostream &operator<<(std::ostream &os, const Cache &c) c.view(0, L1_CACHE_SIZE); std::array, L1_CACHE_SIZE> meta = c.get_meta(); - os << std::setfill(' ') << std::setw(L1_CACHE_SPEC + 1) << " ADDRESS |" - << std::setfill(' ') << std::setw(11) << "0" << std::setfill(' ') - << std::setw(11) << "1" << std::setfill(' ') << std::setw(11) << "2" - << std::setfill(' ') << std::setw(11) << "3" - << " |" << std::setfill(' ') - << std::setw(MEM_SPEC - LINE_SPEC - L1_CACHE_SPEC + 4) << "TAG " - << "| D \n"; + os << " " << std::setfill(' ') << std::setw(L1_CACHE_SPEC + 2) << "INDEX" + << " | " << std::setfill(' ') << std::setw((8 + 3) * 4 - 1) << "DATA" + << " | " << std::setfill(' ') + << std::setw(MEM_SPEC - LINE_SPEC - L1_CACHE_SPEC + 2) << "TAG" + << " | D\n"; for (int i = 0; i < L1_CACHE_SIZE; ++i) { os << " 0b" << std::setw(L1_CACHE_SPEC) << std::bitset(i) << " | "; @@ -116,7 +114,7 @@ std::ostream &operator<<(std::ostream &os, const Cache &c) } os << "| 0x" << std::setfill(' ') << std::bitset(meta.at(i)[0]) - << " | " << (int)(meta.at(i)[0] < 0) << '\n'; + << " | " << (int)(meta.at(i)[0] >= 0) << '\n'; } std::cout.flags(default_flags); diff --git a/src/storage/storage.cc b/src/storage/storage.cc index 62f3699..8e2e461 100644 --- a/src/storage/storage.cc +++ b/src/storage/storage.cc @@ -17,6 +17,8 @@ Storage *Storage::get_lower() { return this->lower; } void Storage::resolve() { + if (this->lower) + this->lower->resolve(); if (this->wait_time == 0) { this->requester = IDLE; this->wait_time = delay; diff --git a/src/utils/accessor.cc b/src/utils/accessor.cc new file mode 100644 index 0000000..86484c5 --- /dev/null +++ b/src/utils/accessor.cc @@ -0,0 +1,8 @@ +#include "accessor.h" +#include + +std::ostream &operator<<(std::ostream &os, Accessor a) +{ + const std::string nameA[] = {"IDLE", "MEM", "FETCH", "L1CACHE", "SIDE"}; + return os << nameA[a]; +} diff --git a/src/utils/response.cc b/src/utils/response.cc new file mode 100644 index 0000000..def6578 --- /dev/null +++ b/src/utils/response.cc @@ -0,0 +1,8 @@ +#include "response.h" +#include + +std::ostream &operator<<(std::ostream &os, Response r) +{ + const std::string nameR[] = {"OK", "WAIT", "BLOCKED"}; + return os << nameR[r]; +} diff --git a/tests/cache.cc b/tests/cache.cc index fc467c7..e8a257f 100644 --- a/tests/cache.cc +++ b/tests/cache.cc @@ -27,7 +27,6 @@ TEST_CASE("no delay stores instantly", "[cache]") r = c->write(MEM, w, 0b0); CHECK(r == OK); - d->resolve(); c->resolve(); actual = d->view(0, 1)[0]; @@ -61,12 +60,10 @@ TEST_CASE("cache takes \"forever\"", "[cache]") actual = c->view(0, 1)[0]; REQUIRE(expected == actual); c->resolve(); - d->resolve(); } r = c->write(MEM, w, 0b0); CHECK(r == OK); - d->resolve(); actual = d->view(0, 1)[0]; // we do NOT write back now! @@ -99,12 +96,10 @@ TEST_CASE("dram takes \"forever\"", "[cache]") actual = c->view(0, 1)[0]; REQUIRE(expected == actual); c->resolve(); - d->resolve(); } r = c->write(MEM, w, 0b0); CHECK(r == OK); - d->resolve(); actual = d->view(0, 1)[0]; // we do NOT write back now! @@ -137,7 +132,6 @@ TEST_CASE("dram and cache take \"forever\"", "[cache]") actual = c->view(0, 1)[0]; REQUIRE(expected == actual); c->resolve(); - d->resolve(); } for (i = 0; i < delay; ++i) { @@ -147,13 +141,11 @@ TEST_CASE("dram and cache take \"forever\"", "[cache]") actual = c->view(0, 1)[0]; REQUIRE(expected == actual); c->resolve(); - d->resolve(); } r = c->write(MEM, w, 0b0); CHECK(r == OK); c->resolve(); - d->resolve(); actual = d->view(0, 1)[0]; // we do NOT write back now! @@ -190,7 +182,6 @@ TEST_CASE( actual = c->view(0, 1)[0]; REQUIRE(expected == actual); c->resolve(); - d->resolve(); } r = c->write(MEM, w, 0b0); @@ -199,7 +190,6 @@ TEST_CASE( CHECK(r == WAIT); c->resolve(); - d->resolve(); actual = d->view(0, 1)[0]; // we do NOT write back now! @@ -214,7 +204,6 @@ TEST_CASE( CHECK(r == OK); c->resolve(); - d->resolve(); expected.at(1) = w; actual = c->view(0, 1)[0]; @@ -248,7 +237,6 @@ TEST_CASE( actual = c->view(0, 1)[0]; REQUIRE(expected == actual); c->resolve(); - d->resolve(); } r = c->write(MEM, w, 0b0); @@ -257,7 +245,6 @@ TEST_CASE( CHECK(r == WAIT); c->resolve(); - d->resolve(); actual = d->view(0, 1)[0]; // we do NOT write back now! @@ -274,14 +261,12 @@ TEST_CASE( actual = c->view(0, 1)[0]; REQUIRE(expected == actual); c->resolve(); - d->resolve(); } r = c->write(FETCH, w, 0b1); CHECK(r == OK); c->resolve(); - d->resolve(); expected.at(1) = w; actual = c->view(0, 1)[0]; -- cgit v1.2.3