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