soc/integration/csr_bridge: use registered version only when SDRAM is present.
[litex.git] / litex / build / sim / core / modules / jtagremote / jtagremote.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include "error.h"
5 #include <unistd.h>
6 #include <event2/listener.h>
7 #include <event2/util.h>
8 #include <event2/event.h>
9
10 #include <json-c/json.h>
11 #include "modules.h"
12
13 struct session_s {
14 char *tdi;
15 char *tdo;
16 char *tck;
17 char *tms;
18 char *sys_clk;
19 struct event *ev;
20 char databuf[2048];
21 int data_start;
22 int datalen;
23 int cntticks;
24 int fd;
25 };
26
27 struct event_base *base;
28
29 int litex_sim_module_get_args( char *args, char *arg, char **val)
30 {
31 int ret = RC_OK;
32 json_object *jsobj = NULL;
33 json_object *obj = NULL;
34 char *value = NULL;
35 int r;
36
37 jsobj = json_tokener_parse(args);
38 if(NULL==jsobj) {
39 fprintf(stderr, "Error parsing json arg: %s \n", args);
40 ret=RC_JSERROR;
41 goto out;
42 }
43 if(!json_object_is_type(jsobj, json_type_object)) {
44 fprintf(stderr, "Arg must be type object! : %s \n", args);
45 ret=RC_JSERROR;
46 goto out;
47 }
48 obj=NULL;
49 r = json_object_object_get_ex(jsobj, arg, &obj);
50 if(!r) {
51 fprintf(stderr, "Could not find object: \"%s\" (%s)\n", arg, args);
52 ret=RC_JSERROR;
53 goto out;
54 }
55 value=strdup(json_object_get_string(obj));
56
57 out:
58 *val = value;
59 return ret;
60 }
61
62 static int litex_sim_module_pads_get( struct pad_s *pads, char *name, void **signal)
63 {
64 int ret;
65 void *sig = NULL;
66 int i;
67
68 if(!pads || !name || !signal) {
69 ret = RC_INVARG;
70 goto out;
71 }
72
73 i = 0;
74 while(pads[i].name) {
75 if(!strcmp(pads[i].name, name)) {
76 sig = (void*)pads[i].signal;
77 break;
78 }
79 i++;
80 }
81
82 out:
83 *signal = sig;
84 return ret;
85 }
86
87 static int jtagremote_start(void *b)
88 {
89 base = (struct event_base *)b;
90 printf("[jtagremote] loaded (%p)\n", base);
91 return RC_OK;
92 }
93
94 void read_handler(int fd, short event, void *arg)
95 {
96 struct session_s *s = (struct session_s*)arg;
97 char buffer[1024];
98 ssize_t read_len;
99
100 int i;
101
102 read_len = read(fd, buffer, 1024);
103 for(i = 0; i < read_len; i++)
104 {
105 s->databuf[(s->data_start + s->datalen ) % 2048] = buffer[i];
106 s->datalen++;
107 }
108 }
109
110 static void event_handler(int fd, short event, void *arg)
111 {
112 if (event & EV_READ)
113 read_handler(fd, event, arg);
114 }
115
116 static void accept_conn_cb(struct evconnlistener *listener, evutil_socket_t fd, struct sockaddr *address, int socklen, void *ctx)
117 {
118 struct session_s *s = (struct session_s*)ctx;
119 struct timeval tv = {1, 0};
120
121 s->fd = fd;
122 s->ev = event_new(base, fd, EV_READ | EV_PERSIST , event_handler, s);
123 event_add(s->ev, &tv);
124 }
125
126 static void
127 accept_error_cb(struct evconnlistener *listener, void *ctx)
128 {
129 struct event_base *base = evconnlistener_get_base(listener);
130 eprintf("ERRROR\n");
131
132 event_base_loopexit(base, NULL);
133 }
134
135 static int jtagremote_new(void **sess, char *args)
136 {
137 int ret = RC_OK;
138 struct session_s *s = NULL;
139 char *cport = NULL;
140 int port;
141 struct evconnlistener *listener;
142 struct sockaddr_in sin;
143
144 if(!sess) {
145 ret = RC_INVARG;
146 goto out;
147 }
148
149 ret = litex_sim_module_get_args(args, "port", &cport);
150 if(RC_OK != ret)
151 goto out;
152
153 printf("Found port %s\n", cport);
154 sscanf(cport, "%d", &port);
155 free(cport);
156 if(!port) {
157 ret = RC_ERROR;
158 fprintf(stderr, "Invalid port selected!\n");
159 goto out;
160 }
161
162 s=(struct session_s*)malloc(sizeof(struct session_s));
163 if(!s) {
164 ret = RC_NOENMEM;
165 goto out;
166 }
167 memset(s, 0, sizeof(struct session_s));
168
169 memset(&sin, 0, sizeof(sin));
170 sin.sin_family = AF_INET;
171 sin.sin_addr.s_addr = htonl(0);
172 sin.sin_port = htons(port);
173 listener = evconnlistener_new_bind(base, accept_conn_cb, s, LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE, -1, (struct sockaddr*)&sin, sizeof(sin));
174 if (!listener) {
175 ret=RC_ERROR;
176 eprintf("Can't bind port %d\n!\n", port);
177 goto out;
178 }
179 evconnlistener_set_error_cb(listener, accept_error_cb);
180
181 out:
182 *sess=(void*)s;
183 return ret;
184 }
185
186 static int jtagremote_add_pads(void *sess, struct pad_list_s *plist)
187 {
188 int ret=RC_OK;
189 struct session_s *s=(struct session_s*)sess;
190 struct pad_s *pads;
191 if(!sess || !plist) {
192 ret = RC_INVARG;
193 goto out;
194 }
195 pads = plist->pads;
196 printf("plist name: %s\n", plist->name);
197 if(!strcmp(plist->name, "jtag")) {
198 litex_sim_module_pads_get(pads, "tck", (void**)&s->tck);
199 litex_sim_module_pads_get(pads, "tdi", (void**)&s->tdi);
200 litex_sim_module_pads_get(pads, "tdo", (void**)&s->tdo);
201 litex_sim_module_pads_get(pads, "tms", (void**)&s->tms);
202 }
203
204 if(!strcmp(plist->name, "sys_clk"))
205 litex_sim_module_pads_get(pads, "sys_clk", (void**)&s->sys_clk);
206
207 out:
208 return ret;
209
210 }
211 static int jtagremote_tick(void *sess, uint64_t time_ps)
212 {
213 static struct clk_edge_t edge;
214 char c, val;
215 int ret = RC_OK;
216
217 struct session_s *s = (struct session_s*)sess;
218 if(!clk_pos_edge(&edge, *s->sys_clk)) {
219 return RC_OK;
220 }
221
222 s->cntticks++;
223 if(s->cntticks % 10)
224 return RC_OK;
225
226 if(s->datalen)
227 {
228 c = s->databuf[s->data_start];
229
230 if((c >= '0') && (c <= '7')){
231 *s->tck = ((c - '0') >> 2) & 1;
232 *s->tms = ((c - '0') >> 1) & 1;
233 *s->tdi = (c - '0') & 1;
234 }
235 if(c == 'R'){
236 val = *s->tdo + '0';
237 if(-1 == write(s->fd, &val, 1)) {
238 eprintf("Error writing on socket\n");
239 ret = RC_ERROR;
240 goto out;
241 }
242 }
243 s->data_start = (s->data_start + 1) % 2048;
244 s->datalen--;
245 }
246
247 out:
248 return ret;
249 }
250
251 static struct ext_module_s ext_mod = {
252 "jtagremote",
253 jtagremote_start,
254 jtagremote_new,
255 jtagremote_add_pads,
256 NULL,
257 jtagremote_tick
258 };
259
260 int litex_sim_ext_module_init(int (*register_module)(struct ext_module_s *))
261 {
262 int ret = RC_OK;
263 ret = register_module(&ext_mod);
264 return ret;
265 }