sim_bram_helpers_c.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. #include <stdio.h>
  2. #include <stdbool.h>
  3. #include <stdint.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <unistd.h>
  7. #include <fcntl.h>
  8. #include <sys/mman.h>
  9. #include <sys/types.h>
  10. #include <sys/stat.h>
  11. #include "sim_vhpi_c.h"
  12. #undef DEBUG
  13. #define ALIGN_UP(VAL, SIZE) (((VAL) + ((SIZE)-1)) & ~((SIZE)-1))
  14. #define MAX_REGIONS 128
  15. struct ram_behavioural {
  16. char *filename;
  17. unsigned long size;
  18. void *m;
  19. };
  20. static struct ram_behavioural behavioural_regions[MAX_REGIONS];
  21. static unsigned long region_nr;
  22. unsigned long behavioural_initialize(void *__f, unsigned long size)
  23. {
  24. struct ram_behavioural *r;
  25. int fd;
  26. struct stat buf;
  27. unsigned long tmp_size;
  28. void *mem;
  29. if (region_nr == MAX_REGIONS) {
  30. fprintf(stderr, "%s: too many regions, bump MAX_REGIONS\n", __func__);
  31. exit(1);
  32. }
  33. r = &behavioural_regions[region_nr];
  34. r->filename = from_string(__f);
  35. r->size = ALIGN_UP(size, getpagesize());
  36. fd = open(r->filename, O_RDWR);
  37. if (fd == -1) {
  38. fprintf(stderr, "%s: could not open %s\n", __func__,
  39. r->filename);
  40. exit(1);
  41. }
  42. if (fstat(fd, &buf)) {
  43. perror("fstat");
  44. exit(1);
  45. }
  46. /* XXX Do we need to truncate the underlying file? */
  47. tmp_size = ALIGN_UP(buf.st_size, getpagesize());
  48. if (r->size > tmp_size) {
  49. void *m;
  50. /*
  51. * We have to pad the file. Allocate the total size, then
  52. * create a space for the file.
  53. */
  54. mem = mmap(NULL, r->size, PROT_READ|PROT_WRITE,
  55. MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
  56. if (mem == MAP_FAILED) {
  57. perror("mmap");
  58. exit(1);
  59. }
  60. if (tmp_size) {
  61. munmap(mem, tmp_size);
  62. m = mmap(mem, tmp_size, PROT_READ|PROT_WRITE,
  63. MAP_PRIVATE|MAP_FIXED, fd, 0);
  64. if (m == MAP_FAILED) {
  65. perror("mmap");
  66. exit(1);
  67. }
  68. if (m != mem) {
  69. fprintf(stderr, "%s: mmap(MAP_FIXED) failed\n",
  70. __func__);
  71. exit(1);
  72. }
  73. }
  74. } else {
  75. mem = mmap(NULL, tmp_size, PROT_READ|PROT_WRITE, MAP_PRIVATE,
  76. fd, 0);
  77. if (mem == MAP_FAILED) {
  78. perror("mmap");
  79. exit(1);
  80. }
  81. }
  82. behavioural_regions[region_nr].m = mem;
  83. return region_nr++;
  84. }
  85. void behavioural_read(unsigned char *__val, unsigned char *__addr,
  86. unsigned long sel, int identifier)
  87. {
  88. struct ram_behavioural *r;
  89. unsigned long val = 0;
  90. unsigned long addr = from_std_logic_vector(__addr, 64);
  91. unsigned char *p;
  92. if (identifier > region_nr) {
  93. fprintf(stderr, "%s: bad index %d\n", __func__, identifier);
  94. exit(1);
  95. }
  96. r = &behavioural_regions[identifier];
  97. for (unsigned long i = 0; i < 8; i++) {
  98. #if 0
  99. /* sel only used on writes */
  100. if (!(sel & (1UL << i)))
  101. continue;
  102. #endif
  103. if ((addr + i) > r->size) {
  104. fprintf(stderr, "%s: bad memory access %lx %lx\n", __func__,
  105. addr+i, r->size);
  106. exit(1);
  107. }
  108. p = (unsigned char *)(((unsigned long)r->m) + addr + i);
  109. val |= (((unsigned long)*p) << (i*8));
  110. }
  111. #ifdef DEBUG
  112. printf("MEM behave %d read %016lx addr %016lx sel %02lx\n", identifier, val,
  113. addr, sel);
  114. #endif
  115. to_std_logic_vector(val, __val, 64);
  116. }
  117. void behavioural_write(unsigned char *__val, unsigned char *__addr,
  118. unsigned int sel, int identifier)
  119. {
  120. struct ram_behavioural *r;
  121. unsigned long val = from_std_logic_vector(__val, 64);
  122. unsigned long addr = from_std_logic_vector(__addr, 64);
  123. unsigned char *p;
  124. if (identifier > region_nr) {
  125. fprintf(stderr, "%s: bad index %d\n", __func__, identifier);
  126. exit(1);
  127. }
  128. r = &behavioural_regions[identifier];
  129. p = (unsigned char *)(((unsigned long)r->m) + addr);
  130. #ifdef DEBUG
  131. printf("MEM behave %d write %016lx addr %016lx sel %02x\n", identifier, val,
  132. addr, sel);
  133. #endif
  134. for (unsigned long i = 0; i < 8; i++) {
  135. if (!(sel & (1UL << i)))
  136. continue;
  137. if ((addr + i) > r->size) {
  138. fprintf(stderr, "%s: bad memory access %lx %lx\n", __func__,
  139. addr+i, r->size);
  140. exit(1);
  141. }
  142. p = (unsigned char *)(((unsigned long)r->m) + addr + i);
  143. *p = (val >> (i*8)) & 0xff;
  144. }
  145. }