59 #include <unordered_map>
61 #include "elfio/elfio.hpp"
64 #define ARMv6M_DEBUG_PRINT 0
65 #define MAX_MEMSEGS 99
67 using namespace etiss;
68 using namespace ELFIO;
75 std::cout << message <<
" (" << (count + 1) <<
"x)" << std::endl;
81 : name_(name), start_addr_(start_addr), end_addr_(start_addr + size - 1), size_(size), mode_(
mode)
92 memInit(initString, randomRoot);
96 std::stringstream memMsg;
97 memMsg <<
"The memory segment is allocated uninitialized with length 0x" << std::hex <<
size_ <<
" !";
105 std::stringstream memMsg;
107 if (initString.find(
"0x") == 0)
109 memMsg <<
"The memory segment is initialized with 0x" << std::hex <<
size_ <<
" elements with hex value: " << initString;
113 initString.erase(initString.begin(),initString.begin()+2);
119 if (j != (initString.length() - 1))
121 dataPtr = initString.substr(j, 2).c_str();
125 dataPtr = initString.substr(j, 1).c_str();
128 j = (j + 2 <= initString.length() - 1) ? j + 2 : 0;
135 catch (std::invalid_argument
const&
exp)
137 memMsg <<
"\n Hex Value MemSegment input is erronous (typo?) at " <<
exp.what();
143 else if (initString.find(
"random") == 0 || initString.find(
"RANDOM") == 0)
145 memMsg <<
"The memory segment is initialized with 0x" << std::hex <<
size_ <<
" random bytes and root: " << randomRoot;
148 static std::default_random_engine generator{randomRoot};
149 std::uniform_int_distribution<int> random_char_{ 0, 255 };
152 mem_[i] = random_char_(generator);
159 memMsg <<
"The memory segment is initialized with 0x" << std::hex <<
size_ <<
" elements with the string: " << initString;
162 const char* data = initString.c_str();
165 mem_[i] = data[i%strlen(data)];
172 if (data !=
nullptr && (offset + file_size_bytes) <=
size_)
187 return (((addr + payload_size - 1) <=
end_addr_) ?
true :
false);
195 std::sort(
msegs_.begin(),
msegs_.end(), [](std::unique_ptr<MemSegment> & a, std::unique_ptr<MemSegment> &
b) {return a->start_addr_ < b->start_addr_;});
199 std::stringstream ss;
202 ss <<
"simple_mem_system.memseg_origin_" << std::setw(2) << std::setfill(
'0') << i;
204 std::stringstream().swap(ss);
206 ss <<
"simple_mem_system.memseg_length_" << std::setw(2) << std::setfill(
'0') << i;
211 std::stringstream().swap(ss);
213 ss <<
"simple_mem_system.memseg_initelement_" << std::setw(2) << std::setfill(
'0') << i;
214 std::string initString =
etiss::cfg().
get<std::string>(ss.str(),
"");
216 std::stringstream().swap(ss);
218 ss <<
"simple_mem_system.memseg_initelement_random_root_" << std::setw(2) << std::setfill(
'0') << i;
220 std::stringstream().swap(ss);
222 ss <<
"simple_mem_system.memseg_image_" << std::setw(2) << std::setfill(
'0') << i;
223 std::string image =
etiss::cfg().
get<std::string>(ss.str(),
"");
224 std::stringstream().swap(ss);
226 ss <<
"simple_mem_system.memseg_mode_" << std::setw(2) << std::setfill(
'0') << i;
228 std::stringstream().swap(ss);
234 std::string modestr =
"";
248 std::stringstream sname;
249 sname << i + 1 <<
" - " << modestr
250 <<
"[0x" << std::hex << std::setfill(
'0') << std::setw(
sizeof(
etiss::uint64) * 2) << origin +
length - 1 <<
" - "
251 <<
"0x" << std::hex << std::setfill(
'0') << std::setw(
sizeof(
etiss::uint64) * 2) << origin <<
"]";
258 std::ifstream ifs(image, std::ifstream::binary | std::ifstream::ate);
260 std::stringstream msg;
261 msg <<
"Error during read of segment image file " << image <<
"!";
265 ifs.seekg(0, std::ifstream::beg);
269 ifs.read((
char*)buf, fsize);
271 std::stringstream mem_msg;
272 mem_msg <<
"The memory segment " << i <<
" is initialized with 0x" << std::hex <<
length <<
" bytes from input_image !";
277 buf, initString, initEleSet, randomRoot);
286 if (!
etiss::cfg().isSet(
"vp.elf_file"))
return;
288 std::string elf_file =
etiss::cfg().
get<std::string>(
"vp.elf_file",
"");
292 if (!
reader.load(elf_file))
298 std::stringstream ss;
299 ss <<
"Assuming CPU architecture " <<
etiss::cfg().
get<std::string>(
"arch.cpu",
"") <<
" as set in configuration file. ELF architecture field will be ignored";
303 if (
reader.get_machine() == EM_RISCV)
305 if ((
reader.get_class() == ELFCLASS64)) {
307 }
else if ((
reader.get_class() == ELFCLASS32)) {
316 std::stringstream ss;
317 ss <<
"Target architecture with code 0x" << std::hex << std::setw(2) << std::setfill(
'0') <<
reader.get_machine() <<
" was not automatically recognized, please set the arch.cpu parameter manually!";
320 std::stringstream ss;
321 ss <<
"Set ETISS architecture to " <<
etiss::cfg().
get<std::string>(
"arch.cpu",
"") <<
" as specified in ELF-file.";
325 for (
auto &seg :
reader.segments)
329 if (size == 0)
continue;
330 size_t file_size = seg->get_file_size();
331 if (seg->get_type() != PT_LOAD)
continue;
334 std::string modestr =
"";
335 if (seg->get_flags() & PF_R) {
339 if (seg->get_flags() & PF_W) {
343 if (seg->get_flags() & PF_X) {
348 std::stringstream sname;
349 sname << seg->get_index() <<
" - " << modestr
350 <<
"[0x" << std::hex << std::setfill(
'0') << std::setw(
sizeof(
etiss::uint64) * 2) << start_addr <<
" - "
351 <<
"0x" << std::hex << std::setfill(
'0') << std::setw(
sizeof(
etiss::uint64) * 2) << start_addr + size - 1 <<
"]";
355 if (mseg_it !=
msegs_.end()) {
356 auto & mseg = *mseg_it;
358 mseg->name_ = sname.str();
361 mseg->load(seg->get_data(), start_addr - mseg->start_addr_, file_size);
363 std::stringstream msg;
364 msg <<
"Initialized the memory segment " << mseg->name_ <<
" from ELF-file";
370 std::stringstream msg;
371 msg <<
"Found no matching memory segments at 0x" << std::hex << std::setfill(
'0') << std::setw(8) << start_addr;
374 msg <<
"! As you turned on error_on_seg_mismatch, ETISS will now terminate.";
377 msg <<
", creating one. WARNING: the segment will be created with the size information present in the ELF-file, the resulting segment may be too small to fit dynamic data (cache, heap)!";
391 std::stringstream msg;
392 msg <<
"New Memory segment added: " << mseg->name_;
395 mseg->load(raw_data, 0, file_size_bytes);
397 msegs_.push_back(std::move(mseg));
401 print_ibus_access_(
etiss::
cfg().get<
bool>(
"simple_mem_system.print_ibus_access",
false)),
402 print_dbus_access_(
etiss::
cfg().get<
bool>(
"simple_mem_system.print_dbus_access",
false)),
403 print_dbgbus_access_(
etiss::
cfg().get<
bool>(
"simple_mem_system.print_dbgbus_access",
false)),
404 print_to_file_(
etiss::
cfg().get<
bool>(
"simple_mem_system.print_to_file",
false)),
405 error_on_seg_mismatch_(
etiss::
cfg().get<
bool>(
"simple_mem_system.error_on_seg_mismatch",
false)),
406 message_max_cnt_(
etiss::
cfg().get<
int>(
"simple_mem_system.message_max_cnt", 100))
417 std::stringstream ss;
419 ss << error <<
", PC = 0x" << std::hex << std::setw(8) << std::setfill(
'0') <<
pc
420 <<
", address 0x" << std::hex << std::setw(8) << std::setfill(
'0') << addr <<
", length " << len;
431 return RETURNCODE::IBUS_READ_ERROR;
437 return RETURNCODE::IBUS_WRITE_ERROR;
451 std::stringstream text;
453 << std::setw(8) << std::setfill(
'0') << std::hex
455 << (isWrite ?
"w" :
"r") <<
";"
462 std::cout << text.str();
465 template <
bool write>
469 if (mseg_it !=
msegs_.end()) {
470 auto & mseg = *mseg_it;
473 if (!(mseg->mode_ & access)) {
477 size_t offset = addr - mseg->start_addr_;
479 void * dest = write ? mseg->mem_ + offset : buf;
480 const void * src = write ? buf : mseg->mem_ + offset;
491 return write ? RETURNCODE::DBUS_WRITE_ERROR : RETURNCODE::DBUS_READ_ERROR;
496 return dbus_access<false>(cpu, addr, buf, len);
501 return dbus_access<true>(cpu, addr, buf, len);
506 return dread(
nullptr, addr, buf, len);
511 return dwrite(
nullptr, addr, buf, len);
contains neccesary interfaces for instruction translation.
general configuration and logging
void access_error(ETISS_CPU *cpu, etiss::uint64 addr, etiss::uint32 len, std::string error, etiss::Verbosity verbosity)
std::unordered_map< std::string, uint32_t > map_messageCounter
void global_sync_time(uint64 time_ps)
uint32_t printMessage(std::string key, std::string message, uint32_t maxCount)
static void trace(ETISS_CPU *cpu, etiss::uint64 addr, etiss::uint32 len, bool isWrite, bool toFile, std::ofstream &file)
simple test system implementation
__DEVICE__ void * memcpy(void *__a, const void *__b, size_t __c)
static __inline__ uint32_t
static __inline__ uint64_t
static __inline__ uint8_t
bool isSet(std::string val)
return true if the value of an configuration key has been set
bool set(const std::string &key, T value)
template function to set the value of a configuration key.
T get(const std::string &key, T default_, bool *default_used=0)
template function to read the value of a configuration key.
bool payload_in_range(etiss::uint64 addr, etiss::uint64 payload_size) const
void memInit(std::string initString, uint64_t randomRoot=0)
bool addr_in_range(etiss::uint64 addr) const
const etiss::uint64 start_addr_
const etiss::uint64 end_addr_
void load(const void *data, size_t offset, size_t file_size_bytes)
MemSegment(etiss::uint64 start_addr, etiss::uint64 size, access_t mode, const std::string name, etiss::uint8 *mem=nullptr, std::string initString="", bool InitEleSet=false, uint64_t randomRoot=0)
Constructor of Memory Segment.
const etiss::uint64 size_
etiss::uint64 start_addr_
std::map< etiss::uint64, etiss::uint64 > configured_address_spaces_
etiss::int32 dread(ETISS_CPU *cpu, etiss::uint64 addr, etiss::uint8 *buf, etiss::uint32 len)
Data read operation.
bool error_on_seg_mismatch_
std::vector< std::unique_ptr< MemSegment > > msegs_
etiss::int32 dwrite(ETISS_CPU *cpu, etiss::uint64 addr, etiss::uint8 *buf, etiss::uint32 len)
Data write operation.
etiss::int32 dbus_access(ETISS_CPU *cpu, etiss::uint64 addr, etiss::uint8 *buf, etiss::uint32 len)
void add_memsegment(std::unique_ptr< MemSegment > &mseg, const void *raw_data, size_t file_size_bytes)
etiss::int32 dbg_write(etiss::uint64 addr, etiss::uint8 *buf, etiss::uint32 len)
Debug write operation.
etiss::int32 dbg_read(etiss::uint64 addr, etiss::uint8 *buf, etiss::uint32 len)
Debug read operation.
etiss::int32 iread(ETISS_CPU *cpu, etiss::uint64 addr, etiss::uint32 len)
Instruction read operation.
etiss::int32 iwrite(ETISS_CPU *cpu, etiss::uint64 addr, etiss::uint8 *buf, etiss::uint32 len)
Instruction write operation.
std::ofstream trace_file_dbus_
void syncTime(ETISS_CPU *cpu)
Synchronize simulation time.
MM_EXPORT const int32_t NOERROR
Page Table Entry (PTE) defines the composition of Page Frame Number (PFN) and relavant flags.
Verbosity
Enumeration type for the log levels.
Configuration & cfg(const std::string &cfgName)
Get reference of the global ETISS configuration object.
Verbosity & verbosity()
Get log level reference.
void log(Verbosity level, std::string msg)
write log message at the given level.
float __ovld __cnfn length(float p)
Return the length of vector p, i.e., sqrt(p.x2 + p.y 2 + ...)
void sort(I begin, I end, const Pred &pred)
basic cpu state structure needed for execution of any cpu architecture.
etiss_uint64 instructionPointer
pointer to next instruction.
etiss_uint64 cpuTime_ps
simulation time of cpu