add ability to load multiple files in microwatt-verilator.cpp
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sun, 2 Jan 2022 14:44:32 +0000 (14:44 +0000)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sun, 2 Jan 2022 14:44:32 +0000 (14:44 +0000)
(currently only 2 supported, one at a hard-coded address of 0x500000)

verilator/microwatt-verilator.cpp

index 324dc5283b652a2d27af8f68c7b355d9fd124745..050d2a6d27eda014454952471e0768c671c9d9c5 100644 (file)
@@ -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();