diff --git a/include/etiss/SimpleMemSystem.h b/include/etiss/SimpleMemSystem.h index 099b4061aa..d066acfce7 100644 --- a/include/etiss/SimpleMemSystem.h +++ b/include/etiss/SimpleMemSystem.h @@ -53,6 +53,7 @@ #include "etiss/System.h" #include "etiss/make_unique.h" #include +#include #include #include @@ -88,20 +89,20 @@ class MemSegment const etiss::uint64 size_; access_t mode_; + /// @brief Constructor of Memory Segment + /// @param start_addr Start address of segment + /// @param size Size in bytes + /// @param mode Access Mode (R/W/X) + /// @param name Segment name + /// @param mem Pre-allocated Memory (not overwritten with initString) + /// @param initString String for initialization with imple_mem_system.memseg_initelement_ value: hex_string with 0x... / string /random options + /// @param InitEleSet Should self allocated MemSegment be initialized? + /// @param randomRoot If initString==Random use this value as generator root MemSegment(etiss::uint64 start_addr, etiss::uint64 size, access_t mode, const std::string name, - etiss::uint8 *mem = nullptr) - : name_(name), start_addr_(start_addr), end_addr_(start_addr + size - 1), size_(size), mode_(mode) - { - if (mem) - { // use reserved memory - mem_ = mem; - } - else - { - mem_ = new etiss::uint8[size]; - self_allocated_ = true; - } - } + etiss::uint8 *mem = nullptr, std::string initString = "", bool InitEleSet = false, uint64_t randomRoot = 0); + + // Can be overwritten afterwards with load_elf + void memInit(std::string initString, uint64_t randomRoot = 0); virtual ~MemSegment(void) { @@ -109,27 +110,11 @@ class MemSegment delete[] mem_; } - void load(const void *data, size_t offset, size_t file_size_bytes) - { - if (data != nullptr && (offset + file_size_bytes) <= size_) - { - memcpy(mem_ + offset, data, file_size_bytes); - } - } + void load(const void *data, size_t offset, size_t file_size_bytes); - inline bool addr_in_range(etiss::uint64 addr) const - { - return ((addr >= start_addr_ && addr <= end_addr_) ? true : false); - } + inline bool addr_in_range(etiss::uint64 addr) const; - inline bool payload_in_range(etiss::uint64 addr, etiss::uint64 payload_size) const - { - if (addr_in_range(addr)) - { - return (((addr + payload_size - 1) <= end_addr_) ? true : false); - } - return false; - } + inline bool payload_in_range(etiss::uint64 addr, etiss::uint64 payload_size) const; }; /** diff --git a/src/SimpleMemSystem.cpp b/src/SimpleMemSystem.cpp index a917133a7b..bc3ba46f91 100644 --- a/src/SimpleMemSystem.cpp +++ b/src/SimpleMemSystem.cpp @@ -76,6 +76,119 @@ uint32_t printMessage(std::string key, std::string message, uint32_t maxCount) return count; } +MemSegment::MemSegment(etiss::uint64 start_addr, etiss::uint64 size, access_t mode, const std::string name, + etiss::uint8 *mem, std::string initString, bool InitEleSet, uint64_t randomRoot) + : name_(name), start_addr_(start_addr), end_addr_(start_addr + size - 1), size_(size), mode_(mode) +{ + if (mem) + { // use reserved memory + mem_ = mem; + } + else + { + mem_ = new etiss::uint8[size]; + if (InitEleSet) + { + memInit(initString, randomRoot); + } + else + { + std::stringstream memMsg; + memMsg << "The memory segment is allocated uninitialized with length 0x" << std::hex << size_ << " !"; + etiss::log(etiss::INFO, memMsg.str()); + } + self_allocated_ = true; + } +} + +void MemSegment::memInit(std::string initString, uint64_t randomRoot) { + std::stringstream memMsg; + + if (initString.find("0x") == 0) + { + memMsg << "The memory segment is initialized with 0x" << std::hex << size_ << " elements with hex value: " << initString; + etiss::log(etiss::INFO, memMsg.str()); + + // actual conversion from hex string to corresponding hex val + initString.erase(initString.begin(),initString.begin()+2); + const char* dataPtr; + size_t j{0}; + + for (etiss::uint64 i = 0; i < size_; ++i) + { + if (j != (initString.length() - 1)) + { + dataPtr = initString.substr(j, 2).c_str(); + } + else + { + dataPtr = initString.substr(j, 1).c_str(); + } + + j = (j + 2 <= initString.length() - 1) ? j + 2 : 0; + + try + { + uint8_t hexVal = static_cast(std::stoi(dataPtr, 0 ,16)); + mem_[i] = hexVal; + } + catch (std::invalid_argument const& exp) + { + memMsg << "\n Hex Value MemSegment input is erronous (typo?) at " << exp.what(); + etiss::log(etiss::FATALERROR, memMsg.str()); + } + } + } + + else if (initString.find("random") == 0 || initString.find("RANDOM") == 0) + { + memMsg << "The memory segment is initialized with 0x" << std::hex << size_ << " random bytes and root: " << randomRoot; + etiss::log(etiss::INFO, memMsg.str()); + + static std::default_random_engine generator{randomRoot}; + std::uniform_int_distribution random_char_{ 0, 255 }; + for (etiss::uint64 i = 0; i < size_; ++i) + { + mem_[i] = random_char_(generator); + } + + } + + else + { + memMsg << "The memory segment is initialized with 0x" << std::hex << size_ << " elements with the string: " << initString; + etiss::log(etiss::INFO, memMsg.str()); + + const char* data = initString.c_str(); + for (etiss::uint64 i = 0; i < size_; ++i) + { + mem_[i] = data[i%strlen(data)]; + } + } +} + +void MemSegment::load(const void *data, size_t offset, size_t file_size_bytes) +{ + if (data != nullptr && (offset + file_size_bytes) <= size_) + { + memcpy(mem_ + offset, data, file_size_bytes); + } +} + +inline bool MemSegment::addr_in_range(etiss::uint64 addr) const +{ + return ((addr >= start_addr_ && addr <= end_addr_) ? true : false); +} + +inline bool MemSegment::payload_in_range(etiss::uint64 addr, etiss::uint64 payload_size) const +{ + if (addr_in_range(addr)) + { + return (((addr + payload_size - 1) <= end_addr_) ? true : false); + } + return false; +} + void SimpleMemSystem::init_memory() { load_segments(); load_elf(); @@ -97,6 +210,15 @@ void SimpleMemSystem::load_segments() { } std::stringstream().swap(ss); + ss << "simple_mem_system.memseg_initelement_" << std::setw(2) << std::setfill('0') << i; + std::string initString = etiss::cfg().get(ss.str(), ""); + bool initEleSet = etiss::cfg().isSet(ss.str()); + std::stringstream().swap(ss); + + ss << "simple_mem_system.memseg_initelement_random_root_" << std::setw(2) << std::setfill('0') << i; + uint64_t randomRoot = etiss::cfg().get(ss.str(), 0); + std::stringstream().swap(ss); + ss << "simple_mem_system.memseg_image_" << std::setw(2) << std::setfill('0') << i; std::string image = etiss::cfg().get(ss.str(), ""); std::stringstream().swap(ss); @@ -131,8 +253,8 @@ void SimpleMemSystem::load_segments() { etiss::uint8 *buf = nullptr; size_t fsize = 0; - if (image != "") - { + + if (image != "") { std::ifstream ifs(image, std::ifstream::binary | std::ifstream::ate); if (!ifs) { std::stringstream msg; @@ -145,10 +267,16 @@ void SimpleMemSystem::load_segments() { buf = new etiss::uint8[fsize]; ifs.read((char*)buf, fsize); + + std::stringstream mem_msg; + mem_msg << "The memory segment " << i << " is initialized with 0x" << std::hex << length << " bytes from input_image !"; + etiss::log(etiss::INFO, mem_msg.str()); } - auto mseg = std::make_unique(origin, length, static_cast(access), sname.str(), nullptr); + auto mseg = std::make_unique(origin, length, static_cast(access), sname.str(), + buf, initString, initEleSet, randomRoot); add_memsegment(mseg, buf, fsize); + delete[] buf; } } }