Add DPI ELF section loader

This commit is contained in:
Florian Zaruba 2017-06-04 18:21:23 +02:00
parent 3d4128a51f
commit 1bd4848c5f
6 changed files with 369 additions and 2 deletions

View file

@ -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

@ -1 +1 @@
Subproject commit 0ac80c22cac54b0f348b051d41fefaffca802d09
Subproject commit 14f61ce4833126b1327926ad12f7d7bc653702b6

View file

@ -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

121
tb/dpi/elf.h Normal file
View file

@ -0,0 +1,121 @@
// See LICENSE for details.
#ifndef _ELF_H
#define _ELF_H
#include <stdint.h>
#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

87
tb/dpi/elfdpi.cc Normal file
View file

@ -0,0 +1,87 @@
#include "vpi_user.h"
#include "elfdpi.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
#include <assert.h>
#include <stdlib.h>
#include "elf.h"
#include <map>
#include <string>
std::map<std::string, uint64_t> 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;
}

151
tb/dpi/elfdpi.h Normal file
View file

@ -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