URL
https://opencores.org/ocsvn/riscv_vhdl/riscv_vhdl/trunk
Subversion Repositories riscv_vhdl
[/] [riscv_vhdl/] [trunk/] [debugger/] [src/] [libdbg64g/] [services/] [mem/] [memsim.cpp] - Rev 4
Compare with Previous | Blame | View Log
/** * @file * @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. * @author Sergey Khabarov - sergeykhbr@gmail.com * @brief ROM functional model implementation. */ #include "api_core.h" #include "memsim.h" #include <iostream> #include <string.h> namespace debugger { /** Class registration in the Core */ REGISTER_CLASS(MemorySim) MemorySim::MemorySim(const char *name) : IService(name) { registerInterface(static_cast<IMemoryOperation *>(this)); registerAttribute("InitFile", &initFile_); registerAttribute("ReadOnly", &readOnly_); registerAttribute("BinaryFile", &binaryFile_); initFile_.make_string(""); readOnly_.make_boolean(false); binaryFile_.make_boolean(false); mem_ = NULL; } MemorySim::~MemorySim() { if (mem_) { delete mem_; } } void MemorySim::postinitService() { // Get global settings: const AttributeType *glb = RISCV_get_global_settings(); if ((*glb)["SimEnable"].to_bool() == false) { return; } mem_ = new uint8_t[static_cast<unsigned>(length_.to_uint64())]; if (initFile_.size() == 0) { return; } std::string filename(initFile_.to_string()); if (strstr(initFile_.to_string(), "..") != NULL || strstr(initFile_.to_string(), "/") == NULL) { char path[1024]; RISCV_get_core_folder(path, sizeof(path)); std::string spath(path); filename = spath + std::string(initFile_.to_string()); } FILE *fp = fopen(initFile_.to_string(), "r"); if (fp == NULL) { for (uint64_t i = 0; i < length_.to_uint64()/4; i++) { // NOP isntruction reinterpret_cast<uint32_t *>(mem_)[i] = 0x00000013; // intialize by NOPs } RISCV_error("Can't open '%s' file", initFile_.to_string()); return; } if (binaryFile_.to_bool()) { fseek(fp, 0, SEEK_END); uint64_t fsz = ftell(fp); if (fsz > length_.to_uint64()) { fsz = length_.to_uint64(); } fseek(fp, 0, SEEK_SET); fread(mem_, 1, static_cast<size_t>(fsz), fp); } else { bool bhalf = false; int rd_symb; uint8_t symb; int linecnt = 0; int symbinline = SYMB_IN_LINE - 1; while (!feof(fp)) { rd_symb = fgetc(fp); if (!chishex(rd_symb)) continue; if (!bhalf) { bhalf = true; symb = chtohex(rd_symb) << 4; continue; } bhalf = false; symb |= chtohex(rd_symb) & 0xf; if ((SYMB_IN_LINE * linecnt + symbinline) >= static_cast<int>(length_.to_uint64())) { RISCV_error("HEX file tries to write out " "of allocated array\n", NULL); break; } mem_[SYMB_IN_LINE * linecnt + symbinline] = symb; if (--symbinline < 0) { linecnt++; symbinline = SYMB_IN_LINE - 1; } } } fclose(fp); } ETransStatus MemorySim::b_transport(Axi4TransactionType *trans) { uint64_t off = (trans->addr - getBaseAddress()) % length_.to_int(); trans->response = MemResp_Valid; if (trans->action == MemAction_Write) { if (readOnly_.to_bool()) { RISCV_error("Write to READ ONLY memory", NULL); trans->response = MemResp_Error; } else { for (uint64_t i = 0; i < trans->xsize; i++) { if (((trans->wstrb >> i) & 0x1) == 0) { continue; } mem_[off + i] = trans->wpayload.b8[i]; } } } else { memcpy(trans->rpayload.b8, &mem_[off], trans->xsize); } const char *rw_str[2] = {"=>", "<="}; uint32_t *pdata[2] = {trans->rpayload.b32, trans->wpayload.b32}; RISCV_debug("[%08" RV_PRI64 "x] %s [%08x %08x]", trans->addr, rw_str[trans->action], pdata[trans->action][1], pdata[trans->action][0]); return TRANS_OK; } bool MemorySim::chishex(int s) { bool ret = false; if (s >= '0' && s <= '9') { ret = true; } else if (s >= 'A' && s <= 'F') { ret = true; } else if (s >= 'a' && s <= 'f') { ret = true; } return ret; } uint8_t MemorySim::chtohex(int s) { if (s >= '0' && s <= '9') { s -= '0'; } else if (s >= 'A' && s <= 'F') { s = s - 'A' + 10; } else if (s >= 'a' && s <= 'f') { s = s - 'a' + 10; } return static_cast<uint8_t>(s); } } // namespace debugger