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