diff --git a/dv/verilator/memutil/cpp/verilator_memutil.cc b/dv/verilator/memutil/cpp/verilator_memutil.cc index 4ea506ec..ebf2d637 100644 --- a/dv/verilator/memutil/cpp/verilator_memutil.cc +++ b/dv/verilator/memutil/cpp/verilator_memutil.cc @@ -31,12 +31,22 @@ extern void simutil_verilator_memload(const char *file); * * @return 1 if successful, 0 otherwise */ -extern int simutil_verilator_set_mem(int index, const svLogicVecVal *val); +extern int simutil_verilator_set_mem(int index, const svBitVecVal *val); } bool VerilatorMemUtil::RegisterMemoryArea(const std::string name, const std::string location) { - MemArea mem = {.name = name, .location = location}; + // Default to 32bit width + return RegisterMemoryArea(name, location, 32); +} + +bool VerilatorMemUtil::RegisterMemoryArea(const std::string name, + const std::string location, + size_t width_bit) { + MemArea mem = {.name = name, .location = location, .width_bit = width_bit}; + + assert((width_bit == 32 || width_bit == 64) && + "TODO: Check if width other than 32 and 64 works as expected."); auto ret = mem_register_.emplace(name, mem); if (ret.second == false) { @@ -130,8 +140,9 @@ bool VerilatorMemUtil::ParseCLIArguments(int argc, char **argv, void VerilatorMemUtil::PrintMemRegions() const { std::cout << "Registered memory regions:" << std::endl; for (const auto &m : mem_register_) { - std::cout << "\t'" << m.second.name << "' at location: '" - << m.second.location << "'" << std::endl; + std::cout << "\t'" << m.second.name << "' (" << m.second.width_bit + << "bits) at location: '" << m.second.location << "'" + << std::endl; } } @@ -386,9 +397,17 @@ bool VerilatorMemUtil::MemWrite(const MemArea &m, const std::string &filepath, return false; } + if ((m.width_bit % 32) != 0) { + std::cerr << "ERROR: width for: " << m.name + << "must be a multiple of 32 (was : " << m.width_bit << ")" + << std::endl; + return false; + } + size_t size_byte = m.width_bit / 8; + switch (type) { case kMemImageElf: - if (!WriteElfToMem(scope, filepath)) { + if (!WriteElfToMem(scope, filepath, size_byte)) { std::cerr << "ERROR: Writing ELF file to memory \"" << m.name << "\" (" << m.location << ") failed." << std::endl; return false; @@ -410,7 +429,8 @@ bool VerilatorMemUtil::MemWrite(const MemArea &m, const std::string &filepath, } bool VerilatorMemUtil::WriteElfToMem(const svScope &scope, - const std::string &filepath) { + const std::string &filepath, + size_t size_byte) { bool retcode; svScope prev_scope = svSetScope(scope); @@ -422,9 +442,9 @@ bool VerilatorMemUtil::WriteElfToMem(const svScope &scope, retcode = false; goto ret; } - for (int i = 0; i < (len_bytes + 3) / 4; ++i) { - if (!simutil_verilator_set_mem(i, (svLogicVecVal *)&buf[4 * i])) { - std::cerr << "ERROR: Could not set memory byte: " << i * 4 << "/" + for (int i = 0; i < (len_bytes + size_byte - 1) / size_byte; ++i) { + if (!simutil_verilator_set_mem(i, (svBitVecVal *)&buf[size_byte * i])) { + std::cerr << "ERROR: Could not set memory byte: " << i * size_byte << "/" << len_bytes << "" << std::endl; retcode = false; diff --git a/dv/verilator/memutil/cpp/verilator_memutil.h b/dv/verilator/memutil/cpp/verilator_memutil.h index edd03ff3..4e6476a9 100644 --- a/dv/verilator/memutil/cpp/verilator_memutil.h +++ b/dv/verilator/memutil/cpp/verilator_memutil.h @@ -21,6 +21,7 @@ enum MemImageType { struct MemArea { std::string name; // Unique identifier std::string location; // Design scope location + size_t width_bit; // Memory width }; /** @@ -41,10 +42,18 @@ class VerilatorMemUtil : public SimCtrlExtension { * instantiated memory, which needs to support the DPI-C interfaces * 'simutil_verilator_memload' and 'simutil_verilator_set_mem' used for * 'vmem' and 'elf' files, respectively. + * The |width_bit| argument specifies the with in bits of the target memory + * instance (used for packing data). * * Memories must be registered before command arguments are parsed by * ParseCommandArgs() in order for them to be known. */ + bool RegisterMemoryArea(const std::string name, const std::string location, + size_t width_bit); + + /** + * Register a memory with default width (32bits) + */ bool RegisterMemoryArea(const std::string name, const std::string location); /** @@ -98,7 +107,8 @@ class VerilatorMemUtil : public SimCtrlExtension { MemImageType type); bool MemWrite(const MemArea &m, const std::string &filepath, MemImageType type); - bool WriteElfToMem(const svScope &scope, const std::string &filepath); + bool WriteElfToMem(const svScope &scope, const std::string &filepath, + size_t size_byte); bool WriteVmemToMem(const svScope &scope, const std::string &filepath); }; diff --git a/shared/rtl/prim_generic_ram_1p.sv b/shared/rtl/prim_generic_ram_1p.sv index 2a33a516..4f0080a1 100644 --- a/shared/rtl/prim_generic_ram_1p.sv +++ b/shared/rtl/prim_generic_ram_1p.sv @@ -71,16 +71,16 @@ module prim_generic_ram_1p #( $readmemh(file, mem); endtask - // TODO: Allow 'val' to have other widths than 32 bit + // Width must be a multiple of 32bit for this function to work // Note that the DPI export and function definition must both be in the same generate // context to get the correct name. - if (Width == 32) begin : gen_32bit - // Function for setting a specific 32 bit element in |mem| + if ((Width % 32) == 0) begin : gen_set_mem + // Function for setting a specific element in |mem| // Returns 1 (true) for success, 0 (false) for errors. export "DPI-C" function simutil_verilator_set_mem; function int simutil_verilator_set_mem(input int index, - input logic[31:0] val); + input bit [Width-1:0] val); if (index >= Depth) begin return 0; end @@ -89,11 +89,11 @@ module prim_generic_ram_1p #( return 1; endfunction end else begin : gen_other - // Function doesn't work for Width != 32 so just return 0 + // Function doesn't work unless Width % 32 so just return 0 export "DPI-C" function simutil_verilator_set_mem; function int simutil_verilator_set_mem(input int index, - input logic[31:0] val); + input bit [Width-1:0] val); return 0; endfunction end