add loading (mmap private) of bram file in microwatt-verilator.cpp
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Fri, 31 Dec 2021 21:12:39 +0000 (21:12 +0000)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Fri, 31 Dec 2021 21:12:39 +0000 (21:12 +0000)
performs a comparison against what was loaded into the actual VHDL,
so that replacing it with runtime stands a chance of being correct

verilator/microwatt-verilator.cpp

index 4eaed1125cf79958d786a7a897c77cc7b6bea093..46df43a9e7538c67d72ac46328f268bb1467bedd 100644 (file)
@@ -1,5 +1,9 @@
 #include <stdlib.h>
 #include <stdio.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
 #include "Vmicrowatt.h"
 #include "verilated.h"
 #include "verilated_vcd_c.h"
@@ -63,6 +67,44 @@ 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];
+    }
+
+    // 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) {
+
+        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);
+        }
+
+        mem = (unsigned char*)mmap(NULL, statbuf.st_size,
+                                   PROT_READ|PROT_WRITE, MAP_PRIVATE,
+                                   fd, 0);
+        if (mem == MAP_FAILED) {
+            printf("Mapping Failed\n");
+            exit(2);
+        }
+        close(fd);
+    }
+    unsigned long long bram_data = 0;
+    unsigned long long bram_data1 = 0; // another clock delay
+    int bram_rd = false;
+
        // init top verilog instance
        Vmicrowatt* top = new Vmicrowatt;
 
@@ -79,6 +121,7 @@ int main(int argc, char **argv)
 
     // read data is one clock cycle delayed
     bool next_read = false;
+    unsigned long bram_addr = 0;
 
        // Reset
        top->ext_rst = 0;
@@ -98,13 +141,23 @@ int main(int argc, char **argv)
             ascii_dump((unsigned char*)&top->bram_di, 8, dump);
             fflush(dump);
         }
-        if (next_read) { // read on one clock delay
+        // read on one clock delay
+        if (next_read) {
             fprintf(dump, "bram rd addr %08x din %16lx sel %x ",
-                    top->bram_addr, top->bram_do, top->bram_sel);
+                    bram_addr, top->bram_do, top->bram_sel);
+            if (bram_data1 != top->bram_do) { // check contents
+                fprintf(dump, "bram != %16lx ", bram_data1 );
+            }
             ascii_dump((unsigned char*)&top->bram_do, 8, dump);
             fflush(dump);
         }
         next_read = top->bram_re;
+        bram_addr = top->bram_addr;
+        bram_data1 = bram_data;
+        // get the contents of the memory
+        if ((mem != NULL) && next_read) {
+            bram_data = ((unsigned long long*)mem)[bram_addr];
+        }
        }
 
     fclose(dump);