diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cli/cli.cc | 362 | ||||
-rw-r--r-- | src/logger/logger.cc | 22 | ||||
-rw-r--r-- | src/main.cc | 51 | ||||
-rw-r--r-- | src/storage/cache.cc | 47 | ||||
-rw-r--r-- | src/storage/dram.cc | 28 | ||||
-rw-r--r-- | src/storage/storage.cc | 6 | ||||
-rw-r--r-- | src/utils/accessor.cc | 8 | ||||
-rw-r--r-- | src/utils/response.cc | 8 | ||||
-rw-r--r-- | src/utils/utils.cc | 25 |
9 files changed, 371 insertions, 186 deletions
diff --git a/src/cli/cli.cc b/src/cli/cli.cc index 5d78744..0729e00 100644 --- a/src/cli/cli.cc +++ b/src/cli/cli.cc @@ -1,187 +1,225 @@ #include "cli.h" -#include <sstream> +#include "cache.h" +#include "definitions.h" +#include "dram.h" +#include "response.h" +#include "utils.h" #include <iostream> -#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() {} - -//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() +{ + this->cache = nullptr; + this->cycle = 0; + this->initialize(); + + commands['l'] = [this](std::vector<std::string> args) { + Accessor a; + if (args.size() >= 2) { + try { + 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; + } + } else { + std::cout << "Usage: l <memory-address>\n"; + } + return; + }; + + commands['s'] = [this](std::vector<std::string> args) { + Accessor a; + if (args.size() >= 3) { + try { + 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; + } + } else { + std::cout << "Usage: s <memory-address> <data>\n"; + } + return; + }; + + commands['r'] = [this](std::vector<std::string> args) { + reset(); + return; + }; + + commands['p'] = [this](std::vector<std::string> args) { + if (args.size() >= 1) { + try { + peek(std::stoi(args[0])); + } catch (const std::invalid_argument &e) { + std::cerr << "Invalid input: " << e.what() << std::endl; + } + } else { + std::cout << "Usage: v <storage-level> <base> <lines>\n"; + } + return; + }; + + commands['c'] = [this](std::vector<std::string> args) { + clock(); + return; + }; + + commands['h'] = [this](std::vector<std::string> args) { + help(); + return; + }; } -void Cli::load(int memory_address, int pipeline_stage) { - std::cout << "Loading data from memory address " << memory_address - << " at pipeline stage " << pipeline_stage << ".\n"; +Cli::~Cli() { delete this->cache; } + +void Cli::help() +{ + std::cout + << "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" + << " [p]eek <storage-level> <base> <lines> - 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 " + "completion" + << std::endl + << " [r]eset - side door function that resets the memory " + "configuration and " + "cycles" + << std::endl + << " [h]elp - prints this help text" << std::endl + << " [q]uit - quits the program" << std::endl; } +void Cli::load(Accessor accessor, int address) +{ + const auto default_flags = std::cout.flags(); + const auto default_fill = std::cout.fill(); -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"; -} - + 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; -void Cli::load_memory_image(const std::string& filename) { - std::cout << "Loading memory image from file: " << filename << ".\n"; + std::cout.flags(default_flags); + std::cout.fill(default_fill); } - -void Cli::reset() { - std::cout << "Resetting memory configuration and cycles.\n"; +void Cli::store(Accessor accessor, int data, int address) +{ + Response r = this->cache->write(accessor, data, address); + std::cout << r << " to " << accessor << " storing " << data << " in" + << address << std::endl; } +void Cli::clock() +{ + this->cache->resolve(); + ++this->cycle; +} -void Cli::update_memory(int memory_address, int data) { - std::cout << "Updating memory at address " << memory_address - << " with data " << data << ".\n"; +void Cli::reset() +{ + this->initialize(); + std::cout << "Done." << std::endl; } +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." + << std::endl; + return; + } + curr = curr->get_lower(); + } + + Cache *c = dynamic_cast<Cache *>(curr); + if (c) { + std::cout << *c << std::endl; + } else { + std::cout << *dynamic_cast<Dram *>(curr) << std::endl; + ; + } +} -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." + << std::endl; + std::string input; + + bool run = true; + while (run) { + std::cout << this->cycle << "> "; + std::getline(std::cin, input); + + std::istringstream iss1(input); + std::vector<std::string> words; + std::string sentence; + std::string word; + + while (std::getline(iss1, sentence, ';')) { + words.clear(); + std::istringstream iss2(sentence); + + while (iss2 >> word) { + words.push_back(word); + } + if (words.empty()) + continue; + + std::string command = words[0]; + words.erase(words.begin()); + + 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; + } + } + } } +void Cli::initialize() +{ + Logger *global_log = Logger::getInstance(); -void Cli::view_memory_address(int memory_address) { - std::cout << "Viewing data at memory address " << memory_address << ".\n"; -} + global_log->log(INFO, "Resetting memory configuration and cycle."); + if (this->cache != nullptr) + delete this->cache; -void Cli::update_controls(const std::string& config_file) { - std::cout << "Updating controls using configuration file: " << config_file << ".\n"; + Dram *d = new Dram(MEM_SIZE, MEM_DELAY); + this->cache = new Cache(d, L1_CACHE_DELAY); + this->cycle = 1; } -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"; - } - } +Accessor Cli::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/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 <sstream> 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 68b3cdf..08b38e6 100644 --- a/src/main.cc +++ b/src/main.cc @@ -1,18 +1,38 @@ -#include "logger.h" #include "cli.h" +#include "logger.h" +#include "definitions.h" #include <getopt.h> #include <iostream> +static Logger *global_log = Logger::getInstance(); +static std::string version_number = "v0.1"; +static std::string banner = + " _/_/_/ _/_/_/ _/_/_/ _/_/_/ \n" + " _/ _/ _/ _/ _/ \n" + " _/_/_/ _/ _/_/ _/ \n" + " _/ _/ _/ _/ _/ \n" + "_/ _/ _/_/_/ _/_/_/ _/_/_/ \n" + " \n" + " \n" + " _/_/ _/_/ \n" + " _/ _/ _/ _/_/_/_/ _/_/_/ _/_/_/_/_/ _/_/ _/_/_/ _/ \n" + " _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ \n" + "_/ _/ _/ _/_/_/ _/ _/ _/ _/ _/_/_/ _/ \n" + " _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ \n" + " _/ _/ _/_/_/_/ _/_/_/ _/ _/_/ _/ _/ _/ \n" + " _/_/ _/_/ "; +static void print_version_number() { std::cout << banner << version_number << '\n'; } -void err() +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, bool &python) { struct option long_options[] = { {"debug", no_argument, 0, 'd'}, @@ -26,11 +46,11 @@ void parseArguments(int argc, char **argv, Logger &logger, 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; default: @@ -42,19 +62,22 @@ void parseArguments(int argc, char **argv, Logger &logger, bool &python) int main(int argc, char **argv) { - Logger logger("vector.log"); - Cli cli; - logger.log(INFO, "Initializing..."); + print_version_number(); + Cli cli; + global_log->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."); + global_log->log(INFO, "Python started."); } - cli.run(); + cli.run(); + + global_log->log(INFO, "Cleaning up..."); + global_log->log(INFO, "Goodbye!"); return EXIT_SUCCESS; -}
\ No newline at end of file +} diff --git a/src/storage/cache.cc b/src/storage/cache.cc index 2031367..1a8a10b 100644 --- a/src/storage/cache.cc +++ b/src/storage/cache.cc @@ -3,6 +3,9 @@ #include "response.h" #include "utils.h" #include <bits/stdc++.h> +#include <bitset> +#include <iostream> +#include <iterator> Cache::Cache(Storage *lower, int delay) { @@ -16,7 +19,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 +83,41 @@ 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() const +{ + std::array<std::array<int, 2>, 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<std::array<signed int, LINE_SIZE>> data = + 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 + 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" << std::endl; + for (int i = 0; i < L1_CACHE_SIZE; ++i) { + os << " 0b" << std::setw(L1_CACHE_SPEC) << std::bitset<L1_CACHE_SPEC>(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<MEM_SPEC - LINE_SPEC - L1_CACHE_SPEC>(meta.at(i)[0]) + << " | " << (int)(meta.at(i)[0] >= 0) << std::endl; + } + + std::cout.flags(default_flags); + std::cout.fill(default_fill); + return os; +} diff --git a/src/storage/dram.cc b/src/storage/dram.cc index 441f10b..e755c2a 100644 --- a/src/storage/dram.cc +++ b/src/storage/dram.cc @@ -2,6 +2,10 @@ #include "definitions.h" #include "response.h" #include <algorithm> +#include <bits/stdc++.h> +#include <bitset> +#include <iostream> +#include <iterator> Dram::Dram(int lines, int delay) { @@ -70,3 +74,27 @@ 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<std::array<signed int, LINE_SIZE>> data = d.view(0, MEM_SIZE); + + os << " " << std::setfill(' ') << std::setw(MEM_SPEC + 2) << "INDEX" + << " | " << 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<MEM_SPEC>(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 << std::endl; + } + + 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 61531d1..8e2e461 100644 --- a/src/storage/storage.cc +++ b/src/storage/storage.cc @@ -3,7 +3,7 @@ #include <algorithm> std::vector<std::array<signed int, LINE_SIZE>> -Storage::view(int base, int lines) +Storage::view(int base, int lines) const { base = (base / LINE_SIZE) * LINE_SIZE; std::vector<std::array<signed int, LINE_SIZE>> ret(lines + 1); @@ -13,8 +13,12 @@ Storage::view(int base, int lines) return ret; } +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/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); +} |