{
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;
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;
}
}
- tick(top);
-
uart_tx(top->uart0_txd);
top->uart0_rxd = uart_rx();