From 101f0facf8002907ca6e19faabfdcf472c0c3152 Mon Sep 17 00:00:00 2001 From: bd Date: Fri, 11 Apr 2025 21:14:25 -0400 Subject: Move source files to top-level src directory --- src/accessor.cc | 10 +++ src/cache.cc | 180 +++++++++++++++++++++++++++++++++++++++++ src/cli/cli.cc | 214 ------------------------------------------------- src/dram.cc | 130 ++++++++++++++++++++++++++++++ src/logger.cc | 71 ++++++++++++++++ src/logger/logger.cc | 71 ---------------- src/response.cc | 8 ++ src/storage.cc | 16 ++++ src/storage/cache.cc | 180 ----------------------------------------- src/storage/dram.cc | 130 ------------------------------ src/storage/storage.cc | 16 ---- src/utils.cc | 42 ++++++++++ src/utils/accessor.cc | 10 --- src/utils/response.cc | 8 -- src/utils/utils.cc | 42 ---------- 15 files changed, 457 insertions(+), 671 deletions(-) create mode 100644 src/accessor.cc create mode 100644 src/cache.cc delete mode 100644 src/cli/cli.cc create mode 100644 src/dram.cc create mode 100644 src/logger.cc delete mode 100644 src/logger/logger.cc create mode 100644 src/response.cc create mode 100644 src/storage.cc delete mode 100644 src/storage/cache.cc delete mode 100644 src/storage/dram.cc delete mode 100644 src/storage/storage.cc create mode 100644 src/utils.cc delete mode 100644 src/utils/accessor.cc delete mode 100644 src/utils/response.cc delete mode 100644 src/utils/utils.cc diff --git a/src/accessor.cc b/src/accessor.cc new file mode 100644 index 0000000..99347ed --- /dev/null +++ b/src/accessor.cc @@ -0,0 +1,10 @@ +#include "accessor.h" +#include + +std::ostream &operator<<(std::ostream &os, Accessor a) +{ + const std::string nameA[] = { + "IDLE", "WRITE", "MEM", "EXEC", "DCDE", "FETCH", "L1CACHE", "SIDE", + }; + return os << nameA[a]; +} diff --git a/src/cache.cc b/src/cache.cc new file mode 100644 index 0000000..80f59ef --- /dev/null +++ b/src/cache.cc @@ -0,0 +1,180 @@ +#include "cache.h" +#include "definitions.h" +#include "response.h" +#include "utils.h" +#include +#include +#include + +Cache::Cache(Storage *lower, int delay) +{ + this->data = new std::vector>; + this->data->resize(L1_CACHE_LINES); + this->delay = delay; + this->is_waiting = false; + this->lower = lower; + this->meta.fill({-1, -1}); + this->requester = IDLE; + this->wait_time = this->delay; +} + +Cache::~Cache() +{ + delete this->lower; + delete this->data; +} + +Response Cache::write_word(Accessor accessor, signed int data, int address) +{ + return process(accessor, address, [&](int index, int offset) { + this->data->at(index).at(offset) = data; + this->meta[index].at(1) = 1; + }); +} + +Response Cache::write_line( + Accessor accessor, std::array data_line, int address) +{ + return process(accessor, address, [&](int index, int offset) { + (void)offset; + this->data->at(index) = data_line; + this->meta[index].at(1) = 1; + }); +} + +// TODO: tests for multi level cache +Response Cache::read_line( + Accessor accessor, + int address, + std::array &data_line) +{ + return process(accessor, address, [&](int index, int offset) { + (void)offset; + data_line = this->data->at(index); + }); +} + +Response Cache::read_word(Accessor accessor, int address, signed int &data) +{ + return process(accessor, address, [&](int index, int offset) { + data = this->data->at(index).at(offset); + }); +} + +Response Cache::process( + Accessor accessor, + int address, + std::function request_handler) +{ + Response r = this->is_access_cleared(accessor, address); + if (r == OK) { + int tag, index, offset; + get_cache_fields(address, &tag, &index, &offset); + request_handler(index, offset); + } + return r; +} + +Response Cache::is_access_cleared(Accessor accessor, int address) +{ + Response r; + r = WAIT; + /* Do this first--then process the first cycle immediately. */ + if (this->requester == IDLE) + this->requester = accessor; + if (this->requester == accessor) { + handle_miss(address); + if (this->is_waiting) + r = BLOCKED; + else if (this->wait_time == 0) { + this->requester = IDLE; + this->wait_time = delay; + r = OK; + } else { + --this->wait_time; + } + } + return r; +} + +void Cache::handle_miss(int expected) +{ + Response r, q; + int tag, index, offset; + std::array *actual; + std::array *meta; + + get_cache_fields(expected, &tag, &index, &offset); + r = OK; + meta = &this->meta.at(index); + actual = &this->data->at(index); + + if (meta->at(0) != tag) { + r = WAIT; + // address not in cache + if (meta->at(1) >= 0) { + // occupant is dirty + // writing line to DRam in case of dirty cache eviction + q = this->lower->write_line( + L1CACHE, *actual, + ((index << LINE_SPEC) + + (meta->at(0) << (L1_CACHE_LINE_SPEC + LINE_SPEC)))); + if (q == OK) { + meta->at(1) = -1; + } + } else { + q = this->lower->read_line(L1CACHE, expected, *actual); + if (q == OK) { + meta->at(0) = tag; + } + } + } + + this->is_waiting = (r == OK) ? false : true; +} + +std::array, L1_CACHE_LINES> Cache::get_meta() const +{ + std::array, L1_CACHE_LINES> 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_LINES); + std::array, L1_CACHE_LINES> meta = c.get_meta(); + + os << " " << std::setfill(' ') << std::setw(L1_CACHE_LINE_SPEC + 2) + << "INDEX" + << " | " << std::setfill(' ') << std::setw((8 + 3) * 4 - 1) << "DATA" + << " | " << std::setfill(' ') + << std::setw(MEM_LINE_SPEC - L1_CACHE_LINE_SPEC + 2) << "TAG" + << " | D" << std::endl; + for (int i = 0; i < L1_CACHE_LINES; ++i) { + os << " 0b" << std::setw(L1_CACHE_LINE_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 << "| 0b" << std::setfill(' '); + + if (meta.at(i)[0] < 0) + os << std::setfill('?') + << std::setw(MEM_LINE_SPEC - L1_CACHE_LINE_SPEC) << ""; + else + os << std::bitset( + meta.at(i)[0]); + + os << " | " << (int)(meta.at(i)[0] >= 0) << std::endl; + } + + std::cout.flags(default_flags); + std::cout.fill(default_fill); + return os; +} diff --git a/src/cli/cli.cc b/src/cli/cli.cc deleted file mode 100644 index 58575cb..0000000 --- a/src/cli/cli.cc +++ /dev/null @@ -1,214 +0,0 @@ -#include "cli.h" -#include "cache.h" -#include "definitions.h" -#include "dram.h" -#include "response.h" -#include "accessor.h" -#include "utils.h" -#include - -Cli::Cli() -{ - this->cache = nullptr; - this->cycle = 0; - this->initialize(); - - commands['l'] = [this](std::vector 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 \n"; - } - return; - }; - - commands['s'] = [this](std::vector 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 \n"; - } - return; - }; - - commands['r'] = [this](std::vector args) { - (void)args; - reset(); - return; - }; - - commands['p'] = [this](std::vector 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 \n"; - } - return; - }; - - commands['h'] = [this](std::vector args) { - (void)args; - help(); - return; - }; -} - -Cli::~Cli() { delete this->cache; } - -void Cli::help() -{ - std::cout - << "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" - << " [p]eek - side door function that " - "peeks the current status of the entire memory subsystem" - << 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) -{ - address = wrap_address(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 << " Got: " << std::hex << data << std::endl; - - std::cout.flags(default_flags); - std::cout.fill(default_fill); -} - -void Cli::store(Accessor accessor, int data, int address) -{ - address = wrap_address(address); - Response r = this->cache->write_word(accessor, data, address); - std::cout << r << " to " << accessor << " storing " << data << " in " - << address << std::endl; -} - -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(curr); - if (c) { - std::cout << *c << std::endl; - } else { - std::cout << *dynamic_cast(curr) << std::endl; - ; - } -} - -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 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(); - - global_log->log(INFO, "Resetting memory configuration and cycle."); - - if (this->cache != nullptr) - delete this->cache; - - Dram *d = new Dram(MEM_DELAY); - this->cache = new Cache(d, L1_CACHE_DELAY); - this->cycle = 1; -} - -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/dram.cc b/src/dram.cc new file mode 100644 index 0000000..f90f8db --- /dev/null +++ b/src/dram.cc @@ -0,0 +1,130 @@ +#include "dram.h" +#include "definitions.h" +#include "response.h" +#include +#include +#include +#include +#include +#include + +Dram::Dram(int delay) +{ + this->data = new std::vector>; + this->data->resize(MEM_LINES); + this->delay = delay; + this->is_waiting = false; + this->lower = nullptr; + this->requester = IDLE; + this->wait_time = this->delay; +} + +Dram::~Dram() { delete this->data; } + +Response Dram::write_line( + Accessor accessor, std::array data_line, int address) +{ + return process(accessor, address, [&](int line, int word) { + (void)word; + this->data->at(line) = data_line; + }); +} + +Response Dram::write_word(Accessor accessor, signed int data, int address) +{ + return process(accessor, address, [&](int line, int word) { + this->data->at(line).at(word) = data; + }); +} + +// TODO requires testing +Response Dram::read_line( + Accessor accessor, + int address, + std::array &data_line) +{ + return process(accessor, address, [&](int line, int word) { + (void)word; + data_line = this->data->at(line); + }); +} + +Response Dram::read_word(Accessor accessor, int address, signed int &data) +{ + return process(accessor, address, [&](int line, int word) { + data = this->data->at(line).at(word); + }); +} + +// TODO load a file instead and test this method +void Dram::load(std::vector program) { + unsigned long i; + for (i = 0; i < program.size(); ++i) { + int line, word; + get_memory_index(i, line, word); + this->data->at(line).at(word) = program[i]; + } +} + +Response Dram::process( + Accessor accessor, + int address, + std::function request_handler) +{ + Response r = this->is_access_cleared(accessor); + if (r == OK) { + int line, word; + get_memory_index(address, line, word); + request_handler(line, word); + } + return r; +} + +Response Dram::is_access_cleared(Accessor accessor) +{ + Response r; + r = WAIT; + /* Do this first--then process the first cycle immediately. */ + if (accessor == SIDE) + r = OK; + else { + if (this->requester == IDLE) + this->requester = accessor; + if (this->requester == accessor) { + if (this->wait_time == 0) { + this->requester = IDLE; + this->wait_time = delay; + r = OK; + } else { + --this->wait_time; + } + } + } + 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_LINES); + + os << " " << std::setfill(' ') << std::setw(MEM_LINE_SPEC + 2 + LINE_SPEC) + << "ADDRESS" + << " | " << std::setfill(' ') << std::setw((8 + 3) * 4 - 1) << "DATA" + << std::endl; + for (int i = 0; i < MEM_LINES; ++i) { + os << " 0b" << std::setw(MEM_LINE_SPEC + LINE_SPEC) << left + << 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 << std::endl; + } + + std::cout.flags(default_flags); + std::cout.fill(default_fill); + return os; +} diff --git a/src/logger.cc b/src/logger.cc new file mode 100644 index 0000000..b07e66f --- /dev/null +++ b/src/logger.cc @@ -0,0 +1,71 @@ +#include "logger.h" +#include +#include +#include +#include +using namespace std; + +LogLevel Logger::level = INFO; +Logger *Logger::logger_instance; + +void Logger::setLevel(LogLevel level) { this->level = level; } + +void Logger::log(LogLevel level, const string &message) +{ + if (level_to_int(level) > level_to_int(this->level)) { + return; + } + + time_t now = time(0); + tm *timeinfo = localtime(&now); + char timestamp[20]; + strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", timeinfo); + + ostringstream logEntry; + logEntry << "[" << timestamp << "] " << level_to_string(level) << ": " + << message << endl; + + cout << logEntry.str(); +} + +Logger *Logger::getInstance() +{ + if (logger_instance == nullptr) { + logger_instance = new Logger(); + } + return logger_instance; +} + +string Logger::level_to_string(LogLevel level) +{ + switch (level) { + case DEBUG: + return "DEBUG"; + case INFO: + return "INFO"; + case WARNING: + return "WARNING"; + case ERROR: + return "ERROR"; + case CRITICAL: + return "CRITICAL"; + default: + return "UNKNOWN"; + } +} + +int Logger::level_to_int(LogLevel level) +{ + switch (level) { + case DEBUG: + return 5; + case INFO: + return 4; + case WARNING: + return 3; + case ERROR: + return 2; + default: + return 1; + } +} diff --git a/src/logger/logger.cc b/src/logger/logger.cc deleted file mode 100644 index b07e66f..0000000 --- a/src/logger/logger.cc +++ /dev/null @@ -1,71 +0,0 @@ -#include "logger.h" -#include -#include -#include -#include -using namespace std; - -LogLevel Logger::level = INFO; -Logger *Logger::logger_instance; - -void Logger::setLevel(LogLevel level) { this->level = level; } - -void Logger::log(LogLevel level, const string &message) -{ - if (level_to_int(level) > level_to_int(this->level)) { - return; - } - - time_t now = time(0); - tm *timeinfo = localtime(&now); - char timestamp[20]; - strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", timeinfo); - - ostringstream logEntry; - logEntry << "[" << timestamp << "] " << level_to_string(level) << ": " - << message << endl; - - cout << logEntry.str(); -} - -Logger *Logger::getInstance() -{ - if (logger_instance == nullptr) { - logger_instance = new Logger(); - } - return logger_instance; -} - -string Logger::level_to_string(LogLevel level) -{ - switch (level) { - case DEBUG: - return "DEBUG"; - case INFO: - return "INFO"; - case WARNING: - return "WARNING"; - case ERROR: - return "ERROR"; - case CRITICAL: - return "CRITICAL"; - default: - return "UNKNOWN"; - } -} - -int Logger::level_to_int(LogLevel level) -{ - switch (level) { - case DEBUG: - return 5; - case INFO: - return 4; - case WARNING: - return 3; - case ERROR: - return 2; - default: - return 1; - } -} diff --git a/src/response.cc b/src/response.cc new file mode 100644 index 0000000..3d6e439 --- /dev/null +++ b/src/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", "STALLED"}; + return os << nameR[r]; +} diff --git a/src/storage.cc b/src/storage.cc new file mode 100644 index 0000000..fed607b --- /dev/null +++ b/src/storage.cc @@ -0,0 +1,16 @@ +#include "storage.h" +#include "definitions.h" +#include + +std::vector> +Storage::view(int base, int lines) const +{ + base = (base / LINE_SIZE) * LINE_SIZE; + std::vector> ret(lines + 1); + std::copy( + this->data->begin() + base, this->data->begin() + base + lines, + ret.begin()); + return ret; +} + +Storage *Storage::get_lower() { return this->lower; } diff --git a/src/storage/cache.cc b/src/storage/cache.cc deleted file mode 100644 index 80f59ef..0000000 --- a/src/storage/cache.cc +++ /dev/null @@ -1,180 +0,0 @@ -#include "cache.h" -#include "definitions.h" -#include "response.h" -#include "utils.h" -#include -#include -#include - -Cache::Cache(Storage *lower, int delay) -{ - this->data = new std::vector>; - this->data->resize(L1_CACHE_LINES); - this->delay = delay; - this->is_waiting = false; - this->lower = lower; - this->meta.fill({-1, -1}); - this->requester = IDLE; - this->wait_time = this->delay; -} - -Cache::~Cache() -{ - delete this->lower; - delete this->data; -} - -Response Cache::write_word(Accessor accessor, signed int data, int address) -{ - return process(accessor, address, [&](int index, int offset) { - this->data->at(index).at(offset) = data; - this->meta[index].at(1) = 1; - }); -} - -Response Cache::write_line( - Accessor accessor, std::array data_line, int address) -{ - return process(accessor, address, [&](int index, int offset) { - (void)offset; - this->data->at(index) = data_line; - this->meta[index].at(1) = 1; - }); -} - -// TODO: tests for multi level cache -Response Cache::read_line( - Accessor accessor, - int address, - std::array &data_line) -{ - return process(accessor, address, [&](int index, int offset) { - (void)offset; - data_line = this->data->at(index); - }); -} - -Response Cache::read_word(Accessor accessor, int address, signed int &data) -{ - return process(accessor, address, [&](int index, int offset) { - data = this->data->at(index).at(offset); - }); -} - -Response Cache::process( - Accessor accessor, - int address, - std::function request_handler) -{ - Response r = this->is_access_cleared(accessor, address); - if (r == OK) { - int tag, index, offset; - get_cache_fields(address, &tag, &index, &offset); - request_handler(index, offset); - } - return r; -} - -Response Cache::is_access_cleared(Accessor accessor, int address) -{ - Response r; - r = WAIT; - /* Do this first--then process the first cycle immediately. */ - if (this->requester == IDLE) - this->requester = accessor; - if (this->requester == accessor) { - handle_miss(address); - if (this->is_waiting) - r = BLOCKED; - else if (this->wait_time == 0) { - this->requester = IDLE; - this->wait_time = delay; - r = OK; - } else { - --this->wait_time; - } - } - return r; -} - -void Cache::handle_miss(int expected) -{ - Response r, q; - int tag, index, offset; - std::array *actual; - std::array *meta; - - get_cache_fields(expected, &tag, &index, &offset); - r = OK; - meta = &this->meta.at(index); - actual = &this->data->at(index); - - if (meta->at(0) != tag) { - r = WAIT; - // address not in cache - if (meta->at(1) >= 0) { - // occupant is dirty - // writing line to DRam in case of dirty cache eviction - q = this->lower->write_line( - L1CACHE, *actual, - ((index << LINE_SPEC) + - (meta->at(0) << (L1_CACHE_LINE_SPEC + LINE_SPEC)))); - if (q == OK) { - meta->at(1) = -1; - } - } else { - q = this->lower->read_line(L1CACHE, expected, *actual); - if (q == OK) { - meta->at(0) = tag; - } - } - } - - this->is_waiting = (r == OK) ? false : true; -} - -std::array, L1_CACHE_LINES> Cache::get_meta() const -{ - std::array, L1_CACHE_LINES> 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_LINES); - std::array, L1_CACHE_LINES> meta = c.get_meta(); - - os << " " << std::setfill(' ') << std::setw(L1_CACHE_LINE_SPEC + 2) - << "INDEX" - << " | " << std::setfill(' ') << std::setw((8 + 3) * 4 - 1) << "DATA" - << " | " << std::setfill(' ') - << std::setw(MEM_LINE_SPEC - L1_CACHE_LINE_SPEC + 2) << "TAG" - << " | D" << std::endl; - for (int i = 0; i < L1_CACHE_LINES; ++i) { - os << " 0b" << std::setw(L1_CACHE_LINE_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 << "| 0b" << std::setfill(' '); - - if (meta.at(i)[0] < 0) - os << std::setfill('?') - << std::setw(MEM_LINE_SPEC - L1_CACHE_LINE_SPEC) << ""; - else - os << std::bitset( - meta.at(i)[0]); - - os << " | " << (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 deleted file mode 100644 index f90f8db..0000000 --- a/src/storage/dram.cc +++ /dev/null @@ -1,130 +0,0 @@ -#include "dram.h" -#include "definitions.h" -#include "response.h" -#include -#include -#include -#include -#include -#include - -Dram::Dram(int delay) -{ - this->data = new std::vector>; - this->data->resize(MEM_LINES); - this->delay = delay; - this->is_waiting = false; - this->lower = nullptr; - this->requester = IDLE; - this->wait_time = this->delay; -} - -Dram::~Dram() { delete this->data; } - -Response Dram::write_line( - Accessor accessor, std::array data_line, int address) -{ - return process(accessor, address, [&](int line, int word) { - (void)word; - this->data->at(line) = data_line; - }); -} - -Response Dram::write_word(Accessor accessor, signed int data, int address) -{ - return process(accessor, address, [&](int line, int word) { - this->data->at(line).at(word) = data; - }); -} - -// TODO requires testing -Response Dram::read_line( - Accessor accessor, - int address, - std::array &data_line) -{ - return process(accessor, address, [&](int line, int word) { - (void)word; - data_line = this->data->at(line); - }); -} - -Response Dram::read_word(Accessor accessor, int address, signed int &data) -{ - return process(accessor, address, [&](int line, int word) { - data = this->data->at(line).at(word); - }); -} - -// TODO load a file instead and test this method -void Dram::load(std::vector program) { - unsigned long i; - for (i = 0; i < program.size(); ++i) { - int line, word; - get_memory_index(i, line, word); - this->data->at(line).at(word) = program[i]; - } -} - -Response Dram::process( - Accessor accessor, - int address, - std::function request_handler) -{ - Response r = this->is_access_cleared(accessor); - if (r == OK) { - int line, word; - get_memory_index(address, line, word); - request_handler(line, word); - } - return r; -} - -Response Dram::is_access_cleared(Accessor accessor) -{ - Response r; - r = WAIT; - /* Do this first--then process the first cycle immediately. */ - if (accessor == SIDE) - r = OK; - else { - if (this->requester == IDLE) - this->requester = accessor; - if (this->requester == accessor) { - if (this->wait_time == 0) { - this->requester = IDLE; - this->wait_time = delay; - r = OK; - } else { - --this->wait_time; - } - } - } - 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_LINES); - - os << " " << std::setfill(' ') << std::setw(MEM_LINE_SPEC + 2 + LINE_SPEC) - << "ADDRESS" - << " | " << std::setfill(' ') << std::setw((8 + 3) * 4 - 1) << "DATA" - << std::endl; - for (int i = 0; i < MEM_LINES; ++i) { - os << " 0b" << std::setw(MEM_LINE_SPEC + LINE_SPEC) << left - << 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 << 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 deleted file mode 100644 index fed607b..0000000 --- a/src/storage/storage.cc +++ /dev/null @@ -1,16 +0,0 @@ -#include "storage.h" -#include "definitions.h" -#include - -std::vector> -Storage::view(int base, int lines) const -{ - base = (base / LINE_SIZE) * LINE_SIZE; - std::vector> ret(lines + 1); - std::copy( - this->data->begin() + base, this->data->begin() + base + lines, - ret.begin()); - return ret; -} - -Storage *Storage::get_lower() { return this->lower; } diff --git a/src/utils.cc b/src/utils.cc new file mode 100644 index 0000000..e12a0e0 --- /dev/null +++ b/src/utils.cc @@ -0,0 +1,42 @@ +#include "utils.h" +#include "definitions.h" +#include +#include +#include + +void get_cache_fields(int address, int *tag, int *index, int *offset) +{ + *tag = GET_MID_BITS(address, L1_CACHE_LINE_SPEC + LINE_SPEC, MEM_WORD_SPEC); + *index = GET_MID_BITS(address, LINE_SPEC, L1_CACHE_LINE_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); +} + +int wrap_address(int address) +{ + if (address < 0) { + return ((address % MEM_WORDS) + MEM_WORDS) % MEM_WORDS; + } + return address % MEM_WORDS; +} + +void get_memory_index(int address, int &line, int &word) +{ + line = wrap_address(address) / LINE_SIZE; + word = address % LINE_SIZE; +} diff --git a/src/utils/accessor.cc b/src/utils/accessor.cc deleted file mode 100644 index 99347ed..0000000 --- a/src/utils/accessor.cc +++ /dev/null @@ -1,10 +0,0 @@ -#include "accessor.h" -#include - -std::ostream &operator<<(std::ostream &os, Accessor a) -{ - const std::string nameA[] = { - "IDLE", "WRITE", "MEM", "EXEC", "DCDE", "FETCH", "L1CACHE", "SIDE", - }; - return os << nameA[a]; -} diff --git a/src/utils/response.cc b/src/utils/response.cc deleted file mode 100644 index 3d6e439..0000000 --- a/src/utils/response.cc +++ /dev/null @@ -1,8 +0,0 @@ -#include "response.h" -#include - -std::ostream &operator<<(std::ostream &os, Response r) -{ - const std::string nameR[] = {"OK", "WAIT", "BLOCKED", "STALLED"}; - return os << nameR[r]; -} diff --git a/src/utils/utils.cc b/src/utils/utils.cc deleted file mode 100644 index e12a0e0..0000000 --- a/src/utils/utils.cc +++ /dev/null @@ -1,42 +0,0 @@ -#include "utils.h" -#include "definitions.h" -#include -#include -#include - -void get_cache_fields(int address, int *tag, int *index, int *offset) -{ - *tag = GET_MID_BITS(address, L1_CACHE_LINE_SPEC + LINE_SPEC, MEM_WORD_SPEC); - *index = GET_MID_BITS(address, LINE_SPEC, L1_CACHE_LINE_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); -} - -int wrap_address(int address) -{ - if (address < 0) { - return ((address % MEM_WORDS) + MEM_WORDS) % MEM_WORDS; - } - return address % MEM_WORDS; -} - -void get_memory_index(int address, int &line, int &word) -{ - line = wrap_address(address) / LINE_SIZE; - word = address % LINE_SIZE; -} -- cgit v1.2.3