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