summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbd <bdunahu@operationnull.com>2025-03-10 14:53:59 -0400
committerbd <bdunahu@operationnull.com>2025-03-10 14:53:59 -0400
commitcdcaec3c1e62b47fcd270df651cd0e343e46f0e7 (patch)
treefc77cc22024b719f14e03e29e2bbd94b3eb645ca
parent1f8b8babcfb383f1fb0281663561161061684206 (diff)
Update cli method signatures, add some getters to cache and storage
-rw-r--r--inc/cache.h7
-rw-r--r--inc/cli.h171
-rw-r--r--inc/definitions.h10
-rw-r--r--inc/storage.h9
-rw-r--r--src/cli/cli.cc316
-rw-r--r--src/main.cc10
-rw-r--r--src/storage/cache.cc11
-rw-r--r--src/storage/storage.cc2
-rw-r--r--tests/cache.cc16
9 files changed, 286 insertions, 266 deletions
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<signed int, LINE_SIZE> &data) 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_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 <unordered_map>
+#include "cache.h"
#include <functional>
#include <string>
+#include <unordered_map>
+
+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<std::string, std::function<void(std::vector<std::string>)>> 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<void(std::vector<std::string>)>>
+ 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
@@ -31,6 +31,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
* @param the number of bits 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.
diff --git a/src/cli/cli.cc b/src/cli/cli.cc
index 5d78744..fea44d7 100644
--- a/src/cli/cli.cc
+++ b/src/cli/cli.cc
@@ -1,187 +1,173 @@
#include "cli.h"
-#include <sstream>
+#include "cache.h"
+#include "definitions.h"
+#include "dram.h"
#include <iostream>
+#include <sstream>
#include <vector>
-Cli::Cli() {
- commands["load"] = [this](std::vector<std::string> args) {
- if (args.size() >= 2){
- try{
- load(std::stoi(args[0]), std::stoi(args[1]));
- } catch(const std::exception &e){
- std::cerr << "Invalid input: " << e.what() << std::endl;
- }
- }
- else {
- std::cout << "Usage: load <memory-address> <pipeline-stage>\n";
- }
- return;
- };
-
- commands["store"] = [this](std::vector<std::string> args) {
- if (args.size() >= 3) {
- try{
- store(std::stoi(args[0]), std::stoi(args[1]), std::stoi(args[2]));
- }catch(const std::exception &e) {
- std::cerr << "Invalid input: " << e.what() << std::endl;
- }
- }
- else {
- std::cout << "Usage: store <memory-address> <pipeline-stage> <data>\n";
- }
- return;
- };
-
- commands["load-memory-image"] = [this](std::vector<std::string> args) {
- if (!args.empty()) {
- load_memory_image(args[0]);
- }
- else {
- std::cout << "Usage: load-memory-image <filename>\n";
- }
- return;
- };
-
- commands["reset"] = [this](std::vector<std::string> args) {
- reset();
- return;
- };
-
- commands["update-memory"] = [this](std::vector<std::string> args) {
- if (args.size() >= 2) {
- try {
- update_memory(std::stoi(args[0]), std::stoi(args[1]));
- } catch(const std::exception &e){
- std::cerr << "Invalid input: all arguments are integers" << e.what() << std::endl;
- }
- }
- else{
- std::cout << "Usage: update-memory <memory-address> <data>\n";
- }
- return;
- };
-
- commands["view-memory"] = [this](std::vector<std::string> args) {
- view_memory();
- return;
- };
-
- commands["view-memory-address"] = [this](std::vector<std::string> args) {
- if (!args.empty()) {
- try{
- view_memory_address(std::stoi(args[0]));
- } catch(const std::exception &e){
- std::cerr << "Invalid input: " << e.what() << std::endl;
- }
- }
- else {
- std::cout << "Usage: view-memory-address <memory-address>\n";
- }
- return;
- };
-
- commands["update-controls"] = [this](std::vector<std::string> args) {
- if (!args.empty()) {
- update_controls(args[0]);
- }
- else {
- std::cout << "Usage: update-controls <configuration-file>\n";
- }
- return;
- };
-
- commands["help"] = [this](std::vector<std::string> args) {
- help();
- return;
- };
+Cli::Cli()
+{
+ Dram *d = new Dram(MEM_SIZE, MEM_DELAY);
+ this->cache = new Cache(d, L1_CACHE_DELAY);
+
+ commands["l"] = [this](std::vector<std::string> args) {
+ if (args.size() >= 1) {
+ try {
+ load(std::stoi(args[0]));
+ } catch (const std::exception &e) {
+ std::cerr << "Invalid input: " << e.what() << std::endl;
+ }
+ } else {
+ std::cout << "Usage: l <memory-address>\n";
+ }
+ return;
+ };
+
+ commands["s"] = [this](std::vector<std::string> args) {
+ if (args.size() >= 2) {
+ try {
+ store(std::stoi(args[0]), std::stoi(args[1]));
+ } catch (const std::exception &e) {
+ std::cerr << "Invalid input: " << e.what() << std::endl;
+ }
+ } else {
+ std::cout << "Usage: s <memory-address> <data>\n";
+ }
+ return;
+ };
+
+ commands["r"] = [this](std::vector<std::string> args) {
+ reset();
+ return;
+ };
+
+ commands["v"] = [this](std::vector<std::string> args) {
+ if (args.size() >= 3) {
+ try {
+ view(
+ std::stoi(args[0]), std::stoi(args[1]), std::stoi(args[2]));
+ } catch (const std::exception &e) {
+ std::cerr << "Invalid input: " << e.what() << std::endl;
+ }
+ } else {
+ std::cout << "Usage: v <storage-level> <base> <lines>\n";
+ }
+ return;
+ };
+
+ commands["h"] = [this](std::vector<std::string> args) {
+ help();
+ return;
+ };
}
-Cli::~Cli() {}
-
-//TODO: These function stubs are to be improved after they have been implemented internally.
-void Cli::help() {
- std::cout << "Available commands:\n"
- << " load <memory-address> <pipeline-stage> - Load data from memory at specified address\n"
- << " store <memory-address> <pipeline-stage> <data> - Stores data into memory at specified address\n"
- << " load-memory-image <filename> - side door function that loads a memory image from a file and configures memory to the image\n"
- << " reset - side door function that resets the memory configuration and cycles\n"
- << " update-memory <memory-address> <data> - side door function that updates the memory at the specified address with data provided\n"
- << " view-memory - side door function that views the current status of the entire memory subsystem\n"
- << " view-memory-address <memory-address> - side door function that views data at specific memory address\n"
- << " update-controls <configuration-file> - side door function that takes in a configuration file and updates the controls\n"
- << " exit - Quits the program\n";
+Cli::~Cli() { delete this->cache; }
+
+void Cli::help()
+{
+ std::cout
+ << "Available commands:\n"
+ << " l <memory-address> - Load data from memory at the specified "
+ "address\n"
+ << " s <memory-address> <data> - Stores data into "
+ "memory at specified address\n"
+ << " c - manually advances the clock\n"
+ << " r - side door function that resets the memory configuration and "
+ "cycles\n"
+ << " u <memory-address> <data> - side door function that updates "
+ "the memory at the specified address with data provided\n"
+ << " v <storage-level> <base> <lines> - side door function that views "
+ "the current status of the entire memory subsystem\n"
+ << " h - Prints this help text\n"
+ << " q - Quits the program\n";
}
-void Cli::load(int memory_address, int pipeline_stage) {
- std::cout << "Loading data from memory address " << memory_address
- << " at pipeline stage " << pipeline_stage << ".\n";
+void Cli::load(int memory_address)
+{
+ std::cout << "Loading data from memory address " << memory_address;
}
-
-void Cli::store(int memory_address, int pipeline_stage, int data) {
- std::cout << "Storing " << data << " into memory address " << memory_address
- << " at pipeline stage " << pipeline_stage << ".\n";
+void Cli::store(int memory_address, int data)
+{
+ std::cout << "Storing " << data << " into memory address "
+ << memory_address;
}
+void Cli::update(int memory_address, int data)
+{
+ std::cout << "Resetting memory configuration and cycles.\n";
+};
-void Cli::load_memory_image(const std::string& filename) {
- std::cout << "Loading memory image from file: " << filename << ".\n";
+void Cli::clock()
+{
+ std::cout << "Resetting memory configuration and cycles.\n";
}
-
-void Cli::reset() {
- std::cout << "Resetting memory configuration and cycles.\n";
+void Cli::reset()
+{
+ std::cout << "Resetting memory configuration and cycles.\n";
}
-
-void Cli::update_memory(int memory_address, int data) {
- std::cout << "Updating memory at address " << memory_address
- << " with data " << data << ".\n";
+void Cli::view(int level, int base, int lines)
+{
+ Storage *curr = this->cache;
+ for (int i = 0; i < level; ++i) {
+ if (!curr) {
+ std::cerr << "Level " << level << " of storage does not exist.\n";
+ return;
+ }
+ curr = curr->get_lower();
+ }
+
+ std::vector<std::array<signed int, LINE_SIZE>> data =
+ curr->view(base, lines);
+
+ if (dynamic_cast<const Cache *>(curr)) {
+
+ } else {
+ std::cout << "dram";
+ }
}
-
-void Cli::view_memory() {
- std::cout << "Viewing current status of memory subsystem.\n";
+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<std::string> tokens;
+ std::string word;
+
+ while (iss >> word)
+ tokens.push_back(word);
+ if (tokens.empty())
+ continue;
+
+ std::string command = tokens[0];
+ tokens.erase(tokens.begin());
+
+ if (command == "q") {
+ std::cout << "Exiting...\n";
+ break;
+ }
+
+ auto it = commands.find(command);
+ if (it != commands.end()) {
+ it->second(tokens);
+ } else {
+ std::cout
+ << "Unknown command. Type 'help' for available commands.\n";
+ }
+ }
}
-
-void Cli::view_memory_address(int memory_address) {
- std::cout << "Viewing data at memory address " << memory_address << ".\n";
+void Cli::initialize()
+{
+ if (this->cache)
+ delete this->cache;
}
-
-
-void Cli::update_controls(const std::string& config_file) {
- std::cout << "Updating controls using configuration file: " << config_file << ".\n";
-}
-
-void Cli::run(){
- std::cout << "Memory Command Processor Started. Type 'help' for a list of commands.\n";
-
- std::string input;
- while (true) {
- std::cout << "> ";
- std::getline(std::cin, input);
- std::istringstream iss(input);
- std::vector<std::string> tokens;
- std::string word;
-
- while (iss >> word) tokens.push_back(word);
- if (tokens.empty()) continue;
-
- std::string command = tokens[0];
- tokens.erase(tokens.begin());
-
- if (command == "exit") {
- std::cout << "Exiting...\n";
- break;
- }
-
- auto it = commands.find(command);
- if (it != commands.end()) {
- it->second(tokens);
- } else {
- std::cout << "Unknown command. Type 'help' for available commands.\n";
- }
- }
-}
-
diff --git a/src/main.cc b/src/main.cc
index 68b3cdf..08cb89f 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -1,10 +1,8 @@
-#include "logger.h"
#include "cli.h"
+#include "logger.h"
#include <getopt.h>
#include <iostream>
-
-
void err()
{
std::cerr << "Usage:\n\trisc_vector [OPTIONS]\nOptions:\n\t--debug,\t-d: "
@@ -43,7 +41,7 @@ void parseArguments(int argc, char **argv, Logger &logger, bool &python)
int main(int argc, char **argv)
{
Logger logger("vector.log");
- Cli cli;
+ Cli cli;
logger.log(INFO, "Initializing...");
bool python = true;
@@ -55,6 +53,6 @@ int main(int argc, char **argv)
logger.log(INFO, "Python started.");
}
- cli.run();
+ cli.run();
return EXIT_SUCCESS;
-} \ No newline at end of file
+}
diff --git a/src/storage/cache.cc b/src/storage/cache.cc
index 2031367..55c8cfa 100644
--- a/src/storage/cache.cc
+++ b/src/storage/cache.cc
@@ -16,7 +16,11 @@ Cache::Cache(Storage *lower, int delay)
this->wait_time = this->delay;
}
-Cache::~Cache() { delete this->data; }
+Cache::~Cache()
+{
+ delete this->lower;
+ delete this->data;
+}
Response Cache::write(Accessor accessor, signed int data, int address)
{
@@ -76,3 +80,8 @@ void Cache::fetch_resource(int expected)
this->is_waiting = (r == OK) ? false : true;
}
+
+std::array<std::array<int, 2>, L1_CACHE_SIZE> *Cache::get_meta()
+{
+ return &(this->meta);
+}
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) {
diff --git a/tests/cache.cc b/tests/cache.cc
index 8d1e806..fc467c7 100644
--- a/tests/cache.cc
+++ b/tests/cache.cc
@@ -38,7 +38,6 @@ TEST_CASE("no delay stores instantly", "[cache]")
actual = c->view(0, 1)[0];
REQUIRE(expected == actual);
- delete d;
delete c;
}
@@ -77,7 +76,6 @@ TEST_CASE("cache takes \"forever\"", "[cache]")
actual = c->view(0, 1)[0];
REQUIRE(expected == actual);
- delete d;
delete c;
}
@@ -116,7 +114,6 @@ TEST_CASE("dram takes \"forever\"", "[cache]")
actual = c->view(0, 1)[0];
REQUIRE(expected == actual);
- delete d;
delete c;
}
@@ -166,11 +163,11 @@ TEST_CASE("dram and cache take \"forever\"", "[cache]")
actual = c->view(0, 1)[0];
REQUIRE(expected == actual);
- delete d;
delete c;
}
-TEST_CASE("dram takes \"forever\", two concurrent requests same index", "[cache]")
+TEST_CASE(
+ "dram takes \"forever\", two concurrent requests same index", "[cache]")
{
int delay = 0;
Dram *d = new Dram(MEM_SIZE, delay + 2);
@@ -223,11 +220,12 @@ TEST_CASE("dram takes \"forever\", two concurrent requests same index", "[cache]
actual = c->view(0, 1)[0];
REQUIRE(expected == actual);
- delete d;
delete c;
}
-TEST_CASE("dram takes \"forever\", two concurrent requests different index", "[cache]")
+TEST_CASE(
+ "dram takes \"forever\", two concurrent requests different index",
+ "[cache]")
{
int delay = 0;
Dram *d = new Dram(MEM_SIZE, delay + 2);
@@ -289,11 +287,11 @@ TEST_CASE("dram takes \"forever\", two concurrent requests different index", "[c
actual = c->view(0, 1)[0];
REQUIRE(expected == actual);
- delete d;
delete c;
}
-TEST_CASE("dram takes \"forever\", two concurrent requests different tag", "[cache]")
+TEST_CASE(
+ "dram takes \"forever\", two concurrent requests different tag", "[cache]")
{
// TODO
}