5b45cb77887fee27722c1da44cf1d7ac0b89dc6e
[litex.git] / litex / build / sim / core / parse.c
1 /* Copyright (C) 2017 LambdaConcept */
2
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <json-c/json.h>
7 #include "error.h"
8 #include "modules.h"
9
10 static int file_to_js(char *filename, json_object **obj)
11 {
12 int ret = RC_OK;
13 struct json_tokener *tok=NULL;
14 json_object *pobj=NULL;
15 enum json_tokener_error jerr;
16 FILE *in=NULL;
17 int linenum=0;
18 char *lineptr=NULL;
19 size_t len, len2;
20
21 if(!filename || !obj)
22 {
23 ret=RC_INVARG;
24 goto out;
25 }
26
27 in = fopen(filename, "r");
28 if(!in)
29 {
30 eprintf("Can't open configuration file: %s\n", filename);
31 ret= RC_ERROR;
32 goto out;
33 }
34
35 tok = json_tokener_new();
36 if(!tok)
37 {
38 ret=RC_ERROR;
39 eprintf("Can't create new tokener\n");
40 goto out;
41 }
42
43 do
44 {
45 linenum++;
46 len=32768;
47 len2 = getline(&lineptr, &len, in);
48 if(len2 == -1)
49 {
50 ret=RC_ERROR;
51 eprintf("End of file !\n");
52 goto out;
53 }
54 pobj = json_tokener_parse_ex(tok, lineptr, len2);
55 if((jerr = json_tokener_get_error(tok)) == json_tokener_success)
56 {
57 break;
58 }
59
60 if((jerr = json_tokener_get_error(tok)) != json_tokener_continue)
61 {
62 fprintf(stderr, "ERROR in %s:\n", filename);
63 fprintf(stderr, "line:%d:\n%s",linenum, lineptr);
64 jerr = json_tokener_get_error(tok);
65 fprintf(stderr, "json parse error: %s\n", json_tokener_error_desc(jerr));
66 goto out;
67 }
68 free(lineptr);
69 lineptr=NULL;
70 }while(1);
71
72 *obj=pobj;
73 pobj=NULL;
74 out:
75
76 if(pobj)
77 {
78 json_object_put(pobj);
79 }
80 if(tok)
81 {
82 json_tokener_free(tok);
83 }
84 if(lineptr)
85 {
86 free(lineptr);
87 }
88 if(in)
89 {
90 fclose(in);
91 }
92 return ret;
93 }
94
95 static int json_to_interface_list(json_object *interface, struct interface_s **iface)
96 {
97 int ret=RC_OK;
98 int n, i;
99 json_object *obj;
100 json_object *name;
101 json_object *index;
102
103 struct interface_s *t_iface=NULL;
104
105 if(!interface || !iface)
106 {
107 ret = RC_INVARG;
108 eprintf("Invalid argument\n");
109 goto out;
110 }
111
112 if(!json_object_is_type(interface, json_type_array))
113 {
114 ret=RC_JSERROR;
115 eprintf("Interface must be an array\n");
116 goto out;
117 }
118
119 n = json_object_array_length(interface);
120 t_iface = (struct interface_s *)malloc(sizeof(struct interface_s) * (n + 1));
121 if(!t_iface)
122 {
123 ret= RC_NOENMEM;
124 eprintf("Not enough memory\n");
125 goto out;
126 }
127 memset(t_iface, 0,sizeof(struct interface_s) * (n + 1));
128
129 for(i = 0; i < n; i++)
130 {
131 obj = json_object_array_get_idx(interface, i);
132 if(json_object_is_type(obj, json_type_object))
133 {
134 if(!json_object_object_get_ex(obj, "name", &name))
135 {
136 ret=RC_JSERROR;
137 eprintf("Module interface must have a name (%s)!\n", json_object_to_json_string(obj));
138 goto out;
139 }
140 t_iface[i].name = strdup(json_object_get_string(name));
141
142 if(json_object_object_get_ex(obj, "index", &index))
143 {
144 if(!json_object_is_type(index, json_type_int))
145 {
146 ret = RC_JSERROR;
147 eprintf("Interface Index must be an int ! (%s)\n", json_object_to_json_string(obj));
148 }
149 t_iface[i].index = json_object_get_int(index);
150 }
151 }
152 if(json_object_is_type(obj, json_type_string))
153 {
154 t_iface[i].name = strdup(json_object_get_string(obj));
155 }
156 }
157 *iface = t_iface;
158 t_iface = NULL;
159 out:
160 if(t_iface)
161 {
162 free(t_iface);
163 }
164 return ret;
165 }
166
167 static int module_list_free(struct module_s *mod)
168 {
169 int ret=RC_OK;
170 struct module_s *mnext;
171 int i;
172 while(mod)
173 {
174 mnext = mod->next;
175 if(mod->iface)
176 {
177 for(i = 0; i < mod->niface; i++)
178 {
179 if(mod->iface[i].name)
180 {
181 free(mod->iface[i].name);
182 }
183 }
184 free(mod->iface);
185 if(mod->name)
186 {
187 free(mod->name);
188 }
189 if(mod->args)
190 {
191 free(mod->args);
192 }
193 }
194 free(mod);
195 mod = mnext;
196 }
197 return ret;
198 }
199
200 static int json_to_module_list(json_object *obj, struct module_s **mod)
201 {
202 struct module_s *m=NULL;
203 struct module_s *first=NULL;
204
205 json_object *tobj;
206 int ret=RC_OK;
207 int i, n, len;
208 json_object *name;
209 json_object *args;
210 json_object *interface;
211 json_object *tickfirst;
212
213 if(!obj || !mod)
214 {
215 ret = RC_INVARG;
216 eprintf("Wrong arguments\n");
217 goto out;
218 }
219
220 if(!json_object_is_type(obj, json_type_array))
221 {
222 ret=RC_JSERROR;
223 eprintf("Config file must be an array\n");
224 goto out;
225 }
226
227 n = json_object_array_length(obj);
228 for(i = 0; i < n; i++)
229 {
230 tobj = json_object_array_get_idx(obj, i);
231
232 if(!json_object_object_get_ex(tobj, "module", &name))
233 {
234 continue;
235 }
236
237 if(!json_object_object_get_ex(tobj, "interface", &interface))
238 {
239 ret=RC_JSERROR;
240 eprintf("expected \"interface\" in object (%s)\n", json_object_to_json_string(tobj));
241 goto out;
242 }
243
244 args = NULL;
245 json_object_object_get_ex(tobj, "args", &args);
246
247 tickfirst=NULL;
248 json_object_object_get_ex(tobj, "tickfirst", &tickfirst);
249
250
251 if(m)
252 {
253 m->next=(struct module_s *)malloc(sizeof(struct module_s));
254 m=m->next;
255 }
256 else
257 {
258 m=(struct module_s *)malloc(sizeof(struct module_s));
259 }
260 if(!m)
261 {
262 ret = RC_NOENMEM;
263 eprintf("Not enough memory\n");
264 goto out;
265 }
266 if(!first)
267 {
268 first = m;
269 }
270 memset(m, 0, sizeof(struct module_s));
271 ret = json_to_interface_list(interface, &m->iface);
272 if(RC_OK != ret)
273 {
274 goto out;
275 }
276 len = 0;
277
278 while(m->iface[len++].name);
279 m->niface= len-1;
280 m->name = strdup(json_object_get_string(name));
281 if(args)
282 {
283 m->args = strdup(json_object_to_json_string(args));
284 }
285 if(tickfirst)
286 {
287 m->tickfirst = json_object_get_boolean(tickfirst);
288 }
289 }
290
291 if (!m)
292 {
293 ret = RC_JSERROR;
294 eprintf("No modules found in config file:\n%s\n", json_object_to_json_string(obj));
295 goto out;
296 }
297
298 *mod = first;
299 first=NULL;
300
301 out:
302 if(first)
303 {
304 module_list_free(first);
305 }
306 return ret;
307 }
308
309 static int json_get_timebase(json_object *obj, uint64_t *timebase)
310 {
311 json_object *tobj;
312 int ret=RC_OK;
313 int i, n;
314 uint64_t _timebase = 0;
315 json_object *json_timebase;
316
317 if(!obj || !timebase)
318 {
319 ret = RC_INVARG;
320 eprintf("Wrong arguments\n");
321 goto out;
322 }
323
324 if(!json_object_is_type(obj, json_type_array))
325 {
326 ret=RC_JSERROR;
327 eprintf("Config file must be an array\n");
328 goto out;
329 }
330
331 n = json_object_array_length(obj);
332 for(i = 0; i < n; i++)
333 {
334 tobj = json_object_array_get_idx(obj, i);
335
336 if(!json_object_object_get_ex(tobj, "timebase", &json_timebase))
337 {
338 continue;
339 }
340
341 if (_timebase != 0)
342 {
343 ret=RC_JSERROR;
344 eprintf("\"timebase\" found multiple times: in object (%s)\n", json_object_to_json_string(tobj));
345 goto out;
346 }
347
348 _timebase = json_object_get_uint64(json_timebase);
349 if (_timebase == 0)
350 {
351 ret=RC_JSERROR;
352 eprintf("\"timebase\" cannot be zero: in object (%s)\n", json_object_to_json_string(tobj));
353 goto out;
354 }
355 }
356
357 if (_timebase == 0)
358 {
359 ret=RC_JSERROR;
360 eprintf("No \"timebase\" found in config:\n%s\n", json_object_to_json_string(obj));
361 goto out;
362 }
363 *timebase = _timebase;
364
365 out:
366 return ret;
367 }
368
369
370 int litex_sim_file_parse(char *filename, struct module_s **mod, uint64_t *timebase)
371 {
372 struct module_s *m=NULL;
373 json_object *obj=NULL;
374 int ret=RC_OK;
375
376 if(!filename || !mod)
377 {
378 ret = RC_INVARG;
379 eprintf("Invalid argument\n");
380 goto out;
381 }
382
383 ret = file_to_js(filename, &obj);
384 if(RC_OK != ret)
385 {
386 goto out;
387 }
388
389 ret = json_get_timebase(obj, timebase);
390 if(RC_OK != ret)
391 {
392 goto out;
393 }
394
395 ret = json_to_module_list(obj, &m);
396 if(RC_OK != ret)
397 {
398 goto out;
399 }
400
401 *mod = m;
402 m = NULL;
403 out:
404 if(m)
405 {
406 module_list_free(m);
407 }
408 if(obj)
409 {
410 json_object_put(obj);
411 }
412 return ret;
413 }