From 84d31414bcf7401d3be09eed54daf2c75f16cea4 Mon Sep 17 00:00:00 2001 From: Saurabh Singh Date: Sat, 14 Oct 2023 16:34:49 -0400 Subject: [PATCH] sim: Update memory-map for atombones - atomsim: - util: add function to resolve environment variables in file path - memory: add initializtion functions using bin, hex - update memory map for atomsim - use hex to initialize bootrom at start --- sim/Makefile | 4 ++++ sim/backend_atombones.cpp | 38 +++++++++++++------------------ sim/backend_atombones.hpp | 11 +++++---- sim/main.cpp | 5 +++-- sim/memory.cpp | 47 +++++++++++++++++++++++++++++++++++++++ sim/memory.hpp | 29 +++++++++++++++++++++++- sim/util.cpp | 36 +++++++++++++++++++++++++----- sim/util.hpp | 9 ++++++++ 8 files changed, 144 insertions(+), 35 deletions(-) diff --git a/sim/Makefile b/sim/Makefile index 31f2cc8d..ecb6d678 100755 --- a/sim/Makefile +++ b/sim/Makefile @@ -67,6 +67,10 @@ LDLIBS := -L include/CppLinuxSerial/ INCLUDES := -I . -I include/ INCLUDES += -I $(VERILATED_DIR) -I $(VERILATOR_INCLUDE_PATH) -I $(VERILATOR_INCLUDE_PATH)/vltstd +ifeq ($(DEBUG), 1) +CFLAGS += -g -O0 +endif + EXE := $(BIN_DIR)/atomsim SRCS := main.cpp atomsim.cpp simstate.cpp vuart.cpp interactive.cpp SRCS += memory.cpp util.cpp diff --git a/sim/backend_atombones.cpp b/sim/backend_atombones.cpp index 01644382..142bbde0 100755 --- a/sim/backend_atombones.cpp +++ b/sim/backend_atombones.cpp @@ -6,7 +6,7 @@ #include "memory.hpp" #include "vuart.hpp" #include "except.hpp" -// #include "util.hpp" +#include "util.hpp" #include "build/verilated/VAtomBones_headers.h" @@ -28,8 +28,8 @@ Backend_atomsim::Backend_atomsim(Atomsim * sim, Backend_config config): // Constuct Memory objects try { - mem_["imem"] = std::shared_ptr (new Memory(config_.imem_size_kb * 1024, config_.imem_offset, true)); - mem_["dmem"] = std::shared_ptr (new Memory(config_.dmem_size_kb * 1024, config_.dmem_offset, false)); + mem_["bootrom"] = std::shared_ptr (new Memory(config_.bootrom_size_kb * 1024, config_.bootrom_offset, true)); + mem_["ram"] = std::shared_ptr (new Memory(config_.ram_size_kb * 1024, config_.ram_offset, false)); } catch(const std::exception& e) { @@ -39,23 +39,17 @@ Backend_atomsim::Backend_atomsim(Atomsim * sim, Backend_config config): // ====== Initialize ======== // Initialize memory - // load text section - try - { - if(sim_->sim_config_.verbose_flag) - std::cout << "Initializing imem:" << std::endl; - mem_["imem"]->set_write_protect(false); - init_from_elf(mem_["imem"].get(), sim_->sim_config_.ifile, std::vector{5, 6}); - mem_["imem"]->set_write_protect(true); - - if(sim_->sim_config_.verbose_flag) - std::cout << "Initializing dmem:" << std::endl; - init_from_elf(mem_["dmem"].get(), sim_->sim_config_.ifile, std::vector{5, 6}); - } - catch(const std::exception& e) - { - std::cerr << e.what() << '\n'; - } + + if(sim_->sim_config_.verbose_flag) + std::cout << "Initializing bootrom" << std::endl; + + mem_["bootrom"]->set_write_protect(false); + init_from_imgfile(mem_["bootrom"].get(), resolve_envvar_in_path(config_.bootrom_img)); + mem_["bootrom"]->set_write_protect(true); + + if(sim_->sim_config_.verbose_flag) + std::cout << "Initializing ram:" << std::endl; + init_from_elf(mem_["ram"].get(), sim_->sim_config_.ifile, std::vector{5, 6}); // Initialize CPU state by resetting @@ -109,7 +103,7 @@ void Backend_atomsim::service_mem_req() if(tb->m_core->iport_valid_o == 1) { Word_alias i_w; - mem_["imem"]->fetch(iaddr, i_w.byte, 4); + this->fetch(iaddr, i_w.byte, 4); tb->m_core->iport_data_i = i_w.word; tb->m_core->iport_ack_i = 1; } @@ -359,7 +353,7 @@ int Backend_atomsim::tick() for(uint32_t addr=begin_signature_at; addrfetch(addr, w.byte, 4); + this->fetch(addr, w.byte, 4); char temp [50]; sprintf(temp, "%08x", w.word); diff --git a/sim/backend_atombones.hpp b/sim/backend_atombones.hpp index 09550c5f..880ab334 100755 --- a/sim/backend_atombones.hpp +++ b/sim/backend_atombones.hpp @@ -8,16 +8,19 @@ #define ATOMSIM_TARGETNAME "atombones" #define TARGET_ATOMBONES +#define DEFAULT_BOOTROM_IMAGE "${RVATOM}/sw/bootloader/bootloader.hex" + class Memory; class Vuart; struct Backend_config { - uint32_t imem_offset = 0x00010000; - uint32_t imem_size_kb = (64*1024); // default: 64 MB + uint32_t bootrom_offset = 0x00010000; + uint32_t bootrom_size_kb = 8; // default: 8 KB + std::string bootrom_img = DEFAULT_BOOTROM_IMAGE; - uint32_t dmem_offset = 0x20000000; - uint32_t dmem_size_kb = (64*1024); // default: 64 MB + uint32_t ram_offset = 0x20000000; + uint32_t ram_size_kb = (80*1024); // default: 80 MB std::string vuart_portname = ""; uint32_t vuart_baudrate = 115200; diff --git a/sim/main.cpp b/sim/main.cpp index 475a9cc9..7a03192a 100755 --- a/sim/main.cpp +++ b/sim/main.cpp @@ -86,8 +86,9 @@ void parse_commandline_args(int argc, char**argv, Atomsim_config &sim_config, Ba ("u,enable-uart-dump", "Enable dumping UART data (from soc) to stdout", cxxopts::value(backend_config.enable_uart_dump)->default_value(default_backend_config.enable_uart_dump?"true":"false")) #ifdef TARGET_ATOMBONES - ("imemsize", "Specify size of instruction memory to simulate (in KB)", cxxopts::value(backend_config.imem_size_kb)->default_value(std::to_string(default_backend_config.imem_size_kb))) - ("dmemsize", "Specify size of data memory to simulate (in KB)", cxxopts::value(backend_config.dmem_size_kb)->default_value(std::to_string(default_backend_config.dmem_size_kb))) + ("bootrom-size", "Specify size of bootrom to simulate (in KB)", cxxopts::value(backend_config.bootrom_size_kb)->default_value(std::to_string(default_backend_config.bootrom_size_kb))) + ("bootrom-image", "Specify bootrom hex image", cxxopts::value(backend_config.bootrom_img)->default_value(default_backend_config.bootrom_img)) + ("ram-size", "Specify size of RAM memory to simulate (in KB)", cxxopts::value(backend_config.ram_size_kb)->default_value(std::to_string(default_backend_config.ram_size_kb))) #endif ; diff --git a/sim/memory.cpp b/sim/memory.cpp index 8a469823..815300ae 100755 --- a/sim/memory.cpp +++ b/sim/memory.cpp @@ -146,4 +146,51 @@ unsigned init_from_elf(Memory * m, std::string filepath, std::vector flag_s i++; } return (unsigned int) reader.get_entry(); +} + + +void init_from_bin(Memory * m, std::string filepath) { + if(!m) { + throw Atomsim_exception("Can't initialize memory; mem pointer == null"); + } + + std::vector fcontents = fReadBin(filepath); + + printf("Loading %ld bytes at 0x%08x from %s\n", fcontents.size(), m->get_base_addr(), filepath.c_str()); + m->store(m->get_base_addr(), (uint8_t*)fcontents.data(), fcontents.size()); +} + + +void init_from_hex(Memory * m, std::string filepath) { + if(!m) { + throw Atomsim_exception("Can't initialize memory; mem pointer == null"); + } + + std::vector fcontents = fRead(filepath); + uint32_t addr = m->get_base_addr(); + + printf("Loading %ld bytes at 0x%08x from %s\n", fcontents.size(), addr, filepath.c_str()); + + // parse + for(unsigned l=0; lstore(addr, wa.byte, 4); + addr += 4; + } +} + + +void init_from_imgfile(Memory * m, std::string filepath) { + std::string ext = filepath.substr(filepath.length()-4, 4); + if(ext == ".hex") + init_from_hex(m, filepath); + else if (ext == ".bin") + init_from_bin(m, filepath); + else + throw Atomsim_exception("invalid image-file format: "+filepath); } \ No newline at end of file diff --git a/sim/memory.hpp b/sim/memory.hpp index 79f50f52..164133cf 100755 --- a/sim/memory.hpp +++ b/sim/memory.hpp @@ -150,4 +150,31 @@ class Memory * @param flag_signatures section signatures to load * @return unsigned entry point */ -unsigned init_from_elf(Memory * m, std::string filepath, std::vector flag_signatures); \ No newline at end of file +unsigned init_from_elf(Memory * m, std::string filepath, std::vector flag_signatures); + + +/** + * @brief Initialize a memory from an bin file + * + * @param m memory ptr + * @param filepath elf file path + */ +void init_from_bin(Memory * m, std::string filepath); + + +/** + * @brief Initialize a memory from an hex file + * + * @param m memory ptr + * @param filepath elf file path + */ +void init_from_hex(Memory * m, std::string filepath); + + +/** + * @brief Initialize a memory from bin/hex file + * + * @param m memory ptr + * @param filepath bin/hex filepath + */ +void init_from_imgfile(Memory * m, std::string filepath); \ No newline at end of file diff --git a/sim/util.cpp b/sim/util.cpp index 8268cc43..53e603b7 100755 --- a/sim/util.cpp +++ b/sim/util.cpp @@ -3,6 +3,8 @@ #include #include #include +#include +#include "except.hpp" // declared in main.cpp extern bool NO_COLOR_OUTPUT; @@ -80,15 +82,37 @@ size_t tokenize(const std::string &txt, std::vector &strs, char ch) return strs.size(); } +std::string resolve_envvar_in_path(std::string path) { + std::string resolvedpath = path; + size_t startpos = resolvedpath.find("${"); -std::vector fReadBin(std::string memfile) + while(startpos != std::string::npos) { + size_t endpos = resolvedpath.find("}", startpos); + if (endpos == std::string::npos) { + throw Atomsim_exception("Malformed Path, can't resolve environment vars"); + } + + std::string var = resolvedpath.substr(startpos+2, endpos-startpos-2); + const char * varval = getenv(var.c_str()); + + if (varval == nullptr) { + throw Atomsim_exception("Can't resolve envvar: " + var); + } + + resolvedpath.replace(startpos, endpos-startpos+1, varval); + startpos = resolvedpath.find("${", startpos + 1); + } + return resolvedpath; +} + +std::vector fReadBin(std::string filepath) { std::vector fcontents; - std::ifstream f (memfile, std::ios::out | std::ios::binary); + std::ifstream f (filepath, std::ios::out | std::ios::binary); if(!f) { - throw "file access failed"; + throw Atomsim_exception("file access failed: "+filepath); } try { @@ -101,7 +125,7 @@ std::vector fReadBin(std::string memfile) } catch(...) { - throw "file reading failed!"; + throw Atomsim_exception("file reading failed: "+filepath); } f.close(); return fcontents; @@ -116,7 +140,7 @@ std::vector fRead (std::string filepath) // input file stream std::ifstream fin(filepath.c_str()); if(!fin){ - throw "file access failed"; + throw Atomsim_exception("file access failed: "+filepath); } // reading file line by line and appending into the vector of strings @@ -137,7 +161,7 @@ void fWrite (std::vector data, std::string filepath) std::ofstream File(filepath); if(!File) { - throw "file writing failed"; + throw Atomsim_exception("file writing failed: " + filepath); } for(unsigned int i=0; i &strs, char ch) ////////////////////////////////////////////////////////////////////////////// // File I/O +/** + * @brief Resolves environment variable in path specified using ${VAR} syntax + * + * @param path input path + * @return std::string resolved oath + */ +std::string resolve_envvar_in_path(std::string path); + + /** * @brief reads a binary file *