summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbd <bdunahu@operationnull.com>2025-03-10 19:42:01 -0400
committerbd <bdunahu@operationnull.com>2025-03-10 19:42:01 -0400
commit4dbe50416eea0fecc2aa6f5ce3dc7032c95234c5 (patch)
tree140af0aec8ee90ac4c15e8b877ff2dc88f33d7ae
parent9009d358f7959b1dd60b77fea181be04ae190ef3 (diff)
CLI view, clock, store, program banner
-rw-r--r--inc/accessor.h15
-rw-r--r--inc/cli.h9
-rw-r--r--inc/response.h3
-rw-r--r--inc/risc_vector.h12
-rw-r--r--inc/storage.h15
-rw-r--r--src/cli/cli.cc65
-rw-r--r--src/main.cc34
-rw-r--r--src/storage/cache.cc14
-rw-r--r--src/storage/storage.cc2
-rw-r--r--src/utils/accessor.cc8
-rw-r--r--src/utils/response.cc8
-rw-r--r--tests/cache.cc15
12 files changed, 132 insertions, 68 deletions
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 <iostream>
+
+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 <iostream>
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 <string>
+
+
+
+/**
+ * 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 <algorithm>
#include <array>
+#include <map>
#include <vector>
-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<std::array<signed int, LINE_SIZE>> view(int base, int lines) const;
+ std::vector<std::array<signed int, LINE_SIZE>>
+ 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 <iostream>
#include <sstream>
#include <vector>
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<std::string> 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<std::string> 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<std::string> args) {
- if (args.size() >= 3) {
+ commands["p"] = [this](std::vector<std::string> 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<std::string> args) {
+ clock();
+ return;
+ };
+
commands["h"] = [this](std::vector<std::string> args) {
help();
return;
@@ -68,16 +79,17 @@ void Cli::help()
{
std::cout
<< "Available commands:\n"
- << " l <memory-address> - Load data from memory at the specified "
+ << " l <address> - Load data from memory at the specified "
"address\n"
- << " s <memory-address> <data> - Stores data into "
- "memory at 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"
<< " r - side door function that resets the memory configuration and "
"cycles\n"
- << " u <memory-address> <data> - side door function that updates "
+ << " u <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 "
+ << " 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";
@@ -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 <getopt.h>
#include <iostream>
-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<std::array<int, 2>, 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<L1_CACHE_SPEC>(i)
<< " | ";
@@ -116,7 +114,7 @@ std::ostream &operator<<(std::ostream &os, const Cache &c)
}
os << "| 0x" << std::setfill(' ')
<< std::bitset<MEM_SPEC - LINE_SPEC - L1_CACHE_SPEC>(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 <iostream>
+
+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 <iostream>
+
+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];