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 <ctype.h>
20 # include <stdlib.h>
21 # include <string.h>
22 # include "config.h"
23 # include "vlog95_priv.h"
24 # include "ivl_alloc.h"
25 
26 /*
27  * Emit a constant delay that has been rescaled to the given scopes timescale.
28  */
emit_scaled_delay(ivl_scope_t scope,uint64_t delay)29 void emit_scaled_delay(ivl_scope_t scope, uint64_t delay)
30 {
31       int scale = ivl_scope_time_units(scope) - sim_precision;
32       int pre = ivl_scope_time_units(scope) - ivl_scope_time_precision(scope);
33       char *frac;
34       unsigned real_dly = 0;
35       assert(scale >= 0);
36       assert(pre >= 0);
37       assert(scale >= pre);
38       frac = (char *)malloc(pre+1);
39       frac[pre] = 0;
40       for (/* none */; scale > 0; scale -= 1) {
41 	    if (scale > pre) {
42 		  assert((delay % 10) == 0);
43 	    } else {
44 		  frac[scale-1] = (delay % 10) + '0';
45 		  if (frac[scale-1] != '0') {
46 			real_dly = 1;
47 		  } else if (!real_dly) {
48 			frac[scale-1] = 0;
49 		  }
50 	    }
51 	    delay /= 10;
52       }
53       if (real_dly) {
54 	    fprintf(vlog_out, "%"PRIu64".%s", delay, frac);
55       } else {
56 	    if (delay & 0xffffffff80000000) {
57 		  fprintf(vlog_out, "(64'd%"PRIu64")", delay);
58 	    } else {
59 		  fprintf(vlog_out, "%"PRIu64, delay);
60 	    }
61       }
62       free(frac);
63 }
64 
emit_delay(ivl_scope_t scope,ivl_expr_t expr,unsigned is_stmt)65 static void emit_delay(ivl_scope_t scope, ivl_expr_t expr, unsigned is_stmt)
66 {
67 	/* A delay in a continuous assignment can also be a continuous
68 	 * assignment expression. */
69       if (ivl_expr_type(expr) == IVL_EX_SIGNAL) {
70 	    ivl_signal_t sig = ivl_expr_signal(expr);
71 	    if (ivl_signal_local(sig)) {
72 		  assert(! is_stmt);
73 		  emit_nexus_as_ca(scope, ivl_signal_nex(sig, 0), 0, 0);
74 		  return;
75 	    }
76       }
77       emit_expr(scope, expr, 0, 0, 0, 1);
78 }
79 
80 /*
81  * Check to see if the bit based expression is of the form (expr) * <scale>
82  */
check_scaled_expr(ivl_expr_t expr,uint64_t scale,const char * msg,unsigned must_match)83 static unsigned check_scaled_expr(ivl_expr_t expr, uint64_t scale,
84                                   const char *msg, unsigned must_match)
85 {
86       uint64_t scale_val;
87       int rtype;
88       if ((ivl_expr_type(expr) != IVL_EX_BINARY) ||
89           (ivl_expr_opcode(expr) != '*') ||
90           (ivl_expr_type(ivl_expr_oper2(expr)) != IVL_EX_NUMBER)) {
91 	    fprintf(stderr, "%s:%u: vlog95 error: %s expression/value "
92 	                    "cannot be scaled.\n ",
93 	                    ivl_expr_file(expr), ivl_expr_lineno(expr), msg);
94 	    vlog_errors += 1;
95 	    return 0;
96       }
97       scale_val = get_uint64_from_number(ivl_expr_oper2(expr), &rtype);
98       if (rtype > 0) {
99 	    fprintf(stderr, "%s:%u: vlog95 error: %s expression/value "
100 	                    "scale coefficient was greater than 64 bits "
101 	                    "(%d).\n", ivl_expr_file(expr),
102 	                    ivl_expr_lineno(expr), msg, rtype);
103 	    vlog_errors += 1;
104 	    return 0;
105       }
106       if (rtype < 0) {
107 	    fprintf(stderr, "%s:%u: vlog95 error: %s expression/value "
108 	                    "scale coefficient has an undefined bit.\n",
109 	                    ivl_expr_file(expr), ivl_expr_lineno(expr), msg);
110 	    vlog_errors += 1;
111 	    return 0;
112       }
113       if (scale != scale_val) {
114 	    if (must_match) {
115 		  fprintf(stderr, "%s:%u: vlog95 error: %s expression/value "
116 		                  "scale coefficient did not match expected "
117 		                  "value (%"PRIu64" != %"PRIu64").\n",
118 		                  ivl_expr_file(expr), ivl_expr_lineno(expr),
119 		                  msg, scale, scale_val);
120 		  vlog_errors += 1;
121 		  return 0;
122 	    }
123 	    return 2;
124       }
125 	/* Yes, this expression is of the correct form. */
126       return 1;
127 }
128 
129 /*
130  * Check to see if the real expression is of the form (expr) * <scale>
131  */
check_scaled_real_expr(ivl_expr_t expr,double scale)132 static unsigned check_scaled_real_expr(ivl_expr_t expr, double scale)
133 {
134       double scale_val;
135       if ((ivl_expr_type(expr) != IVL_EX_BINARY) ||
136           (ivl_expr_opcode(expr) != '*') ||
137           (ivl_expr_type(ivl_expr_oper2(expr)) != IVL_EX_REALNUM)) {
138 	    fprintf(stderr, "%s:%u: vlog95 error: Variable real time unit "
139 	                    " expression/value cannot be scaled.\n ",
140 	                    ivl_expr_file(expr), ivl_expr_lineno(expr));
141 	    vlog_errors += 1;
142 	    return 0;
143       }
144       scale_val = ivl_expr_dvalue(ivl_expr_oper2(expr));
145       if (scale != scale_val) {
146 	    fprintf(stderr, "%s:%u: vlog95 error: Variable real time unit "
147 	                    "expression/value scale coefficient did not "
148 	                    "match expected value (%g != %g).\n",
149 	                    ivl_expr_file(expr), ivl_expr_lineno(expr),
150 	                    scale, scale_val);
151 	    vlog_errors += 1;
152 	    return 0;
153       }
154 	/* Yes, this expression is of the correct form. */
155       return 1;
156 }
157 
158 /*
159  * Emit a constant or variable delay that has been rescaled to the given
160  * scopes timescale.
161  */
emit_scaled_delayx(ivl_scope_t scope,ivl_expr_t expr,unsigned is_stmt)162 void emit_scaled_delayx(ivl_scope_t scope, ivl_expr_t expr, unsigned is_stmt)
163 {
164       ivl_expr_type_t type = ivl_expr_type(expr);
165       if (type == IVL_EX_DELAY) {
166 	    emit_scaled_delay(scope, ivl_expr_delay_val(expr));
167       } else if (type == IVL_EX_NUMBER) {
168 	    assert(! ivl_expr_signed(expr));
169 	    int rtype;
170 	    uint64_t value = get_uint64_from_number(expr, &rtype);
171 	    if (rtype > 0) {
172 		  fprintf(vlog_out, "<invalid>");
173 		  fprintf(stderr, "%s:%u: vlog95 error: Time value is "
174 		                  "greater than 64 bits (%d) and cannot be "
175 		                  "safely represented.\n",
176 		                  ivl_expr_file(expr), ivl_expr_lineno(expr),
177 		                  rtype);
178 		  vlog_errors += 1;
179 		  return;
180 	    }
181 	    if (rtype < 0) {
182 		  fprintf(vlog_out, "<invalid>");
183 		  fprintf(stderr, "%s:%u: vlog95 error: Time value has an "
184 		                  "undefined bit and cannot be represented.\n",
185 		                  ivl_expr_file(expr), ivl_expr_lineno(expr));
186 		  vlog_errors += 1;
187 		  return;
188 	    }
189 	    emit_scaled_delay(scope, value);
190       } else {
191 	    int exponent = ivl_scope_time_units(scope) - sim_precision;
192 	    assert(exponent >= 0);
193 	    if ((exponent == 0) && (type == IVL_EX_SIGNAL)) {
194 		  emit_delay(scope, expr, is_stmt);
195 	      /* A real delay variable is not scaled by the compiler. */
196 	    } else if (type == IVL_EX_SIGNAL) {
197 		  if (is_stmt) {
198 			fprintf(vlog_out, "<invalid>");
199 			fprintf(stderr, "%s:%u: vlog95 error: Only continuous "
200 			                "assignment delay variables are scaled "
201 			                "at run time.\n", ivl_expr_file(expr),
202 			                ivl_expr_lineno(expr));
203 			vlog_errors += 1;
204 			return;
205 		  }
206 		  emit_delay(scope, expr, is_stmt);
207 	    } else {
208 		  uint64_t iscale = 1;
209 		  unsigned rtn;
210 		  assert(! ivl_expr_signed(expr));
211 		    /* Calculate the integer time scaling coefficient. */
212 		  while (exponent > 0) {
213 			iscale *= 10;
214 			exponent -= 1;
215 		  }
216 		    /* Check to see if this is an integer time value. */
217 		  rtn = check_scaled_expr(expr, iscale, "Variable time", 0);
218 		    /* This may be a scaled real value. */
219 		  if (rtn == 2){
220 			ivl_expr_t tmp_expr;
221 			uint64_t rprec = 1;
222 			  /* This could be a scaled real time so calculate
223 			   * the real time scaling coefficients and check
224 			   * that the expression matches (statements only). */
225 			exponent = ivl_scope_time_precision(scope) -
226 			           sim_precision;
227 			assert(exponent >= 0);
228 			while (exponent > 0) {
229 			      rprec *= 10;
230 			      exponent -= 1;
231 			}
232 			  /* Verify that the precision scaling is correct. */
233 			if (! check_scaled_expr(expr, rprec,
234 			                        "Variable real time prec.",
235 			                        1)) {
236 			      fprintf(vlog_out, "<invalid>");
237 			      return;
238 			}
239 			  /* Verify that the left operator is a real to
240 			   * integer cast. */
241 			tmp_expr = ivl_expr_oper1(expr);
242 			if ((ivl_expr_type(tmp_expr) != IVL_EX_UNARY) ||
243 		            (ivl_expr_opcode(tmp_expr) != 'v')) {
244 			      fprintf(vlog_out, "<invalid>");
245 			      fprintf(stderr, "%s:%u: vlog95 error: Real time "
246 			                      "value does not have a cast to "
247 			                      "integer.\n",
248 			                      ivl_expr_file(expr),
249 			                      ivl_expr_lineno(expr));
250 			      vlog_errors += 1;
251 			      return;
252 			}
253 			  /* Check that the cast value is scaled correctly. */
254 			assert(iscale >= rprec);
255 			tmp_expr = ivl_expr_oper1(tmp_expr);
256 			assert(ivl_expr_value(tmp_expr) == IVL_VT_REAL);
257 			if (! check_scaled_real_expr(tmp_expr, iscale/rprec)) {
258 			      fprintf(vlog_out, "<invalid>");
259 			      return;
260 			}
261 			assert(is_stmt);
262 			emit_delay(scope, ivl_expr_oper1(tmp_expr), is_stmt);
263 			return;
264 		  } else if (rtn == 1) {
265 			emit_delay(scope, ivl_expr_oper1(expr), is_stmt);
266 			return;
267 		  }
268 		  fprintf(vlog_out, "<invalid>");
269 	    }
270       }
271 }
272 
get_valid_int64_from_number(ivl_expr_t expr,int * rtype,const char * msg)273 static int64_t get_valid_int64_from_number(ivl_expr_t expr, int *rtype,
274                                            const char *msg)
275 {
276       int64_t value = get_int64_from_number(expr, rtype);
277       if (*rtype > 0) {
278 	    fprintf(vlog_out, "<invalid>");
279 	    fprintf(stderr, "%s:%u: vlog95 error: Scaled %s is greater than "
280 	                    "64 bits (%d) and cannot be safely represented.\n",
281 	                    ivl_expr_file(expr), ivl_expr_lineno(expr),
282 	                    msg, *rtype);
283 	    vlog_errors += 1;
284       } else if (*rtype < 0) {
285 	    fprintf(vlog_out, "<invalid>");
286 	    fprintf(stderr, "%s:%u: vlog95 error: Scaled %s has an undefined "
287 	                    "bit and cannot be represented.\n",
288 	                    ivl_expr_file(expr), ivl_expr_lineno(expr), msg);
289 	    vlog_errors += 1;
290       }
291       return value;
292 }
293 
294 // HERE: Probably need to pass in a msg string to make this work with
295 //       indexed part selects.
is_scaled_expr(ivl_expr_t expr,int msb,int lsb)296 static unsigned is_scaled_expr(ivl_expr_t expr, int msb, int lsb)
297 {
298       int64_t scale_val;
299       int rtype;
300 	/* This is as easy as removing the addition/subtraction that was
301 	 * added to scale the value to be zero based, but we need to verify
302 	 * that the scaling value is correct first. */
303       if (msb > lsb) {
304 	    if ((ivl_expr_type(expr) != IVL_EX_BINARY) ||
305 	        ((ivl_expr_opcode(expr) != '+') &&
306 	         (ivl_expr_opcode(expr) != '-')) ||
307 	        (ivl_expr_type(ivl_expr_oper2(expr)) != IVL_EX_NUMBER)) {
308 		  fprintf(vlog_out, "<invalid>");
309 		  fprintf(stderr, "%s:%u: vlog95 error: Scaled "
310 		                  "expression value cannot be scaled.\n",
311 		                  ivl_expr_file(expr),
312 		                  ivl_expr_lineno(expr));
313 		  vlog_errors += 1;
314 		  return 0;
315 	    }
316 	    scale_val = get_valid_int64_from_number(
317 	                      ivl_expr_oper2(expr), &rtype,
318 	                      "expression value scale coefficient");
319       } else {
320 	    if ((ivl_expr_type(expr) != IVL_EX_BINARY) ||
321 	        ((ivl_expr_opcode(expr) != '+') &&
322 	         (ivl_expr_opcode(expr) != '-')) ||
323 	        (ivl_expr_type(ivl_expr_oper1(expr)) != IVL_EX_NUMBER)) {
324 		  fprintf(vlog_out, "<invalid>");
325 		  fprintf(stderr, "%s:%u: vlog95 error: Scaled "
326 		                  "expression value cannot be scaled.\n",
327 		                  ivl_expr_file(expr),
328 		                  ivl_expr_lineno(expr));
329 		  vlog_errors += 1;
330 		  return 0;
331 	    }
332 	    scale_val = get_valid_int64_from_number(
333 	                      ivl_expr_oper1(expr), &rtype,
334 	                      "expression value scale coefficient");
335       }
336       if (rtype) return 0;
337       if (ivl_expr_opcode(expr) == '+') scale_val *= -1;
338       if (lsb !=  scale_val) {
339 	    fprintf(vlog_out, "<invalid>");
340 	    fprintf(stderr, "%s:%u: vlog95 error: Scaled expression value "
341 	                    "scaling coefficient did not match expected "
342 	                    "value (%d != %"PRIu64").\n",
343 	                    ivl_expr_file(expr), ivl_expr_lineno(expr),
344 	                    lsb, scale_val);
345 	    vlog_errors += 1;
346 	    return 0;
347       }
348       return 1;
349 }
350 
get_in_range_int64_from_number(ivl_expr_t expr,int * rtype,const char * msg)351 static int64_t get_in_range_int64_from_number(ivl_expr_t expr, int *rtype,
352                                               const char *msg)
353 {
354       int64_t value = get_int64_from_number(expr, rtype);
355       if (*rtype > 0) {
356 	    fprintf(vlog_out, "<invalid>");
357 	    fprintf(stderr, "%s:%u: vlog95 error: Scaled %s is greater than "
358 	                    "64 bits (%d) and cannot be safely represented.\n",
359 	                    ivl_expr_file(expr), ivl_expr_lineno(expr),
360 	                    msg, *rtype);
361 	    vlog_errors += 1;
362       }
363       return value;
364 }
365 
emit_scaled_range(ivl_scope_t scope,ivl_expr_t expr,unsigned width,int msb,int lsb)366 void emit_scaled_range(ivl_scope_t scope, ivl_expr_t expr, unsigned width,
367                        int msb, int lsb)
368 {
369       int rtype;
370       int64_t value = get_in_range_int64_from_number(expr, &rtype,
371                                                      "range value");
372       (void)scope;  /* Parameter is not used. */
373       if (rtype < 0) fprintf(vlog_out, "[1'bx:1'bx]");
374       if (rtype) return;
375 
376       if (msb >= lsb) {
377 	    value += lsb;
378 	    fprintf(vlog_out, "[%"PRId64":%"PRId64"]",
379 	                      value + (int64_t)(width - 1), value);
380       } else {
381 	    value = (int64_t)lsb - value;
382 	    fprintf(vlog_out, "[%"PRId64":%"PRId64"]",
383 	                      value - (int64_t)(width - 1), value);
384       }
385 }
386 
emit_scaled_expr(ivl_scope_t scope,ivl_expr_t expr,int msb,int lsb)387 void emit_scaled_expr(ivl_scope_t scope, ivl_expr_t expr, int msb, int lsb)
388 {
389       if (msb >= lsb) {
390 	    if (ivl_expr_type(expr) == IVL_EX_NUMBER) {
391 		  int rtype;
392 		  int64_t value = get_in_range_int64_from_number(expr, &rtype,
393 		                                                 "value");
394 		  if (rtype < 0) fprintf(vlog_out, "1'bx");
395 		  if (rtype) return;
396 		  value += lsb;
397 		  fprintf(vlog_out, "%"PRId64, value);
398 	    } else if (lsb == 0) {
399 		    /* If the LSB is zero then there is no scale. */
400 		  emit_expr(scope, expr, 0, 0, 0, 1);
401 	    } else {
402 		  if (is_scaled_expr(expr, msb, lsb)) {
403 			emit_expr(scope, ivl_expr_oper1(expr), 0, 0, 0, 1);
404 		  }
405 	    }
406       } else {
407 	    if (ivl_expr_type(expr) == IVL_EX_NUMBER) {
408 		  int rtype;
409 		  int64_t value = get_in_range_int64_from_number(expr, &rtype,
410 		                                                 "value");
411 		  if (rtype < 0) fprintf(vlog_out, "1'bx");
412 		  if (rtype) return;
413 		  value = (int64_t)lsb - value;
414 		  fprintf(vlog_out, "%"PRId64, value);
415 	    } else {
416 		  if (is_scaled_expr(expr, msb, lsb)) {
417 			emit_expr(scope, ivl_expr_oper2(expr), 0, 0, 0, 1);
418 		  }
419 	    }
420       }
421 }
422 
find_signal_in_nexus(ivl_scope_t scope,ivl_nexus_t nex)423 static unsigned find_signal_in_nexus(ivl_scope_t scope, ivl_nexus_t nex)
424 {
425       ivl_signal_t use_sig = 0;
426       unsigned is_driver = 0;
427       unsigned is_array = 0;
428       int64_t array_idx = 0;
429       unsigned idx, count = ivl_nexus_ptrs(nex);
430 
431       for (idx = 0; idx < count; idx += 1) {
432 	    ivl_nexus_ptr_t nex_ptr = ivl_nexus_ptr(nex, idx);
433 	    ivl_signal_t sig = ivl_nexus_ptr_sig(nex_ptr);
434 	    if (! sig) continue;
435 	    if (ivl_signal_local(sig)) {
436 		    /* If the local signal is another receiver skip it. */
437 		  if ((ivl_nexus_ptr_drive1(nex_ptr) == IVL_DR_HiZ) &&
438 		      (ivl_nexus_ptr_drive0(nex_ptr) == IVL_DR_HiZ)) {
439 			continue;
440 		  }
441 	          assert(0);
442 	    }
443 	      /* We have a signal that can be used to find the name. */
444 	    if (scope == ivl_signal_scope(sig)) {
445 		  if (use_sig) {
446 			  /* Swap a receiver for a driver. */
447 			if (is_driver &&
448 			    (ivl_nexus_ptr_drive1(nex_ptr) == IVL_DR_HiZ) &&
449 			    (ivl_nexus_ptr_drive0(nex_ptr) == IVL_DR_HiZ)) {
450 			      use_sig = sig;
451 			      is_driver = 0;
452 			      if (ivl_signal_dimensions(sig) > 0) {
453 				    is_array = 1;
454 				    array_idx = ivl_nexus_ptr_pin(nex_ptr);
455 				    array_idx += ivl_signal_array_base(sig);
456 			      }
457 			      continue;
458 			}
459 // HERE: Which one should we use? For now it's the first one found.
460 //       I believe this needs to be solved (see the inout.v test).
461 			fprintf(stderr, "%s:%u: vlog95 warning: Duplicate "
462 			                "name (%s",
463 			                ivl_signal_file(sig),
464 			                ivl_signal_lineno(sig),
465 			                ivl_signal_basename(sig));
466 			if (ivl_signal_dimensions(sig) > 0) {
467 			      int64_t tmp_idx = ivl_nexus_ptr_pin(nex_ptr);
468 			      tmp_idx += ivl_signal_array_base(sig);
469 			      fprintf(stderr, "[%"PRId64"]", tmp_idx);
470 			}
471 			fprintf(stderr, ") found for nexus (%s",
472 			                ivl_signal_basename(use_sig));
473 			if (is_array) fprintf(stderr, "[%"PRId64"]", array_idx);
474 			fprintf(stderr, ")\n");
475 		  } else {
476 			use_sig = sig;
477 			  /* This signal is a driver. */
478 			if ((ivl_nexus_ptr_drive1(nex_ptr) != IVL_DR_HiZ) ||
479 			    (ivl_nexus_ptr_drive0(nex_ptr) != IVL_DR_HiZ)) {
480 			      is_driver = 1;
481 			}
482 			if (ivl_signal_dimensions(sig) > 0) {
483 			      is_array = 1;
484 			      array_idx = ivl_nexus_ptr_pin(nex_ptr);
485 			      array_idx += ivl_signal_array_base(sig);
486 			}
487 		  }
488 	    }
489       }
490 
491       if (use_sig) {
492 	    emit_id(ivl_signal_basename(use_sig));
493 	    if (is_array) fprintf(vlog_out, "[%"PRId64"]", array_idx);
494 	    return 1;
495       }
496 
497       return 0;
498 }
499 
emit_number_as_string(ivl_net_const_t net_const)500 static void emit_number_as_string(ivl_net_const_t net_const)
501 {
502       const char *bits = ivl_const_bits(net_const);
503       unsigned count = ivl_const_width(net_const);
504       int idx;
505 
506       assert((count % 8) == 0);
507       fprintf(vlog_out, "\"");
508       for (idx = (int)count-1; idx >= 0; idx -= 8) {
509 	    unsigned bit;
510 	    char val = 0;
511 	    for (bit = 0; bit < 8; bit += 1) {
512 		  val |= (bits[idx-bit] == '1') ?  1 << (7-bit) : 0x00;
513 	    }
514 
515 	      /* Skip any NULL bytes. */
516 	    if (val == 0) continue;
517 	      /* Print some values that can be escaped. */
518 	    if (val == '"') fprintf(vlog_out, "\\\"");
519 	    else if (val == '\\') fprintf(vlog_out, "\\\\");
520 	    else if (val == '\n') fprintf(vlog_out, "\\n");
521 	    else if (val == '\t') fprintf(vlog_out, "\\t");
522 	      /* Print the printable characters. */
523 	    else if (isprint((int)val)) fprintf(vlog_out, "%c", val);
524 	      /* Print the non-printable characters as an octal escape. */
525 	    else fprintf(vlog_out, "\\%03o", val);
526       }
527       fprintf(vlog_out, "\"");
528 }
529 
emit_as_input(ivl_scope_t scope,ivl_net_const_t net_const)530 static unsigned emit_as_input(ivl_scope_t scope, ivl_net_const_t net_const)
531 {
532       ivl_scope_t const_scope = ivl_const_scope(net_const);
533       ivl_scope_t parent = ivl_scope_parent(scope);
534 
535 	/* Look to see if the constant scope is a parent of this scope. */
536       while (parent) {
537 	    if (parent == const_scope) break;
538 	    parent = ivl_scope_parent(parent);
539       }
540 
541 	/* If the constant scope is a parent then look for an input in
542 	 * this scope and use that for the name. */
543       if (parent) {
544 	    ivl_nexus_t nex = ivl_const_nex(net_const);
545 	    unsigned idx, count = ivl_nexus_ptrs(nex);
546 	    for (idx = 0; idx < count; idx += 1) {
547 		  ivl_nexus_ptr_t nex_ptr = ivl_nexus_ptr(nex, idx);
548 		  ivl_signal_t sig = ivl_nexus_ptr_sig(nex_ptr);
549 		  if (sig && (ivl_signal_port(sig) == IVL_SIP_INPUT)) {
550 			emit_id(ivl_signal_basename(sig));
551 			return 1;
552 		  }
553 	    }
554       }
555 
556       return 0;
557 }
558 
emit_const_nexus(ivl_scope_t scope,ivl_net_const_t net_const)559 void emit_const_nexus(ivl_scope_t scope, ivl_net_const_t net_const)
560 {
561       ivl_scope_t const_scope = ivl_const_scope(net_const);
562       unsigned idx, count, lineno;
563       const char *file;
564       count = ivl_scope_params(const_scope);
565       file = ivl_const_file(net_const);
566       lineno = ivl_const_lineno(net_const);
567 	/* Look to see if the constant matches a parameter in its scope. */
568       for (idx = 0; idx < count; idx += 1) {
569 	    ivl_parameter_t par = ivl_scope_param(const_scope, idx);
570 	    if (lineno != ivl_parameter_lineno(par)) continue;
571 	    if (strcmp(file, ivl_parameter_file(par)) == 0) {
572 		    /* Check that the appropriate expression bits match the
573 		     * original parameter bits. */
574 // HERE: Verify that the values match and then print the name.
575 //       Does this work with out of scope references? Check real parameters.
576 		  emit_id(ivl_parameter_basename(par));
577 		  return;
578 	    }
579       }
580 
581 	/* If the scopes don't match then we assume this is an empty port. */
582       if (const_scope != scope)  {
583 	      /* This constant could really be from an input port. */
584 	    if (emit_as_input(scope, net_const)) return;
585 	    fprintf(vlog_out, "/* Empty */");
586 	    return;
587       }
588 
589       switch (ivl_const_type(net_const)) {
590 	case IVL_VT_LOGIC:
591 	case IVL_VT_BOOL:
592 	    emit_number(ivl_const_bits(net_const),
593 	                ivl_const_width(net_const),
594 	                ivl_const_signed(net_const),
595 	                ivl_const_file(net_const),
596 	                ivl_const_lineno(net_const));
597 	    break;
598 	case IVL_VT_STRING:
599 	    emit_number_as_string(net_const);
600 	    break;
601 	case IVL_VT_REAL:
602 	    emit_real_number(ivl_const_real(net_const));
603 	    break;
604 	default:
605 	    fprintf(vlog_out, "<invalid>");
606 	    fprintf(stderr, "%s:%u: vlog95 error: Unknown constant type "
607 	                    "(%d).\n",
608 	                    ivl_const_file(net_const),
609 	                    ivl_const_lineno(net_const),
610 	                    (int)ivl_const_type(net_const));
611 	    vlog_errors += 1;
612 	    break;
613       }
614 }
615 
find_const_nexus(ivl_scope_t scope,ivl_nexus_t nex)616 static unsigned find_const_nexus(ivl_scope_t scope, ivl_nexus_t nex)
617 {
618       unsigned idx, count;
619 
620       count = ivl_nexus_ptrs(nex);
621       for (idx = 0; idx < count; idx += 1) {
622 	    ivl_nexus_ptr_t nex_ptr = ivl_nexus_ptr(nex, idx);
623 	    ivl_net_const_t net_const = ivl_nexus_ptr_con(nex_ptr);
624 // HERE: Do we need to check for duplicates?
625 	    if (net_const) {
626 		  assert(! ivl_nexus_ptr_pin(nex_ptr));
627 		  emit_const_nexus(scope, net_const);
628 		  return 1;
629 	    }
630       }
631       return 0;
632 }
633 
find_driving_signal(ivl_scope_t scope,ivl_nexus_t nex)634 static unsigned find_driving_signal(ivl_scope_t scope, ivl_nexus_t nex)
635 {
636       ivl_signal_t sig = 0;
637       unsigned is_array = 0;
638       int64_t array_idx = 0;
639       unsigned idx, count = ivl_nexus_ptrs(nex);
640 
641       for (idx = 0; idx < count; idx += 1) {
642 	    ivl_nexus_ptr_t nex_ptr = ivl_nexus_ptr(nex, idx);
643 	    ivl_signal_t t_sig = ivl_nexus_ptr_sig(nex_ptr);
644 	    if (! t_sig) continue;
645 	    if (ivl_signal_local(t_sig)) continue;
646 	      /* An output can be used if it is driven by this nexus. */
647 	    if ((ivl_nexus_ptr_drive1(nex_ptr) == IVL_DR_HiZ) &&
648 	        (ivl_nexus_ptr_drive0(nex_ptr) == IVL_DR_HiZ) &&
649 	        (ivl_signal_port(t_sig) != IVL_SIP_OUTPUT)) {
650 		  continue;
651 	    }
652 	      /* We have a signal that can be used to find the name. */
653 	    if (sig) {
654 // HERE: Which one should we use? For now it's the first one found.
655 //       I believe this needs to be solved (see above).
656 		  fprintf(stderr, "%s:%u: vlog95 warning: Duplicate name (%s",
657 		          ivl_signal_file(t_sig), ivl_signal_lineno(t_sig),
658 		          ivl_signal_basename(t_sig));
659 		  if (ivl_signal_dimensions(t_sig) > 0) {
660 			int64_t tmp_idx = ivl_nexus_ptr_pin(nex_ptr);
661 			tmp_idx += ivl_signal_array_base(t_sig);
662 			fprintf(stderr, "[%"PRId64"]", tmp_idx);
663 		  }
664 		  fprintf(stderr, ") found for nexus (%s",
665 		          ivl_signal_basename(sig));
666 		  if (is_array) fprintf(stderr, "[%"PRId64"]", array_idx);
667 		  fprintf(stderr, ")\n");
668 	    } else {
669 		  sig = t_sig;
670 		  if (ivl_signal_dimensions(sig) > 0) {
671 			is_array = 1;
672 			array_idx = ivl_nexus_ptr_pin(nex_ptr);
673 			array_idx += ivl_signal_array_base(sig);
674 		  }
675 	    }
676       }
677 
678       if (sig) {
679 	    emit_scope_call_path(scope, ivl_signal_scope(sig));
680 	    emit_id(ivl_signal_basename(sig));
681 	    if (is_array) fprintf(vlog_out, "[%"PRId64"]", array_idx);
682 	    return 1;
683       }
684 
685       return 0;
686 }
687 
is_local_input(ivl_scope_t scope,ivl_nexus_t nex)688 static unsigned is_local_input(ivl_scope_t scope, ivl_nexus_t nex)
689 {
690       ivl_signal_t sig = 0;
691       unsigned idx, count = ivl_nexus_ptrs(nex);
692 
693       (void)scope;  /* Parameter is not used. */
694       for (idx = 0; idx < count; idx += 1) {
695 	    ivl_nexus_ptr_t nex_ptr = ivl_nexus_ptr(nex, idx);
696 	    ivl_signal_t t_sig = ivl_nexus_ptr_sig(nex_ptr);
697 	    if (! t_sig) continue;
698 	    if (! ivl_signal_local(t_sig)) continue;
699 	    if (ivl_signal_port(t_sig) != IVL_SIP_INPUT) continue;
700 	    assert(! sig);
701 	    assert(ivl_signal_dimensions(t_sig) == 0);
702 	    sig = t_sig;
703       }
704       if (sig) {
705 	    fprintf(vlog_out, "ivlog%s", ivl_signal_basename(sig));
706 	    return 1;
707       }
708       return 0;
709 }
710 
711 // HERE: Does this work correctly with an array reference created from @*?
emit_name_of_nexus(ivl_scope_t scope,ivl_nexus_t nex,unsigned allow_UD)712 void emit_name_of_nexus(ivl_scope_t scope, ivl_nexus_t nex, unsigned allow_UD)
713 {
714       unsigned idx;
715 
716       ivl_scope_t mod_scope;
717 	/* First look in the local scope for the nexus name. */
718       if (find_signal_in_nexus(scope, nex)) return;
719 
720 	/* If the signal was not found in the passed scope then look in
721 	 * the module scope if the passed scope was not the module scope. */
722       mod_scope = get_module_scope(scope);
723       if (mod_scope != scope) {
724 	    if (find_signal_in_nexus(mod_scope, nex)) return;
725       }
726 
727 	/* Look to see if this is a up/down reference. */
728       if (allow_UD && find_driving_signal(scope, nex)) return;
729 
730 	/* If there is no signals driving this then look for a constant. */
731       if (find_const_nexus(scope, nex)) return;
732 
733 	/* Module inputs that are split (arg[7:4], arg[3:0]) need to use
734 	 * the local signal names. */
735       if (is_local_input(scope, nex)) return;
736 
737 // HERE: Need to check arr[var]? Can this be rebuilt?
738 //       Then look for down scopes and then any scope. For all this warn if
739 //       multiples are found in a given scope. This all needs to be before
740 //       the constant code.
741 
742 	/* It is possible that the nexus does not have a name. First check
743 	   if it drives another nexus through a transparent buffer. */
744       for (idx = 0; idx < ivl_nexus_ptrs(nex); idx += 1) {
745 	    ivl_nexus_ptr_t nex_ptr = ivl_nexus_ptr(nex, idx);
746 	    ivl_net_logic_t nlogic = ivl_nexus_ptr_log(nex_ptr);
747 	    if (nlogic && ivl_logic_type(nlogic) == IVL_LO_BUFT
748 		&& ivl_logic_pin(nlogic, 1) == nex) {
749 		  emit_name_of_nexus(scope, ivl_logic_pin(nlogic, 0), allow_UD);
750 		  return;
751 	    }
752       }
753 
754 	/* If not, do not print an actual name. */
755       fprintf(vlog_out, "/* Empty */");
756 //      dump_nexus_information(scope, nex);
757 }
758 
759 /*
760  * This function traverses the scope tree looking for the enclosing module
761  * scope. When it is found the module scope is returned. As far as this
762  * translation is concerned a package is a special form of a module
763  * definition and a class is also a top level scope. In SystemVerilog,
764  * tasks and functions can also be top level scopes - we create a wrapper
765  * module for these later.
766  */
get_module_scope(ivl_scope_t scope)767 ivl_scope_t get_module_scope(ivl_scope_t scope)
768 {
769 
770       while ((ivl_scope_type(scope) != IVL_SCT_MODULE) &&
771              (ivl_scope_type(scope) != IVL_SCT_PACKAGE) &&
772              (ivl_scope_type(scope) != IVL_SCT_CLASS)) {
773 	    ivl_scope_t pscope = ivl_scope_parent(scope);
774 	    if (pscope == 0) {
775 		  if (ivl_scope_type(scope) == IVL_SCT_TASK)
776 			break;
777 		  if (ivl_scope_type(scope) == IVL_SCT_FUNCTION)
778 			break;
779 	    }
780 	    assert(pscope);
781 	    scope = pscope;
782       }
783       return scope;
784 }
785 
786 /*
787  * A package is emitted as a module with a special name. This routine
788  * calculates the name for the package. The returned string must be freed
789  * by the calling routine.
790  */
get_package_name(ivl_scope_t scope)791 char * get_package_name(ivl_scope_t scope)
792 {
793       char *package_name;
794       const char *name = ivl_scope_basename(scope);
795       package_name = (char *)malloc(strlen(name)+13);
796       strcpy(package_name, "ivl_package_");
797       strcat(package_name, name);
798       return package_name;
799 }
800 
emit_scope_piece(ivl_scope_t scope,ivl_scope_t call_scope)801 static void emit_scope_piece(ivl_scope_t scope, ivl_scope_t call_scope)
802 {
803       ivl_scope_t parent = ivl_scope_parent(call_scope);
804 	/* If we are not at the top of the scope (parent != 0) and the two
805 	 * scopes do not match then print the parent scope. */
806       if ((parent != 0) && (scope != parent)) {
807 	    emit_scope_piece(scope, parent);
808       }
809 	/* If the scope is a package then add the special part of the name. */
810       if (ivl_scope_type(call_scope) == IVL_SCT_PACKAGE) {
811 	    char *package_name = get_package_name(call_scope);
812 	    emit_id(package_name);
813 	    free(package_name);
814 	/* Print the base scope. */
815       } else emit_id(ivl_scope_basename(call_scope));
816       fprintf(vlog_out, ".");
817 }
818 
819 /*
820  * This routine emits the appropriate string to call the call_scope from the
821  * given scope. If the module scopes for the two match then do nothing. If
822  * the module scopes are different, but the call_scope begins with the
823  * entire module scope of scope then we can trim the top off the call_scope
824  * (it is a sub-scope of the module that contains scope). Otherwise we need
825  * to print the entire path of call_scope.
826  */
emit_scope_module_path(ivl_scope_t scope,ivl_scope_t call_scope)827 void emit_scope_module_path(ivl_scope_t scope, ivl_scope_t call_scope)
828 {
829       ivl_scope_t mod_scope = get_module_scope(scope);
830       ivl_scope_t call_mod_scope = get_module_scope(call_scope);
831 
832       if (mod_scope == call_mod_scope) return;
833       emit_scope_piece(mod_scope, call_mod_scope);
834 }
835 
836 /* This is the same as emit_scope_module_path() except we need to add down
837  * references for variables, etc. */
emit_scope_call_path(ivl_scope_t scope,ivl_scope_t call_scope)838 void emit_scope_call_path(ivl_scope_t scope, ivl_scope_t call_scope)
839 {
840       ivl_scope_t mod_scope, call_mod_scope;
841 
842       if (scope == call_scope) return;
843 
844       mod_scope = get_module_scope(scope);
845       call_mod_scope = get_module_scope(call_scope);
846 
847       if (mod_scope != call_mod_scope) {
848 	    emit_scope_piece(mod_scope, call_mod_scope);
849       } else if (scope != call_scope) {
850 	    ivl_scope_t parent;
851 	      /* We only emit a scope path if the scope is a parent of the
852 	       * call scope. */
853 	    for (parent = ivl_scope_parent(call_scope);
854 	         parent != 0;
855 	         parent = ivl_scope_parent(parent)) {
856 		  if (parent == scope) {
857 			emit_scope_piece(scope, call_scope);
858 			return;
859 		  }
860 	    }
861       }
862 }
863 
emit_scope_path_piece(ivl_scope_t scope,ivl_scope_t call_scope)864 static void emit_scope_path_piece(ivl_scope_t scope, ivl_scope_t call_scope)
865 {
866       ivl_scope_t parent = ivl_scope_parent(call_scope);
867 	/* If we are not at the top of the scope (parent != 0) and the two
868 	 * scopes do not match then print the parent scope. */
869       if ((parent != 0) && (scope != parent)) {
870 	    emit_scope_path_piece(scope, parent);
871 	    fprintf(vlog_out, ".");
872       }
873 	/* If the scope is a package then add the special part of the name. */
874       if (ivl_scope_type(call_scope) == IVL_SCT_PACKAGE) {
875 	    char *package_name = get_package_name(call_scope);
876 	    emit_id(package_name);
877 	    free(package_name);
878 	/* Print the base scope. */
879       } else emit_id(ivl_scope_basename(call_scope));
880 }
881 
882 /*
883  * This routine emits the appropriate string to call the call_scope from the
884  * given scope. If the module scopes for the two match then just return the
885  * base name of the call_scope. If the module scopes are different, but the
886  * call_scope begins with the entire module scope of scope then we can trim
887  * the top off the call_scope (it is a sub-scope of the module that contains
888  * scope). Otherwise we need to print the entire path of call_scope.
889  */
emit_scope_path(ivl_scope_t scope,ivl_scope_t call_scope)890 void emit_scope_path(ivl_scope_t scope, ivl_scope_t call_scope)
891 {
892       ivl_scope_t mod_scope, call_mod_scope;
893 
894 	/* Check to see if this is a root scope task or function. */
895       if (ivl_scope_parent(call_scope) == 0) {
896 	    fprintf(vlog_out, "ivl_root_scope_%s.",
897 		    ivl_scope_basename(call_scope));
898 	    mod_scope = 0;
899 	    call_mod_scope = 0;
900       } else {
901 	    mod_scope = get_module_scope(scope);
902 	    call_mod_scope = get_module_scope(call_scope);
903       }
904 
905       if (mod_scope == call_mod_scope) {
906 	    emit_id(ivl_scope_basename(call_scope));
907       } else {
908 	    emit_scope_path_piece(mod_scope, call_scope);
909       }
910 }
911 
is_escaped(const char * id)912 static unsigned is_escaped(const char *id)
913 {
914       assert(id);
915 	/* The first digit must be alpha or '_' to be a normal id. */
916       if (isalpha((int)id[0]) || id[0] == '_') {
917 	    unsigned idx;
918 	    for (idx = 1; id[idx] != '\0'; idx += 1) {
919 		  if (! (isalnum((int)id[idx]) ||
920 		         id[idx] == '_' || id[idx] == '$')) {
921 			return 1;
922 		  }
923 	    }
924 	      /* Any Verilog keyword should also be escaped. */
925 // HERE: Create a keyword.gperf file to do this check.
926 	    if ((strcmp(id, "input") == 0)  ||
927 	        (strcmp(id, "output") == 0) ) return 1;
928 	      /* We looked at all the digits, so this is a normal id. */
929 	    return 0;
930       }
931       return 1;
932 }
933 
emit_id(const char * id)934 void emit_id(const char *id)
935 {
936       if (is_escaped(id)) fprintf(vlog_out, "\\%s ", id);
937       else fprintf(vlog_out, "%s", id);
938 }
939 
940 /*
941  * Get the correct MSB and LSB for a signal.
942  */
get_sig_msb_lsb(ivl_signal_t sig,int * msb,int * lsb)943 void get_sig_msb_lsb(ivl_signal_t sig, int *msb, int *lsb)
944 {
945       switch (ivl_signal_packed_dimensions(sig)) {
946 	  /* For a scalar we use zero for both the MSB and LSB. */
947 	case 0:
948 	    *msb = 0;
949 	    *lsb = 0;
950 	    break;
951 	case 1:
952 	  /* For a vector we use the real MSB and LSB. */
953 	    *msb = ivl_signal_packed_msb(sig, 0);
954 	    *lsb = ivl_signal_packed_lsb(sig, 0);
955 	    break;
956 	  /* For a packed vector we use the normalized MSB and LSB. */
957 	default:
958 	    *msb = ivl_signal_width(sig) - 1;
959 	    *lsb = 0;
960 	    break;
961       }
962 }
963 
get_time_const(int time_value)964 const char*get_time_const(int time_value)
965 {
966       switch (time_value) {
967 	case   2: return "100s";
968 	case   1: return "10s";
969 	case   0: return "1s";
970 	case  -1: return "100ms";
971 	case  -2: return "10ms";
972 	case  -3: return "1ms";
973 	case  -4: return "100us";
974 	case  -5: return "10us";
975 	case  -6: return "1us";
976 	case  -7: return "100ns";
977 	case  -8: return "10ns";
978 	case  -9: return "1ns";
979 	case -10: return "100ps";
980 	case -11: return "10ps";
981 	case -12: return "1ps";
982 	case -13: return "100fs";
983 	case -14: return "10fs";
984 	case -15: return "1fs";
985 	default:
986 	    fprintf(stderr, "Invalid time constant value %d.\n", time_value);
987 	    return "N/A";
988       }
989 }
990