summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbd <bdunahu@operationnull.com>2025-03-11 00:09:12 -0400
committerbd <bdunahu@operationnull.com>2025-03-11 00:09:12 -0400
commitf34156105801c81677c54d1713104ac3d7c1c112 (patch)
treea37a0e14ec5cef442d979852876dd307c6d4bf22
parent17dfdb2e00b609e3c7e975ce7a7c19da43318b79 (diff)
cli display clock cycle, parse ';' delimited commands
-rw-r--r--CMakeLists.txt3
-rw-r--r--inc/cli.h28
-rw-r--r--inc/definitions.h6
-rw-r--r--inc/utils.h9
-rw-r--r--src/cli/cli.cc139
-rw-r--r--src/main.cc5
-rw-r--r--src/storage/cache.cc1
-rw-r--r--src/storage/dram.cc1
-rw-r--r--src/utils/utils.cc25
9 files changed, 139 insertions, 78 deletions
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);
@@ -43,15 +44,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.
*/
void clock();
@@ -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<void(std::vector<std::string>)>>
+ std::unordered_map<char, std::function<void(std::vector<std::string>)>>
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<int>(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<int>(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<int>(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 <string>
/**
* 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 <stdio.h>
+#include "utils.h"
+#include <iostream>
Cli::Cli()
{
this->cache = nullptr;
+ this->cycle = 0;
this->initialize();
- commands["l"] = [this](std::vector<std::string> args) {
- if (args.size() >= 1) {
+ commands['l'] = [this](std::vector<std::string> 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<std::string> args) {
+ commands['s'] = [this](std::vector<std::string> 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<std::string> args) {
+ commands['r'] = [this](std::vector<std::string> args) {
reset();
return;
};
- commands["p"] = [this](std::vector<std::string> args) {
+ commands['p'] = [this](std::vector<std::string> args) {
if (args.size() >= 1) {
try {
peek(std::stoi(args[0]));
@@ -61,12 +60,12 @@ Cli::Cli()
return;
};
- commands["c"] = [this](std::vector<std::string> args) {
+ commands['c'] = [this](std::vector<std::string> args) {
clock();
return;
};
- commands["h"] = [this](std::vector<std::string> args) {
+ commands['h'] = [this](std::vector<std::string> args) {
help();
return;
};
@@ -77,23 +76,29 @@ Cli::~Cli() { delete this->cache; }
void Cli::help()
{
std::cout
- << "Available commands:\n"
- << " l <address> - Load data from memory at the specified "
- "address\n"
- << " s <accessor> <data> <address> - 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 <storage-level> <base> <lines> - 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 <address> - Load data from memory at the specified "
+ "address"
+ << std::endl
+ << " [s]tore <accessor> <data> <address> - 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 <storage-level> <base> <lines> - 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<std::string> tokens;
+ std::istringstream iss1(input);
+ std::vector<std::string> 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<std::array<int, 2>, 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<std::array<signed int, LINE_SIZE>> 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 <cstdarg>
+#include <string>
+#include <vector>
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<char> zc(iLen + 1);
+ std::vsnprintf(zc.data(), zc.size(), zcFormat, vaArgs);
+ va_end(vaArgs);
+ return std::string(zc.data(), iLen);
+}