1 /*
2 * Copyright (C) 2011-2020 Cary R. (cygcary@yahoo.com)
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18
19 # include <stdlib.h>
20 # include <string.h>
21 # include "config.h"
22 # include "vlog95_priv.h"
23
24 static unsigned single_indent = 0;
25
get_indent(void)26 static unsigned get_indent(void)
27 {
28 if (single_indent) {
29 single_indent = 0;
30 return single_indent;
31 }
32 return indent;
33 }
34
emit_stmt_file_line(ivl_statement_t stmt)35 static void emit_stmt_file_line(ivl_statement_t stmt)
36 {
37 if (emit_file_line) {
38 fprintf(vlog_out, " /* %s:%u */",
39 ivl_stmt_file(stmt),
40 ivl_stmt_lineno(stmt));
41 }
42 }
43
emit_stmt_block_body(ivl_scope_t scope,ivl_statement_t stmt)44 static void emit_stmt_block_body(ivl_scope_t scope, ivl_statement_t stmt)
45 {
46 unsigned idx, count = ivl_stmt_block_count(stmt);
47 ivl_scope_t my_scope = ivl_stmt_block_scope(stmt);
48 indent += indent_incr;
49 if (my_scope) emit_scope_variables(my_scope);
50 else my_scope = scope;
51 for (idx = 0; idx < count; idx += 1) {
52 emit_stmt(my_scope, ivl_stmt_block_stmt(stmt, idx));
53 }
54 assert(indent >= indent_incr);
55 indent -= indent_incr;
56 }
57
emit_stmt_inter_delay(ivl_scope_t scope,ivl_statement_t stmt)58 static void emit_stmt_inter_delay(ivl_scope_t scope, ivl_statement_t stmt)
59 {
60 ivl_expr_t delay = ivl_stmt_delay_expr(stmt);
61 unsigned nevents = ivl_stmt_nevent(stmt);
62 if (nevents) {
63 ivl_expr_t count = ivl_stmt_cond_expr(stmt);
64 if (count) {
65 if (ivl_expr_type(count) == IVL_EX_ULONG) {
66 unsigned long repeat = ivl_expr_uvalue(count);
67 if (repeat != 1) {
68 fprintf(vlog_out, "repeat(%lu) ", repeat);
69 }
70 } else {
71 fprintf(vlog_out, "repeat(");
72 emit_expr(scope, count, 0, 0, 0, 0);
73 fprintf(vlog_out, ") ");
74 }
75 }
76 assert(delay == 0);
77 fprintf(vlog_out, "@(");
78 emit_event(scope, stmt);
79 fprintf(vlog_out, ") ");
80 }
81 if (delay) {
82 assert(nevents == 0);
83 fprintf(vlog_out, "#(");
84 emit_scaled_delayx(scope, delay, 1);
85 fprintf(vlog_out, ") ");
86 }
87 }
88
emit_stmt_lval_name(ivl_scope_t scope,ivl_lval_t lval,ivl_signal_t sig)89 static void emit_stmt_lval_name(ivl_scope_t scope, ivl_lval_t lval,
90 ivl_signal_t sig)
91 {
92 ivl_expr_t array_idx = ivl_lval_idx(lval);
93 emit_scope_call_path(scope, ivl_signal_scope(sig));
94 emit_id(ivl_signal_basename(sig));
95 if (array_idx) {
96 int msb, lsb;
97 ivl_type_t net_type = ivl_signal_net_type(sig);
98 fprintf(vlog_out, "[");
99 if (ivl_type_base(net_type) == IVL_VT_QUEUE) {
100 lsb = 0;
101 msb = 1;
102 } else {
103 assert(ivl_signal_dimensions(sig));
104 /* For an array the LSB/MSB order is not important.
105 * They are always accessed from base counting up. */
106 lsb = ivl_signal_array_base(sig);
107 msb = lsb + ivl_signal_array_count(sig) - 1;
108 }
109 emit_scaled_expr(scope, array_idx, msb, lsb);
110 fprintf(vlog_out, "]");
111 }
112 }
113
emit_stmt_lval_packed(ivl_scope_t scope,ivl_lval_t lval,ivl_signal_t sig,ivl_expr_t sel_expr,unsigned wid)114 static void emit_stmt_lval_packed(ivl_scope_t scope, ivl_lval_t lval,
115 ivl_signal_t sig, ivl_expr_t sel_expr,
116 unsigned wid)
117 {
118 unsigned idx;
119 assert(wid > 0);
120 fprintf(vlog_out, "{");
121 for (idx = wid - 1; idx > 0; idx -= 1) {
122 emit_stmt_lval_name(scope, lval, sig);
123 fprintf(vlog_out, "[");
124 emit_expr(scope, sel_expr, 0, 0, 0, 1);
125 fprintf(vlog_out, " + %u], ", idx);
126 }
127 emit_stmt_lval_name(scope, lval, sig);
128 fprintf(vlog_out, "[");
129 emit_expr(scope, sel_expr, 0, 0, 0, 1);
130 fprintf(vlog_out, "]}");
131 }
132
emit_stmt_lval_ips(ivl_scope_t scope,ivl_lval_t lval,ivl_signal_t sig,ivl_expr_t sel_expr,ivl_select_type_t sel_type,unsigned wid,int msb,int lsb)133 static void emit_stmt_lval_ips(ivl_scope_t scope, ivl_lval_t lval,
134 ivl_signal_t sig, ivl_expr_t sel_expr,
135 ivl_select_type_t sel_type,
136 unsigned wid, int msb, int lsb)
137 {
138 unsigned idx;
139 assert(wid > 0);
140 fprintf(vlog_out, "{");
141 if (msb >= lsb) {
142 if (sel_type == IVL_SEL_IDX_DOWN) {
143 lsb += wid - 1;
144 msb += wid - 1;
145 emit_stmt_lval_name(scope, lval, sig);
146 fprintf(vlog_out, "[");
147 emit_scaled_expr(scope, sel_expr, msb, lsb);
148 fprintf(vlog_out, "]");
149 for (idx = 1; idx < wid; idx += 1) {
150 fprintf(vlog_out, ", ");
151 emit_stmt_lval_name(scope, lval, sig);
152 fprintf(vlog_out, "[");
153 emit_scaled_expr(scope, sel_expr, msb, lsb);
154 fprintf(vlog_out, " - %u]", idx);
155 }
156 fprintf(vlog_out, "}");
157 } else {
158 assert(sel_type == IVL_SEL_IDX_UP);
159 for (idx = wid - 1; idx > 0; idx -= 1) {
160 emit_stmt_lval_name(scope, lval, sig);
161 fprintf(vlog_out, "[");
162 emit_scaled_expr(scope, sel_expr, msb, lsb);
163 fprintf(vlog_out, " + %u], ", idx);
164 }
165 emit_stmt_lval_name(scope, lval, sig);
166 fprintf(vlog_out, "[");
167 emit_scaled_expr(scope, sel_expr, msb, lsb);
168 fprintf(vlog_out, "]}");
169 }
170 } else {
171 if (sel_type == IVL_SEL_IDX_UP) {
172 lsb -= wid - 1;
173 msb -= wid - 1;
174 emit_stmt_lval_name(scope, lval, sig);
175 fprintf(vlog_out, "[");
176 emit_scaled_expr(scope, sel_expr, msb, lsb);
177 fprintf(vlog_out, "]");
178 for (idx = 1; idx < wid; idx += 1) {
179 fprintf(vlog_out, ", ");
180 emit_stmt_lval_name(scope, lval, sig);
181 fprintf(vlog_out, "[");
182 emit_scaled_expr(scope, sel_expr, msb, lsb);
183 fprintf(vlog_out, " + %u]", idx);
184 }
185 fprintf(vlog_out, "}");
186 } else {
187 assert(sel_type == IVL_SEL_IDX_DOWN);
188 for (idx = wid - 1; idx > 0; idx -= 1) {
189 emit_stmt_lval_name(scope, lval, sig);
190 fprintf(vlog_out, "[");
191 emit_scaled_expr(scope, sel_expr, msb, lsb);
192 fprintf(vlog_out, " - %u], ", idx);
193 }
194 emit_stmt_lval_name(scope, lval, sig);
195 fprintf(vlog_out, "[");
196 emit_scaled_expr(scope, sel_expr, msb, lsb);
197 fprintf(vlog_out, "]}");
198 }
199 }
200 }
201
202 /*
203 * Dynamic arrays are not supported in vlog95, but this assignment can be
204 * translated correctly.
205 */
emit_stmt_lval_darray(ivl_scope_t scope,ivl_lval_t lval,ivl_signal_t sig)206 static void emit_stmt_lval_darray(ivl_scope_t scope, ivl_lval_t lval,
207 ivl_signal_t sig)
208 {
209 ivl_expr_t idx = ivl_lval_idx(lval);
210 emit_scope_call_path(scope, ivl_signal_scope(sig));
211 emit_id(ivl_signal_basename(sig));
212 if (idx) {
213 fprintf(vlog_out, "[");
214 emit_expr(scope, idx, 0, 0, 0, 1);
215 fprintf(vlog_out, "]");
216 }
217 }
218
219 /*
220 * Class or class properties are not supported in vlog95, but this assignment
221 * can be translated correctly.
222 */
emit_stmt_lval_class(ivl_scope_t scope,ivl_lval_t lval)223 static ivl_type_t emit_stmt_lval_class(ivl_scope_t scope, ivl_lval_t lval)
224 {
225 ivl_lval_t nest = ivl_lval_nest(lval);
226 ivl_signal_t sig = ivl_lval_sig(lval);
227 ivl_type_t type;
228 int idx = ivl_lval_property_idx(lval);
229
230 if (nest) {
231 type = emit_stmt_lval_class(scope, nest);
232 assert(type);
233 } else {
234 assert(sig);
235 emit_scope_call_path(scope, ivl_signal_scope(sig));
236 emit_id(ivl_signal_basename(sig));
237 type = ivl_signal_net_type(sig);
238 }
239
240 if (idx >= 0) {
241 fprintf(vlog_out, ".%s", ivl_type_prop_name(type, idx));
242 return ivl_type_prop_type(type, idx);
243 } else return 0;
244 }
245
emit_stmt_lval_piece(ivl_scope_t scope,ivl_lval_t lval)246 static void emit_stmt_lval_piece(ivl_scope_t scope, ivl_lval_t lval)
247 {
248 ivl_signal_t sig = ivl_lval_sig(lval);
249 ivl_expr_t sel_expr;
250 ivl_select_type_t sel_type;
251 unsigned width = ivl_lval_width(lval);
252 int msb, lsb;
253 assert(width > 0);
254
255 /* A class supports a nested L-value so it may not have a signal
256 * at this level. */
257 if (! sig) {
258 (void) emit_stmt_lval_class(scope, lval);
259 return;
260 }
261
262 switch (ivl_signal_data_type(sig)) {
263 case IVL_VT_DARRAY:
264 emit_stmt_lval_darray(scope, lval, sig);
265 return;
266 case IVL_VT_CLASS:
267 (void) emit_stmt_lval_class(scope, lval);
268 return;
269 default:
270 break;
271 }
272
273 /* If there are no selects then just print the name. */
274 sel_expr = ivl_lval_part_off(lval);
275 if (! sel_expr && ((width == ivl_signal_width(sig)) ||
276 (ivl_signal_data_type(sig) == IVL_VT_QUEUE))) {
277 emit_stmt_lval_name(scope, lval, sig);
278 return;
279 }
280
281 /* We have some kind of select. */
282 get_sig_msb_lsb(sig, &msb, &lsb);
283 sel_type = ivl_lval_sel_type(lval);
284 assert(sel_expr);
285 /* A bit select. */
286 if (width == 1) {
287 emit_stmt_lval_name(scope, lval, sig);
288 fprintf(vlog_out, "[");
289 emit_scaled_expr(scope, sel_expr, msb, lsb);
290 fprintf(vlog_out, "]");
291 } else if (ivl_expr_type(sel_expr) == IVL_EX_NUMBER) {
292 /* A constant part select. */
293 emit_stmt_lval_name(scope, lval, sig);
294 emit_scaled_range(scope, sel_expr, width, msb, lsb);
295 } else if (sel_type == IVL_SEL_OTHER) {
296 assert(lsb == 0);
297 assert(msb >= 0);
298 emit_stmt_lval_packed(scope, lval, sig, sel_expr, width);
299 } else {
300 /* An indexed part select. */
301 emit_stmt_lval_ips(scope, lval, sig, sel_expr, sel_type,
302 width, msb, lsb);
303 }
304 }
305
emit_stmt_lval(ivl_scope_t scope,ivl_statement_t stmt)306 static unsigned emit_stmt_lval(ivl_scope_t scope, ivl_statement_t stmt)
307 {
308 unsigned count = ivl_stmt_lvals(stmt);
309 unsigned wid = 0;
310 if (count > 1) {
311 unsigned idx;
312 ivl_lval_t lval;
313 fprintf(vlog_out, "{");
314 for (idx = count - 1; idx > 0; idx -= 1) {
315 lval = ivl_stmt_lval(stmt, idx);
316 wid += ivl_lval_width(lval);
317 emit_stmt_lval_piece(scope, lval);
318 fprintf(vlog_out, ", ");
319 }
320 lval = ivl_stmt_lval(stmt, 0);
321 wid += ivl_lval_width(lval);
322 emit_stmt_lval_piece(scope, lval);
323 fprintf(vlog_out, "}");
324 } else {
325 ivl_lval_t lval = ivl_stmt_lval(stmt, 0);
326 wid = ivl_lval_width(lval);
327 emit_stmt_lval_piece(scope, lval);
328 }
329 return wid;
330 }
331
332 /*
333 * Icarus translated <var> = <delay or event> <value> into
334 * begin
335 * <tmp> = <value>;
336 * <delay or event> <var> = <tmp>;
337 * end
338 * This routine looks for this pattern and turns it back into the
339 * appropriate blocking assignment.
340 */
is_delayed_or_event_assign(ivl_scope_t scope,ivl_statement_t stmt)341 static unsigned is_delayed_or_event_assign(ivl_scope_t scope,
342 ivl_statement_t stmt)
343 {
344 unsigned wid;
345 ivl_statement_t assign, delay, delayed_assign;
346 ivl_statement_type_t delay_type;
347 ivl_lval_t lval;
348 ivl_expr_t rval;
349 ivl_signal_t lsig, rsig;
350
351 /* We must have two block elements. */
352 if (ivl_stmt_block_count(stmt) != 2) return 0;
353 /* The first must be an assign. */
354 assign = ivl_stmt_block_stmt(stmt, 0);
355 if (ivl_statement_type(assign) != IVL_ST_ASSIGN) return 0;
356 /* The second must be a delayx. */
357 delay = ivl_stmt_block_stmt(stmt, 1);
358 delay_type = ivl_statement_type(delay);
359 if ((delay_type != IVL_ST_DELAYX) &&
360 (delay_type != IVL_ST_WAIT)) return 0;
361 /* The statement for the delayx must be an assign. */
362 delayed_assign = ivl_stmt_sub_stmt(delay);
363 if (ivl_statement_type(delayed_assign) != IVL_ST_ASSIGN) return 0;
364 /* The L-value must be a single signal. */
365 if (ivl_stmt_lvals(assign) != 1) return 0;
366 lval = ivl_stmt_lval(assign, 0);
367 /* It must not have an array select. */
368 if (ivl_lval_idx(lval)) return 0;
369 /* It must not have a non-zero base. */
370 if (ivl_lval_part_off(lval)) return 0;
371 lsig = ivl_lval_sig(lval);
372 /* It must not be part of the signal. */
373 if (ivl_lval_width(lval) != ivl_signal_width(lsig)) return 0;
374 /* The R-value must be a single signal. */
375 rval = ivl_stmt_rval(delayed_assign);
376 if (ivl_expr_type(rval) != IVL_EX_SIGNAL) return 0;
377 /* It must not be an array word. */
378 if (ivl_expr_oper1(rval)) return 0;
379 rsig = ivl_expr_signal(rval);
380 /* The two signals must be the same. */
381 if (lsig != rsig) return 0;
382 /* And finally the three statements must have the same line number
383 * as the block. */
384 if ((ivl_stmt_lineno(stmt) != ivl_stmt_lineno(assign)) ||
385 (ivl_stmt_lineno(stmt) != ivl_stmt_lineno(delay)) ||
386 (ivl_stmt_lineno(stmt) != ivl_stmt_lineno(delayed_assign))) {
387 return 0;
388 }
389
390 /* The pattern matched so generate the appropriate code. */
391 fprintf(vlog_out, "%*c", get_indent(), ' ');
392 wid = emit_stmt_lval(scope, delayed_assign);
393 fprintf(vlog_out, " = ");
394 if (delay_type == IVL_ST_DELAYX) {
395 fprintf(vlog_out, "#(");
396 emit_scaled_delayx(scope, ivl_stmt_delay_expr(delay), 1);
397 } else {
398 fprintf(vlog_out, "@(");
399 emit_event(scope, delay);
400 }
401 fprintf(vlog_out, ") ");
402 emit_expr(scope, ivl_stmt_rval(assign), wid, 1, 0, 0);
403 fprintf(vlog_out, ";");
404 emit_stmt_file_line(stmt);
405 fprintf(vlog_out, "\n");
406
407 return 1;
408 }
409
410 /*
411 * A common routine to emit the basic assignment construct. It can also
412 * translate an assignment with an opcode when allowed.
413 */
emit_assign_and_opt_opcode(ivl_scope_t scope,ivl_statement_t stmt,unsigned allow_opcode)414 static void emit_assign_and_opt_opcode(ivl_scope_t scope, ivl_statement_t stmt,
415 unsigned allow_opcode)
416 {
417 unsigned wid;
418 char opcode;
419 const char *opcode_str;
420
421 assert (ivl_statement_type(stmt) == IVL_ST_ASSIGN);
422 // HERE: Do we need to calculate the width? The compiler should have already
423 // done this for us.
424 wid = emit_stmt_lval(scope, stmt);
425 /* Get the opcode and the string version of the opcode. */
426 opcode = ivl_stmt_opcode(stmt);
427 switch (opcode) {
428 case 0: opcode_str = ""; break;
429 case '+': opcode_str = "+"; break;
430 case '-': opcode_str = "-"; break;
431 case '*': opcode_str = "*"; break;
432 case '/': opcode_str = "/"; break;
433 case '%': opcode_str = "%"; break;
434 case '&': opcode_str = "&"; break;
435 case '|': opcode_str = "|"; break;
436 case '^': opcode_str = "^"; break;
437 case 'l': opcode_str = "<<"; break;
438 case 'r': opcode_str = ">>"; break;
439 case 'R': opcode_str = ">>>"; break;
440 default:
441 fprintf(stderr, "%s:%u: vlog95 error: unknown assignment operator "
442 "(%c).\n",
443 ivl_stmt_file(stmt), ivl_stmt_lineno(stmt),
444 opcode);
445 vlog_errors += 1;
446 opcode_str = "<unknown>";
447 break;
448 }
449 if (opcode && ! allow_opcode) {
450 fprintf(stderr, "%s:%u: vlog95 error: assignment operator %s= is "
451 "not allowed in this context.\n",
452 ivl_stmt_file(stmt), ivl_stmt_lineno(stmt),
453 opcode_str);
454 vlog_errors += 1;
455 }
456 fprintf(vlog_out, " = ");
457 if (opcode) {
458 unsigned twid = emit_stmt_lval(scope, stmt);
459 assert(twid == wid);
460 fprintf(vlog_out, " %s ", opcode_str);
461 /* The >>>= assignment operator is only allowed when the allow
462 * signed flag is true. */
463 if ((! allow_signed) && (opcode == 'R')) {
464 fprintf(stderr, "%s:%u: vlog95 error: >>>= operator is not "
465 "supported.\n",
466 ivl_stmt_file(stmt), ivl_stmt_lineno(stmt));
467 vlog_errors += 1;
468 }
469 }
470 emit_expr(scope, ivl_stmt_rval(stmt), wid, 1, 0, 0);
471 }
472
473 /*
474 * Icarus translated for(<assign>; <cond>; <incr_assign>) <body> into
475 *
476 * begin
477 * <assign>;
478 * while (<cond>) begin
479 * <body>
480 * <incr_assign>
481 * end
482 * end
483 * This routine looks for this pattern and turns it back into the
484 * appropriate for loop.
485 */
is_for_loop(ivl_scope_t scope,ivl_statement_t stmt)486 static unsigned is_for_loop(ivl_scope_t scope, ivl_statement_t stmt)
487 {
488 ivl_statement_t assign, while_lp, while_blk, body, incr_assign;
489
490 /* We must have two block elements. */
491 if (ivl_stmt_block_count(stmt) != 2) return 0;
492 /* The first must be an assign. */
493 assign = ivl_stmt_block_stmt(stmt, 0);
494 if (ivl_statement_type(assign) != IVL_ST_ASSIGN) return 0;
495 /* The second must be a while. */
496 while_lp = ivl_stmt_block_stmt(stmt, 1);
497 if (ivl_statement_type(while_lp) != IVL_ST_WHILE) return 0;
498 /* The while statement must be a block. */
499 while_blk = ivl_stmt_sub_stmt(while_lp);
500 if (ivl_statement_type(while_blk) != IVL_ST_BLOCK) return 0;
501 /* It must not be a named block. */
502 if (ivl_stmt_block_scope(while_blk)) return 0;
503 /* It must have two elements. */
504 if (ivl_stmt_block_count(while_blk) != 2) return 0;
505 /* The first block element (the body) can be anything. */
506 body = ivl_stmt_block_stmt(while_blk, 0);
507 /* The second block element must be the increment assign. */
508 incr_assign = ivl_stmt_block_stmt(while_blk, 1);
509 if (ivl_statement_type(incr_assign) != IVL_ST_ASSIGN) return 0;
510 /* And finally the for statements must have the same line number
511 * as the block. */
512 if ((ivl_stmt_lineno(stmt) != ivl_stmt_lineno(assign)) ||
513 (ivl_stmt_lineno(stmt) != ivl_stmt_lineno(while_lp)) ||
514 (ivl_stmt_lineno(stmt) != ivl_stmt_lineno(while_blk)) ||
515 (ivl_stmt_lineno(stmt) != ivl_stmt_lineno(incr_assign))) {
516 return 0;
517 }
518
519 /* The pattern matched so generate the appropriate code. */
520 fprintf(vlog_out, "%*cfor(", get_indent(), ' ');
521 /* Emit the initialization statement (no opcode is allowed). */
522 emit_assign_and_opt_opcode(scope, assign, 0);
523 fprintf(vlog_out, "; ");
524 /* Emit the condition. */
525 emit_expr(scope, ivl_stmt_cond_expr(while_lp), 0, 0, 0, 0);
526 fprintf(vlog_out, "; ");
527 /* Emit the increment statement (an opcode is allowed). */
528 emit_assign_and_opt_opcode(scope, incr_assign, 1);
529 fprintf(vlog_out, ")");
530 emit_stmt_file_line(stmt);
531 /* Now emit the body. */
532 single_indent = 1;
533 emit_stmt(scope, body);
534
535 return 1;
536 }
537
538 /*
539 * Icarus translated <var> = repeat(<count>) <event> <value> into
540 * begin
541 * <tmp> = <value>;
542 * repeat(<count>) <event>;
543 * <var> = <tmp>;
544 * end
545 * This routine looks for this pattern and turns it back into the
546 * appropriate blocking assignment.
547 */
is_repeat_event_assign(ivl_scope_t scope,ivl_statement_t stmt)548 static unsigned is_repeat_event_assign(ivl_scope_t scope, ivl_statement_t stmt)
549 {
550 unsigned wid;
551 ivl_statement_t assign, event, event_assign, repeat;
552 ivl_lval_t lval;
553 ivl_expr_t rval;
554 ivl_signal_t lsig, rsig;
555
556 /* We must have three block elements. */
557 if (ivl_stmt_block_count(stmt) != 3) return 0;
558 /* The first must be an assign. */
559 assign = ivl_stmt_block_stmt(stmt, 0);
560 if (ivl_statement_type(assign) != IVL_ST_ASSIGN) return 0;
561 /* The second must be a repeat with an event or an event. */
562 repeat = ivl_stmt_block_stmt(stmt, 1);
563 if (ivl_statement_type(repeat) != IVL_ST_REPEAT) return 0;
564 /* The repeat must have an event statement. */
565 event = ivl_stmt_sub_stmt(repeat);
566 if (ivl_statement_type(event) != IVL_ST_WAIT) return 0;
567 /* The third must be an assign. */
568 event_assign = ivl_stmt_block_stmt(stmt, 2);
569 if (ivl_statement_type(event_assign) != IVL_ST_ASSIGN) return 0;
570 /* The L-value must be a single signal. */
571 if (ivl_stmt_lvals(assign) != 1) return 0;
572 lval = ivl_stmt_lval(assign, 0);
573 /* It must not have an array select. */
574 if (ivl_lval_idx(lval)) return 0;
575 /* It must not have a non-zero base. */
576 if (ivl_lval_part_off(lval)) return 0;
577 lsig = ivl_lval_sig(lval);
578 /* It must not be part of the signal. */
579 if (ivl_lval_width(lval) != ivl_signal_width(lsig)) return 0;
580 /* The R-value must be a single signal. */
581 rval = ivl_stmt_rval(event_assign);
582 if (ivl_expr_type(rval) != IVL_EX_SIGNAL) return 0;
583 /* It must not be an array word. */
584 if (ivl_expr_oper1(rval)) return 0;
585 rsig = ivl_expr_signal(rval);
586 /* The two signals must be the same. */
587 if (lsig != rsig) return 0;
588 /* And finally the four statements must have the same line number
589 * as the block. */
590 if ((ivl_stmt_lineno(stmt) != ivl_stmt_lineno(assign)) ||
591 (ivl_stmt_lineno(stmt) != ivl_stmt_lineno(repeat)) ||
592 (ivl_stmt_lineno(stmt) != ivl_stmt_lineno(event)) ||
593 (ivl_stmt_lineno(stmt) != ivl_stmt_lineno(event_assign))) {
594 return 0;
595 }
596
597 /* The pattern matched so generate the appropriate code. */
598 fprintf(vlog_out, "%*c", get_indent(), ' ');
599 wid = emit_stmt_lval(scope, event_assign);
600 fprintf(vlog_out, " =");
601 if (repeat) {
602 fprintf(vlog_out, " repeat (");
603 emit_expr(scope, ivl_stmt_cond_expr(repeat), 0, 0, 0, 0);
604 fprintf(vlog_out, ")");
605 }
606 fprintf(vlog_out, " @(");
607 emit_event(scope, event);
608 fprintf(vlog_out, ") ");
609 emit_expr(scope, ivl_stmt_rval(assign), wid, 1, 0, 0);
610 fprintf(vlog_out, ";");
611 emit_stmt_file_line(stmt);
612 fprintf(vlog_out, "\n");
613
614 return 1;
615 }
616
617 /*
618 * Icarus translated wait(<expr) <stmt> into
619 * begin
620 * while (<expr> !== 1'b1) @(<expr sensitivities>);
621 * <stmt>
622 * end
623 * This routine looks for this pattern and turns it back into a
624 * wait statement.
625 */
is_wait(ivl_scope_t scope,ivl_statement_t stmt)626 static unsigned is_wait(ivl_scope_t scope, ivl_statement_t stmt)
627 {
628 ivl_statement_t while_wait, wait, wait_stmt;
629 ivl_expr_t while_expr, expr;
630 const char *bits;
631 /* We must have two block elements. */
632 if (ivl_stmt_block_count(stmt) != 2) return 0;
633 /* The first must be a while. */
634 while_wait = ivl_stmt_block_stmt(stmt, 0);
635 if (ivl_statement_type(while_wait) != IVL_ST_WHILE) return 0;
636 /* That has a wait with a NOOP statement. */
637 wait = ivl_stmt_sub_stmt(while_wait);
638 if (ivl_statement_type(wait) != IVL_ST_WAIT) return 0;
639 wait_stmt = ivl_stmt_sub_stmt(wait);
640 if (ivl_statement_type(wait_stmt) != IVL_ST_NOOP) return 0;
641 /* Check that the while condition has the correct form. */
642 while_expr = ivl_stmt_cond_expr(while_wait);
643 if (ivl_expr_type(while_expr) != IVL_EX_BINARY) return 0;
644 if (ivl_expr_opcode(while_expr) != 'N') return 0;
645 /* Has a second operator that is a constant 1'b1. */
646 expr = ivl_expr_oper2(while_expr);
647 if (ivl_expr_type(expr) != IVL_EX_NUMBER) return 0;
648 if (ivl_expr_width(expr) != 1) return 0;
649 bits = ivl_expr_bits(expr);
650 if (*bits != '1') return 0;
651 // HERE: There is no easy way to verify that the @ sensitivity list
652 // matches the first expression so we don't check for that yet.
653 /* And finally the two statements that represent the wait must
654 * have the same line number as the block. */
655 if ((ivl_stmt_lineno(stmt) != ivl_stmt_lineno(while_wait)) ||
656 (ivl_stmt_lineno(stmt) != ivl_stmt_lineno(wait))) {
657 return 0;
658 }
659
660 /* The pattern matched so generate the appropriate code. */
661 fprintf(vlog_out, "%*cwait(", get_indent(), ' ');
662 emit_expr(scope, ivl_expr_oper1(while_expr), 0, 0, 0, 0);
663 fprintf(vlog_out, ")");
664 emit_stmt_file_line(stmt);
665 single_indent = 1;
666 emit_stmt(scope, ivl_stmt_block_stmt(stmt, 1));
667 return 1;
668 }
669
670 /*
671 * Check to see if the statement L-value is a port in the given scope.
672 * If it is return the zero based port number.
673 */
utask_in_port_idx(ivl_scope_t scope,ivl_statement_t stmt)674 static unsigned utask_in_port_idx(ivl_scope_t scope, ivl_statement_t stmt)
675 {
676 unsigned idx, ports = ivl_scope_ports(scope);
677 unsigned first_arg = is_void_function(scope) ? 1 : 0;
678 ivl_lval_t lval = ivl_stmt_lval(stmt, 0);
679 ivl_signal_t lsig = ivl_lval_sig(lval);
680 const char *sig_name;
681 /* The L-value must be a single signal. */
682 if (ivl_stmt_lvals(stmt) != 1) return ports;
683 /* It must not have an array select. */
684 if (ivl_lval_idx(lval)) return ports;
685 /* It must not have a non-zero base. */
686 if (ivl_lval_part_off(lval)) return ports;
687 /* It must not be part of the signal. */
688 if (ivl_lval_width(lval) != ivl_signal_width(lsig)) return ports;
689 /* It must have the same scope as the task. */
690 if (scope != ivl_signal_scope(lsig)) return ports;
691 /* It must be an input or inout port of the task. */
692 sig_name = ivl_signal_basename(lsig);
693 for (idx = first_arg; idx < ports; idx += 1) {
694 ivl_signal_t port = ivl_scope_port(scope, idx);
695 ivl_signal_port_t port_type = ivl_signal_port(port);
696 if ((port_type != IVL_SIP_INPUT) &&
697 (port_type != IVL_SIP_INOUT)) continue;
698 if (strcmp(sig_name, ivl_signal_basename(port)) == 0) break;
699 }
700 return idx;
701 }
702
703 /*
704 * Check to see if the statement R-value is a port in the given scope.
705 * If it is return the zero based port number.
706 */
utask_out_port_idx(ivl_scope_t scope,ivl_statement_t stmt)707 static unsigned utask_out_port_idx(ivl_scope_t scope, ivl_statement_t stmt)
708 {
709 unsigned idx, ports = ivl_scope_ports(scope);
710 unsigned first_arg = is_void_function(scope) ? 1 : 0;
711 ivl_expr_t rval = ivl_stmt_rval(stmt);
712 ivl_signal_t rsig = 0;
713 ivl_expr_type_t expr_type = ivl_expr_type(rval);
714 const char *sig_name;
715 /* We can have a simple signal. */
716 if (expr_type == IVL_EX_SIGNAL) {
717 rsig = ivl_expr_signal(rval);
718 /* Or a simple select of a simple signal. */
719 } else if (expr_type == IVL_EX_SELECT) {
720 ivl_expr_t expr = ivl_expr_oper1(rval);
721 /* We must have a zero select base. */
722 if (ivl_expr_oper2(rval)) return ports;
723 /* We must be selecting a signal. */
724 if (ivl_expr_type(expr) != IVL_EX_SIGNAL) return ports;
725 rsig = ivl_expr_signal(expr);
726 /* Or a cast of a simple signal. */
727 } else if (expr_type == IVL_EX_UNARY) {
728 ivl_expr_t expr = ivl_expr_oper1(rval);
729 char opcode = ivl_expr_opcode(rval);
730 /* This must be a cast opcode. */
731 if ((opcode != '2') && (opcode != 'v') &&
732 (opcode != 'r')) return ports;
733 /* We must be casting a signal. */
734 if (ivl_expr_type(expr) != IVL_EX_SIGNAL) return ports;
735 rsig = ivl_expr_signal(expr);
736 } else return ports;
737 /* The R-value must have the same scope as the task. */
738 if (scope != ivl_signal_scope(rsig)) return ports;
739 /* It must not be an array element. */
740 if (ivl_signal_dimensions(rsig)) return ports;
741 /* It must be an output or inout port of the task. */
742 sig_name = ivl_signal_basename(rsig);
743 for (idx = first_arg; idx < ports; idx += 1) {
744 ivl_signal_t port = ivl_scope_port(scope, idx);
745 ivl_signal_port_t port_type = ivl_signal_port(port);
746 if ((port_type != IVL_SIP_OUTPUT) &&
747 (port_type != IVL_SIP_INOUT)) continue;
748 if (strcmp(sig_name, ivl_signal_basename(port)) == 0) break;
749 }
750 return idx;
751 }
752
753 /*
754 * Structure to hold the port information as we extract it from the block.
755 */
756 typedef struct port_expr_s {
757 ivl_signal_port_t type;
758 union {
759 ivl_statement_t lval;
760 ivl_expr_t rval;
761 } expr;
762 } *port_expr_t;
763
764 /*
765 * An input prints the R-value and an output or inout print the L-value.
766 */
emit_port(ivl_scope_t scope,struct port_expr_s port_expr)767 static void emit_port(ivl_scope_t scope, struct port_expr_s port_expr)
768 {
769 if (port_expr.type == IVL_SIP_INPUT) {
770 // HERE: For a user should the argument width be used here.
771 emit_expr(scope, port_expr.expr.rval, 0, 1, 0, 0);
772 } else {
773 /* This is a self-determined context so we don't care about
774 * the width of the L-value. */
775 (void) emit_stmt_lval(scope, port_expr.expr.lval);
776 }
777 }
778
779 /*
780 * Icarus encodes a user task call with arguments as:
781 * begin
782 * <input 1> = <arg>
783 * ...
784 * <input n> = <arg>
785 * <task_call>
786 * <arg> = <output 1>
787 * ...
788 * <arg> = <output n>
789 * end
790 * This routine looks for that pattern and translates it into the
791 * appropriate task call. It returns true (1) if it successfully
792 * translated the block to a task call, otherwise it returns false
793 * (0) to indicate the block needs to be emitted.
794 *
795 * When calling automatic tasks there is an initial ALLOC statement
796 * and a final FREE statement.
797 */
is_utask_call_with_args(ivl_scope_t scope,ivl_statement_t stmt)798 static unsigned is_utask_call_with_args(ivl_scope_t scope,
799 ivl_statement_t stmt)
800 {
801 unsigned idx, ports, task_idx = 0;
802 unsigned count = ivl_stmt_block_count(stmt);
803 unsigned lineno = ivl_stmt_lineno(stmt);
804 unsigned start, stop, is_auto = 0;
805 ivl_scope_t task_scope = 0;
806 unsigned is_void_func = 0;
807 port_expr_t port_exprs;
808 /* Check to see if the block is of the basic form first. */
809 for (idx = 0; idx < count; idx += 1) {
810 ivl_statement_t tmp = ivl_stmt_block_stmt(stmt, idx);
811 /* For an automatic task the ALLOC must be first. */
812 if (ivl_statement_type(tmp) == IVL_ST_ALLOC) {
813 if (idx == 0) {
814 is_auto = 1;
815 continue;
816 }
817 }
818 if (ivl_statement_type(tmp) == IVL_ST_ASSIGN) continue;
819 if (ivl_statement_type(tmp) == IVL_ST_UTASK && !task_scope) {
820 task_idx = idx;
821 task_scope = ivl_stmt_call(tmp);
822 is_void_func = is_void_function(task_scope);
823 assert(ivl_scope_type(task_scope) == IVL_SCT_TASK || is_void_func);
824 continue;
825 }
826 /* For an automatic task the FREE must be last. */
827 if (ivl_statement_type(tmp) == IVL_ST_FREE) {
828 if (idx == count-1) {
829 if (is_auto) continue;
830 }
831 }
832 return 0;
833 }
834 /* If there is no task call or it takes no argument then return. */
835 if (!task_scope) return 0;
836 ports = ivl_scope_ports(task_scope);
837 if (ports == 0) return 0;
838
839 /* Allocate space to save the port information and initialize it. */
840 port_exprs = (port_expr_t) malloc(sizeof(struct port_expr_s)*ports);
841 for (idx = 0; idx < ports; idx += 1) {
842 port_exprs[idx].type = IVL_SIP_NONE;
843 port_exprs[idx].expr.rval = 0;
844 }
845
846 /* Check that the input arguments are correct. */
847 if (is_auto) start = 1;
848 else start = 0;
849 for (idx = start; idx < task_idx; idx += 1) {
850 ivl_statement_t assign = ivl_stmt_block_stmt(stmt, idx);
851 unsigned port = utask_in_port_idx(task_scope, assign);
852 if ((port == ports) || (lineno != ivl_stmt_lineno(assign))) {
853 free(port_exprs);
854 return 0;
855 }
856 port_exprs[port].type = IVL_SIP_INPUT;
857 port_exprs[port].expr.rval = ivl_stmt_rval(assign);
858 }
859 /* Check that the output arguments are correct. */
860 if (is_auto) stop = count-1;
861 else stop = count;
862 for (idx = task_idx + 1; idx < stop; idx += 1) {
863 ivl_statement_t assign = ivl_stmt_block_stmt(stmt, idx);
864 unsigned port = utask_out_port_idx(task_scope, assign);
865 if ((port == ports) || (lineno != ivl_stmt_lineno(assign))) {
866 free(port_exprs);
867 return 0;
868 }
869 if (port_exprs[port].type == IVL_SIP_INPUT) {
870 port_exprs[port].type = IVL_SIP_INOUT;
871 // HERE: We probably should verify that the current R-value matches the
872 // new L-value.
873 } else {
874 port_exprs[port].type = IVL_SIP_OUTPUT;
875 }
876 port_exprs[port].expr.lval = assign;
877 }
878 /* Check that the task call has the correct line number. */
879 if (lineno != ivl_stmt_lineno(ivl_stmt_block_stmt(stmt, task_idx))) {
880 free(port_exprs);
881 return 0;
882 }
883
884 /* Verify that all the ports were defined. */
885 start = is_void_func ? 1 : 0;
886 for (idx = start; idx < ports; idx += 1) {
887 if (port_exprs[idx].type == IVL_SIP_NONE) {
888 free(port_exprs);
889 return 0;
890 }
891 }
892
893 /* Now that we have the arguments figured out, print the task call. */
894 fprintf(vlog_out, "%*c", get_indent(), ' ');
895 if (is_void_func)
896 fprintf(vlog_out, "if (");
897 emit_scope_path(scope, task_scope);
898 fprintf(vlog_out, "(");
899 emit_port(scope, port_exprs[start]);
900 for (idx = start + 1; idx < ports; idx += 1) {
901 fprintf(vlog_out, ", ");
902 emit_port(scope, port_exprs[idx]);
903 }
904 free(port_exprs);
905 if (is_void_func)
906 fprintf(vlog_out, ")");
907 fprintf(vlog_out, ");");
908 emit_stmt_file_line(stmt);
909 fprintf(vlog_out, "\n");
910 return 1;
911 }
912
emit_stmt_assign(ivl_scope_t scope,ivl_statement_t stmt)913 static void emit_stmt_assign(ivl_scope_t scope, ivl_statement_t stmt)
914 {
915 fprintf(vlog_out, "%*c", get_indent(), ' ');
916 /* Emit the basic assignment (an opcode is allowed).*/
917 emit_assign_and_opt_opcode(scope, stmt, 1);
918 fprintf(vlog_out, ";");
919 emit_stmt_file_line(stmt);
920 fprintf(vlog_out, "\n");
921 }
922
emit_stmt_assign_nb(ivl_scope_t scope,ivl_statement_t stmt)923 static void emit_stmt_assign_nb(ivl_scope_t scope, ivl_statement_t stmt)
924 {
925 unsigned wid;
926 fprintf(vlog_out, "%*c", get_indent(), ' ');
927 // HERE: Do we need to calculate the width? The compiler should have already
928 // done this for us.
929 wid = emit_stmt_lval(scope, stmt);
930 fprintf(vlog_out, " <= ");
931 emit_stmt_inter_delay(scope, stmt);
932 emit_expr(scope, ivl_stmt_rval(stmt), wid, 1, 0, 0);
933 fprintf(vlog_out, ";");
934 emit_stmt_file_line(stmt);
935 fprintf(vlog_out, "\n");
936 }
937
emit_stmt_block(ivl_scope_t scope,ivl_statement_t stmt)938 static void emit_stmt_block(ivl_scope_t scope, ivl_statement_t stmt)
939 {
940 fprintf(vlog_out, "%*cbegin", get_indent(), ' ');
941 emit_stmt_file_line(stmt);
942 fprintf(vlog_out, "\n");
943 emit_stmt_block_body(scope, stmt);
944 fprintf(vlog_out, "%*cend\n", get_indent(), ' ');
945 }
946
emit_stmt_block_named(ivl_scope_t scope,ivl_statement_t stmt)947 static void emit_stmt_block_named(ivl_scope_t scope, ivl_statement_t stmt)
948 {
949 ivl_scope_t my_scope = ivl_stmt_block_scope(stmt);
950 fprintf(vlog_out, "%*cbegin: ", get_indent(), ' ');
951 emit_id(ivl_scope_basename(my_scope));
952 emit_stmt_file_line(stmt);
953 fprintf(vlog_out, "\n");
954 emit_stmt_block_body(scope, stmt);
955 fprintf(vlog_out, "%*cend /* %s */\n", get_indent(), ' ',
956 ivl_scope_basename(my_scope));
957 }
958
emit_stmt_case(ivl_scope_t scope,ivl_statement_t stmt)959 static void emit_stmt_case(ivl_scope_t scope, ivl_statement_t stmt)
960 {
961 const char *case_type = 0;
962 unsigned idx, default_case, count = ivl_stmt_case_count(stmt);
963 switch (ivl_statement_type(stmt)) {
964 case IVL_ST_CASE:
965 case IVL_ST_CASER:
966 case_type = "case";
967 break;
968 case IVL_ST_CASEX:
969 case_type = "casex";
970 break;
971 case IVL_ST_CASEZ:
972 case_type = "casez";
973 break;
974 default:
975 assert(0);
976 }
977 fprintf(vlog_out, "%*c%s (", get_indent(), ' ', case_type);
978 emit_expr(scope, ivl_stmt_cond_expr(stmt), 0, 0, 0, 0);
979 fprintf(vlog_out, ")");
980 emit_stmt_file_line(stmt);
981 fprintf(vlog_out, "\n");
982 indent += indent_incr;
983 default_case = count;
984 for (idx = 0; idx < count; idx += 1) {
985 ivl_expr_t expr = ivl_stmt_case_expr(stmt, idx);
986 /* This is the default case so emit it last. */
987 if (expr == 0) {
988 assert(default_case == count);
989 default_case = idx;
990 continue;
991 }
992 fprintf(vlog_out, "%*c", get_indent(), ' ');
993 emit_expr(scope, expr, 0, 0, 0, 0);
994 fprintf(vlog_out, ":");
995 single_indent = 1;
996 emit_stmt(scope, ivl_stmt_case_stmt(stmt, idx));
997 }
998 if (default_case < count) {
999 fprintf(vlog_out, "%*cdefault:", get_indent(), ' ');
1000 single_indent = 1;
1001 emit_stmt(scope, ivl_stmt_case_stmt(stmt, default_case));
1002 }
1003 assert(indent >= indent_incr);
1004 indent -= indent_incr;
1005 fprintf(vlog_out, "%*cendcase\n", get_indent(), ' ');
1006 }
1007
emit_stmt_cassign(ivl_scope_t scope,ivl_statement_t stmt)1008 static void emit_stmt_cassign(ivl_scope_t scope, ivl_statement_t stmt)
1009 {
1010 unsigned wid;
1011 fprintf(vlog_out, "%*cassign ", get_indent(), ' ');
1012 // HERE: Do we need to calculate the width? The compiler should have already
1013 // done this for us.
1014 wid = emit_stmt_lval(scope, stmt);
1015 fprintf(vlog_out, " = ");
1016 emit_expr(scope, ivl_stmt_rval(stmt), wid, 1, 0, 0);
1017 fprintf(vlog_out, ";");
1018 emit_stmt_file_line(stmt);
1019 fprintf(vlog_out, "\n");
1020 }
1021
emit_stmt_condit(ivl_scope_t scope,ivl_statement_t stmt)1022 static void emit_stmt_condit(ivl_scope_t scope, ivl_statement_t stmt)
1023 {
1024 ivl_statement_t true_stmt = ivl_stmt_cond_true(stmt);
1025 ivl_statement_t false_stmt = ivl_stmt_cond_false(stmt);
1026 unsigned nest = 0;
1027 fprintf(vlog_out, "%*cif (", get_indent(), ' ');
1028 emit_expr(scope, ivl_stmt_cond_expr(stmt), 0, 0, 0, 0);
1029 fprintf(vlog_out, ")");
1030 emit_stmt_file_line(stmt);
1031 if (true_stmt) {
1032 /* If we have a false statement and the true statement is a
1033 * condition that does not have a false clause then we need
1034 * to add a begin/end pair to keep the else clause attached
1035 * to this condition. */
1036 if (false_stmt &&
1037 (ivl_statement_type(true_stmt) == IVL_ST_CONDIT) &&
1038 (! ivl_stmt_cond_false(true_stmt))) nest = 1;
1039 if (nest) {
1040 fprintf(vlog_out, " begin\n");
1041 indent += indent_incr;
1042 } else single_indent = 1;
1043 emit_stmt(scope, true_stmt);
1044 } else {
1045 fprintf(vlog_out, ";\n");
1046 }
1047 if (false_stmt) {
1048 if (nest) {
1049 assert(indent >= indent_incr);
1050 indent -= indent_incr;
1051 }
1052 fprintf(vlog_out, "%*c", get_indent(), ' ');
1053 if (nest) fprintf(vlog_out, "end ");
1054 fprintf(vlog_out, "else");
1055 single_indent = 1;
1056 emit_stmt(scope, false_stmt);
1057 }
1058 }
1059
emit_stmt_deassign(ivl_scope_t scope,ivl_statement_t stmt)1060 static void emit_stmt_deassign(ivl_scope_t scope, ivl_statement_t stmt)
1061 {
1062 fprintf(vlog_out, "%*cdeassign ", get_indent(), ' ');
1063 (void) emit_stmt_lval(scope, stmt);
1064 fprintf(vlog_out, ";");
1065 emit_stmt_file_line(stmt);
1066 fprintf(vlog_out, "\n");
1067 }
1068
emit_stmt_delay(ivl_scope_t scope,ivl_statement_t stmt)1069 static void emit_stmt_delay(ivl_scope_t scope, ivl_statement_t stmt)
1070 {
1071 fprintf(vlog_out, "%*c#", get_indent(), ' ');
1072 emit_scaled_delay(scope, ivl_stmt_delay_val(stmt));
1073 emit_stmt_file_line(stmt);
1074 single_indent = 1;
1075 emit_stmt(scope, ivl_stmt_sub_stmt(stmt));
1076 }
1077
emit_stmt_delayx(ivl_scope_t scope,ivl_statement_t stmt)1078 static void emit_stmt_delayx(ivl_scope_t scope, ivl_statement_t stmt)
1079 {
1080 fprintf(vlog_out, "%*c#(", get_indent(), ' ');
1081 emit_scaled_delayx(scope, ivl_stmt_delay_expr(stmt), 1);
1082 fprintf(vlog_out, ")");
1083 emit_stmt_file_line(stmt);
1084 single_indent = 1;
1085 emit_stmt(scope, ivl_stmt_sub_stmt(stmt));
1086 }
1087
is_func_disable(ivl_scope_t scope,ivl_scope_t disable_scope)1088 static unsigned is_func_disable(ivl_scope_t scope, ivl_scope_t disable_scope)
1089 {
1090 assert(func_rtn_name);
1091 /* Find the enclosing function scope. */
1092 while (ivl_scope_type(scope) != IVL_SCT_FUNCTION) {
1093 scope = ivl_scope_parent(scope);
1094 assert(scope);
1095 }
1096 /* If the function scope and the scope to be disabled match then this
1097 * is a function disable (SystemVerilog return). */
1098 return scope == disable_scope;
1099 }
1100
emit_stmt_disable(ivl_scope_t scope,ivl_statement_t stmt)1101 static void emit_stmt_disable(ivl_scope_t scope, ivl_statement_t stmt)
1102 {
1103 ivl_scope_t disable_scope = ivl_stmt_call(stmt);
1104 fprintf(vlog_out, "%*cdisable ", get_indent(), ' ');
1105 /* A normal disable statement. */
1106 if (disable_scope) {
1107 /* If this disable is in a function and it is disabling the
1108 * function then emit the appropriate function return name. */
1109 if (func_rtn_name && is_func_disable(scope, disable_scope)) {
1110 fprintf(vlog_out, "%s", func_rtn_name);
1111 } else emit_scope_path(scope, disable_scope);
1112 /* A SystemVerilog disable fork statement cannot be converted. */
1113 } else {
1114 fprintf(vlog_out, "fork");
1115 fprintf(stderr, "%s:%u: vlog95 sorry: disable fork is not "
1116 "currently translated.\n",
1117 ivl_stmt_file(stmt),
1118 ivl_stmt_lineno(stmt));
1119 vlog_errors += 1;
1120 }
1121 fprintf(vlog_out, ";");
1122 emit_stmt_file_line(stmt);
1123 fprintf(vlog_out, "\n");
1124 }
1125
1126 /*
1127 * Emit just the statements for this named block since an outer named block
1128 * was added to keep all the translated code inside a single named block.
1129 */
emit_stmt_do_while_body(ivl_scope_t scope,ivl_statement_t stmt)1130 static void emit_stmt_do_while_body(ivl_scope_t scope, ivl_statement_t stmt)
1131 {
1132 unsigned idx, count = ivl_stmt_block_count(stmt);
1133 unsigned is_begin = 0;
1134 assert(ivl_stmt_block_scope(stmt));
1135 switch (ivl_statement_type(stmt)) {
1136 case IVL_ST_BLOCK:
1137 fprintf(vlog_out, "%*cbegin", get_indent(), ' ');
1138 is_begin = 1;
1139 break;
1140 case IVL_ST_FORK_JOIN_ANY:
1141 fprintf(stderr, "%s:%u: vlog95 sorry: fork/join_any is not "
1142 "currently translated.\n",
1143 ivl_stmt_file(stmt),
1144 ivl_stmt_lineno(stmt));
1145 vlog_errors += 1;
1146 return;
1147 case IVL_ST_FORK_JOIN_NONE:
1148 fprintf(stderr, "%s:%u: vlog95 sorry: fork/join_none is not "
1149 "currently translated.\n",
1150 ivl_stmt_file(stmt),
1151 ivl_stmt_lineno(stmt));
1152 vlog_errors += 1;
1153 return;
1154 case IVL_ST_FORK:
1155 fprintf(vlog_out, "%*cfork", get_indent(), ' ');
1156 break;
1157 /* Only named blocks should make it to this code. */
1158 default:
1159 assert(0);
1160 break;
1161 }
1162 emit_stmt_file_line(stmt);
1163 fprintf(vlog_out, "\n");
1164 indent += indent_incr;
1165 for (idx = 0; idx < count; idx += 1) {
1166 emit_stmt(scope, ivl_stmt_block_stmt(stmt, idx));
1167 }
1168 assert(indent >= indent_incr);
1169 indent -= indent_incr;
1170 if (is_begin) fprintf(vlog_out, "%*cend\n", get_indent(), ' ');
1171 else fprintf(vlog_out, "%*cjoin\n", get_indent(), ' ');
1172 }
1173
1174 /*
1175 * Currently a do/while can be translated in two ways: no named blocks in
1176 * the do/while statement and only a named block as the top level statement.
1177 * Anything else cannot be translated since a hierarchical variable reference
1178 * or disable cannot work correctly when the statement is duplicated.
1179 */
1180 typedef enum stmt_named_type_e {
1181 NO_NAMED = 0,
1182 TOP_NAMED = 1,
1183 OTHER_NAMED = 2
1184 } stmt_named_type_t;
1185
1186 static stmt_named_type_t get_named_type(ivl_statement_t stmt, unsigned is_top);
1187
1188 /*
1189 * A block can start as either a NO_NAMED or a TOP_NAMED so pass this in.
1190 */
get_named_type_block(ivl_statement_t stmt,stmt_named_type_t def_type)1191 static stmt_named_type_t get_named_type_block(ivl_statement_t stmt,
1192 stmt_named_type_t def_type)
1193 {
1194 stmt_named_type_t rtn = def_type;
1195 unsigned idx, count = ivl_stmt_block_count(stmt);
1196 for (idx = 0; idx < count; idx += 1) {
1197 stmt_named_type_t lrtn;
1198 lrtn = get_named_type(ivl_stmt_block_stmt(stmt, idx), 0);
1199 if (lrtn > rtn) rtn = lrtn;
1200 if (rtn == OTHER_NAMED) break;
1201 }
1202 return rtn;
1203 }
1204
get_named_type_case(ivl_statement_t stmt)1205 static stmt_named_type_t get_named_type_case(ivl_statement_t stmt)
1206 {
1207 stmt_named_type_t rtn = NO_NAMED;
1208 unsigned idx, count = ivl_stmt_case_count(stmt);
1209 for (idx = 0; idx < count; idx += 1) {
1210 stmt_named_type_t lrtn;
1211 lrtn = get_named_type(ivl_stmt_case_stmt(stmt, idx), 0);
1212 if (lrtn > rtn) rtn = lrtn;
1213 if (rtn == OTHER_NAMED) break;
1214 }
1215 return rtn;
1216 }
1217
get_named_type_condit(ivl_statement_t stmt)1218 static stmt_named_type_t get_named_type_condit(ivl_statement_t stmt)
1219 {
1220 stmt_named_type_t true_rtn, false_rtn;
1221 true_rtn = get_named_type(ivl_stmt_cond_true(stmt), 0);
1222 false_rtn = get_named_type(ivl_stmt_cond_false(stmt), 0);
1223 if (false_rtn > true_rtn) return false_rtn;
1224 return true_rtn;
1225 }
1226
get_named_type(ivl_statement_t stmt,unsigned is_top)1227 static stmt_named_type_t get_named_type(ivl_statement_t stmt, unsigned is_top)
1228 {
1229 stmt_named_type_t rtn = NO_NAMED;
1230
1231 if (! stmt) return NO_NAMED;
1232
1233 switch (ivl_statement_type(stmt)) {
1234 case IVL_ST_BLOCK:
1235 case IVL_ST_FORK:
1236 case IVL_ST_FORK_JOIN_ANY:
1237 case IVL_ST_FORK_JOIN_NONE:
1238 /* Check to see if this is a named top block or sub block. */
1239 if (ivl_stmt_block_scope(stmt)) {
1240 if (is_top) rtn = TOP_NAMED;
1241 else return OTHER_NAMED;
1242 }
1243 rtn = get_named_type_block(stmt, rtn);
1244 break;
1245 case IVL_ST_CASE:
1246 case IVL_ST_CASER:
1247 case IVL_ST_CASEX:
1248 case IVL_ST_CASEZ:
1249 rtn = get_named_type_case(stmt);
1250 break;
1251 case IVL_ST_CONDIT:
1252 rtn = get_named_type_condit(stmt);
1253 break;
1254 /* These statements only have a single sub-statement that is not
1255 * a top level statement relative to the original do/while. */
1256 case IVL_ST_DELAY:
1257 case IVL_ST_DELAYX:
1258 case IVL_ST_DO_WHILE:
1259 case IVL_ST_FOREVER:
1260 case IVL_ST_REPEAT:
1261 case IVL_ST_WAIT:
1262 case IVL_ST_WHILE:
1263 rtn = get_named_type(ivl_stmt_sub_stmt(stmt), 0);
1264 break;
1265 default:
1266 /* The rest of the statement types do not have sub-statements. */
1267 break;
1268 }
1269 return rtn;
1270 }
1271
1272 /*
1273 * Translate a do/while to the following:
1274 *
1275 * statement
1276 * while (expr) statement
1277 */
emit_stmt_do_while(ivl_scope_t scope,ivl_statement_t stmt)1278 static void emit_stmt_do_while(ivl_scope_t scope, ivl_statement_t stmt)
1279 {
1280 ivl_statement_t sub_stmt = ivl_stmt_sub_stmt(stmt);
1281 stmt_named_type_t named_type = get_named_type(sub_stmt, 1);
1282
1283 /* If just the original do/while statement is named then emit it as:
1284 *
1285 * begin : name
1286 * <var defs in named>
1287 * statement
1288 * while (expr) statement
1289 * end
1290 */
1291 if (named_type == TOP_NAMED) {
1292 ivl_scope_t my_scope = ivl_stmt_block_scope(sub_stmt);
1293 assert(my_scope);
1294 fprintf(vlog_out, "%*cbegin: ", get_indent(), ' ');
1295 emit_id(ivl_scope_basename(my_scope));
1296 emit_stmt_file_line(stmt);
1297 fprintf(vlog_out, "\n");
1298 indent += indent_incr;
1299 emit_scope_variables(my_scope);
1300 emit_stmt_do_while_body(my_scope, sub_stmt);
1301 fprintf(vlog_out, "%*cwhile (", get_indent(), ' ');
1302 emit_expr(scope, ivl_stmt_cond_expr(stmt), 0, 0, 0, 0);
1303 fprintf(vlog_out, ")");
1304 emit_stmt_file_line(stmt);
1305 single_indent = 1;
1306 emit_stmt_do_while_body(my_scope, sub_stmt);
1307 assert(indent >= indent_incr);
1308 indent -= indent_incr;
1309 fprintf(vlog_out, "%*cend /* %s */\n", get_indent(), ' ',
1310 ivl_scope_basename(my_scope));
1311 } else {
1312 emit_stmt(scope, sub_stmt);
1313 fprintf(vlog_out, "%*cwhile (", get_indent(), ' ');
1314 emit_expr(scope, ivl_stmt_cond_expr(stmt), 0, 0, 0, 0);
1315 fprintf(vlog_out, ")");
1316 emit_stmt_file_line(stmt);
1317 single_indent = 1;
1318 emit_stmt(scope, sub_stmt);
1319 }
1320
1321 /*
1322 * If the do/while has sub-statements that are named it cannot be
1323 * translated since the original do/while statement needs to be
1324 * duplicated and doing this will create two statements with the
1325 * same name.
1326 */
1327 if (named_type == OTHER_NAMED) {
1328 fprintf(stderr, "%s:%u: vlog95 sorry: do/while with named "
1329 "sub-statements cannot be translated.\n",
1330 ivl_stmt_file(stmt), ivl_stmt_lineno(stmt));
1331 vlog_errors += 1;
1332 }
1333 }
1334
emit_stmt_force(ivl_scope_t scope,ivl_statement_t stmt)1335 static void emit_stmt_force(ivl_scope_t scope, ivl_statement_t stmt)
1336 {
1337 unsigned wid;
1338 fprintf(vlog_out, "%*cforce ", get_indent(), ' ');
1339 // HERE: Do we need to calculate the width? The compiler should have already
1340 // done this for us.
1341 wid = emit_stmt_lval(scope, stmt);
1342 fprintf(vlog_out, " = ");
1343 emit_expr(scope, ivl_stmt_rval(stmt), wid, 1, 0, 0);
1344 fprintf(vlog_out, ";");
1345 emit_stmt_file_line(stmt);
1346 fprintf(vlog_out, "\n");
1347 }
1348
emit_stmt_forever(ivl_scope_t scope,ivl_statement_t stmt)1349 static void emit_stmt_forever(ivl_scope_t scope, ivl_statement_t stmt)
1350 {
1351 fprintf(vlog_out, "%*cforever", get_indent(), ' ');
1352 emit_stmt_file_line(stmt);
1353 single_indent = 1;
1354 emit_stmt(scope, ivl_stmt_sub_stmt(stmt));
1355 }
1356
emit_stmt_fork(ivl_scope_t scope,ivl_statement_t stmt)1357 static void emit_stmt_fork(ivl_scope_t scope, ivl_statement_t stmt)
1358 {
1359 fprintf(vlog_out, "%*cfork", get_indent(), ' ');
1360 emit_stmt_file_line(stmt);
1361 fprintf(vlog_out, "\n");
1362 emit_stmt_block_body(scope, stmt);
1363 fprintf(vlog_out, "%*cjoin\n", get_indent(), ' ');
1364 }
1365
emit_stmt_fork_named(ivl_scope_t scope,ivl_statement_t stmt)1366 static void emit_stmt_fork_named(ivl_scope_t scope, ivl_statement_t stmt)
1367 {
1368 ivl_scope_t my_scope = ivl_stmt_block_scope(stmt);
1369 fprintf(vlog_out, "%*cfork: ", get_indent(), ' ');
1370 emit_id(ivl_scope_basename(my_scope));
1371 emit_stmt_file_line(stmt);
1372 fprintf(vlog_out, "\n");
1373 emit_stmt_block_body(scope, stmt);
1374 fprintf(vlog_out, "%*cjoin /* %s */\n", get_indent(), ' ',
1375 ivl_scope_basename(my_scope));
1376 }
1377
emit_stmt_release(ivl_scope_t scope,ivl_statement_t stmt)1378 static void emit_stmt_release(ivl_scope_t scope, ivl_statement_t stmt)
1379 {
1380 fprintf(vlog_out, "%*crelease ", get_indent(), ' ');
1381 (void) emit_stmt_lval(scope, stmt);
1382 fprintf(vlog_out, ";");
1383 emit_stmt_file_line(stmt);
1384 fprintf(vlog_out, "\n");
1385 }
1386
emit_stmt_repeat(ivl_scope_t scope,ivl_statement_t stmt)1387 static void emit_stmt_repeat(ivl_scope_t scope, ivl_statement_t stmt)
1388 {
1389 fprintf(vlog_out, "%*crepeat (", get_indent(), ' ');
1390 emit_expr(scope, ivl_stmt_cond_expr(stmt), 0, 0, 0, 0);
1391 fprintf(vlog_out, ")");
1392 emit_stmt_file_line(stmt);
1393 single_indent = 1;
1394 emit_stmt(scope, ivl_stmt_sub_stmt(stmt));
1395 }
1396
emit_stmt_stask(ivl_scope_t scope,ivl_statement_t stmt)1397 static void emit_stmt_stask(ivl_scope_t scope, ivl_statement_t stmt)
1398 {
1399 unsigned count = ivl_stmt_parm_count(stmt);
1400 fprintf(vlog_out, "%*c%s", get_indent(), ' ', ivl_stmt_name(stmt));
1401 if (count != 0) {
1402 unsigned idx;
1403 ivl_expr_t expr;
1404 fprintf(vlog_out, "(");
1405 count -= 1;
1406 for (idx = 0; idx < count; idx += 1) {
1407 expr = ivl_stmt_parm(stmt, idx);
1408 if (expr) emit_expr(scope, expr, 0, 0, 0, 0);
1409 fprintf(vlog_out, ", ");
1410 }
1411 expr = ivl_stmt_parm(stmt, count);
1412 if (expr) emit_expr(scope, expr, 0, 0, 0, 0);
1413 fprintf(vlog_out, ")");
1414 }
1415 fprintf(vlog_out, ";");
1416 emit_stmt_file_line(stmt);
1417 fprintf(vlog_out, "\n");
1418 }
1419
emit_stmt_trigger(ivl_scope_t scope,ivl_statement_t stmt)1420 static void emit_stmt_trigger(ivl_scope_t scope, ivl_statement_t stmt)
1421 {
1422 fprintf(vlog_out, "%*c-> ", get_indent(), ' ');
1423 assert(ivl_stmt_nevent(stmt) == 1);
1424 emit_event(scope, stmt);
1425 fprintf(vlog_out, ";");
1426 emit_stmt_file_line(stmt);
1427 fprintf(vlog_out, "\n");
1428 }
1429
1430 /*
1431 * A user defined task call with arguments is generated as a block with
1432 * input assignments, a simple call and then output assignments. This is
1433 * handled by the is_utask_call_with_args() routine above.
1434 */
emit_stmt_utask(ivl_scope_t scope,ivl_statement_t stmt)1435 static void emit_stmt_utask(ivl_scope_t scope, ivl_statement_t stmt)
1436 {
1437 ivl_scope_t task_scope = ivl_stmt_call(stmt);
1438 assert((ivl_scope_type(task_scope) == IVL_SCT_TASK
1439 && ivl_scope_ports(task_scope) == 0)
1440 || (is_void_function(task_scope)
1441 && ivl_scope_ports(task_scope) == 1));
1442 fprintf(vlog_out, "%*c", get_indent(), ' ');
1443 if (is_void_function(task_scope))
1444 fprintf(vlog_out, "if (");
1445 emit_scope_path(scope, task_scope);
1446 if (is_void_function(task_scope))
1447 fprintf(vlog_out, "(1'bx))");
1448 fprintf(vlog_out, ";");
1449 emit_stmt_file_line(stmt);
1450 fprintf(vlog_out, "\n");
1451 }
1452
1453 /* Look to see if this is a SystemVerilog wait fork statement. */
is_wait_fork(ivl_scope_t scope,ivl_statement_t stmt)1454 static unsigned is_wait_fork(ivl_scope_t scope, ivl_statement_t stmt)
1455 {
1456 (void)scope; /* Parameter is not used. */
1457 if (ivl_stmt_nevent(stmt) != 1) return 0;
1458 if (ivl_stmt_events(stmt, 0) != 0) return 0;
1459 assert(ivl_statement_type(ivl_stmt_sub_stmt(stmt)) == IVL_ST_NOOP);
1460
1461 fprintf(vlog_out, "%*cwait fork;", get_indent(), ' ');
1462 emit_stmt_file_line(stmt);
1463 fprintf(vlog_out, "\n");
1464 fprintf(stderr, "%s:%u: vlog95 sorry: wait fork is not currently "
1465 "translated.\n",
1466 ivl_stmt_file(stmt), ivl_stmt_lineno(stmt));
1467 vlog_errors += 1;
1468 return 1;
1469 }
1470
emit_stmt_wait(ivl_scope_t scope,ivl_statement_t stmt)1471 static void emit_stmt_wait(ivl_scope_t scope, ivl_statement_t stmt)
1472 {
1473 fprintf(vlog_out, "%*c@(", get_indent(), ' ');
1474 emit_event(scope, stmt);
1475 fprintf(vlog_out, ")");
1476 emit_stmt_file_line(stmt);
1477 single_indent = 1;
1478 emit_stmt(scope, ivl_stmt_sub_stmt(stmt));
1479 }
1480
emit_stmt_while(ivl_scope_t scope,ivl_statement_t stmt)1481 static void emit_stmt_while(ivl_scope_t scope, ivl_statement_t stmt)
1482 {
1483 fprintf(vlog_out, "%*cwhile (", get_indent(), ' ');
1484 emit_expr(scope, ivl_stmt_cond_expr(stmt), 0, 0, 0, 0);
1485 fprintf(vlog_out, ")");
1486 emit_stmt_file_line(stmt);
1487 single_indent = 1;
1488 emit_stmt(scope, ivl_stmt_sub_stmt(stmt));
1489 }
1490
emit_stmt(ivl_scope_t scope,ivl_statement_t stmt)1491 void emit_stmt(ivl_scope_t scope, ivl_statement_t stmt)
1492 {
1493 switch (ivl_statement_type(stmt)) {
1494 case IVL_ST_NOOP:
1495 /* If this is a statement termination then just finish the
1496 * statement, otherwise print an empty begin/end pair. */
1497 if (single_indent) {
1498 single_indent = 0;
1499 fprintf(vlog_out, ";\n");
1500 } else {
1501 fprintf(vlog_out, "%*cbegin\n", get_indent(), ' ');
1502 fprintf(vlog_out, "%*cend\n", get_indent(), ' ');
1503 }
1504 break;
1505 case IVL_ST_ALLOC:
1506 /* This statement is only used with an automatic task so we
1507 * can safely skip it. The automatic task definition will
1508 * generate an appropriate error message.*/
1509 break;
1510 case IVL_ST_ASSIGN:
1511 emit_stmt_assign(scope, stmt);
1512 break;
1513 case IVL_ST_ASSIGN_NB:
1514 emit_stmt_assign_nb(scope, stmt);
1515 break;
1516 case IVL_ST_BLOCK:
1517 if (ivl_stmt_block_scope(stmt)) {
1518 emit_stmt_block_named(scope, stmt);
1519 } else {
1520 if (is_delayed_or_event_assign(scope, stmt)) break;
1521 if (is_for_loop(scope, stmt)) break;
1522 if (is_repeat_event_assign(scope, stmt)) break;
1523 if (is_wait(scope, stmt)) break;
1524 if (is_utask_call_with_args(scope, stmt)) break;
1525 emit_stmt_block(scope, stmt);
1526 }
1527 break;
1528 case IVL_ST_CASE:
1529 case IVL_ST_CASER:
1530 case IVL_ST_CASEX:
1531 case IVL_ST_CASEZ:
1532 emit_stmt_case(scope, stmt);
1533 break;
1534 case IVL_ST_CASSIGN:
1535 emit_stmt_cassign(scope, stmt);
1536 break;
1537 case IVL_ST_CONDIT:
1538 emit_stmt_condit(scope, stmt);
1539 break;
1540 case IVL_ST_DEASSIGN:
1541 emit_stmt_deassign(scope, stmt);
1542 break;
1543 case IVL_ST_DELAY:
1544 emit_stmt_delay(scope, stmt);
1545 break;
1546 case IVL_ST_DELAYX:
1547 emit_stmt_delayx(scope, stmt);
1548 break;
1549 case IVL_ST_DISABLE:
1550 emit_stmt_disable(scope, stmt);
1551 break;
1552 case IVL_ST_DO_WHILE:
1553 emit_stmt_do_while(scope, stmt);
1554 break;
1555 case IVL_ST_FORCE:
1556 emit_stmt_force(scope, stmt);
1557 break;
1558 case IVL_ST_FOREVER:
1559 emit_stmt_forever(scope, stmt);
1560 break;
1561 case IVL_ST_FORK:
1562 if (ivl_stmt_block_scope(stmt)) {
1563 emit_stmt_fork_named(scope, stmt);
1564 } else {
1565 emit_stmt_fork(scope, stmt);
1566 }
1567 break;
1568 case IVL_ST_FORK_JOIN_ANY:
1569 fprintf(stderr, "%s:%u: vlog95 sorry: fork/join_any is not "
1570 "currently translated.\n",
1571 ivl_stmt_file(stmt),
1572 ivl_stmt_lineno(stmt));
1573 vlog_errors += 1;
1574 break;
1575 case IVL_ST_FORK_JOIN_NONE:
1576 fprintf(stderr, "%s:%u: vlog95 sorry: fork/join_none is not "
1577 "currently translated.\n",
1578 ivl_stmt_file(stmt),
1579 ivl_stmt_lineno(stmt));
1580 vlog_errors += 1;
1581 break;
1582 case IVL_ST_FREE:
1583 /* This statement is only used with an automatic task so we
1584 * can safely skip it. The automatic task definition will
1585 * generate an appropriate error message.*/
1586 break;
1587 case IVL_ST_RELEASE:
1588 emit_stmt_release(scope, stmt);
1589 break;
1590 case IVL_ST_REPEAT:
1591 emit_stmt_repeat(scope, stmt);
1592 break;
1593 case IVL_ST_STASK:
1594 emit_stmt_stask(scope, stmt);
1595 break;
1596 case IVL_ST_TRIGGER:
1597 emit_stmt_trigger(scope, stmt);
1598 break;
1599 case IVL_ST_UTASK:
1600 emit_stmt_utask(scope, stmt);
1601 break;
1602 case IVL_ST_WAIT:
1603 if (is_wait_fork(scope, stmt)) break;
1604 emit_stmt_wait(scope, stmt);
1605 break;
1606 case IVL_ST_WHILE:
1607 emit_stmt_while(scope, stmt);
1608 break;
1609 default:
1610 fprintf(vlog_out, "%*c<unknown>;\n", get_indent(), ' ');
1611 fprintf(stderr, "%s:%u: vlog95 error: Unknown statement "
1612 "type (%d).\n",
1613 ivl_stmt_file(stmt),
1614 ivl_stmt_lineno(stmt),
1615 (int)ivl_statement_type(stmt));
1616 vlog_errors += 1;
1617 break;
1618 }
1619 }
1620
emit_process(ivl_scope_t scope,ivl_process_t proc)1621 void emit_process(ivl_scope_t scope, ivl_process_t proc)
1622 {
1623 ivl_statement_t stmt = ivl_process_stmt(proc);
1624 if (ivl_statement_type(stmt) == IVL_ST_NOOP) return;
1625 fprintf(vlog_out, "\n%*c", get_indent(), ' ');
1626 switch (ivl_process_type(proc)) {
1627 case IVL_PR_INITIAL:
1628 fprintf(vlog_out, "initial");
1629 break;
1630 case IVL_PR_ALWAYS:
1631 case IVL_PR_ALWAYS_COMB:
1632 case IVL_PR_ALWAYS_FF:
1633 case IVL_PR_ALWAYS_LATCH:
1634 fprintf(vlog_out, "always");
1635 break;
1636 case IVL_PR_FINAL:
1637 fprintf(vlog_out, "final");
1638 fprintf(stderr, "%s:%u: vlog95 sorry: final blocks are not "
1639 "currently translated.\n",
1640 ivl_process_file(proc), ivl_process_lineno(proc));
1641 vlog_errors+= 1;
1642 break;
1643 default:
1644 fprintf(vlog_out, "<unknown>");
1645 fprintf(stderr, "%s:%u: vlog95 error: Unknown process type (%d).\n",
1646 ivl_process_file(proc), ivl_process_lineno(proc),
1647 (int)ivl_process_type(proc));
1648 vlog_errors+= 1;
1649 break;
1650 }
1651 if (emit_file_line) {
1652 fprintf(vlog_out, " /* %s:%u */",
1653 ivl_process_file(proc),
1654 ivl_process_lineno(proc));
1655 }
1656 if (ivl_statement_type(stmt) == IVL_ST_NOOP) {
1657 fprintf(vlog_out, " begin\n%*cend\n", get_indent(), ' ');
1658 } else {
1659 single_indent = 1;
1660 emit_stmt(scope, stmt);
1661 }
1662 }
1663