From 5a0fddb9771953112e24f9719fc8ec6d20bf24c9 Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Sun, 2 Jan 2022 14:44:32 +0000 Subject: [PATCH] add ability to load multiple files in microwatt-verilator.cpp (currently only 2 supported, one at a hard-coded address of 0x500000) --- verilator/microwatt-verilator.cpp | 96 +++++++++++++++++++------------ 1 file changed, 58 insertions(+), 38 deletions(-) diff --git a/verilator/microwatt-verilator.cpp b/verilator/microwatt-verilator.cpp index 324dc52..050d2a6 100644 --- a/verilator/microwatt-verilator.cpp +++ b/verilator/microwatt-verilator.cpp @@ -83,48 +83,68 @@ int main(int argc, char **argv) { Verilated::commandArgs(argc, argv); - // identify bram file to load. first argument if not starting "+[verilator]" - char *bram_file = NULL; - if (argc > 1 && (argv[1][0] != '+')) { - // assume rest of argument is "+verilator", assume it is the filename - bram_file = argv[1]; - } + // allocate a stonking chunk of memory but don't use it yet + unsigned char *_mem = NULL; // gets deleted if not required + unsigned char *mem = NULL; // the actual memory (only set on file load) + size_t sz = 0x10000000; + _mem = (unsigned char*)malloc(sz); + memset(_mem, sz, 0); + + // identify bram files to load (if not starting "+[verilator]") + // here we can specify any number of files, but at present only + // (realistically) two are supported: the bootloader (at address 0x0) + // and the second file (linux kernel) at hard-coded 0x500000. + // it would be much better to use elf-reading here but that's a lot + // of hassle + for (int i = 1; i < argc; i++) { + char *bram_file = NULL; + if (argv[i][0] != '+') { + // assume rest of argument is "+verilator", assume a filename + bram_file = argv[i]; + } - // mmap the file in private (copy-on-write) mode so that its original - // contents are not overwritten - unsigned char *mem = NULL; - if (bram_file != NULL) { - unsigned char *fmem = NULL; + // mmap the file in private (copy-on-write) mode so that its original + // contents are not overwritten + if (bram_file != NULL) { + unsigned char *fmem = NULL; - int fd = open(bram_file, O_RDONLY); - if (fd < 0) { - printf("\n\"%s \" could not open\n", bram_file); - exit(1); - } + int fd = open(bram_file, O_RDONLY); + if (fd < 0) { + printf("\n\"%s \" could not open\n", bram_file); + exit(1); + } - struct stat statbuf; - int err = fstat(fd, &statbuf); - if (err < 0) { - printf("\n\"%s \" could not stat\n", bram_file); - exit(2); - } + struct stat statbuf; + int err = fstat(fd, &statbuf); + if (err < 0) { + printf("\n\"%s \" could not stat\n", bram_file); + exit(2); + } + + fmem = (unsigned char*)mmap(NULL, statbuf.st_size, + PROT_READ|PROT_WRITE, MAP_PRIVATE, + fd, 0); + if (fmem == MAP_FAILED) { + printf("Mapping Failed\n"); + exit(2); + } + close(fd); - fmem = (unsigned char*)mmap(NULL, statbuf.st_size, - PROT_READ|PROT_WRITE, MAP_PRIVATE, - fd, 0); - if (fmem == MAP_FAILED) { - printf("Mapping Failed\n"); - exit(2); + // copy the file over (bit of a hack, here) + mem = _mem; + size_t offs = 0x0; // normal start + if (i == 2) { + offs = 0x500000; // hard-coded offset of the linux binary + } + memcpy(mem+offs, fmem, statbuf.st_size); + munmap(fmem, statbuf.st_size); } - close(fd); - - // allocate more memory than is in the file, copy it over - size_t sz = 0x20000000; - mem = (unsigned char*)malloc(sz); - memset(mem, sz, 0); - memcpy(mem, fmem, statbuf.st_size); - munmap(fmem, statbuf.st_size); } + // a file wasn't loaded so the stonking-chunk-o-mem can be free'd + if (mem == NULL) { + free(_mem); + } + unsigned long long bram_data = 0; unsigned long long bram_data1 = 0; // another clock delay int bram_rd = false; @@ -157,6 +177,8 @@ int main(int argc, char **argv) while(!Verilated::gotFinish()) { + tick(top); + // read/write the memory to/from the mmap'd file (if given) if (mem != NULL) { top->bram_do = bram_do; @@ -168,8 +190,6 @@ int main(int argc, char **argv) } } - tick(top); - uart_tx(top->uart0_txd); top->uart0_rxd = uart_rx(); -- 2.30.2