diff --git a/Makefile b/Makefile index 0164077f2..ca43341aa 100644 --- a/Makefile +++ b/Makefile @@ -54,6 +54,8 @@ build: $(library) build-agents build-interfaces vlog${questa_version} ${compile_flag} -work ${library} -incr ${envs} ${sequences} ${test_pkg} ${list_incdir} -suppress 2583 # Compile source files vlog${questa_version} ${compile_flag} -work ${library} -incr ${src} ${tbs} ${list_incdir} -suppress 2583 + # Compile top level with DPI headers + vlog -sv tb/core_tb.sv tb/dpi/elfdpi.cc -ccflags "-g -std=c++11 " -dpiheader tb/dpi/elfdpi.h # Optimize top level vopt${questa_version} ${compile_flag} -work ${library} ${test_top_level} -o ${test_top_level}_optimized +acc -check_synthesis diff --git a/lib/riscv-fesvr b/lib/riscv-fesvr index 0ac80c22c..14f61ce48 160000 --- a/lib/riscv-fesvr +++ b/lib/riscv-fesvr @@ -1 +1 @@ -Subproject commit 0ac80c22cac54b0f348b051d41fefaffca802d09 +Subproject commit 14f61ce4833126b1327926ad12f7d7bc653702b6 diff --git a/tb/core_tb.sv b/tb/core_tb.sv index a68201871..12a09e23b 100644 --- a/tb/core_tb.sv +++ b/tb/core_tb.sv @@ -9,6 +9,8 @@ import ariane_pkg::*; module core_tb; + import "DPI-C" function chandle read_elf(string fn); + import "DPI-C" function longint unsigned get_symbol_address(string sym); import uvm_pkg::*; import core_lib_pkg::*; @@ -123,9 +125,13 @@ module core_tb; end task preload_memories(); + longint unsigned address; logic [7:0] rmem [0:16384]; - $display("Reading memory"); + void'(read_elf("/home/zarubaf/ariane/sourcecode/test/rv64ui-p-add")); + address = get_symbol_address("tohost"); + $display("tohost: %0h\n", address); + $readmemh("test/rv64ui-p-add.v", rmem); // copy bitwise from verilog file diff --git a/tb/dpi/elf.h b/tb/dpi/elf.h new file mode 100644 index 000000000..b66038d7a --- /dev/null +++ b/tb/dpi/elf.h @@ -0,0 +1,121 @@ +// See LICENSE for details. + +#ifndef _ELF_H +#define _ELF_H + +#include + +#define IS_ELF(hdr) \ + ((hdr).e_ident[0] == 0x7f && (hdr).e_ident[1] == 'E' && \ + (hdr).e_ident[2] == 'L' && (hdr).e_ident[3] == 'F') + +#define IS_ELF32(hdr) (IS_ELF(hdr) && (hdr).e_ident[4] == 1) +#define IS_ELF64(hdr) (IS_ELF(hdr) && (hdr).e_ident[4] == 2) + +#define PT_LOAD 1 + +#define SHT_NOBITS 8 + +typedef struct { + uint8_t e_ident[16]; + uint16_t e_type; + uint16_t e_machine; + uint32_t e_version; + uint32_t e_entry; + uint32_t e_phoff; + uint32_t e_shoff; + uint32_t e_flags; + uint16_t e_ehsize; + uint16_t e_phentsize; + uint16_t e_phnum; + uint16_t e_shentsize; + uint16_t e_shnum; + uint16_t e_shstrndx; +} Elf32_Ehdr; + +typedef struct { + uint32_t sh_name; + uint32_t sh_type; + uint32_t sh_flags; + uint32_t sh_addr; + uint32_t sh_offset; + uint32_t sh_size; + uint32_t sh_link; + uint32_t sh_info; + uint32_t sh_addralign; + uint32_t sh_entsize; +} Elf32_Shdr; + +typedef struct +{ + uint32_t p_type; + uint32_t p_offset; + uint32_t p_vaddr; + uint32_t p_paddr; + uint32_t p_filesz; + uint32_t p_memsz; + uint32_t p_flags; + uint32_t p_align; +} Elf32_Phdr; + +typedef struct +{ + uint32_t st_name; + uint32_t st_value; + uint32_t st_size; + uint8_t st_info; + uint8_t st_other; + uint16_t st_shndx; +} Elf32_Sym; + +typedef struct { + uint8_t e_ident[16]; + uint16_t e_type; + uint16_t e_machine; + uint32_t e_version; + uint64_t e_entry; + uint64_t e_phoff; + uint64_t e_shoff; + uint32_t e_flags; + uint16_t e_ehsize; + uint16_t e_phentsize; + uint16_t e_phnum; + uint16_t e_shentsize; + uint16_t e_shnum; + uint16_t e_shstrndx; +} Elf64_Ehdr; + +typedef struct { + uint32_t sh_name; + uint32_t sh_type; + uint64_t sh_flags; + uint64_t sh_addr; + uint64_t sh_offset; + uint64_t sh_size; + uint32_t sh_link; + uint32_t sh_info; + uint64_t sh_addralign; + uint64_t sh_entsize; +} Elf64_Shdr; + +typedef struct { + uint32_t p_type; + uint32_t p_flags; + uint64_t p_offset; + uint64_t p_vaddr; + uint64_t p_paddr; + uint64_t p_filesz; + uint64_t p_memsz; + uint64_t p_align; +} Elf64_Phdr; + +typedef struct { + uint32_t st_name; + uint8_t st_info; + uint8_t st_other; + uint16_t st_shndx; + uint64_t st_value; + uint64_t st_size; +} Elf64_Sym; + +#endif diff --git a/tb/dpi/elfdpi.cc b/tb/dpi/elfdpi.cc new file mode 100644 index 000000000..da4cc5d40 --- /dev/null +++ b/tb/dpi/elfdpi.cc @@ -0,0 +1,87 @@ +#include "vpi_user.h" +#include "elfdpi.h" +#include +#include +#include +#include +#include +#include +#include +#include "elf.h" +#include +#include + +std::map symbols; + +uint64_t get_symbol_address (const char* symb) { + return symbols[symb]; +} + +void* read_elf(const char* fn) { + + int fd = open(fn, O_RDONLY); + struct stat s; + // check thtat the file exists + assert(fd != -1); + + if (fstat(fd, &s) < 0) + abort(); + size_t size = s.st_size; + // map the file to memory + char* buf = (char*)mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); + assert(buf != MAP_FAILED); + close(fd); + // check that this is an elf file + assert(size >= sizeof(Elf64_Ehdr)); + const Elf64_Ehdr* eh64 = (const Elf64_Ehdr*)buf; + assert(IS_ELF32(*eh64) || IS_ELF64(*eh64)); + + #define LOAD_ELF(ehdr_t, phdr_t, shdr_t, sym_t) do { \ + ehdr_t* eh = (ehdr_t*)buf; \ + phdr_t* ph = (phdr_t*)(buf + eh->e_phoff); \ + assert(size >= eh->e_phoff + eh->e_phnum*sizeof(*ph)); \ + for (unsigned i = 0; i < eh->e_phnum; i++) { \ + if(ph[i].p_type == PT_LOAD && ph[i].p_memsz) { \ + if (ph[i].p_filesz) { \ + assert(size >= ph[i].p_offset + ph[i].p_filesz); \ + } \ + } \ + } \ + shdr_t* sh = (shdr_t*)(buf + eh->e_shoff); \ + assert(size >= eh->e_shoff + eh->e_shnum*sizeof(*sh)); \ + assert(eh->e_shstrndx < eh->e_shnum); \ + assert(size >= sh[eh->e_shstrndx].sh_offset + sh[eh->e_shstrndx].sh_size); \ + char *shstrtab = buf + sh[eh->e_shstrndx].sh_offset; \ + unsigned strtabidx = 0, symtabidx = 0; \ + for (unsigned i = 0; i < eh->e_shnum; i++) { \ + unsigned max_len = sh[eh->e_shstrndx].sh_size - sh[i].sh_name; \ + assert(sh[i].sh_name < sh[eh->e_shstrndx].sh_size); \ + assert(strnlen(shstrtab + sh[i].sh_name, max_len) < max_len); \ + if (sh[i].sh_type & SHT_NOBITS) continue; \ + assert(size >= sh[i].sh_offset + sh[i].sh_size); \ + if (strcmp(shstrtab + sh[i].sh_name, ".strtab") == 0) \ + strtabidx = i; \ + if (strcmp(shstrtab + sh[i].sh_name, ".symtab") == 0) \ + symtabidx = i; \ + } \ + if (strtabidx && symtabidx) { \ + char* strtab = buf + sh[strtabidx].sh_offset; \ + sym_t* sym = (sym_t*)(buf + sh[symtabidx].sh_offset); \ + for (unsigned i = 0; i < sh[symtabidx].sh_size/sizeof(sym_t); i++) { \ + unsigned max_len = sh[strtabidx].sh_size - sym[i].st_name; \ + assert(sym[i].st_name < sh[strtabidx].sh_size); \ + assert(strnlen(strtab + sym[i].st_name, max_len) < max_len); \ + symbols[strtab + sym[i].st_name] = sym[i].st_value; \ + } \ + } \ + } while(0) + + if (IS_ELF32(*eh64)) + LOAD_ELF(Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Sym); + else + LOAD_ELF(Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Sym); + + munmap(buf, size); + + return &symbols; +} \ No newline at end of file diff --git a/tb/dpi/elfdpi.h b/tb/dpi/elfdpi.h new file mode 100644 index 000000000..5e1ce7623 --- /dev/null +++ b/tb/dpi/elfdpi.h @@ -0,0 +1,151 @@ +/* MTI_DPI */ + +/* + * Copyright 2002-2016 Mentor Graphics Corporation. + * + * Note: + * This file is automatically generated. + * Please do not edit this file - you will lose your edits. + * + * Settings when this file was generated: + * PLATFORM = 'linux_x86_64' + */ +#ifndef INCLUDED_ELFDPI +#define INCLUDED_ELFDPI + +#ifdef __cplusplus +#define DPI_LINK_DECL extern "C" +#else +#define DPI_LINK_DECL +#endif + +#include "svdpi.h" + + +#ifndef MTI_INCLUDED_TYPEDEF_uvm_hdl_path_slice +#define MTI_INCLUDED_TYPEDEF_uvm_hdl_path_slice + +typedef struct { + const char* path; + int offset; + int size; +} uvm_hdl_path_slice; + +#endif + +#ifndef MTI_INCLUDED_TYPEDEF_uvm_printer_row_info +#define MTI_INCLUDED_TYPEDEF_uvm_printer_row_info + +typedef struct { + int level; + const char* name; + const char* type_name; + const char* size; + const char* val; +} uvm_printer_row_info; + +#endif + +#ifndef MTI_INCLUDED_TYPEDEF_uvm_reg_bus_op +#define MTI_INCLUDED_TYPEDEF_uvm_reg_bus_op + +typedef struct { + int kind; + svBitVecVal addr[SV_PACKED_DATA_NELEMS(64)]; + svBitVecVal data[SV_PACKED_DATA_NELEMS(64)]; + int n_bits; + svBitVecVal byte_en[SV_PACKED_DATA_NELEMS(8)]; + int status; +} uvm_reg_bus_op; + +#endif + + +DPI_LINK_DECL DPI_DLLESPEC +uint64_t +get_symbol_address( + const char* sym); + +DPI_LINK_DECL DPI_DLLESPEC +void* +read_elf( + const char* fn); + +DPI_LINK_DECL DPI_DLLESPEC +const char* +uvm_dpi_get_next_arg_c(); + +DPI_LINK_DECL DPI_DLLESPEC +const char* +uvm_dpi_get_tool_name_c(); + +DPI_LINK_DECL DPI_DLLESPEC +const char* +uvm_dpi_get_tool_version_c(); + +DPI_LINK_DECL DPI_DLLESPEC +void* +uvm_dpi_regcomp( + const char* regex); + +DPI_LINK_DECL DPI_DLLESPEC +int +uvm_dpi_regexec( + void* preg, + const char* str); + +DPI_LINK_DECL DPI_DLLESPEC +void +uvm_dpi_regfree( + void* preg); + +DPI_LINK_DECL DPI_DLLESPEC +void +uvm_dump_re_cache(); + +DPI_LINK_DECL DPI_DLLESPEC +const char* +uvm_glob_to_re( + const char* glob); + +DPI_LINK_DECL DPI_DLLESPEC +int +uvm_hdl_check_path( + const char* path); + +DPI_LINK_DECL DPI_DLLESPEC +int +uvm_hdl_deposit( + const char* path, + const svLogicVecVal* value); + +DPI_LINK_DECL DPI_DLLESPEC +int +uvm_hdl_force( + const char* path, + const svLogicVecVal* value); + +DPI_LINK_DECL DPI_DLLESPEC +int +uvm_hdl_read( + const char* path, + svLogicVecVal* value); + +DPI_LINK_DECL DPI_DLLESPEC +int +uvm_hdl_release( + const char* path); + +DPI_LINK_DECL DPI_DLLESPEC +int +uvm_hdl_release_and_read( + const char* path, + svLogicVecVal* value); + +DPI_LINK_DECL DPI_DLLESPEC +int +uvm_re_match( + const char* re, + const char* str); + +#endif