Add log_debug() framework
[yosys.git] / frontends / ilang / ilang_parser.y
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 * A very simple and straightforward frontend for the RTLIL text
21 * representation (as generated by the 'ilang' backend).
22 *
23 */
24
25 %{
26 #include <list>
27 #include "frontends/ilang/ilang_frontend.h"
28 YOSYS_NAMESPACE_BEGIN
29 namespace ILANG_FRONTEND {
30 std::istream *lexin;
31 RTLIL::Design *current_design;
32 RTLIL::Module *current_module;
33 RTLIL::Wire *current_wire;
34 RTLIL::Memory *current_memory;
35 RTLIL::Cell *current_cell;
36 RTLIL::Process *current_process;
37 std::vector<std::vector<RTLIL::SwitchRule*>*> switch_stack;
38 std::vector<RTLIL::CaseRule*> case_stack;
39 dict<RTLIL::IdString, RTLIL::Const> attrbuf;
40 bool flag_nooverwrite, flag_overwrite, flag_lib;
41 bool delete_current_module;
42 }
43 using namespace ILANG_FRONTEND;
44 YOSYS_NAMESPACE_END
45 USING_YOSYS_NAMESPACE
46 %}
47
48 %name-prefix "rtlil_frontend_ilang_yy"
49
50 %union {
51 char *string;
52 int integer;
53 YOSYS_NAMESPACE_PREFIX RTLIL::Const *data;
54 YOSYS_NAMESPACE_PREFIX RTLIL::SigSpec *sigspec;
55 std::vector<YOSYS_NAMESPACE_PREFIX RTLIL::SigSpec> *rsigspec;
56 }
57
58 %token <string> TOK_ID TOK_VALUE TOK_STRING
59 %token <integer> TOK_INT
60 %token TOK_AUTOIDX TOK_MODULE TOK_WIRE TOK_WIDTH TOK_INPUT TOK_OUTPUT TOK_INOUT
61 %token TOK_CELL TOK_CONNECT TOK_SWITCH TOK_CASE TOK_ASSIGN TOK_SYNC
62 %token TOK_LOW TOK_HIGH TOK_POSEDGE TOK_NEGEDGE TOK_EDGE TOK_ALWAYS TOK_GLOBAL TOK_INIT
63 %token TOK_UPDATE TOK_PROCESS TOK_END TOK_INVALID TOK_EOL TOK_OFFSET
64 %token TOK_PARAMETER TOK_ATTRIBUTE TOK_MEMORY TOK_SIZE TOK_SIGNED TOK_UPTO
65
66 %type <rsigspec> sigspec_list_reversed
67 %type <sigspec> sigspec sigspec_list
68 %type <integer> sync_type
69 %type <data> constant
70
71 %expect 0
72 %debug
73
74 %%
75
76 input:
77 optional_eol {
78 attrbuf.clear();
79 } design {
80 if (attrbuf.size() != 0)
81 rtlil_frontend_ilang_yyerror("dangling attribute");
82 };
83
84 EOL:
85 optional_eol TOK_EOL;
86
87 optional_eol:
88 optional_eol TOK_EOL | /* empty */;
89
90 design:
91 design module |
92 design attr_stmt |
93 design autoidx_stmt |
94 /* empty */;
95
96 module:
97 TOK_MODULE TOK_ID EOL {
98 delete_current_module = false;
99 if (current_design->has($2)) {
100 RTLIL::Module *existing_mod = current_design->module($2);
101 if (!flag_overwrite && (flag_lib || (attrbuf.count("\\blackbox") && attrbuf.at("\\blackbox").as_bool()))) {
102 log("Ignoring blackbox re-definition of module %s.\n", $2);
103 delete_current_module = true;
104 } else if (!flag_nooverwrite && !flag_overwrite && !existing_mod->get_bool_attribute("\\blackbox")) {
105 rtlil_frontend_ilang_yyerror(stringf("ilang error: redefinition of module %s.", $2).c_str());
106 } else if (flag_nooverwrite) {
107 log("Ignoring re-definition of module %s.\n", $2);
108 delete_current_module = true;
109 } else {
110 log("Replacing existing%s module %s.\n", existing_mod->get_bool_attribute("\\blackbox") ? " blackbox" : "", $2);
111 current_design->remove(existing_mod);
112 }
113 }
114 current_module = new RTLIL::Module;
115 current_module->name = $2;
116 current_module->attributes = attrbuf;
117 if (!delete_current_module)
118 current_design->add(current_module);
119 attrbuf.clear();
120 free($2);
121 } module_body TOK_END {
122 if (attrbuf.size() != 0)
123 rtlil_frontend_ilang_yyerror("dangling attribute");
124 current_module->fixup_ports();
125 if (delete_current_module)
126 delete current_module;
127 else if (flag_lib)
128 current_module->makeblackbox();
129 current_module = nullptr;
130 } EOL;
131
132 module_body:
133 module_body module_stmt |
134 /* empty */;
135
136 module_stmt:
137 param_stmt | attr_stmt | wire_stmt | memory_stmt | cell_stmt | proc_stmt | conn_stmt;
138
139 param_stmt:
140 TOK_PARAMETER TOK_ID EOL {
141 current_module->avail_parameters.insert($2);
142 free($2);
143 };
144
145 attr_stmt:
146 TOK_ATTRIBUTE TOK_ID constant EOL {
147 attrbuf[$2] = *$3;
148 delete $3;
149 free($2);
150 };
151
152 autoidx_stmt:
153 TOK_AUTOIDX TOK_INT EOL {
154 autoidx = max(autoidx, $2);
155 };
156
157 wire_stmt:
158 TOK_WIRE {
159 current_wire = current_module->addWire("$__ilang_frontend_tmp__");
160 current_wire->attributes = attrbuf;
161 attrbuf.clear();
162 } wire_options TOK_ID EOL {
163 if (current_module->wires_.count($4) != 0)
164 rtlil_frontend_ilang_yyerror(stringf("ilang error: redefinition of wire %s.", $4).c_str());
165 current_module->rename(current_wire, $4);
166 free($4);
167 };
168
169 wire_options:
170 wire_options TOK_WIDTH TOK_INT {
171 current_wire->width = $3;
172 } |
173 wire_options TOK_UPTO {
174 current_wire->upto = true;
175 } |
176 wire_options TOK_OFFSET TOK_INT {
177 current_wire->start_offset = $3;
178 } |
179 wire_options TOK_INPUT TOK_INT {
180 current_wire->port_id = $3;
181 current_wire->port_input = true;
182 current_wire->port_output = false;
183 } |
184 wire_options TOK_OUTPUT TOK_INT {
185 current_wire->port_id = $3;
186 current_wire->port_input = false;
187 current_wire->port_output = true;
188 } |
189 wire_options TOK_INOUT TOK_INT {
190 current_wire->port_id = $3;
191 current_wire->port_input = true;
192 current_wire->port_output = true;
193 } |
194 /* empty */;
195
196 memory_stmt:
197 TOK_MEMORY {
198 current_memory = new RTLIL::Memory;
199 current_memory->attributes = attrbuf;
200 attrbuf.clear();
201 } memory_options TOK_ID EOL {
202 if (current_module->memories.count($4) != 0)
203 rtlil_frontend_ilang_yyerror(stringf("ilang error: redefinition of memory %s.", $4).c_str());
204 current_memory->name = $4;
205 current_module->memories[$4] = current_memory;
206 free($4);
207 };
208
209 memory_options:
210 memory_options TOK_WIDTH TOK_INT {
211 current_memory->width = $3;
212 } |
213 memory_options TOK_SIZE TOK_INT {
214 current_memory->size = $3;
215 } |
216 memory_options TOK_OFFSET TOK_INT {
217 current_memory->start_offset = $3;
218 } |
219 /* empty */;
220
221 cell_stmt:
222 TOK_CELL TOK_ID TOK_ID EOL {
223 if (current_module->cells_.count($3) != 0)
224 rtlil_frontend_ilang_yyerror(stringf("ilang error: redefinition of cell %s.", $3).c_str());
225 current_cell = current_module->addCell($3, $2);
226 current_cell->attributes = attrbuf;
227 attrbuf.clear();
228 free($2);
229 free($3);
230 } cell_body TOK_END EOL;
231
232 cell_body:
233 cell_body TOK_PARAMETER TOK_ID constant EOL {
234 current_cell->parameters[$3] = *$4;
235 free($3);
236 delete $4;
237 } |
238 cell_body TOK_PARAMETER TOK_SIGNED TOK_ID constant EOL {
239 current_cell->parameters[$4] = *$5;
240 current_cell->parameters[$4].flags |= RTLIL::CONST_FLAG_SIGNED;
241 free($4);
242 delete $5;
243 } |
244 cell_body TOK_CONNECT TOK_ID sigspec EOL {
245 if (current_cell->hasPort($3))
246 rtlil_frontend_ilang_yyerror(stringf("ilang error: redefinition of cell port %s.", $3).c_str());
247 current_cell->setPort($3, *$4);
248 delete $4;
249 free($3);
250 } |
251 /* empty */;
252
253 proc_stmt:
254 TOK_PROCESS TOK_ID EOL {
255 if (current_module->processes.count($2) != 0)
256 rtlil_frontend_ilang_yyerror(stringf("ilang error: redefinition of process %s.", $2).c_str());
257 current_process = new RTLIL::Process;
258 current_process->name = $2;
259 current_process->attributes = attrbuf;
260 current_module->processes[$2] = current_process;
261 switch_stack.clear();
262 switch_stack.push_back(&current_process->root_case.switches);
263 case_stack.clear();
264 case_stack.push_back(&current_process->root_case);
265 attrbuf.clear();
266 free($2);
267 } case_body sync_list TOK_END EOL;
268
269 switch_stmt:
270 attr_list TOK_SWITCH sigspec EOL {
271 RTLIL::SwitchRule *rule = new RTLIL::SwitchRule;
272 rule->signal = *$3;
273 rule->attributes = attrbuf;
274 switch_stack.back()->push_back(rule);
275 attrbuf.clear();
276 delete $3;
277 } switch_body TOK_END EOL;
278
279 attr_list:
280 /* empty */ |
281 attr_list attr_stmt;
282
283 switch_body:
284 switch_body TOK_CASE {
285 RTLIL::CaseRule *rule = new RTLIL::CaseRule;
286 switch_stack.back()->back()->cases.push_back(rule);
287 switch_stack.push_back(&rule->switches);
288 case_stack.push_back(rule);
289 } compare_list EOL case_body {
290 switch_stack.pop_back();
291 case_stack.pop_back();
292 } |
293 /* empty */;
294
295 compare_list:
296 sigspec {
297 case_stack.back()->compare.push_back(*$1);
298 delete $1;
299 } |
300 compare_list ',' sigspec {
301 case_stack.back()->compare.push_back(*$3);
302 delete $3;
303 } |
304 /* empty */;
305
306 case_body:
307 case_body switch_stmt |
308 case_body assign_stmt |
309 /* empty */;
310
311 assign_stmt:
312 TOK_ASSIGN sigspec sigspec EOL {
313 case_stack.back()->actions.push_back(RTLIL::SigSig(*$2, *$3));
314 delete $2;
315 delete $3;
316 };
317
318 sync_list:
319 sync_list TOK_SYNC sync_type sigspec EOL {
320 RTLIL::SyncRule *rule = new RTLIL::SyncRule;
321 rule->type = RTLIL::SyncType($3);
322 rule->signal = *$4;
323 current_process->syncs.push_back(rule);
324 delete $4;
325 } update_list |
326 sync_list TOK_SYNC TOK_ALWAYS EOL {
327 RTLIL::SyncRule *rule = new RTLIL::SyncRule;
328 rule->type = RTLIL::SyncType::STa;
329 rule->signal = RTLIL::SigSpec();
330 current_process->syncs.push_back(rule);
331 } update_list |
332 sync_list TOK_SYNC TOK_GLOBAL EOL {
333 RTLIL::SyncRule *rule = new RTLIL::SyncRule;
334 rule->type = RTLIL::SyncType::STg;
335 rule->signal = RTLIL::SigSpec();
336 current_process->syncs.push_back(rule);
337 } update_list |
338 sync_list TOK_SYNC TOK_INIT EOL {
339 RTLIL::SyncRule *rule = new RTLIL::SyncRule;
340 rule->type = RTLIL::SyncType::STi;
341 rule->signal = RTLIL::SigSpec();
342 current_process->syncs.push_back(rule);
343 } update_list |
344 /* empty */;
345
346 sync_type:
347 TOK_LOW { $$ = RTLIL::ST0; } |
348 TOK_HIGH { $$ = RTLIL::ST1; } |
349 TOK_POSEDGE { $$ = RTLIL::STp; } |
350 TOK_NEGEDGE { $$ = RTLIL::STn; } |
351 TOK_EDGE { $$ = RTLIL::STe; };
352
353 update_list:
354 update_list TOK_UPDATE sigspec sigspec EOL {
355 current_process->syncs.back()->actions.push_back(RTLIL::SigSig(*$3, *$4));
356 delete $3;
357 delete $4;
358 } |
359 /* empty */;
360
361 constant:
362 TOK_VALUE {
363 char *ep;
364 int width = strtol($1, &ep, 10);
365 std::list<RTLIL::State> bits;
366 while (*(++ep) != 0) {
367 RTLIL::State bit = RTLIL::Sx;
368 switch (*ep) {
369 case '0': bit = RTLIL::S0; break;
370 case '1': bit = RTLIL::S1; break;
371 case 'x': bit = RTLIL::Sx; break;
372 case 'z': bit = RTLIL::Sz; break;
373 case '-': bit = RTLIL::Sa; break;
374 case 'm': bit = RTLIL::Sm; break;
375 }
376 bits.push_front(bit);
377 }
378 if (bits.size() == 0)
379 bits.push_back(RTLIL::Sx);
380 while ((int)bits.size() < width) {
381 RTLIL::State bit = bits.back();
382 if (bit == RTLIL::S1)
383 bit = RTLIL::S0;
384 bits.push_back(bit);
385 }
386 while ((int)bits.size() > width)
387 bits.pop_back();
388 $$ = new RTLIL::Const;
389 for (auto it = bits.begin(); it != bits.end(); it++)
390 $$->bits.push_back(*it);
391 free($1);
392 } |
393 TOK_INT {
394 $$ = new RTLIL::Const($1, 32);
395 } |
396 TOK_STRING {
397 $$ = new RTLIL::Const($1);
398 free($1);
399 };
400
401 sigspec:
402 constant {
403 $$ = new RTLIL::SigSpec(*$1);
404 delete $1;
405 } |
406 TOK_ID {
407 if (current_module->wires_.count($1) == 0)
408 rtlil_frontend_ilang_yyerror(stringf("ilang error: wire %s not found", $1).c_str());
409 $$ = new RTLIL::SigSpec(current_module->wires_[$1]);
410 free($1);
411 } |
412 sigspec '[' TOK_INT ']' {
413 $$ = new RTLIL::SigSpec($1->extract($3));
414 delete $1;
415 } |
416 sigspec '[' TOK_INT ':' TOK_INT ']' {
417 $$ = new RTLIL::SigSpec($1->extract($5, $3 - $5 + 1));
418 delete $1;
419 } |
420 '{' sigspec_list '}' {
421 $$ = $2;
422 };
423
424 sigspec_list_reversed:
425 sigspec_list_reversed sigspec {
426 $$->push_back(*$2);
427 delete $2;
428 } |
429 /* empty */ {
430 $$ = new std::vector<RTLIL::SigSpec>;
431 };
432
433 sigspec_list: sigspec_list_reversed {
434 $$ = new RTLIL::SigSpec;
435 for (auto it = $1->rbegin(); it != $1->rend(); it++)
436 $$->append(*it);
437 delete $1;
438 };
439
440 conn_stmt:
441 TOK_CONNECT sigspec sigspec EOL {
442 if (attrbuf.size() != 0)
443 rtlil_frontend_ilang_yyerror("dangling attribute");
444 current_module->connect(*$2, *$3);
445 delete $2;
446 delete $3;
447 };
448