From 486d18df5ca93e043fdd14fac1d22b5fe40fb6f6 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 --- inc/cache.h | 7 +++ inc/cli.h | 171 +++++++++++++++++++++++++++--------------------------- inc/definitions.h | 10 ++++ inc/storage.h | 9 +++ 4 files changed, 112 insertions(+), 85 deletions(-) (limited to 'inc') diff --git a/inc/cache.h b/inc/cache.h index e8b7030..b7b72cf 100644 --- a/inc/cache.h +++ b/inc/cache.h @@ -25,6 +25,13 @@ class Cache : public Storage int address, std::array &data) override; + /** + * Getter for the meta attribute. + * TODO this doesn't seem like good object-oriented practice. + * @return this->meta + */ + std::array, L1_CACHE_SIZE> *get_meta(); + private: /** * Fetches `address` from a lower level of storage if it is not already diff --git a/inc/cli.h b/inc/cli.h index 69bd3a9..4a5726c 100644 --- a/inc/cli.h +++ b/inc/cli.h @@ -1,95 +1,96 @@ #ifndef CLI_H #define CLI_H -#include +#include "cache.h" #include #include +#include + +class Cli +{ + public: + /** + * Constructor. + * @return A newly allocated CLI object. + */ + Cli(); + ~Cli(); + + /** + * Prints all available commands to the console. + */ + void help(); + + /** + * Loads data from memory from the specified memory address. + * @param memory_address address of the memory where data needs to be loaded + * from + */ + void load(int memory_address); + + /** + * Stores data into memory at the specified address. + * @param memory_address address of the memory where data needs to be stored + * @param data data value to be written to the memory + */ + void store(int memory_address, int data); + + /** + * Resets the memory configuration and cycles to their initial state. + * This function provides a side door reset interface to the memory system, + * allowing the user to reset the memory configuration directly. + */ + void reset(); + + /** + * Updates the memory at the specified address with the given data. + * This function provides a side door modification interface to the memory + * system, allowing the user to modify the memory configuration directly. + * @param memory_address address of the memory to be updated + * @param data data value to be written to the memory + */ + void update(int memory_address, int data); -class Cli { - public: - - Cli(); - - ~Cli(); - - /** - * Prints all available commands to the console. - */ - void help(); - - /** - * Loads data from memory from the specified memory address. - * @param memory_address address of the memory where data needs to be loaded from - * @param pipeline_stage pipeline stage to be served by memory subsystem - */ - void load(int memory_address, int pipeline_stage); - - /** - * Stores data into memory at the specified address. - * @param memory_address address of the memory where data needs to be stored - * @param pipeline_stage pipeline stage to be served by memory subsystem - * @param data data value to be written to the memory - */ - void store(int memory_address, int pipeline_stage, int data); - - /** - * Loads a memory image from a file and configures memory to the image. - * This function provides a side door memory image loading interface to the memory system, - * allowing the user to load a memory image from a file and configure the memory subsystem to the image. - * @param filename name of file containing memory image - */ - void load_memory_image(const std::string& filename); - - /** - * Resets the memory configuration and cycles to their initial state. - * This function provides a side door reset interface to the memory system, - * allowing the user to reset the memory configuration directly. - */ - void reset(); - - /** - * Updates the memory at the specified address with the given data. - * This function provides a side door modification interface to the memory system, - * allowing the user to modify the memory configuration directly. - * @param memory_address address of the memory to be updated - * @param data data value to be written to the memory - */ - void update_memory(int memory_address, int data); - - /** - * Displays the current status of the entire memory subsystem. - * This function provides a side door view into the memory system, - * showing its current state and configuration. - */ - void view_memory(); - - /** - * Displays the data at the specified memory address. - * This function provides a side door view into the memory system, - * showing the data at the specified memory address. - * @param memory_address address of the memory to be viewed - */ - void view_memory_address(int memory_address); - - /** - * Updates the controls using a configuration file. - * This function provides a side door modification interface to the control system, - * allowing the user to update the controls directly. - * @param config_file name of file containing control configuration - */ - void update_controls(const std::string& config_file); + /** + * Advance the clock one cycle, refreshing the storage devices. + */ + void clock(); - /** - * Runs the command line interface - * This function is the main entry point for the command line interface. - */ - void run(); + /** + * Displays `lines` lines of the data in `level`, starting from `base`. + * + * + * This function provides a side door view into the storage system, showing + * its current state and configuration. + * @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); - private: + /** + * Runs the command line interface + * This function is the main entry point for the command line interface. + */ + void run(); - /** Map of commands and their corresponding functions. - * This map is used to store the commands and their corresponding functions. - */ - std::unordered_map)>> commands; + private: + /** + * Initializes the cache object. + */ + void initialize(); + /** Map of commands and their corresponding functions. + * This map is used to store the commands and their corresponding functions. + */ + std::unordered_map< + std::string, + std::function)>> + commands; + /** + * The cache object to interface with. + */ + Cache *cache; }; -#endif /* CLI_H_INCLUDED */ \ No newline at end of file +#endif /* CLI_H_INCLUDED */ diff --git a/inc/definitions.h b/inc/definitions.h index 877065e..8cafab3 100644 --- a/inc/definitions.h +++ b/inc/definitions.h @@ -30,6 +30,16 @@ */ #define L1_CACHE_SIZE (int)pow(2, L1_CACHE_SPEC) +/** + * The total number of cycles a memory access takes. + */ +#define MEM_DELAY 4 + +/** + * The total number of cycles a level one cache access takes + */ +#define L1_CACHE_DELAY 1 + /** * Return the N least-significant bits from integer K using a bit mask * @param the integer to be parsed diff --git a/inc/storage.h b/inc/storage.h index 793b982..0ab16e4 100644 --- a/inc/storage.h +++ b/inc/storage.h @@ -17,6 +17,8 @@ enum Accessor { class Storage { public: + virtual ~Storage() = default; + /** * Write `data` into `address`. * @param the source making the request. @@ -49,6 +51,13 @@ class Storage */ void resolve(); + /** + * Getter for lower attribute. + * TODO this doesn't seem like good object-oriented practice. + * @return this->lower + */ + Storage *get_lower(); + protected: /** * The data currently stored in this level of storage. -- cgit v1.2.3 From 141494cb961b72a7ad56c3e754af43a07f1b8c23 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 'inc') 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 3f07846136767cbed13fd83baaba416f19c61667 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 'inc') 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 From d16bb09d1e3bc79f94a7fcc43153fceb00af0df9 Mon Sep 17 00:00:00 2001 From: bd Date: Mon, 10 Mar 2025 20:06:43 -0400 Subject: Make logger a global singleton class --- inc/logger.h | 26 +++++++++++++-------- src/logger/logger.cc | 22 ++++++++++++++---- src/main.cc | 20 ++++++++-------- tests/logger.cc | 65 ---------------------------------------------------- 4 files changed, 44 insertions(+), 89 deletions(-) delete mode 100644 tests/logger.cc (limited to 'inc') diff --git a/inc/logger.h b/inc/logger.h index 7ab3051..38527c8 100644 --- a/inc/logger.h +++ b/inc/logger.h @@ -9,13 +9,14 @@ enum LogLevel { DEBUG, INFO, WARNING, ERROR, CRITICAL }; class Logger { public: + static Logger* getInstance(); + + ~Logger(); + /** - * Constructor. - * @param The file name to log to. - * @return A new logger object. + * Do not allow copies. */ - Logger(const string &); - ~Logger(); + Logger(const Logger& obj) = delete; /** * Set the log level. @@ -31,10 +32,17 @@ class Logger void log(LogLevel, const string &); private: - LogLevel level = INFO; - ofstream logFile; - string levelToString(LogLevel); - int levelToInt(LogLevel); + /** + * Constructor. + * @param The file name to log to. + * @return A new logger object. + */ + Logger(const string &); + static Logger* logger_instance; + static LogLevel level; + static ofstream logFile; + static string level_to_string(LogLevel); + static int level_to_int(LogLevel); }; #endif /* LOGGER_H_INCLUDED */ diff --git a/src/logger/logger.cc b/src/logger/logger.cc index fb5052a..55d7a15 100644 --- a/src/logger/logger.cc +++ b/src/logger/logger.cc @@ -5,6 +5,10 @@ #include using namespace std; +LogLevel Logger::level = INFO; +ofstream Logger::logFile; +Logger *Logger::logger_instance; + Logger::Logger(const string &filename) { if (!filename.empty()) { @@ -17,11 +21,11 @@ Logger::Logger(const string &filename) Logger::~Logger() { logFile.close(); } -void Logger::setLevel(LogLevel level) { this->level = level; } +void Logger::setLevel(LogLevel level) { level = level; } void Logger::log(LogLevel level, const string &message) { - if (levelToInt(level) > levelToInt(this->level)) { + if (level_to_int(level) > level_to_int(level)) { return; } @@ -31,7 +35,7 @@ void Logger::log(LogLevel level, const string &message) strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", timeinfo); ostringstream logEntry; - logEntry << "[" << timestamp << "] " << levelToString(level) << ": " + logEntry << "[" << timestamp << "] " << level_to_string(level) << ": " << message << endl; cout << logEntry.str(); @@ -42,7 +46,15 @@ void Logger::log(LogLevel level, const string &message) } } -string Logger::levelToString(LogLevel level) +Logger *Logger::getInstance() +{ + if (logger_instance == nullptr) { + logger_instance = new Logger("vector.log"); + } + return logger_instance; +} + +string Logger::level_to_string(LogLevel level) { switch (level) { case DEBUG: @@ -60,7 +72,7 @@ string Logger::levelToString(LogLevel level) } } -int Logger::levelToInt(LogLevel level) +int Logger::level_to_int(LogLevel level) { switch (level) { case DEBUG: diff --git a/src/main.cc b/src/main.cc index cc5fbb3..520a7e1 100644 --- a/src/main.cc +++ b/src/main.cc @@ -31,26 +31,26 @@ static void err() << std::endl; } -static void parseArguments(int argc, char **argv, Logger &logger, bool &python) +static void parseArguments(int argc, char **argv, bool &python) { + Logger *logger = Logger::getInstance(); 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:v", long_options, NULL)) != -1) { + while ((opt = getopt_long(argc, argv, "d:p", long_options, NULL)) != -1) { switch (opt) { case 'd': - logger.setLevel(DEBUG); - logger.log(DEBUG, "DEBUG output enabled."); + logger->setLevel(DEBUG); + logger->log(DEBUG, "DEBUG output enabled."); break; case 'p': - logger.log(INFO, "Python will NOT be started!"); + logger->log(INFO, "Python will NOT be started!"); python = false; break; case 'v': @@ -66,17 +66,17 @@ static void parseArguments(int argc, char **argv, Logger &logger, bool &python) int main(int argc, char **argv) { print_version_number(); - Logger logger("vector.log"); + Logger *logger = Logger::getInstance(); Cli cli; - logger.log(INFO, "Initializing..."); + logger->log(INFO, "Initializing..."); bool python = true; - parseArguments(argc, argv, logger, python); + parseArguments(argc, argv, python); if (python) { // fork off python here ; - logger.log(INFO, "Python started."); + logger->log(INFO, "Python started."); } cli.run(); diff --git a/tests/logger.cc b/tests/logger.cc deleted file mode 100644 index 711dd0e..0000000 --- a/tests/logger.cc +++ /dev/null @@ -1,65 +0,0 @@ -#include "logger.h" -#include -#include -#include -#include - -TEST_CASE("Logger logs higher log level", "[logger]") -{ - std::streambuf *coutBuffer = std::cout.rdbuf(); - std::ostringstream oss; - std::cout.rdbuf(oss.rdbuf()); - - Logger logger(""); - logger.setLevel(INFO); - - logger.log(ERROR, "foo bar baz qux"); - - std::cout.rdbuf(coutBuffer); - - std::string actual = oss.str(); - std::regex expected( - "\\[\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}\\] ERROR: " - "foo bar baz qux\\n"); - - REQUIRE(std::regex_match(actual, expected)); -} - -TEST_CASE("Logger logs equal log level", "[logger]") -{ - std::streambuf *coutBuffer = std::cout.rdbuf(); - std::ostringstream oss; - std::cout.rdbuf(oss.rdbuf()); - - Logger logger(""); - logger.setLevel(INFO); - - logger.log(INFO, "foo bar baz qux"); - - std::cout.rdbuf(coutBuffer); - - std::string actual = oss.str(); - std::regex expected("\\[\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}\\] INFO: " - "foo bar baz qux\\n"); - - REQUIRE(std::regex_match(actual, expected)); -} - -TEST_CASE("Logger ignores lower log level", "[logger]") -{ - std::streambuf *coutBuffer = std::cout.rdbuf(); - std::ostringstream oss; - std::cout.rdbuf(oss.rdbuf()); - - Logger logger(""); - logger.setLevel(INFO); - - logger.log(DEBUG, "foo bar baz qux"); - - std::cout.rdbuf(coutBuffer); - - std::string actual = oss.str(); - std::string expected(""); - - REQUIRE(actual == expected); -} -- cgit v1.2.3 From 25d6d41af95cc2a2db3ba2651e5d784413c7058f Mon Sep 17 00:00:00 2001 From: bd Date: Mon, 10 Mar 2025 20:55:21 -0400 Subject: before error with catch crashing with global singleton logger --- inc/definitions.h | 1 + src/cli/cli.cc | 19 ++++++++----------- src/main.cc | 17 ++++++++--------- 3 files changed, 17 insertions(+), 20 deletions(-) (limited to 'inc') diff --git a/inc/definitions.h b/inc/definitions.h index 8cafab3..98c4575 100644 --- a/inc/definitions.h +++ b/inc/definitions.h @@ -1,5 +1,6 @@ #ifndef DEFINITIONS_H #define DEFINITIONS_H +#include "logger.h" #include /** diff --git a/src/cli/cli.cc b/src/cli/cli.cc index a5706fb..2126798 100644 --- a/src/cli/cli.cc +++ b/src/cli/cli.cc @@ -3,9 +3,7 @@ #include "definitions.h" #include "dram.h" #include "response.h" -#include -#include -#include +#include Cli::Cli() { @@ -95,10 +93,7 @@ void Cli::help() << " q - Quits the program\n"; } -void Cli::load(int memory_address) -{ - std::cout << "Loading data from memory address " << memory_address; -} +void Cli::load(int memory_address) { ; } void Cli::store(Accessor accessor, int data, int address) { @@ -142,11 +137,12 @@ void Cli::run() { std::cout << "Memory Command Processor Started. Type 'h' for a list of " "commands.\n"; - std::string input; + while (true) { std::cout << "> "; std::getline(std::cin, input); + std::istringstream iss(input); std::vector tokens; std::string word; @@ -168,15 +164,16 @@ void Cli::run() if (it != commands.end()) { it->second(tokens); } else { - std::cout - << "Unknown command. Type 'help' for available commands.\n"; + std::cout << "Unknown command: '" << command + << "'. Type 'help' for available commands.\n"; } } } void Cli::initialize() { - std::cout << "Resetting memory configuration.\n"; + Logger *global_log = Logger::getInstance(); + global_log->log(INFO, "Resetting memory configuration.\n"); if (this->cache == nullptr) delete this->cache; Dram *d = new Dram(MEM_SIZE, MEM_DELAY); diff --git a/src/main.cc b/src/main.cc index 520a7e1..8a24fdb 100644 --- a/src/main.cc +++ b/src/main.cc @@ -1,10 +1,10 @@ #include "cli.h" #include "logger.h" +#include "definitions.h" #include #include static std::string version_number = "v0.1"; - static std::string banner = " _/_/_/ _/_/_/ _/_/_/ _/_/_/ \n" " _/ _/ _/ _/ _/ \n" @@ -20,7 +20,6 @@ static std::string banner = " _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ \n" " _/ _/ _/_/_/_/ _/_/_/ _/ _/_/ _/ _/ _/ \n" " _/_/ _/_/ \n"; - static void print_version_number() { std::cout << banner << version_number << '\n'; } static void err() @@ -33,7 +32,7 @@ static void err() static void parseArguments(int argc, char **argv, bool &python) { - Logger *logger = Logger::getInstance(); + Logger *global_log = Logger::getInstance(); struct option long_options[] = { {"debug", no_argument, 0, 'd'}, {"no-python", no_argument, 0, 'p'}, @@ -46,11 +45,11 @@ static void parseArguments(int argc, char **argv, bool &python) while ((opt = getopt_long(argc, argv, "d:p", long_options, NULL)) != -1) { switch (opt) { case 'd': - logger->setLevel(DEBUG); - logger->log(DEBUG, "DEBUG output enabled."); + global_log->setLevel(DEBUG); + global_log->log(DEBUG, "DEBUG output enabled."); break; case 'p': - logger->log(INFO, "Python will NOT be started!"); + global_log->log(INFO, "Python will NOT be started!"); python = false; break; case 'v': @@ -65,10 +64,10 @@ static void parseArguments(int argc, char **argv, bool &python) int main(int argc, char **argv) { + Logger *global_log = Logger::getInstance(); print_version_number(); - Logger *logger = Logger::getInstance(); Cli cli; - logger->log(INFO, "Initializing..."); + global_log->log(INFO, "Initializing..."); bool python = true; parseArguments(argc, argv, python); @@ -76,7 +75,7 @@ int main(int argc, char **argv) if (python) { // fork off python here ; - logger->log(INFO, "Python started."); + global_log->log(INFO, "Python started."); } cli.run(); -- cgit v1.2.3 From 85078b99e4cf652fcbd5f4d36b061674a2fe8aa6 Mon Sep 17 00:00:00 2001 From: bd Date: Mon, 10 Mar 2025 22:07:36 -0400 Subject: overload << operator for dram --- inc/cache.h | 2 +- inc/definitions.h | 2 +- inc/dram.h | 14 ++++++++++---- src/cli/cli.cc | 10 ++++++---- src/main.cc | 4 ++-- src/storage/cache.cc | 1 + src/storage/dram.cc | 29 +++++++++++++++++++++++++++++ 7 files changed, 50 insertions(+), 12 deletions(-) (limited to 'inc') diff --git a/inc/cache.h b/inc/cache.h index 0c9b3d7..04f6181 100644 --- a/inc/cache.h +++ b/inc/cache.h @@ -50,6 +50,6 @@ class Cache : public Storage std::array, L1_CACHE_SIZE> meta; }; -std::ostream &operator<<(std::ostream &os, const Cache &a); +std::ostream &operator<<(std::ostream &os, const Cache &c); #endif /* CACHE_H_INCLUDED */ diff --git a/inc/definitions.h b/inc/definitions.h index 98c4575..62ed0f6 100644 --- a/inc/definitions.h +++ b/inc/definitions.h @@ -16,7 +16,7 @@ * The number of bits to specify a memory line * calculated as: (/ (expt 2 15) 4) */ -#define MEM_SPEC 13 +#define MEM_SPEC 8 /** * The total number of words in memory */ diff --git a/inc/dram.h b/inc/dram.h index 20221b7..e8d3573 100644 --- a/inc/dram.h +++ b/inc/dram.h @@ -1,5 +1,7 @@ #ifndef DRAM_H #define DRAM_H +#include "definitions.h" +#include #include class Dram : public Storage @@ -16,9 +18,12 @@ class Dram : public Storage ~Dram(); Response write(Accessor accessor, signed int data, int address) override; - Response read(Accessor accessor, int address, std::array& data) override; + Response read( + Accessor accessor, + int address, + std::array &data) override; - private: + private: /** * Helper for `write`. */ @@ -26,8 +31,9 @@ class Dram : public Storage /** * Helper for `read`. */ - void do_read(std::array& data_line, int address); + void do_read(std::array &data_line, int address); }; -#endif /* DRAM_H_INCLUDED */ +std::ostream &operator<<(std::ostream &os, const Dram &d); +#endif /* DRAM_H_INCLUDED */ diff --git a/src/cli/cli.cc b/src/cli/cli.cc index 2126798..e968a42 100644 --- a/src/cli/cli.cc +++ b/src/cli/cli.cc @@ -5,6 +5,8 @@ #include "response.h" #include +static Logger *global_log = Logger::getInstance(); + Cli::Cli() { this->initialize(); @@ -83,10 +85,9 @@ void Cli::help() "specified address. Accessor must be one of: \"MEM\", \"FETCH\", " "\"L1CACHE\".\n" << " c - manually advances the clock\n" + << " f - advances the clock until one operation reports completion\n" << " r - side door function that resets the memory configuration and " "cycles\n" - << " u
- side door function that updates " - "the memory at the specified address with data provided\n" << " p - side door function that peeks " "the current status of the entire memory subsystem\n" << " h - Prints this help text\n" @@ -129,7 +130,8 @@ void Cli::peek(int level) if (c) { std::cout << *c; } else { - std::cout << "dram"; + std::cout << *dynamic_cast(curr); + ; } } @@ -173,7 +175,7 @@ void Cli::run() void Cli::initialize() { Logger *global_log = Logger::getInstance(); - global_log->log(INFO, "Resetting memory configuration.\n"); + global_log->log(INFO, "Resetting memory configuration."); if (this->cache == nullptr) delete this->cache; Dram *d = new Dram(MEM_SIZE, MEM_DELAY); diff --git a/src/main.cc b/src/main.cc index 8a24fdb..f2f416d 100644 --- a/src/main.cc +++ b/src/main.cc @@ -4,6 +4,8 @@ #include #include +static Logger *global_log = Logger::getInstance(); + static std::string version_number = "v0.1"; static std::string banner = " _/_/_/ _/_/_/ _/_/_/ _/_/_/ \n" @@ -32,7 +34,6 @@ static void err() static void parseArguments(int argc, char **argv, bool &python) { - Logger *global_log = Logger::getInstance(); struct option long_options[] = { {"debug", no_argument, 0, 'd'}, {"no-python", no_argument, 0, 'p'}, @@ -64,7 +65,6 @@ static void parseArguments(int argc, char **argv, bool &python) int main(int argc, char **argv) { - Logger *global_log = Logger::getInstance(); print_version_number(); Cli cli; global_log->log(INFO, "Initializing..."); diff --git a/src/storage/cache.cc b/src/storage/cache.cc index d382c3d..6dd0b8a 100644 --- a/src/storage/cache.cc +++ b/src/storage/cache.cc @@ -100,6 +100,7 @@ std::ostream &operator<<(std::ostream &os, const Cache &c) c.view(0, L1_CACHE_SIZE); std::array, L1_CACHE_SIZE> meta = c.get_meta(); + cout << data.capacity(); os << " " << std::setfill(' ') << std::setw(L1_CACHE_SPEC + 2) << "INDEX" << " | " << std::setfill(' ') << std::setw((8 + 3) * 4 - 1) << "DATA" << " | " << std::setfill(' ') diff --git a/src/storage/dram.cc b/src/storage/dram.cc index 441f10b..5c6d719 100644 --- a/src/storage/dram.cc +++ b/src/storage/dram.cc @@ -1,7 +1,11 @@ #include "dram.h" #include "definitions.h" #include "response.h" +#include #include +#include +#include +#include Dram::Dram(int lines, int delay) { @@ -70,3 +74,28 @@ Response Dram::read( 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> data = + d.view(0, MEM_SIZE); + + cout << data.capacity(); + os << " " << std::setfill(' ') << std::setw(MEM_SPEC + 2) << "INDEX" + << " | " << std::setfill(' ') << std::setw((8 + 3) * 4 - 1) << "DATA" << '\n'; + for (int i = 0; i < MEM_SIZE; ++i) { + os << " 0b" << std::setw(MEM_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 << '\n'; + } + + std::cout.flags(default_flags); + std::cout.fill(default_fill); + return os; +} -- cgit v1.2.3 From 11182ea41cc5f453b06d769dea6e157aa9c3cf86 Mon Sep 17 00:00:00 2001 From: bd Date: Tue, 11 Mar 2025 00:09:12 -0400 Subject: cli display clock cycle, parse ';' delimited commands --- CMakeLists.txt | 3 ++ inc/cli.h | 28 ++++++----- inc/definitions.h | 6 +-- inc/utils.h | 9 ++++ src/cli/cli.cc | 139 ++++++++++++++++++++++++++++++--------------------- src/main.cc | 5 +- src/storage/cache.cc | 1 - src/storage/dram.cc | 1 - src/utils/utils.cc | 25 +++++++-- 9 files changed, 139 insertions(+), 78 deletions(-) (limited to 'inc') diff --git a/CMakeLists.txt b/CMakeLists.txt index 17ec29f..6a48922 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,6 +3,9 @@ project(risc_vector) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +add_compile_options(-Wall -lstdc++) +add_compile_options(-Wextra -Wpedantic) + # cpp standard set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) diff --git a/inc/cli.h b/inc/cli.h index 2194228..a0c698a 100644 --- a/inc/cli.h +++ b/inc/cli.h @@ -25,13 +25,14 @@ class Cli * @param memory_address address of the memory where data needs to be loaded * from */ - void load(int memory_address); + void load(Accessor accessor, int memory_address); /** * Stores data into memory at the specified address. * @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 + * @return the response from the storage device */ void store(Accessor accessor, int data, int address); @@ -42,15 +43,6 @@ class Cli */ void reset(); - /** - * Updates the memory at the specified address with the given data. - * This function provides a side door modification interface to the memory - * system, allowing the user to modify the memory configuration directly. - * @param memory_address address of the memory to be updated - * @param data data value to be written to the memory - */ - void update(int memory_address, int data); - /** * Advance the clock one cycle, refreshing the storage devices. */ @@ -79,17 +71,27 @@ class Cli * Initializes the cache object. */ void initialize(); + /** + * Attempts to match string to either fetch or mem, or throws + * std::invalid_argument otherwise. + * @param the string to be converted accessor + * @return the corresponding accessor + * @throws invalid_argument if the string is not fetch or mem + */ + Accessor match_accessor_or_die(std::string s); /** Map of commands and their corresponding functions. * This map is used to store the commands and their corresponding functions. */ - std::unordered_map< - std::string, - std::function)>> + std::unordered_map)>> commands; /** * The cache object to interface with. */ Cache *cache; + /** + * The current cycle. + */ + int cycle; }; #endif /* CLI_H_INCLUDED */ diff --git a/inc/definitions.h b/inc/definitions.h index 62ed0f6..f015ce9 100644 --- a/inc/definitions.h +++ b/inc/definitions.h @@ -10,7 +10,7 @@ /** * The total number of words in a line */ -#define LINE_SIZE (int)pow(2, 2) +#define LINE_SIZE static_cast(pow(2, 2)) /** * The number of bits to specify a memory line @@ -20,7 +20,7 @@ /** * The total number of words in memory */ -#define MEM_SIZE (int)pow(2, MEM_SPEC) +#define MEM_SIZE static_cast(pow(2, MEM_SPEC)) /** * The number of bits to specify a l1 cache line @@ -29,7 +29,7 @@ /** * The total number of words in l1 cache */ -#define L1_CACHE_SIZE (int)pow(2, L1_CACHE_SPEC) +#define L1_CACHE_SIZE static_cast(pow(2, L1_CACHE_SPEC)) /** * The total number of cycles a memory access takes. diff --git a/inc/utils.h b/inc/utils.h index e258ed8..71e515b 100644 --- a/inc/utils.h +++ b/inc/utils.h @@ -1,5 +1,6 @@ #ifndef UTILS_H #define UTILS_H +#include /** * Parse an address into a tag, index into the cache table, and a line @@ -11,4 +12,12 @@ */ void get_bit_fields(int address, int *tag, int *index, int *offset); +/** + * Formats a string using snprintf. + * @param an object that represents the format string + * @param arguments to be formatted + * @return a string object holding the formatted result + */ +const std::string string_format(const char *const zcFormat, ...); + #endif /* UTILS_H_INCLUDED */ diff --git a/src/cli/cli.cc b/src/cli/cli.cc index 272c246..033849e 100644 --- a/src/cli/cli.cc +++ b/src/cli/cli.cc @@ -3,17 +3,21 @@ #include "definitions.h" #include "dram.h" #include "response.h" -#include +#include "utils.h" +#include Cli::Cli() { this->cache = nullptr; + this->cycle = 0; this->initialize(); - commands["l"] = [this](std::vector args) { - if (args.size() >= 1) { + commands['l'] = [this](std::vector args) { + Accessor a; + if (args.size() >= 2) { try { - load(std::stoi(args[0])); + 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; } @@ -23,16 +27,11 @@ Cli::Cli() return; }; - commands["s"] = [this](std::vector args) { + commands['s'] = [this](std::vector args) { Accessor a; if (args.size() >= 3) { try { - if (tolower(args[0][0]) == 'f') - a = FETCH; - else if (tolower(args[0][0]) == 'm') - a = MEM; - else - throw std::invalid_argument(args[0]); + 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; @@ -43,12 +42,12 @@ Cli::Cli() return; }; - commands["r"] = [this](std::vector args) { + commands['r'] = [this](std::vector args) { reset(); return; }; - commands["p"] = [this](std::vector args) { + commands['p'] = [this](std::vector args) { if (args.size() >= 1) { try { peek(std::stoi(args[0])); @@ -61,12 +60,12 @@ Cli::Cli() return; }; - commands["c"] = [this](std::vector args) { + commands['c'] = [this](std::vector args) { clock(); return; }; - commands["h"] = [this](std::vector args) { + commands['h'] = [this](std::vector args) { help(); return; }; @@ -77,23 +76,29 @@ Cli::~Cli() { delete this->cache; } void Cli::help() { std::cout - << "Available commands:\n" - << " l
- Load data from memory at the 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" - << " f - advances the clock until one operation reports completion\n" - << " r - side door function that resets the memory configuration and " - "cycles\n" - << " 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"; + << "Available commands:" << std::endl + << " [l]oad
- Load data from memory at the specified " + "address" + << std::endl + << " [s]tore
- Stores data into memory at " + "specified address. Acessor must be one of: [f]etch, [m]em" + << std::endl + << " [c]ycle - manually advances the clock" << std::endl + << " [f]orce - advances the clock until one operation reports " + "completion" + << std::endl + << " [r]eset - side door function that resets the memory " + "configuration and " + "cycles" + << std::endl + << " [p]eek - side door function that " + "peeks the current status of the entire memory subsystem" + << std::endl + << " [h]elp - Prints this help text" << std::endl + << " [q]uit - Quits the program" << std::endl; } -void Cli::load(int memory_address) { ; } +void Cli::load(Accessor accessor, int address) { ; } void Cli::store(Accessor accessor, int data, int address) { @@ -101,12 +106,11 @@ void Cli::store(Accessor accessor, int data, int address) std::cout << r << " to " << accessor << " storing " << data << '\n'; } -void Cli::update(int memory_address, int data) +void Cli::clock() { - std::cout << "Resetting memory configuration and cycles.\n"; -}; - -void Cli::clock() { this->cache->resolve(); } + this->cache->resolve(); + ++this->cycle; +} void Cli::reset() { @@ -140,33 +144,42 @@ void Cli::run() "commands.\n"; std::string input; - while (true) { - std::cout << "> "; + bool run = true; + while (run) { + std::cout << this->cycle << "> "; std::getline(std::cin, input); - std::istringstream iss(input); - std::vector tokens; + std::istringstream iss1(input); + std::vector words; + std::string sentence; std::string word; - while (iss >> word) - tokens.push_back(word); - if (tokens.empty()) - continue; + while (std::getline(iss1, sentence, ';')) { + words.clear(); + std::istringstream iss2(sentence); - std::string command = tokens[0]; - tokens.erase(tokens.begin()); + while (iss2 >> word) { + words.push_back(word); + } + if (words.empty()) + continue; - if (command == "q") { - std::cout << "Exiting...\n"; - break; - } + std::string command = words[0]; + words.erase(words.begin()); - auto it = commands.find(command); - if (it != commands.end()) { - it->second(tokens); - } else { - std::cout << "Unknown command: '" << command - << "'. Type 'help' for available commands.\n"; + 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; + } } } } @@ -174,9 +187,23 @@ void Cli::run() void Cli::initialize() { Logger *global_log = Logger::getInstance(); - global_log->log(INFO, "Resetting memory configuration."); + + global_log->log(INFO, "Resetting memory configuration and cycle."); + if (this->cache != nullptr) delete this->cache; + Dram *d = new Dram(MEM_SIZE, MEM_DELAY); this->cache = new Cache(d, L1_CACHE_DELAY); + this->cycle = 1; +} + +Accessor 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/main.cc b/src/main.cc index f2f416d..1259729 100644 --- a/src/main.cc +++ b/src/main.cc @@ -21,7 +21,7 @@ static std::string banner = "_/ _/ _/ _/_/_/ _/ _/ _/ _/ _/_/_/ _/ \n" " _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ \n" " _/ _/ _/_/_/_/ _/_/_/ _/ _/_/ _/ _/ _/ \n" - " _/_/ _/_/ \n"; + " _/_/ _/_/ "; static void print_version_number() { std::cout << banner << version_number << '\n'; } static void err() @@ -79,5 +79,8 @@ int main(int argc, char **argv) } cli.run(); + + global_log->log(INFO, "Cleaning up..."); + global_log->log(INFO, "Goodbye!"); return EXIT_SUCCESS; } diff --git a/src/storage/cache.cc b/src/storage/cache.cc index 6dd0b8a..d382c3d 100644 --- a/src/storage/cache.cc +++ b/src/storage/cache.cc @@ -100,7 +100,6 @@ std::ostream &operator<<(std::ostream &os, const Cache &c) c.view(0, L1_CACHE_SIZE); std::array, L1_CACHE_SIZE> meta = c.get_meta(); - cout << data.capacity(); os << " " << std::setfill(' ') << std::setw(L1_CACHE_SPEC + 2) << "INDEX" << " | " << std::setfill(' ') << std::setw((8 + 3) * 4 - 1) << "DATA" << " | " << std::setfill(' ') diff --git a/src/storage/dram.cc b/src/storage/dram.cc index 5c6d719..7353bce 100644 --- a/src/storage/dram.cc +++ b/src/storage/dram.cc @@ -83,7 +83,6 @@ std::ostream &operator<<(std::ostream &os, const Dram &d) std::vector> data = d.view(0, MEM_SIZE); - cout << data.capacity(); os << " " << std::setfill(' ') << std::setw(MEM_SPEC + 2) << "INDEX" << " | " << std::setfill(' ') << std::setw((8 + 3) * 4 - 1) << "DATA" << '\n'; for (int i = 0; i < MEM_SIZE; ++i) { diff --git a/src/utils/utils.cc b/src/utils/utils.cc index dfeb2b3..5de8e89 100644 --- a/src/utils/utils.cc +++ b/src/utils/utils.cc @@ -1,11 +1,30 @@ #include "utils.h" #include "definitions.h" +#include +#include +#include void get_bit_fields(int address, int *tag, int *index, int *offset) { - *tag = - GET_MID_BITS(address, LINE_SPEC + L1_CACHE_SPEC, - MEM_SPEC + LINE_SPEC + L1_CACHE_SPEC); + *tag = GET_MID_BITS( + address, LINE_SPEC + L1_CACHE_SPEC, + MEM_SPEC + LINE_SPEC + L1_CACHE_SPEC); *index = GET_MID_BITS(address, LINE_SPEC, L1_CACHE_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 zc(iLen + 1); + std::vsnprintf(zc.data(), zc.size(), zcFormat, vaArgs); + va_end(vaArgs); + return std::string(zc.data(), iLen); +} -- cgit v1.2.3 From ceff6a4d11b93130b9b1f13c1ce8e51490ffd188 Mon Sep 17 00:00:00 2001 From: bd Date: Tue, 11 Mar 2025 10:50:11 -0400 Subject: fix namespace issues with match function --- inc/dram.h | 2 +- src/cli/cli.cc | 42 +++++++++++++++++++++++++++++------------- src/main.cc | 3 --- src/storage/cache.cc | 4 ++-- src/storage/dram.cc | 10 +++++----- 5 files changed, 37 insertions(+), 24 deletions(-) (limited to 'inc') diff --git a/inc/dram.h b/inc/dram.h index e8d3573..2d4088f 100644 --- a/inc/dram.h +++ b/inc/dram.h @@ -1,8 +1,8 @@ #ifndef DRAM_H #define DRAM_H #include "definitions.h" +#include "storage.h" #include -#include class Dram : public Storage { diff --git a/src/cli/cli.cc b/src/cli/cli.cc index 033849e..0729e00 100644 --- a/src/cli/cli.cc +++ b/src/cli/cli.cc @@ -82,6 +82,9 @@ void Cli::help() << std::endl << " [s]tore
- Stores data into memory at " "specified address. Acessor must be one of: [f]etch, [m]em" + << " [p]eek - side door function that " + "peeks the current status of the entire memory subsystem" + << std::endl << std::endl << " [c]ycle - manually advances the clock" << std::endl << " [f]orce - advances the clock until one operation reports " @@ -91,19 +94,30 @@ void Cli::help() "configuration and " "cycles" << std::endl - << " [p]eek - side door function that " - "peeks the current status of the entire memory subsystem" - << std::endl - << " [h]elp - Prints this help text" << std::endl - << " [q]uit - Quits the program" << std::endl; + << " [h]elp - prints this help text" << std::endl + << " [q]uit - quits the program" << std::endl; } -void Cli::load(Accessor accessor, int address) { ; } +void Cli::load(Accessor accessor, int 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 << "\tGot:" << std::hex << data; + + std::cout.flags(default_flags); + std::cout.fill(default_fill); +} void Cli::store(Accessor accessor, int data, int address) { Response r = this->cache->write(accessor, data, address); - std::cout << r << " to " << accessor << " storing " << data << '\n'; + std::cout << r << " to " << accessor << " storing " << data << " in" + << address << std::endl; } void Cli::clock() @@ -115,7 +129,7 @@ void Cli::clock() void Cli::reset() { this->initialize(); - std::cout << "Done.\n"; + std::cout << "Done." << std::endl; } void Cli::peek(int level) @@ -123,7 +137,8 @@ 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.\n"; + std::cerr << "Level " << level << " of storage does not exist." + << std::endl; return; } curr = curr->get_lower(); @@ -131,9 +146,9 @@ void Cli::peek(int level) Cache *c = dynamic_cast(curr); if (c) { - std::cout << *c; + std::cout << *c << std::endl; } else { - std::cout << *dynamic_cast(curr); + std::cout << *dynamic_cast(curr) << std::endl; ; } } @@ -141,7 +156,8 @@ void Cli::peek(int level) void Cli::run() { std::cout << "Memory Command Processor Started. Type 'h' for a list of " - "commands.\n"; + "commands." + << std::endl; std::string input; bool run = true; @@ -198,7 +214,7 @@ void Cli::initialize() this->cycle = 1; } -Accessor match_accessor_or_die(std::string s) +Accessor Cli::match_accessor_or_die(std::string s) { if (tolower(s[0]) == 'f') return FETCH; diff --git a/src/main.cc b/src/main.cc index 1259729..08b38e6 100644 --- a/src/main.cc +++ b/src/main.cc @@ -53,9 +53,6 @@ static void parseArguments(int argc, char **argv, bool &python) global_log->log(INFO, "Python will NOT be started!"); python = false; break; - case 'v': - print_version_number(); - exit(EXIT_SUCCESS); default: err(); exit(EXIT_FAILURE); diff --git a/src/storage/cache.cc b/src/storage/cache.cc index d382c3d..1a8a10b 100644 --- a/src/storage/cache.cc +++ b/src/storage/cache.cc @@ -104,7 +104,7 @@ std::ostream &operator<<(std::ostream &os, const Cache &c) << " | " << std::setfill(' ') << std::setw((8 + 3) * 4 - 1) << "DATA" << " | " << std::setfill(' ') << std::setw(MEM_SPEC - LINE_SPEC - L1_CACHE_SPEC + 2) << "TAG" - << " | D\n"; + << " | D" << std::endl; for (int i = 0; i < L1_CACHE_SIZE; ++i) { os << " 0b" << std::setw(L1_CACHE_SPEC) << std::bitset(i) << " | "; @@ -114,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) << std::endl; } std::cout.flags(default_flags); diff --git a/src/storage/dram.cc b/src/storage/dram.cc index 7353bce..e755c2a 100644 --- a/src/storage/dram.cc +++ b/src/storage/dram.cc @@ -1,8 +1,8 @@ #include "dram.h" #include "definitions.h" #include "response.h" -#include #include +#include #include #include #include @@ -80,18 +80,18 @@ 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> data = - d.view(0, MEM_SIZE); + std::vector> data = d.view(0, MEM_SIZE); os << " " << std::setfill(' ') << std::setw(MEM_SPEC + 2) << "INDEX" - << " | " << std::setfill(' ') << std::setw((8 + 3) * 4 - 1) << "DATA" << '\n'; + << " | " << std::setfill(' ') << std::setw((8 + 3) * 4 - 1) << "DATA" + << std::endl; for (int i = 0; i < MEM_SIZE; ++i) { os << " 0b" << std::setw(MEM_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 << '\n'; + os << std::endl; } std::cout.flags(default_flags); -- cgit v1.2.3 From fde996690d77b81e445450671a0723f837de4eb3 Mon Sep 17 00:00:00 2001 From: bd Date: Tue, 11 Mar 2025 10:53:14 -0400 Subject: Remove header with unimplemented functions --- inc/risc_vector.h | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 inc/risc_vector.h (limited to 'inc') diff --git a/inc/risc_vector.h b/inc/risc_vector.h deleted file mode 100644 index 244adb6..0000000 --- a/inc/risc_vector.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef RISC_VECTOR_H -#define RISC_VECTOR_H -#include - - - -/** - * Outputs the program version and banner. - */ -void print_version_number(); - -#endif /* RISC_VECTOR_H_INCLUDED */ -- cgit v1.2.3