diff options
| author | bd <bdunahu@operationnull.com> | 2025-03-10 14:53:59 -0400 | 
|---|---|---|
| committer | bd <bdunahu@operationnull.com> | 2025-03-10 14:53:59 -0400 | 
| commit | cdcaec3c1e62b47fcd270df651cd0e343e46f0e7 (patch) | |
| tree | fc77cc22024b719f14e03e29e2bbd94b3eb645ca | |
| parent | 1f8b8babcfb383f1fb0281663561161061684206 (diff) | |
Update cli method signatures, add some getters to cache and storage
| -rw-r--r-- | inc/cache.h | 7 | ||||
| -rw-r--r-- | inc/cli.h | 171 | ||||
| -rw-r--r-- | inc/definitions.h | 10 | ||||
| -rw-r--r-- | inc/storage.h | 9 | ||||
| -rw-r--r-- | src/cli/cli.cc | 316 | ||||
| -rw-r--r-- | src/main.cc | 10 | ||||
| -rw-r--r-- | src/storage/cache.cc | 11 | ||||
| -rw-r--r-- | src/storage/storage.cc | 2 | ||||
| -rw-r--r-- | tests/cache.cc | 16 | 
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 @@ -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  } | 
