Merge pull request #966 from YosysHQ/clifford/fix956
[yosys.git] / frontends / json / jsonparse.cc
1 /*
2 * yosys -- Yosys Open SYnthesis Suite
3 *
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 */
19
20 #include "kernel/yosys.h"
21
22 YOSYS_NAMESPACE_BEGIN
23
24 struct JsonNode
25 {
26 char type; // S=String, N=Number, A=Array, D=Dict
27 string data_string;
28 int data_number;
29 vector<JsonNode*> data_array;
30 dict<string, JsonNode*> data_dict;
31 vector<string> data_dict_keys;
32
33 JsonNode(std::istream &f)
34 {
35 type = 0;
36 data_number = 0;
37
38 while (1)
39 {
40 int ch = f.get();
41
42 if (ch == EOF)
43 log_error("Unexpected EOF in JSON file.\n");
44
45 if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n')
46 continue;
47
48 if (ch == '"')
49 {
50 type = 'S';
51
52 while (1)
53 {
54 ch = f.get();
55
56 if (ch == EOF)
57 log_error("Unexpected EOF in JSON string.\n");
58
59 if (ch == '"')
60 break;
61
62 if (ch == '\\') {
63 int ch = f.get();
64
65 if (ch == EOF)
66 log_error("Unexpected EOF in JSON string.\n");
67 }
68
69 data_string += ch;
70 }
71
72 break;
73 }
74
75 if ('0' <= ch && ch <= '9')
76 {
77 type = 'N';
78 data_number = ch - '0';
79 data_string += ch;
80
81 while (1)
82 {
83 ch = f.get();
84
85 if (ch == EOF)
86 break;
87
88 if (ch == '.')
89 goto parse_real;
90
91 if (ch < '0' || '9' < ch) {
92 f.unget();
93 break;
94 }
95
96 data_number = data_number*10 + (ch - '0');
97 data_string += ch;
98 }
99
100 data_string = "";
101 break;
102
103 parse_real:
104 type = 'S';
105 data_number = 0;
106 data_string += ch;
107
108 while (1)
109 {
110 ch = f.get();
111
112 if (ch == EOF)
113 break;
114
115 if (ch < '0' || '9' < ch) {
116 f.unget();
117 break;
118 }
119
120 data_string += ch;
121 }
122
123 break;
124 }
125
126 if (ch == '[')
127 {
128 type = 'A';
129
130 while (1)
131 {
132 ch = f.get();
133
134 if (ch == EOF)
135 log_error("Unexpected EOF in JSON file.\n");
136
137 if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n' || ch == ',')
138 continue;
139
140 if (ch == ']')
141 break;
142
143 f.unget();
144 data_array.push_back(new JsonNode(f));
145 }
146
147 break;
148 }
149
150 if (ch == '{')
151 {
152 type = 'D';
153
154 while (1)
155 {
156 ch = f.get();
157
158 if (ch == EOF)
159 log_error("Unexpected EOF in JSON file.\n");
160
161 if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n' || ch == ',')
162 continue;
163
164 if (ch == '}')
165 break;
166
167 f.unget();
168 JsonNode key(f);
169
170 while (1)
171 {
172 ch = f.get();
173
174 if (ch == EOF)
175 log_error("Unexpected EOF in JSON file.\n");
176
177 if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n' || ch == ':')
178 continue;
179
180 f.unget();
181 break;
182 }
183
184 JsonNode *value = new JsonNode(f);
185
186 if (key.type != 'S')
187 log_error("Unexpected non-string key in JSON dict.\n");
188
189 data_dict[key.data_string] = value;
190 data_dict_keys.push_back(key.data_string);
191 }
192
193 break;
194 }
195
196 log_error("Unexpected character in JSON file: '%c'\n", ch);
197 }
198 }
199
200 ~JsonNode()
201 {
202 for (auto it : data_array)
203 delete it;
204 for (auto &it : data_dict)
205 delete it.second;
206 }
207 };
208
209 void json_parse_attr_param(dict<IdString, Const> &results, JsonNode *node)
210 {
211 if (node->type != 'D')
212 log_error("JSON attributes or parameters node is not a dictionary.\n");
213
214 for (auto it : node->data_dict)
215 {
216 IdString key = RTLIL::escape_id(it.first.c_str());
217 JsonNode *value_node = it.second;
218 Const value;
219
220 if (value_node->type == 'S') {
221 string &s = value_node->data_string;
222 if (s.find_first_not_of("01xz") == string::npos)
223 value = Const::from_string(s);
224 else
225 value = Const(s);
226 } else
227 if (value_node->type == 'N') {
228 value = Const(value_node->data_number, 32);
229 } else
230 if (value_node->type == 'A') {
231 log_error("JSON attribute or parameter value is an array.\n");
232 } else
233 if (value_node->type == 'D') {
234 log_error("JSON attribute or parameter value is a dict.\n");
235 } else {
236 log_abort();
237 }
238
239 results[key] = value;
240 }
241 }
242
243 void json_import(Design *design, string &modname, JsonNode *node)
244 {
245 log("Importing module %s from JSON tree.\n", modname.c_str());
246
247 Module *module = new RTLIL::Module;
248 module->name = RTLIL::escape_id(modname.c_str());
249
250 if (design->module(module->name))
251 log_error("Re-definition of module %s.\n", log_id(module->name));
252
253 design->add(module);
254
255 if (node->data_dict.count("attributes"))
256 json_parse_attr_param(module->attributes, node->data_dict.at("attributes"));
257
258 dict<int, SigBit> signal_bits;
259
260 if (node->data_dict.count("ports"))
261 {
262 JsonNode *ports_node = node->data_dict.at("ports");
263
264 if (ports_node->type != 'D')
265 log_error("JSON ports node is not a dictionary.\n");
266
267 for (int port_id = 1; port_id <= GetSize(ports_node->data_dict_keys); port_id++)
268 {
269 IdString port_name = RTLIL::escape_id(ports_node->data_dict_keys[port_id-1].c_str());
270 JsonNode *port_node = ports_node->data_dict.at(ports_node->data_dict_keys[port_id-1]);
271
272 if (port_node->type != 'D')
273 log_error("JSON port node '%s' is not a dictionary.\n", log_id(port_name));
274
275 if (port_node->data_dict.count("direction") == 0)
276 log_error("JSON port node '%s' has no direction attribute.\n", log_id(port_name));
277
278 if (port_node->data_dict.count("bits") == 0)
279 log_error("JSON port node '%s' has no bits attribute.\n", log_id(port_name));
280
281 JsonNode *port_direction_node = port_node->data_dict.at("direction");
282 JsonNode *port_bits_node = port_node->data_dict.at("bits");
283
284 if (port_direction_node->type != 'S')
285 log_error("JSON port node '%s' has non-string direction attribute.\n", log_id(port_name));
286
287 if (port_bits_node->type != 'A')
288 log_error("JSON port node '%s' has non-array bits attribute.\n", log_id(port_name));
289
290 Wire *port_wire = module->wire(port_name);
291
292 if (port_wire == nullptr)
293 port_wire = module->addWire(port_name, GetSize(port_bits_node->data_array));
294
295 if (port_direction_node->data_string == "input") {
296 port_wire->port_input = true;
297 } else
298 if (port_direction_node->data_string == "output") {
299 port_wire->port_output = true;
300 } else
301 if (port_direction_node->data_string == "inout") {
302 port_wire->port_input = true;
303 port_wire->port_output = true;
304 } else
305 log_error("JSON port node '%s' has invalid '%s' direction attribute.\n", log_id(port_name), port_direction_node->data_string.c_str());
306
307 port_wire->port_id = port_id;
308
309 for (int i = 0; i < GetSize(port_bits_node->data_array); i++)
310 {
311 JsonNode *bitval_node = port_bits_node->data_array.at(i);
312 SigBit sigbit(port_wire, i);
313
314 if (bitval_node->type == 'S') {
315 if (bitval_node->data_string == "0")
316 module->connect(sigbit, State::S0);
317 else if (bitval_node->data_string == "1")
318 module->connect(sigbit, State::S1);
319 else if (bitval_node->data_string == "x")
320 module->connect(sigbit, State::Sx);
321 else if (bitval_node->data_string == "z")
322 module->connect(sigbit, State::Sz);
323 else
324 log_error("JSON port node '%s' has invalid '%s' bit string value on bit %d.\n",
325 log_id(port_name), bitval_node->data_string.c_str(), i);
326 } else
327 if (bitval_node->type == 'N') {
328 int bitidx = bitval_node->data_number;
329 if (signal_bits.count(bitidx)) {
330 if (port_wire->port_output) {
331 module->connect(sigbit, signal_bits.at(bitidx));
332 } else {
333 module->connect(signal_bits.at(bitidx), sigbit);
334 signal_bits[bitidx] = sigbit;
335 }
336 } else {
337 signal_bits[bitidx] = sigbit;
338 }
339 } else
340 log_error("JSON port node '%s' has invalid bit value on bit %d.\n", log_id(port_name), i);
341 }
342 }
343
344 module->fixup_ports();
345 }
346
347 if (node->data_dict.count("netnames"))
348 {
349 JsonNode *netnames_node = node->data_dict.at("netnames");
350
351 if (netnames_node->type != 'D')
352 log_error("JSON netnames node is not a dictionary.\n");
353
354 for (auto &net : netnames_node->data_dict)
355 {
356 IdString net_name = RTLIL::escape_id(net.first.c_str());
357 JsonNode *net_node = net.second;
358
359 if (net_node->type != 'D')
360 log_error("JSON netname node '%s' is not a dictionary.\n", log_id(net_name));
361
362 if (net_node->data_dict.count("bits") == 0)
363 log_error("JSON netname node '%s' has no bits attribute.\n", log_id(net_name));
364
365 JsonNode *bits_node = net_node->data_dict.at("bits");
366
367 if (bits_node->type != 'A')
368 log_error("JSON netname node '%s' has non-array bits attribute.\n", log_id(net_name));
369
370 Wire *wire = module->wire(net_name);
371
372 if (wire == nullptr)
373 wire = module->addWire(net_name, GetSize(bits_node->data_array));
374
375 for (int i = 0; i < GetSize(bits_node->data_array); i++)
376 {
377 JsonNode *bitval_node = bits_node->data_array.at(i);
378 SigBit sigbit(wire, i);
379
380 if (bitval_node->type == 'S') {
381 if (bitval_node->data_string == "0")
382 module->connect(sigbit, State::S0);
383 else if (bitval_node->data_string == "1")
384 module->connect(sigbit, State::S1);
385 else if (bitval_node->data_string == "x")
386 module->connect(sigbit, State::Sx);
387 else if (bitval_node->data_string == "z")
388 module->connect(sigbit, State::Sz);
389 else
390 log_error("JSON netname node '%s' has invalid '%s' bit string value on bit %d.\n",
391 log_id(net_name), bitval_node->data_string.c_str(), i);
392 } else
393 if (bitval_node->type == 'N') {
394 int bitidx = bitval_node->data_number;
395 if (signal_bits.count(bitidx)) {
396 if (sigbit != signal_bits.at(bitidx))
397 module->connect(sigbit, signal_bits.at(bitidx));
398 } else {
399 signal_bits[bitidx] = sigbit;
400 }
401 } else
402 log_error("JSON netname node '%s' has invalid bit value on bit %d.\n", log_id(net_name), i);
403 }
404
405 if (net_node->data_dict.count("attributes"))
406 json_parse_attr_param(wire->attributes, net_node->data_dict.at("attributes"));
407 }
408 }
409
410 if (node->data_dict.count("cells"))
411 {
412 JsonNode *cells_node = node->data_dict.at("cells");
413
414 if (cells_node->type != 'D')
415 log_error("JSON cells node is not a dictionary.\n");
416
417 for (auto &cell_node_it : cells_node->data_dict)
418 {
419 IdString cell_name = RTLIL::escape_id(cell_node_it.first.c_str());
420 JsonNode *cell_node = cell_node_it.second;
421
422 if (cell_node->type != 'D')
423 log_error("JSON cells node '%s' is not a dictionary.\n", log_id(cell_name));
424
425 if (cell_node->data_dict.count("type") == 0)
426 log_error("JSON cells node '%s' has no type attribute.\n", log_id(cell_name));
427
428 JsonNode *type_node = cell_node->data_dict.at("type");
429
430 if (type_node->type != 'S')
431 log_error("JSON cells node '%s' has a non-string type.\n", log_id(cell_name));
432
433 IdString cell_type = RTLIL::escape_id(type_node->data_string.c_str());
434
435 Cell *cell = module->addCell(cell_name, cell_type);
436
437 if (cell_node->data_dict.count("connections") == 0)
438 log_error("JSON cells node '%s' has no connections attribute.\n", log_id(cell_name));
439
440 JsonNode *connections_node = cell_node->data_dict.at("connections");
441
442 if (connections_node->type != 'D')
443 log_error("JSON cells node '%s' has non-dictionary connections attribute.\n", log_id(cell_name));
444
445 for (auto &conn_it : connections_node->data_dict)
446 {
447 IdString conn_name = RTLIL::escape_id(conn_it.first.c_str());
448 JsonNode *conn_node = conn_it.second;
449
450 if (conn_node->type != 'A')
451 log_error("JSON cells node '%s' connection '%s' is not an array.\n", log_id(cell_name), log_id(conn_name));
452
453 SigSpec sig;
454
455 for (int i = 0; i < GetSize(conn_node->data_array); i++)
456 {
457 JsonNode *bitval_node = conn_node->data_array.at(i);
458
459 if (bitval_node->type == 'S') {
460 if (bitval_node->data_string == "0")
461 sig.append(State::S0);
462 else if (bitval_node->data_string == "1")
463 sig.append(State::S1);
464 else if (bitval_node->data_string == "x")
465 sig.append(State::Sx);
466 else if (bitval_node->data_string == "z")
467 sig.append(State::Sz);
468 else
469 log_error("JSON cells node '%s' connection '%s' has invalid '%s' bit string value on bit %d.\n",
470 log_id(cell_name), log_id(conn_name), bitval_node->data_string.c_str(), i);
471 } else
472 if (bitval_node->type == 'N') {
473 int bitidx = bitval_node->data_number;
474 if (signal_bits.count(bitidx) == 0)
475 signal_bits[bitidx] = module->addWire(NEW_ID);
476 sig.append(signal_bits.at(bitidx));
477 } else
478 log_error("JSON cells node '%s' connection '%s' has invalid bit value on bit %d.\n",
479 log_id(cell_name), log_id(conn_name), i);
480
481 }
482
483 cell->setPort(conn_name, sig);
484 }
485
486 if (cell_node->data_dict.count("attributes"))
487 json_parse_attr_param(cell->attributes, cell_node->data_dict.at("attributes"));
488
489 if (cell_node->data_dict.count("parameters"))
490 json_parse_attr_param(cell->parameters, cell_node->data_dict.at("parameters"));
491 }
492 }
493 }
494
495 struct JsonFrontend : public Frontend {
496 JsonFrontend() : Frontend("json", "read JSON file") { }
497 void help() YS_OVERRIDE
498 {
499 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
500 log("\n");
501 log(" read_json [filename]\n");
502 log("\n");
503 log("Load modules from a JSON file into the current design See \"help write_json\"\n");
504 log("for a description of the file format.\n");
505 log("\n");
506 }
507 void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
508 {
509 log_header(design, "Executing JSON frontend.\n");
510
511 size_t argidx;
512 for (argidx = 1; argidx < args.size(); argidx++) {
513 // std::string arg = args[argidx];
514 // if (arg == "-sop") {
515 // sop_mode = true;
516 // continue;
517 // }
518 break;
519 }
520 extra_args(f, filename, args, argidx);
521
522 JsonNode root(*f);
523
524 if (root.type != 'D')
525 log_error("JSON root node is not a dictionary.\n");
526
527 if (root.data_dict.count("modules") != 0)
528 {
529 JsonNode *modules = root.data_dict.at("modules");
530
531 if (modules->type != 'D')
532 log_error("JSON modules node is not a dictionary.\n");
533
534 for (auto &it : modules->data_dict)
535 json_import(design, it.first, it.second);
536 }
537 }
538 } JsonFrontend;
539
540 YOSYS_NAMESPACE_END
541