• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nickg / nvc / 20414172721

21 Dec 2025 06:41PM UTC coverage: 92.602% (+0.006%) from 92.596%
20414172721

push

github

nickg
Move all printf-related functions to a new file

357 of 413 new or added lines in 12 files covered. (86.44%)

3 existing lines in 3 files now uncovered.

75646 of 81689 relevant lines covered (92.6%)

463080.1 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

61.78
/src/dump.c
1
//
2
//  Copyright (C) 2011-2024  Nick Gasson
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 3 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
15
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
//
17

18
#include "util.h"
19
#include "common.h"
20
#include "hash.h"
21
#include "ident.h"
22
#include "phase.h"
23
#include "printf.h"
24
#include "psl/psl-phase.h"
25
#include "tree.h"
26
#include "type.h"
27
#include "vlog/vlog-node.h"
28
#include "vlog/vlog-phase.h"
29

30
#include <assert.h>
31
#include <string.h>
32
#include <ctype.h>
33
#include <inttypes.h>
34

35
#define DUMP_TYPE_HINT  0
36
#define DUMP_ADDRESS    0
37
#define DUMP_STATICNESS 0
38
#define DUMP_GEN_NAMES  0
39

40
static void dump_expr(tree_t t);
41
static void dump_stmt(tree_t t, int indent);
42
static void dump_port(tree_t t, int indent);
43
static void dump_decl(tree_t t, int indent);
44
static void dump_decls(tree_t t, int indent);
45
static void dump_type(type_t type);
46
static void dump_package(tree_t t, int indent);
47
static void dump_package_body(tree_t t, int indent);
48
static void dump_constraint(tree_t t);
49
static void dump_elem_constraints(type_t type);
50
static void dump_psl(tree_t t, int indent);
51

52
typedef tree_t (*get_fn_t)(tree_t, unsigned);
53

54
static void tab(int indent)
245✔
55
{
56
   print_syntax("%*s", indent, "");
245✔
57
}
245✔
58

59
static void cannot_dump(tree_t t, const char *hint)
×
60
{
61
   print_syntax("\n");
×
62
   fflush(stdout);
×
63
   fatal("cannot dump %s kind %s", hint, tree_kind_str(tree_kind(t)));
×
64
}
65

66
static void dump_param(tree_t p)
32✔
67
{
68
   switch (tree_subkind(p)) {
32✔
69
   case P_POS:
70
      break;
71
   case P_NAMED:
3✔
72
      dump_expr(tree_name(p));
3✔
73
      print_syntax(" => ");
3✔
74
      break;
3✔
75
   }
76
   dump_expr(tree_value(p));
32✔
77
}
32✔
78

79
static void dump_params(tree_t t, get_fn_t get, int n, const char *prefix)
18✔
80
{
81
   if (n > 0) {
18✔
82
      if (prefix != NULL) {
17✔
83
         print_syntax(prefix, "");
4✔
84
         print_syntax(" ");
4✔
85
      }
86
      print_syntax("(");
17✔
87
      for (int i = 0; i < n; i++) {
49✔
88
         if (i > 0)
32✔
89
            print_syntax(", ");
15✔
90
         dump_param((*get)(t, i));
32✔
91
      }
92
      print_syntax(")");
17✔
93
   }
94
}
18✔
95

96
static void dump_range(tree_t r)
7✔
97
{
98
   switch (tree_subkind(r)) {
7✔
99
   case RANGE_TO:
5✔
100
      dump_expr(tree_left(r));
5✔
101
      print_syntax(" #to ");
5✔
102
      dump_expr(tree_right(r));
5✔
103
      break;
5✔
104
   case RANGE_DOWNTO:
2✔
105
      dump_expr(tree_left(r));
2✔
106
      print_syntax(" #downto ");
2✔
107
      dump_expr(tree_right(r));
2✔
108
      break;
2✔
109
   case RANGE_EXPR:
×
110
   case RANGE_ERROR:
111
      if (tree_has_value(r))
×
112
         dump_expr(tree_value(r));
×
113
      return;
114
   }
115
}
116

117
static void dump_type_hint(tree_t t)
118
{
119
#if DUMP_TYPE_HINT
120
   static int nested = 0;
121
   if (++nested == 1 && tree_has_type(t)) {
122
      nvc_printf("$red$/*");
123
      dump_type(tree_type(t));
124
      nvc_printf("$red$*/$$");
125
   }
126
   --nested;
127
#endif
128
}
129

130
static void dump_address(tree_t t)
131
{
132
#if DUMP_ADDRESS
133
   uint32_t a = (uint32_t)((uintptr_t)tree_arena(t) >> 2);
134
   a = (a ^ 61) ^ (a >> 16);
135
   a = a + (a << 3);
136
   a = a ^ (a >> 4);
137
   a = a * UINT32_C(0x27d4eb2d);
138
   a = a ^ (a >> 15);
139

140
   const int r = 1 + a % 5;
141
   const int g = 1 + (a >> 8) % 5;
142
   const int b = 1 + (a >> 16) % 5;
143

144
   const int color = 16 + 36*r + 6*g + b;
145

146
   char *LOCAL fmt = xasprintf("$!#%d${%%p:%s}$$", color,
147
                               tree_kind_str(tree_kind(t)));
148
   color_printf(fmt, t);
149
#endif
150
}
151

152
static void dump_waveform(tree_t w)
4✔
153
{
154
   if (tree_has_value(w))
4✔
155
      dump_expr(tree_value(w));
4✔
156
   else
157
      print_syntax("#null");
×
158

159
   if (tree_has_delay(w)) {
4✔
160
      print_syntax(" #after ");
3✔
161
      dump_expr(tree_delay(w));
3✔
162
   }
163
}
4✔
164

165
static void dump_external_name(tree_t t)
2✔
166
{
167
   print_syntax("<< #%s ", class_str(tree_class(t)));
2✔
168
   const int nparts = tree_parts(t);
2✔
169
   for (int i = 0; i < nparts; i++) {
8✔
170
      tree_t part = tree_part(t, i);
6✔
171
      switch (tree_subkind(part)) {
6✔
172
      case PE_ABSOLUTE:
1✔
173
         print_syntax(".");
1✔
174
         break;
1✔
175
      case PE_SIMPLE:
3✔
176
         print_syntax("%s%s", istr(tree_ident(part)),
3✔
177
                      i + 1 < nparts ? "." : "");
3✔
178
         break;
3✔
179
      case PE_CARET:
1✔
180
         print_syntax("^.");
1✔
181
         break;
1✔
182
      case PE_GENERATE:
×
183
         print_syntax("%s(", istr(tree_ident(part)));
×
184
         dump_expr(tree_value(part));
×
185
         print_syntax(").");
×
186
         break;
×
187
      }
188
   }
189
   print_syntax(" : ");
2✔
190
   dump_type(tree_type(t));
2✔
191
   print_syntax(" >>");
2✔
192
}
2✔
193

194
static void dump_expr(tree_t t)
206✔
195
{
196
   switch (tree_kind(t)) {
207✔
197
   case T_PROT_FCALL:
1✔
198
      dump_expr(tree_name(t));
1✔
199
      print_syntax(".");
1✔
200
      // Fall-through
201
   case T_FCALL:
13✔
202
      if (tree_has_ref(t)) {
13✔
203
         tree_t decl = tree_ref(t);
13✔
204
         dump_address(decl);
13✔
205
         print_syntax("%s", istr(tree_ident(decl)));
13✔
206
      }
207
      else
208
         print_syntax("%s", istr(tree_ident(t)));
×
209
      dump_params(t, tree_param, tree_params(t), NULL);
13✔
210
#if DUMP_STATICNESS
211
      if (tree_flags(t) & TREE_F_LOCALLY_STATIC)
212
         color_printf("$red$/* locally static */$$");
213
      else if (tree_flags(t) & TREE_F_GLOBALLY_STATIC)
214
         color_printf("$red$/* globally static */$$");
215
#endif
216
      break;
13✔
217

218
   case T_CONV_FUNC:
×
219
      if (tree_has_ref(t)) {
×
220
         tree_t decl = tree_ref(t);
×
221
         dump_address(decl);
×
222
         print_syntax("%s", istr(tree_ident(decl)));
×
223
      }
224
      else
225
         print_syntax("%s", istr(tree_ident(t)));
×
226
      print_syntax("(");
×
227
      dump_expr(tree_value(t));
×
228
      print_syntax(")");
×
229
      break;
×
230

231
   case T_LITERAL:
37✔
232
      switch (tree_subkind(t)) {
37✔
233
      case L_INT:
31✔
234
         print_syntax("%"PRIi64, tree_ival(t));
31✔
235
         break;
31✔
236
      case L_PHYSICAL:
4✔
237
         if (tree_has_ident(t))
4✔
238
            print_syntax("%"PRIi64" %s", tree_ival(t), istr(tree_ident(t)));
4✔
239
         else
240
            print_syntax("%"PRIi64, tree_ival(t));
×
241
         break;
242
      case L_REAL:
2✔
243
         print_syntax("%lf", tree_dval(t));
2✔
244
         break;
2✔
245
      case L_NULL:
×
246
         print_syntax("#null");
×
247
         break;
×
248
      default:
×
249
         should_not_reach_here();
250
      }
251
      break;
252

253
   case T_STRING:
6✔
254
      {
255
         print_syntax("\"");
6✔
256
         const int nchars = tree_chars(t);
6✔
257
         for (int i = 0; i < nchars; i++) {
30✔
258
            ident_t rune = tree_ident(tree_char(t, i));
24✔
259
            if (ident_char(rune, 0) == '\'')
24✔
260
               print_syntax("%c", ident_char(rune, 1));
24✔
261
            else
262
               print_syntax("\" & %s & \"", istr(rune));
×
263
         }
264
         print_syntax("\"");
6✔
265
      }
266
      break;
6✔
267

268
   case T_NEW:
×
269
      print_syntax("#new ");
×
270
      dump_expr(tree_value(t));
×
271
      break;
×
272

273
   case T_ALL:
×
274
      if (tree_has_value(t)) {
×
275
         dump_expr(tree_value(t));
×
276
         print_syntax(".#all");
×
277
      }
278
      else
279
         print_syntax("#all");
×
280
      break;
281

282
   case T_TYPE_REF:
1✔
283
      dump_type(tree_type(t));
1✔
284
      break;
1✔
285

286
   case T_AGGREGATE:
3✔
287
      print_syntax("(");
3✔
288
      for (unsigned i = 0; i < tree_assocs(t); i++) {
7✔
289
         if (i > 0)
4✔
290
            print_syntax(", ");
1✔
291
         tree_t a = tree_assoc(t, i);
4✔
292
         tree_t value = tree_value(a);
4✔
293
         switch (tree_subkind(a)) {
4✔
294
         case A_CONCAT:
×
295
            print_syntax("/* concat */");
×
296
            // Fall-through
297
         case A_POS:
×
298
            dump_expr(value);
×
299
            break;
×
300
         case A_NAMED:
1✔
301
            dump_expr(tree_name(a));
1✔
302
            print_syntax(" => ");
1✔
303
            dump_expr(value);
1✔
304
            break;
1✔
305
         case A_OTHERS:
3✔
306
            print_syntax("#others ");
3✔
307
            if (tree_ranges(a) > 0) {
3✔
308
               print_syntax("/*");
×
309
               dump_range(tree_range(a, 0));
×
310
               print_syntax("*/ ");
×
311
            }
312
            print_syntax("=> ");
3✔
313
            dump_expr(value);
3✔
314
            break;
3✔
315
         case A_SLICE:
×
316
            print_syntax("/* slice */");
×
317
            // Fall-through
318
         case A_RANGE:
×
319
            dump_range(tree_range(a, 0));
×
320
            print_syntax(" => ");
×
321
            dump_expr(value);
×
322
            break;
×
323
         default:
×
324
            should_not_reach_here();
325
         }
326
      }
327
      print_syntax(")");
3✔
328
      break;
3✔
329

330
   case T_REF:
56✔
331
      if (tree_has_ref(t)) {
56✔
332
         tree_t decl = tree_ref(t);
56✔
333
         dump_address(decl);
56✔
334
         print_syntax("%s", istr(tree_ident(decl)));
56✔
335
      }
336
      else
337
         print_syntax("%s", istr(tree_ident(t)));
×
338
      break;
339

340
   case T_ATTR_REF:
2✔
341
      dump_expr(tree_name(t));
2✔
342
      print_syntax("'%s", istr(tree_ident(t)));
2✔
343
      if (tree_params(t) > 0)
2✔
344
         dump_params(t, tree_param, tree_params(t), NULL);
×
345
      break;
346

347
   case T_EXTERNAL_NAME:
2✔
348
      dump_external_name(t);
2✔
349
      break;
2✔
350

351
   case T_ARRAY_REF:
1✔
352
      dump_expr(tree_value(t));
1✔
353
      dump_params(t, tree_param, tree_params(t), NULL);
1✔
354
      break;
1✔
355

356
   case T_ARRAY_SLICE:
×
357
      dump_expr(tree_value(t));
×
358
      print_syntax("(");
×
359
      dump_range(tree_range(t, 0));
×
360
      print_syntax(")");
×
361
      break;
×
362

363
   case T_RECORD_REF:
×
364
      dump_expr(tree_value(t));
×
365
      print_syntax(".%s", istr(tree_ident(t)));
×
366
      break;
×
367

368
   case T_TYPE_CONV:
4✔
369
      dump_type(tree_type(t));
4✔
370
      print_syntax("(");
4✔
371
      dump_expr(tree_value(t));
4✔
372
      print_syntax(")");
4✔
373
      break;
4✔
374

375
   case T_QUALIFIED:
×
376
      if (tree_has_value(t)) {
×
377
         print_syntax("%s'(", istr(type_ident(tree_type(t))));
×
378
         dump_expr(tree_value(t));
×
379
         print_syntax(")");
×
380
      }
381
      else
382
         dump_type(tree_type(t));
×
383
      break;
384

385
   case T_OPEN:
1✔
386
      print_syntax("#open");
1✔
387
      break;
1✔
388

389
   case T_BOX:
80✔
390
      print_syntax("<>");
80✔
391
      break;
80✔
392

393
   case T_WAVEFORM:
×
394
      dump_waveform(t);
×
395
      break;
×
396

397
   case T_PACKAGE_MAP:
×
398
      print_syntax("%s ", istr(tree_ident(t)));
×
399
      switch (tree_subkind(t)) {
×
400
      case PACKAGE_MAP_BOX:
×
401
         print_syntax("#generic #map (<>)");
×
402
         break;
×
403
      case PACKAGE_MAP_DEFAULT:
×
404
         print_syntax("#generic map (#default)");
×
405
         break;
×
406
      case PACKAGE_MAP_MATCHING:
×
407
         dump_params(t, tree_genmap, tree_genmaps(t), "#generic #map");
×
408
         break;
×
409
      }
410
      return;
411

412
   case T_COND_VALUE:
413
      for (int i = 0; i < tree_conds(t); i++) {
×
414
         tree_t c = tree_cond(t, i);
×
415
         if (i > 0)
×
416
            print_syntax(" #else ");
×
417
         if (tree_has_result(c))
×
418
            dump_expr(tree_result(c));
×
419
         else
420
            print_syntax("#unaffected");
×
421
         if (tree_has_value(c)) {
×
422
            print_syntax(" #when ");
×
423
            dump_expr(tree_value(c));
×
424
         }
425
      }
426
      break;
427

428
   case T_INERTIAL:
1✔
429
      print_syntax("#inertial ");
1✔
430
      dump_expr(tree_value(t));
1✔
431
      break;
1✔
432

433
   default:
×
434
      cannot_dump(t, "expr");
×
435
   }
436

437
   dump_type_hint(t);
206✔
438
}
439

440
static void dump_record_elem_constraint(tree_t t)
×
441
{
442
   print_syntax("%s", istr(tree_ident(t)));
×
443

444
   type_t ftype = tree_type(t);
×
445
   if (type_has_constraint(ftype))
×
446
      dump_constraint(type_constraint(ftype));
×
447

448
   dump_elem_constraints(ftype);
×
449
}
×
450

451
static void dump_constraint(tree_t t)
5✔
452
{
453
   const int nranges = tree_ranges(t);
5✔
454

455
   switch (tree_subkind(t)) {
5✔
456
   case C_RANGE:
1✔
457
      print_syntax(" #range ");
1✔
458
      dump_range(tree_range(t, 0));
1✔
459
      break;
1✔
460
   case C_INDEX:
4✔
461
      print_syntax("(");
4✔
462
      for (int i = 0; i < nranges; i++) {
8✔
463
         if (i > 0) print_syntax(", ");
4✔
464
         dump_range(tree_range(t, i));
4✔
465
      }
466
      print_syntax(")");
4✔
467
      break;
4✔
468
   case C_RECORD:
×
469
      print_syntax("(");
×
470
      for (int i = 0; i < nranges; i++) {
×
471
         if (i > 0) print_syntax(", ");
×
472
         dump_record_elem_constraint(tree_range(t, i));
×
473
      }
474
      print_syntax(")");
×
475
      break;
×
476
   }
477
}
5✔
478

479
static void dump_elem_constraints(type_t type)
5✔
480
{
481
   if (type_is_array(type) && type_has_elem(type)) {
5✔
482
      type_t elem = type_elem(type);
×
483
      if (is_anonymous_subtype(elem)) {
×
484
         // Anonymous subtype created for element constraints
485
         if (type_has_constraint(elem))
×
486
            dump_constraint(type_constraint(elem));
×
487
         else
488
            print_syntax("(#open)");
×
489
         dump_elem_constraints(elem);
×
490
      }
491
   }
492
}
5✔
493

494
static void dump_type(type_t type)
123✔
495
{
496
   if (is_anonymous_subtype(type)) {
123✔
497
      // Anonymous subtype
498
      print_syntax("%s", type_pp(type));
4✔
499
      if (type_ident(type) == type_ident(type_base(type))) {
4✔
500
         if (type_has_constraint(type))
4✔
501
            dump_constraint(type_constraint(type));
4✔
502
      }
503
      dump_elem_constraints(type);
4✔
504
   }
505
   else if (type_is_none(type))
119✔
506
      print_syntax("/* error */");
×
507
   else
508
      print_syntax("%s", type_pp(type));
119✔
509
}
123✔
510

511
static void dump_arguments(tree_t t, int indent, const char *trailer)
7✔
512
{
513
   const int nports = tree_ports(t);
7✔
514
   if (nports > 0) {
7✔
515
      print_syntax(" (");
3✔
516
      if (nports > 1) {
3✔
517
         print_syntax("\n");
1✔
518
         for (int i = 0; i < nports; i++) {
3✔
519
            if (i > 0) print_syntax(";\n");
2✔
520
            dump_port(tree_port(t, i), indent + 4);
2✔
521
         }
522
      }
523
      else
524
         dump_port(tree_port(t, 0), 1);
2✔
525
      print_syntax(" )%s", trailer);
3✔
526
   }
527
}
7✔
528

529
static void dump_ports(tree_t t, int indent)
5✔
530
{
531
   const int nports = tree_ports(t);
5✔
532
   if (nports > 0) {
5✔
533
      tab(indent);
4✔
534
      print_syntax("#port (");
4✔
535
      if (nports > 1) {
4✔
536
         print_syntax("\n");
3✔
537
         for (unsigned i = 0; i < nports; i++) {
9✔
538
            if (i > 0) print_syntax(";\n");
6✔
539
            dump_port(tree_port(t, i), indent + 2);
6✔
540
         }
541
      }
542
      else
543
         dump_port(tree_port(t, 0), 1);
1✔
544
      print_syntax(" );\n");
4✔
545
   }
546
}
5✔
547

548
static void dump_generics(tree_t t, int indent, const char *trailer)
13✔
549
{
550
   const int ngenerics = tree_generics(t);
13✔
551
   if (ngenerics > 0) {
13✔
552
      tab(indent);
3✔
553
      print_syntax("#generic (");
3✔
554
      if (ngenerics > 1) {
3✔
555
         print_syntax("\n");
2✔
556
         for (int i = 0; i < ngenerics; i++) {
93✔
557
            tree_t g = tree_generic(t, i);
91✔
558
            dump_port(g, indent + 2);
91✔
559
            if (i + 1 == ngenerics && (tree_flags(g) & TREE_F_PREDEFINED)) {
91✔
560
               print_syntax(";\n");
2✔
561
               tab(indent - 1);
2✔
562
            }
563
            else if (i + 1 < ngenerics)
89✔
564
               print_syntax(";\n");
89✔
565
         }
566
      }
567
      else
568
         dump_port(tree_generic(t, 0), 1);
1✔
569
      print_syntax(" )%s", trailer);
3✔
570
   }
571
}
13✔
572

573
static void dump_port_map(tree_t t, int indent, const char *trailer)
3✔
574
{
575
   const int nparams = tree_params(t);
3✔
576
   if (nparams > 0) {
3✔
577
      tab(indent);
3✔
578
      dump_params(t, tree_param, nparams, "#port #map");
3✔
579
      print_syntax("%s", trailer);
3✔
580
   }
581
}
3✔
582

583
static void dump_generic_map(tree_t t, int indent, const char *trailer)
4✔
584
{
585
   const int ngenmaps = tree_genmaps(t);
4✔
586
   if (ngenmaps > 0) {
4✔
587
      tab(indent);
1✔
588
      dump_params(t, tree_genmap, ngenmaps, "#generic #map");
1✔
589
      print_syntax("%s", trailer);
1✔
590
   }
591
}
4✔
592

593
static void dump_binding(tree_t t, int indent)
×
594
{
595
   dump_address(t);
×
596
   print_syntax("#use %s", istr(tree_ident(t)));
×
597
   if (tree_has_ident2(t))
×
598
      print_syntax("(%s)", istr(tree_ident2(t)));
×
599
   if (tree_genmaps(t) > 0 || tree_params(t) > 0)
×
600
      print_syntax("\n");
×
601
   dump_generic_map(t, indent + 2, tree_params(t) > 0 ? "\n" : "");
×
602
   dump_port_map(t, indent + 2, "");
×
603
   print_syntax(";\n");
×
604
}
×
605

606
static void dump_stmts(tree_t t, int indent)
16✔
607
{
608
   bool last_was_newline = false;
16✔
609
   const int nstmts = tree_stmts(t);
16✔
610
   for (int i = 0; i < nstmts; i++) {
31✔
611
      tree_t s = tree_stmt(t, i);
15✔
612
      const tree_kind_t kind = tree_kind(s);
15✔
613

614
      bool needs_newline;
15✔
615
      if (kind == T_VERILOG) {
15✔
616
         const vlog_kind_t vkind = vlog_kind(tree_vlog(s));
×
617
         needs_newline = (vkind == V_ALWAYS || vkind == V_INITIAL);
×
618
      }
619
      else
620
         needs_newline = (kind == T_BLOCK || kind == T_PROCESS
15✔
621
                          || kind == T_INSTANCE);
622

623
      if (needs_newline && i > 0 && !last_was_newline)
15✔
624
         print_syntax("\n");
×
625

626
      dump_stmt(s, indent);
15✔
627

628
      if (needs_newline && i + 1 < nstmts) {
15✔
629
         print_syntax("\n");
×
630
         last_was_newline = true;
×
631
      }
632
      else
633
         last_was_newline = false;
634
   }
635
}
16✔
636

637
static void dump_block(tree_t t, int indent)
7✔
638
{
639
   dump_decls(t, indent + 2);
7✔
640
   tab(indent);
7✔
641
   print_syntax("#begin\n");
7✔
642
   dump_stmts(t, indent + 2);
7✔
643
}
7✔
644

645
static void dump_wait_level(tree_t t)
3✔
646
{
647
   const tree_flags_t flags = tree_flags(t);
3✔
648
   if (flags & TREE_F_NEVER_WAITS)
3✔
649
      print_syntax("   -- Never waits");
3✔
650
   else if (flags & TREE_F_HAS_WAIT)
×
651
      print_syntax("   -- Contains wait statement");
×
652
}
3✔
653

654
static void dump_type_decl(tree_t t, int indent)
2✔
655
{
656
   type_t type = tree_type(t);
2✔
657
   const type_kind_t kind = type_kind(type);
2✔
658

659
   print_syntax("#type %s", istr(tree_ident(t)));
2✔
660

661
   if (kind == T_INCOMPLETE) {
2✔
662
      print_syntax(";\n");
×
663
      return;
×
664
   }
665

666
   print_syntax(" #is ");
2✔
667

668
   if (type_is_integer(type) || type_is_real(type)) {
2✔
669
      print_syntax("#range ");
×
670
      dump_range(type_dim(type, 0));
×
671
   }
672
   else if (type_is_physical(type)) {
2✔
673
      print_syntax("#range ");
×
674
      dump_range(type_dim(type, 0));
×
675
      print_syntax("\n");
×
676
      tab(indent + 2);
×
677
      print_syntax("#units\n");
×
678
      {
679
         const int nunits = type_units(type);
×
680
         for (int i = 0; i < nunits; i++) {
×
681
            tree_t u = type_unit(type, i);
×
682
            tab(indent + 4);
×
683
            print_syntax("%s = ", istr(tree_ident(u)));
×
684
            dump_expr(tree_value(u));
×
685
            print_syntax(";\n");
×
686
         }
687
      }
688
      tab(indent + 2);
×
689
      print_syntax("#end #units");
×
690
   }
691
   else if (type_is_array(type)) {
2✔
692
      print_syntax("#array ");
1✔
693
      if (kind == T_ARRAY) {
1✔
694
         print_syntax("(");
1✔
695
         const int nindex = type_indexes(type);
1✔
696
         for (int i = 0; i < nindex; i++) {
2✔
697
            if (i > 0) print_syntax(", ");
1✔
698
            dump_type(type_index(type, i));
1✔
699
            print_syntax(" #range <>");
1✔
700
         }
701
         print_syntax(")");
1✔
702
      }
703
      else if (kind == T_SUBTYPE) {
×
704
         if (type_has_constraint(type))
×
705
            dump_constraint(type_constraint(type));
×
706
      }
707
      else {
708
         print_syntax("(");
×
709
         const int ndims = type_dims(type);
×
710
         for (int i = 0; i < ndims; i++) {
×
711
            if (i > 0) print_syntax(", ");
×
712
            dump_range(type_dim(type, i));
×
713
         }
714
         print_syntax(")");
×
715
      }
716
      print_syntax(" #of ");
1✔
717
      dump_type(type_elem(type));
1✔
718
   }
719
   else if (type_is_record(type)) {
1✔
720
      print_syntax("#record\n");
1✔
721
      const int nfields = type_fields(type);
1✔
722
      for (int i = 0; i < nfields; i++)
3✔
723
         dump_decl(type_field(type, i), indent + 2);
2✔
724
      tab(indent);
1✔
725
      print_syntax("#end #record");
1✔
726
   }
727
   else if (kind == T_ENUM) {
×
728
      print_syntax("(");
×
729
      for (unsigned i = 0; i < type_enum_literals(type); i++) {
×
730
         if (i > 0) print_syntax(", ");
×
731
         print_syntax("%s", istr(tree_ident(type_enum_literal(type, i))));
×
732
      }
733
      print_syntax(")");
×
734
   }
735
   else if (kind == T_INCOMPLETE)
×
736
      ;
737
   else
738
      dump_type(type);
×
739

740
   print_syntax(";\n");
2✔
741
}
742

743
static void dump_subtype_decl(tree_t t, int indent)
1✔
744
{
745
   type_t type = tree_type(t);
1✔
746

747
   print_syntax("#subtype %s #is ", istr(tree_ident(t)));
1✔
748
   if (type_has_resolution(type)) {
1✔
749
      dump_expr(type_resolution(type));
×
750
      print_syntax(" ");
×
751
   }
752
   print_syntax("%s", type_pp(type_base(type)));
1✔
753

754
   if (type_has_constraint(type))
1✔
755
      dump_constraint(type_constraint(type));
1✔
756

757
   dump_elem_constraints(type);
1✔
758

759
   print_syntax(";\n");
1✔
760
}
1✔
761

762
static void dump_component(tree_t t, int indent)
1✔
763
{
764
   print_syntax("#component %s #is\n", istr(tree_ident(t)));
1✔
765
   dump_generics(t, indent + 2, ";\n");
1✔
766
   dump_ports(t, indent + 2);
1✔
767
   print_syntax("#end #component;\n");
1✔
768
}
1✔
769

770
static void dump_use(tree_t t)
7✔
771
{
772
   print_syntax("#use %s", istr(tree_ident(t)));
7✔
773
   if (tree_has_ident2(t))
7✔
774
      print_syntax(".%s", istr(tree_ident2(t)));
7✔
775
   print_syntax(";\n");
7✔
776
}
7✔
777

778
static void dump_attr_spec(tree_t t)
4✔
779
{
780
   print_syntax("#attribute %s #of ", istr(tree_ident(t)));
4✔
781

782
   switch (tree_subkind(t)) {
4✔
783
   case SPEC_EXACT:
2✔
784
      print_syntax("%s", istr(tree_ident2(t)));
2✔
785
      break;
2✔
786
   case SPEC_ALL:
1✔
787
      print_syntax("#all");
1✔
788
      break;
1✔
789
   case SPEC_OTHERS:
1✔
790
      print_syntax("#others");
1✔
791
      break;
1✔
792
   }
793

794
   print_syntax(" : #%s #is ", class_str(tree_class(t)));
4✔
795
   dump_expr(tree_value(t));
4✔
796
   print_syntax(";\n");
4✔
797
}
4✔
798

799
static void dump_view_decl(tree_t t, int indent)
1✔
800
{
801
   type_t type = tree_type(t);
1✔
802
   print_syntax("#view %s #of ", istr(tree_ident(t)));
1✔
803
   dump_type(type_designated(type));
1✔
804
   print_syntax(" #is\n");
1✔
805

806
   const int nfields = type_fields(type);
1✔
807
   for (int i = 0; i < nfields; i++) {
3✔
808
      tree_t elem = type_field(type, i);
2✔
809
      tab(indent + 2);
2✔
810
      print_syntax("%s : #%s;\n", istr(tree_ident(elem)),
2✔
811
                   port_mode_str(tree_subkind(elem)));
2✔
812
   }
813

814
   tab(indent);
1✔
815
   print_syntax("#end #view;\n");
1✔
816
}
1✔
817

818
static void dump_decl(tree_t t, int indent)
35✔
819
{
820
   tab(indent);
35✔
821

822
   const tree_kind_t kind = tree_kind(t);
35✔
823
   if (kind != T_HIER)
35✔
824
      dump_address(t);
825

826
   switch (kind) {
35✔
827
   case T_IMPLICIT_SIGNAL:
×
828
      print_syntax("/* implicit */ ");
×
829
      // Fall-through
830
   case T_SIGNAL_DECL:
5✔
831
      print_syntax("#signal %s : ", istr(tree_ident(t)));
5✔
832
      break;
5✔
833

834
   case T_VAR_DECL:
3✔
835
      print_syntax("#variable %s : ", istr(tree_ident(t)));
3✔
836
      break;
3✔
837

838
   case T_CONST_DECL:
3✔
839
      print_syntax("#constant %s : ", istr(tree_ident(t)));
3✔
840
      break;
3✔
841

842
   case T_GENERIC_DECL:
1✔
843
      // Loop variable in for-generate statement
844
      print_syntax("/* loop variable */ %s : ", istr(tree_ident(t)));
1✔
845
      break;
1✔
846

847
   case T_FIELD_DECL:
2✔
848
      print_syntax("%s : ", istr(tree_ident(t)));
2✔
849
      break;
2✔
850

851
   case T_TYPE_DECL:
2✔
852
      dump_type_decl(t, indent);
2✔
853
      return;
2✔
854

855
   case T_SUBTYPE_DECL:
1✔
856
      dump_subtype_decl(t, indent);
1✔
857
      return;
1✔
858

859
   case T_SPEC:
×
860
      if (tree_has_ident(t))
×
861
         print_syntax("#for %s", istr(tree_ident(t)));
×
862
      else
863
         print_syntax("#for #others");
×
864
      if (tree_has_ref(t))
×
865
         print_syntax(" : %s", istr(tree_ident(tree_ref(t))));
×
866
      print_syntax("\n");
×
867
      tab(indent + 2);
×
868
      dump_binding(tree_value(t), indent + 2);
×
869
      dump_decls(t, indent + 2);
×
870
      tab(indent);
×
871
      print_syntax("#end #for;\n");
×
872
      return;
×
873

874
   case T_BLOCK_CONFIG:
×
875
      print_syntax("#for %s\n", istr(tree_ident(t)));
×
876
      dump_decls(t, indent + 2);
×
877
      tab(indent);
×
878
      print_syntax("#end #for;\n");
×
879
      return;
×
880

881
   case T_ENUM_LIT:
×
882
      print_syntax("%s", istr(tree_ident(t)));
×
883
      return;
×
884

885
   case T_ALIAS:
×
886
      if (tree_flags(t) & TREE_F_PREDEFINED)
×
887
         print_syntax("-- predefined ");
×
888
      print_syntax("#alias %s", istr(tree_ident(t)));
×
889
      if (tree_has_type(t)) {
×
890
         print_syntax(" : ");
×
891
         dump_type(tree_type(t));
×
892
      }
893
      print_syntax(" #is ");
×
894
      dump_expr(tree_value(t));
×
895
      print_syntax(";\n");
×
896
      return;
×
897

898
   case T_ATTR_SPEC:
4✔
899
      dump_attr_spec(t);
4✔
900
      return;
4✔
901

902
   case T_ATTR_DECL:
2✔
903
      print_syntax("#attribute %s : ", istr(tree_ident(t)));
2✔
904
      dump_type(tree_type(t));
2✔
905
      print_syntax(";\n");
2✔
906
      return;
2✔
907

908
   case T_FUNC_DECL:
2✔
909
      if (tree_flags(t) & TREE_F_PREDEFINED)
2✔
910
         print_syntax("-- predefined %s\n", type_pp(tree_type(t)));
×
911
      else {
912
         print_syntax("#function %s", istr(tree_ident(t)));
2✔
913
         dump_generics(t, indent + 2, "");
2✔
914
         dump_arguments(t, indent, "");
2✔
915
         print_syntax(" #return ");
2✔
916
         dump_type(type_result(tree_type(t)));
2✔
917
         print_syntax(";\n");
2✔
918
         if (tree_has_ident2(t)) {
2✔
919
            tab(indent + 2);
2✔
920
            print_syntax("-- %s\n", istr(tree_ident2(t)));
2✔
921
         }
922
      }
923
      return;
924

925
   case T_FUNC_INST:
2✔
926
   case T_FUNC_BODY:
927
      print_syntax("#function %s", istr(tree_ident(t)));
2✔
928
      dump_type_hint(t);
2✔
929
      dump_generics(t, indent + 2, tree_ports(t) > 0 ? "\n" : "");
3✔
930
      if (tree_kind(t) == T_FUNC_INST)
2✔
931
         dump_generic_map(t, indent + 2, tree_ports(t) > 0 ? "\n" : "");
×
932
      dump_arguments(t, indent, "");
2✔
933
      print_syntax(" #return ");
2✔
934
      dump_type(type_result(tree_type(t)));
2✔
935
      print_syntax(" #is\n");
2✔
936
      if (tree_has_ident2(t)) {
2✔
937
         tab(indent + 2);
2✔
938
         print_syntax("-- %s\n", istr(tree_ident2(t)));
2✔
939
      }
940
      dump_block(t, indent);
2✔
941
      tab(indent);
2✔
942
      print_syntax("#end #function;\n");
2✔
943
      return;
2✔
944

945
   case T_PROC_DECL:
×
946
      if (tree_flags(t) & TREE_F_PREDEFINED)
×
947
         print_syntax("-- predefined %s\n", type_pp(tree_type(t)));
×
948
      else {
949
         print_syntax("#procedure %s", istr(tree_ident(t)));
×
950
         dump_generics(t, indent + 2, tree_ports(t) > 0 ? "\n" : "");
×
951
         dump_arguments(t, indent, "");
×
952
         print_syntax(";");
×
953
         dump_wait_level(t);
×
954
         print_syntax("\n");
×
955
         if (tree_has_ident2(t)) {
×
956
            tab(indent + 2);
×
957
            print_syntax("-- %s\n", istr(tree_ident2(t)));
×
958
         }
959
      }
960
      return;
961

962
   case T_PROC_INST:
3✔
963
   case T_PROC_BODY:
964
      print_syntax("#procedure %s", istr(tree_ident(t)));
3✔
965
      dump_type_hint(t);
3✔
966
      dump_generics(t, indent + 2, tree_ports(t) > 0 ? "\n" : "");
5✔
967
      if (tree_kind(t) == T_PROC_INST)
3✔
968
         dump_generic_map(t, indent + 2, tree_ports(t) > 0 ? "\n" : "");
×
969
      dump_arguments(t, indent, "");
3✔
970
      print_syntax(" #is");
3✔
971
      dump_wait_level(t);
3✔
972
      print_syntax("\n");
3✔
973
      if (tree_has_ident2(t)) {
3✔
974
         tab(indent + 2);
3✔
975
         print_syntax("-- %s\n", istr(tree_ident2(t)));
3✔
976
      }
977
      dump_block(t, indent);
3✔
978
      tab(indent);
3✔
979
      print_syntax("#end #procedure;\n");
3✔
980
      return;
3✔
981

982
   case T_HIER:
×
983
      {
984
         const char *kind = "Scope";
×
985
         switch (tree_subkind(t)) {
×
986
         case T_ARCH: kind = "Instance"; break;
×
987
         case T_IF_GENERATE: kind = "If generate"; break;
×
988
         case T_FOR_GENERATE: kind = "For generate"; break;
×
989
         case T_BLOCK: kind = "Block"; break;
×
990
         }
991

992
         ident_t dotted = tree_ident(t);
×
993
         ident_t symbol = tree_ident2(t);
×
994

995
         print_syntax("-- %s %s", kind, istr(dotted));
×
996
         if (dotted != symbol)
×
997
            print_syntax(" (clone of %s)", istr(symbol));
×
998
         print_syntax("\n");
×
999
      }
1000
      return;
×
1001

1002
   case T_COMPONENT:
1✔
1003
      dump_component(t, indent);
1✔
1004
      return;
1✔
1005

1006
   case T_PROT_DECL:
1✔
1007
      print_syntax("#type %s #is #protected\n", istr(tree_ident(t)));
1✔
1008
      dump_decls(t, indent + 2);
1✔
1009
      tab(indent);
1✔
1010
      print_syntax("#end #protected;\n");
1✔
1011
      return;
1✔
1012

1013
   case T_PROT_BODY:
1✔
1014
      print_syntax("#type %s #is #protected #body\n", istr(tree_ident(t)));
1✔
1015
      dump_decls(t, indent + 2);
1✔
1016
      tab(indent);
1✔
1017
      print_syntax("#end #protected #body;\n");
1✔
1018
      return;
1✔
1019

1020
   case T_FILE_DECL:
×
1021
      print_syntax("#file %s : ", istr(tree_ident(t)));
×
1022
      dump_type(tree_type(t));
×
1023
      if (tree_has_value(t)) {
×
1024
         print_syntax(" #open ");
×
1025
         dump_expr(tree_file_mode(t));
×
1026
         print_syntax(" #is ");
×
1027
         dump_expr(tree_value(t));
×
1028
      }
1029
      print_syntax(";\n");
×
1030
      return;
×
1031

1032
   case T_USE:
×
1033
      dump_use(t);
×
1034
      return;
×
1035

1036
   case T_PACKAGE:
×
1037
   case T_PACK_INST:
1038
      dump_package(t, indent);
×
1039
      return;
×
1040

1041
   case T_PACK_BODY:
×
1042
      dump_package_body(t, indent);
×
1043
      return;
×
1044

1045
   case T_PSL_DECL:
1✔
1046
   case T_PSL_DIRECT:
1047
      dump_psl(t, 0);
1✔
1048
      print_syntax(";\n");
1✔
1049
      return;
1✔
1050

1051
   case T_VIEW_DECL:
1✔
1052
      dump_view_decl(t, 0);
1✔
1053
      return;
1✔
1054

1055
   case T_VERILOG:
×
1056
      vlog_dump(tree_vlog(t), indent);
×
1057
      return;
×
1058

1059
   default:
×
1060
      cannot_dump(t, "decl");
×
1061
   }
1062

1063
   dump_type(tree_type(t));
14✔
1064

1065
   if (tree_kind(t) != T_FIELD_DECL && tree_has_value(t)) {
14✔
1066
      print_syntax(" := ");
6✔
1067
      dump_expr(tree_value(t));
6✔
1068
   }
1069
   print_syntax(";\n");
14✔
1070
}
1071

1072
static void dump_waveforms(tree_t t)
3✔
1073
{
1074
   const int nwaves = tree_waveforms(t);
3✔
1075
   for (int i = 0; i < nwaves; i++) {
7✔
1076
      if (i > 0) print_syntax(", ");
4✔
1077
      dump_waveform(tree_waveform(t, i));
4✔
1078
   }
1079
}
3✔
1080

1081
static void dump_alternative(tree_t t, int indent)
2✔
1082
{
1083
   tab(indent);
2✔
1084
   print_syntax("#when ");
2✔
1085

1086
   if (tree_has_ident(t))
2✔
1087
      print_syntax("%s: ", istr(tree_ident(t)));
×
1088

1089
   const int nchoices = tree_choices(t);
2✔
1090
   for (int i = 0; i < nchoices; i++) {
5✔
1091
      if (i > 0) print_syntax(" | ");
3✔
1092
      tree_t a = tree_choice(t, i);
3✔
1093
      if (tree_has_name(a))
3✔
1094
         dump_expr(tree_name(a));
1✔
1095
      else if (tree_ranges(a) > 0)
2✔
1096
         dump_range(tree_range(a, 0));
1✔
1097
      else
1098
         print_syntax("#others");
1✔
1099
   }
1100

1101
   print_syntax(" =>\n");
2✔
1102

1103
   if (tree_decls(t) > 0) {
2✔
1104
      dump_decls(t, indent + 4);
×
1105
      tab(indent + 2);
×
1106
      print_syntax("#begin\n");
×
1107
      dump_stmts(t, indent + 4);
×
1108
      tab(indent + 2);
×
1109
      print_syntax("#end;\n");
×
1110
   }
1111
   else
1112
      dump_stmts(t, indent + 2);
2✔
1113
}
2✔
1114

1115
static void dump_psl(tree_t t, int indent)
2✔
1116
{
1117
   if (standard() < STD_08)
2✔
1118
      print_syntax("-- psl ");
×
1119
   psl_dump(tree_psl(t));
2✔
1120
}
2✔
1121

1122
static void dump_instance(tree_t t, int indent)
1✔
1123
{
1124
   switch (tree_class(t)) {
1✔
1125
   case C_ENTITY:        print_syntax("#entity "); break;
×
1126
   case C_COMPONENT:     print_syntax("#component "); break;
1✔
1127
   case C_CONFIGURATION: print_syntax("#configuration "); break;
×
1128
   default: break;
1129
   }
1130

1131
   print_syntax("%s", istr(tree_ident2(t)));
1✔
1132

1133
   const int nparams = tree_params(t);
1✔
1134
   const int ngenmaps = tree_genmaps(t);
1✔
1135

1136
   if (tree_has_spec(t)) {
1✔
1137
      tree_t spec = tree_spec(t);
×
1138
      if (tree_has_value(spec)) {
×
1139
         tree_t bind = tree_value(spec);
×
1140
         LOCAL_TEXT_BUF tb = tb_new();
×
1141
         tb_cat(tb, istr(tree_ident(bind)));
×
1142
         if (tree_has_ident2(bind))
×
1143
            tb_printf(tb, "(%s)", istr(tree_ident2(bind)));
×
1144
         print_syntax("  -- bound to %s\n", tb_get(tb));
×
1145
      }
1146
   }
1147
   else if (nparams > 0 || ngenmaps > 0)
1✔
1148
      print_syntax("\n");
1✔
1149

1150
   dump_generic_map(t, indent + 2, nparams > 0 ? "\n" : "");
1✔
1151
   dump_port_map(t, indent + 2, "");
1✔
1152
   print_syntax(";\n");
1✔
1153
}
1✔
1154

1155
static void dump_stmt(tree_t t, int indent)
22✔
1156
{
1157
   const tree_kind_t kind = tree_kind(t);
25✔
1158
   if (kind == T_VERILOG) {
25✔
1159
      vlog_dump(tree_vlog(t), indent);
×
1160
      return;
×
1161
   }
1162

1163
   tab(indent);
25✔
1164

1165
   if (tree_has_ident(t)) {
25✔
1166
      const char *label = istr(tree_ident(t));
10✔
1167
#if !DUMP_GEN_NAMES
1168
      if (label[0] != '_')   // Skip generated labels
10✔
1169
#endif
1170
         print_syntax("%s: ", label);
6✔
1171
   }
1172

1173
   switch (tree_kind(t)) {
25✔
1174
   case T_PROCESS:
2✔
1175
      dump_address(t);
2✔
1176
      if (tree_flags(t) & TREE_F_POSTPONED)
2✔
1177
         print_syntax("#postponed ");
×
1178
      print_syntax("#process ");
2✔
1179
      if (tree_triggers(t) > 0) {
2✔
1180
         print_syntax("(");
2✔
1181
         for (unsigned i = 0; i < tree_triggers(t); i++) {
4✔
1182
            if (i > 0)
2✔
1183
               print_syntax(", ");
×
1184
            dump_expr(tree_trigger(t, i));
2✔
1185
         }
1186
         print_syntax(") ");
2✔
1187
      }
1188
      print_syntax("#is\n");
2✔
1189
      dump_decls(t, indent + 2);
2✔
1190
      tab(indent);
2✔
1191
      print_syntax("#begin\n");
2✔
1192
      dump_stmts(t, indent + 2);
2✔
1193
      tab(indent);
2✔
1194
      print_syntax("#end #process;\n");
2✔
1195
      return;
2✔
1196

1197
   case T_SIGNAL_ASSIGN:
2✔
1198
      dump_expr(tree_target(t));
2✔
1199
      print_syntax(" <= #reject ");
2✔
1200
      if (tree_has_reject(t))
2✔
1201
         dump_expr(tree_reject(t));
1✔
1202
      else
1203
         print_syntax("0 ps");
1✔
1204
      print_syntax(" #inertial ");
2✔
1205
      dump_waveforms(t);
2✔
1206
      break;
2✔
1207

1208
   case T_FORCE:
×
1209
      dump_expr(tree_target(t));
×
1210
      print_syntax(" <= #force ");
×
1211
      dump_expr(tree_value(t));
×
1212
      break;
×
1213

1214
   case T_RELEASE:
×
1215
      dump_expr(tree_target(t));
×
1216
      print_syntax(" <= #release");
×
1217
      break;
×
1218

1219
   case T_VAR_ASSIGN:
2✔
1220
      dump_expr(tree_target(t));
2✔
1221
      print_syntax(" := ");
2✔
1222
      dump_expr(tree_value(t));
2✔
1223
      break;
2✔
1224

1225
   case T_WAIT:
×
1226
      print_syntax("#wait");
×
1227
      if (tree_triggers(t) > 0) {
×
1228
         print_syntax(" #on ");
×
1229
         for (unsigned i = 0; i < tree_triggers(t); i++) {
×
1230
            if (i > 0)
×
1231
               print_syntax(", ");
×
1232
            dump_expr(tree_trigger(t, i));
×
1233
         }
1234
      }
1235
      if (tree_has_value(t)) {
×
1236
         print_syntax(" #until ");
×
1237
         dump_expr(tree_value(t));
×
1238
      }
1239
      if (tree_has_delay(t)) {
×
1240
         print_syntax(" #for ");
×
1241
         dump_expr(tree_delay(t));
×
1242
      }
1243
      print_syntax(";");
×
1244
      if (tree_flags(t) & TREE_F_STATIC_WAIT)
×
1245
         print_syntax("   -- static");
×
1246
      print_syntax("\n");
×
1247
      return;
×
1248

1249
   case T_BLOCK:
2✔
1250
      dump_address(t);
2✔
1251
      print_syntax("#block #is\n");
2✔
1252
      dump_generics(t, indent + 2, ";\n");
2✔
1253
      dump_generic_map(t, indent + 2, ";\n");
2✔
1254
      dump_ports(t, indent + 2);
2✔
1255
      dump_port_map(t, indent + 2, ";\n");
2✔
1256
      dump_block(t, indent);
2✔
1257
      tab(indent);
2✔
1258
      print_syntax("#end #block;\n");
2✔
1259
      return;
2✔
1260

1261
   case T_SEQUENCE:
×
1262
      print_syntax("#block #is\n");
×
1263
      dump_block(t, indent);
×
1264
      tab(indent);
×
1265
      print_syntax("#end #block;\n");
×
1266
      return;
×
1267

1268
   case T_ASSERT:
2✔
1269
      print_syntax("#assert ");
2✔
1270
      dump_expr(tree_value(t));
2✔
1271
      if (tree_has_message(t)) {
2✔
1272
         print_syntax(" #report ");
×
1273
         dump_expr(tree_message(t));
×
1274
      }
1275
      if (tree_has_severity(t)) {
2✔
1276
         print_syntax(" #severity ");
×
1277
         dump_expr(tree_severity(t));
×
1278
      }
1279
      break;
1280

1281
   case T_REPORT:
1✔
1282
      print_syntax("#report ");
1✔
1283
      dump_expr(tree_message(t));
1✔
1284
      if (tree_has_severity(t)) {
1✔
1285
         print_syntax(" #severity ");
×
1286
         dump_expr(tree_severity(t));
×
1287
      }
1288
      break;
1289

1290
   case T_WHILE:
×
1291
      print_syntax("#while ");
×
1292
      dump_expr(tree_value(t));
×
1293
      print_syntax(" ");
×
1294
      // Fall-through
1295
   case T_LOOP:
×
1296
      print_syntax("#loop\n");
×
1297
      dump_stmts(t, indent + 2);
×
1298
      tab(indent);
×
1299
      print_syntax("#end #loop");
×
1300
      break;
×
1301

1302
   case T_IF:
1303
      for (unsigned i = 0; i < tree_conds(t); i++) {
3✔
1304
         tree_t c = tree_cond(t, i);
2✔
1305
         if (tree_has_value(c)) {
2✔
1306
            if (i > 0)
1✔
1307
               tab(indent);
×
1308
            print_syntax(i > 0 ? "#elsif " : "#if ");
2✔
1309
            dump_expr(tree_value(c));
1✔
1310
            print_syntax(" #then\n");
1✔
1311
         }
1312
         else {
1313
            tab(indent);
1✔
1314
            print_syntax("#else\n");
1✔
1315
         }
1316
         dump_stmts(c, indent + 2);
2✔
1317
      }
1318
      tab(indent);
1✔
1319
      print_syntax("#end #if");
1✔
1320
      break;
1✔
1321

1322
   case T_EXIT:
×
1323
      print_syntax("#exit %s", istr(tree_ident2(t)));
×
1324
      if (tree_has_value(t)) {
×
1325
         print_syntax(" #when ");
×
1326
         dump_expr(tree_value(t));
×
1327
      }
1328
      break;
1329

1330
   case T_CASE:
1✔
1331
   case T_MATCH_CASE:
1332
      {
1333
         const char *suffix = tree_kind(t) == T_MATCH_CASE ? "?" : "";
1✔
1334
         print_syntax("#case%s ", suffix);
1✔
1335
         dump_expr(tree_value(t));
1✔
1336
         print_syntax(" #is\n");
1✔
1337
         const int nstmts = tree_stmts(t);
1✔
1338
         for (int i = 0; i < nstmts; i++)
3✔
1339
            dump_alternative(tree_stmt(t, i), indent + 2);
2✔
1340
         tab(indent);
1✔
1341
         print_syntax("#end #case%s", suffix);
1✔
1342
      }
1343
      break;
1✔
1344

1345
   case T_RETURN:
3✔
1346
      print_syntax("#return");
3✔
1347
      if (tree_has_value(t)) {
3✔
1348
         print_syntax(" ");
3✔
1349
         dump_expr(tree_value(t));
3✔
1350
      }
1351
      break;
1352

1353
   case T_COND_RETURN:
×
1354
      print_syntax("#return #when ");
×
1355
      dump_expr(tree_value(t));
×
1356
      break;
×
1357

1358
   case T_FOR:
×
1359
      print_syntax("#for %s #in ", istr(tree_ident(tree_decl(t, 0))));
×
1360
      dump_range(tree_range(t, 0));
×
1361
      print_syntax(" #loop\n");
×
1362
      dump_stmts(t, indent + 2);
×
1363
      tab(indent);
×
1364
      print_syntax("#end #for");
×
1365
      break;
×
1366

1367
   case T_PROT_PCALL:
×
1368
      dump_expr(tree_name(t));
×
1369
      print_syntax(".");
×
1370
      // Fall-through
1371
   case T_PCALL:
×
1372
      if (tree_has_ref(t)) {
×
1373
         tree_t decl = tree_ref(t);
×
1374
         dump_address(decl);
×
1375
         print_syntax("%s", istr(tree_ident(decl)));
×
1376
      }
1377
      else
1378
         print_syntax("%s", istr(tree_ident2(t)));
×
1379
      dump_params(t, tree_param, tree_params(t), NULL);
×
1380
      break;
×
1381

1382
   case T_FOR_GENERATE:
1✔
1383
      print_syntax("#for %s #in ", istr(tree_ident(tree_decl(t, 0))));
1✔
1384
      dump_range(tree_range(t, 0));
1✔
1385
      print_syntax(" #generate\n");
1✔
1386
      dump_decls(t, indent + 2);
1✔
1387
      tab(indent);
1✔
1388
      print_syntax("#begin\n");
1✔
1389
      dump_stmts(t, indent + 2);
1✔
1390
      tab(indent);
1✔
1391
      print_syntax("#end #generate");
1✔
1392
      break;
1✔
1393

1394
   case T_CASE_GENERATE:
×
1395
      {
1396
         print_syntax("#case ");
×
1397
         dump_expr(tree_value(t));
×
1398
         print_syntax(" #generate\n");
×
1399

1400
         const int nstmts = tree_stmts(t);
×
1401
         for (int i = 0; i < nstmts; i++)
×
1402
            dump_alternative(tree_stmt(t, i), indent + 2);
×
1403

1404
         print_syntax("#end #generate");
×
1405
         tab(indent);
×
1406
      }
1407
      break;
×
1408

1409
   case T_IF_GENERATE:
1410
      for (unsigned i = 0; i < tree_conds(t); i++) {
×
1411
         tree_t c = tree_cond(t, i);
×
1412
         if (tree_has_value(c)) {
×
1413
            if (i > 0)
×
1414
               tab(indent);
×
1415
            print_syntax(i > 0 ? "#elsif " : "#if ");
×
1416
            dump_expr(tree_value(c));
×
1417
            print_syntax(" #generate\n");
×
1418
         }
1419
         else {
1420
            tab(indent);
×
1421
            print_syntax("#else\n");
×
1422
         }
1423
         for (unsigned i = 0; i < tree_stmts(c); i++)
×
1424
            dump_stmt(tree_stmt(c, i), indent + 2);
×
1425
      }
1426
      tab(indent);
×
1427
      print_syntax("#end #generate");
×
1428
      break;
×
1429

1430
   case T_INSTANCE:
1✔
1431
      dump_instance(t, indent);
1✔
1432
      return;
1✔
1433

1434
   case T_NEXT:
×
1435
      print_syntax("#next");
×
1436
      if (tree_has_value(t)) {
×
1437
         print_syntax(" #when ");
×
1438
         dump_expr(tree_value(t));
×
1439
      }
1440
      break;
1441

1442
   case T_NULL:
2✔
1443
      print_syntax("#null");
2✔
1444
      break;
2✔
1445

1446
   case T_COND_ASSIGN:
1✔
1447
      dump_expr(tree_target(t));
1✔
1448
      print_syntax(" <= ");
1✔
1449
      if (tree_has_guard(t))
1✔
1450
         print_syntax("#guarded ");
×
1451
      for (int i = 0; i < tree_conds(t); i++) {
2✔
1452
         tree_t c = tree_cond(t, i);
1✔
1453
         dump_waveforms(tree_stmt(c, 0));
1✔
1454
         if (tree_has_value(c)) {
1✔
1455
            print_syntax(" #when ");
×
1456
            dump_expr(tree_value(c));
×
1457
         }
1458
      }
1459
      break;
1460

1461
   case T_SELECT:
×
1462
      print_syntax(" <= ");
×
1463
      if (tree_has_guard(t)) print_syntax("#guarded ");
×
NEW
1464
      nvc_printf("$red$/* TODO: T_SELECT */$$");
×
1465
      break;
×
1466

1467
   case T_CONCURRENT:
3✔
1468
      if (tree_flags(t) & TREE_F_POSTPONED)
3✔
1469
         print_syntax("#postponed ");
×
1470
      dump_stmt(tree_stmt(t, 0), 0);
3✔
1471
      return;
3✔
1472

1473
   case T_DUMMY_DRIVER:
×
1474
      print_syntax("-- dummy driver for ");
×
1475
      dump_expr(tree_target(t));
×
1476
      print_syntax("\n");
×
1477
      return;
×
1478

1479
   case T_PSL_DIRECT:
1✔
1480
      dump_psl(t, indent);
1✔
1481
      break;
1✔
1482

1483
   default:
×
1484
      cannot_dump(t, "stmt");
×
1485
   }
1486

1487
   print_syntax(";\n");
17✔
1488
}
1489

1490
static void dump_port(tree_t t, int indent)
103✔
1491
{
1492
   tab(indent);
103✔
1493
   dump_address(t);
103✔
1494

1495
   if (tree_flags(t) & TREE_F_PREDEFINED)
103✔
1496
      print_syntax("-- predefined ");
80✔
1497

1498
   const class_t class = tree_class(t);
103✔
1499
   print_syntax("#%s %s", class_str(class), istr(tree_ident(t)));
103✔
1500

1501
   const port_mode_t mode = tree_subkind(t);
103✔
1502

1503
   type_t type = get_type_or_null(t);
103✔
1504
   if (class == C_PACKAGE) {
103✔
1505
      print_syntax(" #is #new ");
×
1506
      dump_expr(tree_value(t));
×
1507
   }
1508
   else if (class == C_TYPE && type_kind(type) == T_GENERIC) {
103✔
1509
      print_syntax(" #is ");
10✔
1510

1511
      switch (type_subkind(type)) {
10✔
1512
      case GTYPE_PRIVATE:
2✔
1513
         print_syntax("#private");
2✔
1514
         break;
2✔
1515
      case GTYPE_SCALAR:
1✔
1516
         print_syntax("<>");
1✔
1517
         break;
1✔
1518
      case GTYPE_DISCRETE:
1✔
1519
         print_syntax("(<>)");
1✔
1520
         break;
1✔
1521
      case GTYPE_INTEGER:
1✔
1522
         print_syntax("#range <>");
1✔
1523
         break;
1✔
1524
      case GTYPE_PHYSICAL:
1✔
1525
         print_syntax("#units <>");
1✔
1526
         break;
1✔
1527
      case GTYPE_FLOATING:
1✔
1528
         print_syntax("#range <> . <>");
1✔
1529
         break;
1✔
1530
      case GTYPE_ARRAY:
1✔
1531
         {
1532
            print_syntax("#array (");
1✔
1533
            const int nindex = type_indexes(type);
1✔
1534
            for (int i = 0; i < nindex; i++) {
2✔
1535
               if (i > 0) print_syntax(", ");
1✔
1536
               dump_type(type_index(type, i));
1✔
1537
               print_syntax(" #range <>");
1✔
1538
            }
1539
            print_syntax(") #of ");
1✔
1540
            dump_type(type_elem(type));
1✔
1541
         }
1542
         break;
1✔
1543
      case GTYPE_ACCESS:
1✔
1544
         print_syntax("#access ..");
1✔
1545
         break;
1✔
1546
      case GTYPE_FILE:
1✔
1547
         print_syntax("#file #of ..");
1✔
1548
         break;
1✔
1549
      }
1550
   }
1551
   else if (mode == PORT_ARRAY_VIEW || mode == PORT_RECORD_VIEW) {
93✔
1552
      print_syntax(" : #view ");
2✔
1553
      dump_expr(tree_value(t));
2✔
1554
   }
1555
   else {
1556
      static const char *map[] = {
91✔
1557
         "??", "in", "out", "inout", "buffer", "linkage"
1558
      };
1559
      print_syntax(" : #%s ", map[mode]);
91✔
1560
      dump_type(type);
91✔
1561

1562
      if (tree_has_value(t)) {
91✔
1563
         print_syntax(" := ");
81✔
1564
         dump_expr(tree_value(t));
81✔
1565
      }
1566
   }
1567
}
103✔
1568

1569
static void dump_context(tree_t t, int indent)
7✔
1570
{
1571
   const int nctx = tree_contexts(t);
7✔
1572
   for (int i = 0; i < nctx; i++) {
28✔
1573
      tree_t c = tree_context(t, i);
21✔
1574
      switch (tree_kind(c)) {
21✔
1575
      case T_LIBRARY:
14✔
1576
         switch (is_well_known(tree_ident(c))) {
14✔
1577
         case W_STD:
1578
         case W_WORK:
1579
            break;
1580
         default:
×
1581
            print_syntax("#library %s;\n", istr(tree_ident(c)));
×
1582
         }
1583
         break;
1584

1585
      case T_USE:
7✔
1586
         dump_use(c);
7✔
1587
         break;
7✔
1588

1589
      case T_CONTEXT_REF:
×
1590
         print_syntax("#context %s;\n", istr(tree_ident(t)));
×
1591
         break;
×
1592

1593
      default:
1594
         break;
1595
      }
1596

1597
      tab(indent);
21✔
1598
   }
1599

1600
   if (nctx > 0) {
7✔
1601
      print_syntax("\n");
7✔
1602
      tab(indent);
7✔
1603
   }
1604
}
7✔
1605

1606
static void dump_elab(tree_t t)
×
1607
{
1608
   dump_context(t, 0);
×
1609
   dump_address(t);
×
1610
   print_syntax("#entity %s #is\n#end #entity;\n\n", istr(tree_ident(t)));
×
1611
   print_syntax("#architecture #elab #of %s #is\n", istr(tree_ident(t)));
×
1612
   dump_decls(t, 2);
×
1613
   print_syntax("#begin\n");
×
1614
   for (unsigned i = 0; i < tree_stmts(t); i++)
×
1615
      dump_stmt(tree_stmt(t, i), 2);
×
1616
   print_syntax("#end #architecture;\n\n");
×
1617
}
×
1618

1619
static void dump_entity(tree_t t)
2✔
1620
{
1621
   dump_context(t, 0);
2✔
1622
   dump_address(t);
2✔
1623
   print_syntax("#entity %s #is\n", istr(tree_ident(t)));
2✔
1624
   dump_generics(t, 2, ";\n");
2✔
1625
   dump_ports(t, 2);
2✔
1626
   dump_decls(t, 2);
2✔
1627
   if (tree_stmts(t) > 0) {
2✔
1628
      print_syntax("#begin\n");
×
1629
      for (unsigned i = 0; i < tree_stmts(t); i++) {
×
1630
         dump_stmt(tree_stmt(t, i), 2);
×
1631
      }
1632
   }
1633
   print_syntax("#end #entity;\n\n");
2✔
1634
}
2✔
1635

1636
static void dump_decls(tree_t t, int indent)
19✔
1637
{
1638
   const int ndecls = tree_decls(t);
19✔
1639
   bool was_body = false;
19✔
1640
   for (unsigned i = 0; i < ndecls; i++) {
42✔
1641
      tree_t d = tree_decl(t, i);
23✔
1642
      tree_kind_t dkind = tree_kind(d);
23✔
1643
      const bool is_body = dkind == T_FUNC_BODY || dkind == T_PROT_BODY
46✔
1644
         || dkind == T_PROC_BODY;
23✔
1645
      if ((was_body && !is_body) || (is_body && i > 0))
23✔
1646
         print_syntax("\n");
5✔
1647
      was_body = is_body;
23✔
1648
      dump_decl(d, indent);
23✔
1649
   }
1650
}
19✔
1651

1652
static void dump_arch(tree_t t)
2✔
1653
{
1654
   dump_context(t, 0);
2✔
1655
   dump_address(t);
2✔
1656
   print_syntax("#architecture %s #of %s #is\n",
2✔
1657
                istr(tree_ident(t)), istr(tree_ident2(t)));
1658
   dump_decls(t, 2);
2✔
1659
   print_syntax("#begin\n");
2✔
1660
   dump_stmts(t, 2);
2✔
1661
   print_syntax("#end #architecture;\n\n");
2✔
1662
}
2✔
1663

1664
static void dump_package(tree_t t, int indent)
1✔
1665
{
1666
   dump_context(t, indent);
1✔
1667
   dump_address(t);
1✔
1668
   print_syntax("#package %s #is\n", istr(tree_ident(t)));
1✔
1669
   if (tree_kind(t) == T_PACK_INST && tree_has_ref(t)) {
1✔
1670
      tab(indent);
×
1671
      print_syntax("  -- Instantiated from %s\n", istr(tree_ident(tree_ref(t))));
×
1672
   }
1673
   dump_generics(t, indent + 2, ";\n");
1✔
1674
   dump_generic_map(t, indent + 2, ";\n");
1✔
1675
   dump_decls(t, indent + 2);
1✔
1676
   tab(indent);
1✔
1677
   print_syntax("#end #package;\n\n");
1✔
1678
}
1✔
1679

1680
static void dump_package_body(tree_t t, int indent)
2✔
1681
{
1682
   dump_context(t, indent);
2✔
1683
   dump_address(t);
2✔
1684
   print_syntax("#package #body %s #is\n", istr(tree_ident(t)));
2✔
1685
   dump_decls(t, indent + 2);
2✔
1686
   tab(indent);
2✔
1687
   print_syntax("#end #package #body;\n\n");
2✔
1688
}
2✔
1689

1690
static void dump_configuration(tree_t t)
×
1691
{
1692
   dump_address(t);
×
1693
   print_syntax("#configuration %s #of %s #is\n",
×
1694
          istr(tree_ident(t)), istr(tree_ident2(t)));
1695
   dump_decls(t, 2);
×
1696
   print_syntax("#end #configuration\n");
×
1697
}
×
1698

1699
void vhdl_dump(tree_t t, int indent)
49✔
1700
{
1701
   switch (tree_kind(t)) {
49✔
1702
   case T_ELAB:
×
1703
      dump_elab(t);
×
1704
      break;
×
1705
   case T_ENTITY:
2✔
1706
      dump_entity(t);
2✔
1707
      break;
2✔
1708
   case T_ARCH:
2✔
1709
      dump_arch(t);
2✔
1710
      break;
2✔
1711
   case T_PACKAGE:
1✔
1712
   case T_PACK_INST:
1713
      dump_package(t, indent);
1✔
1714
      break;
1✔
1715
   case T_PACK_BODY:
2✔
1716
      dump_package_body(t, indent);
2✔
1717
      break;
2✔
1718
   case T_CONFIGURATION:
×
1719
      dump_configuration(t);
×
1720
      break;
×
1721
   case T_REF:
25✔
1722
   case T_FCALL:
1723
   case T_PROT_FCALL:
1724
   case T_LITERAL:
1725
   case T_AGGREGATE:
1726
   case T_ARRAY_REF:
1727
   case T_ARRAY_SLICE:
1728
   case T_TYPE_CONV:
1729
   case T_RECORD_REF:
1730
   case T_ATTR_REF:
1731
   case T_CONV_FUNC:
1732
   case T_QUALIFIED:
1733
   case T_EXTERNAL_NAME:
1734
   case T_STRING:
1735
   case T_PACKAGE_MAP:
1736
   case T_TYPE_REF:
1737
      dump_expr(t);
25✔
1738
      break;
25✔
1739
   case T_INSTANCE:
7✔
1740
   case T_FOR_GENERATE:
1741
   case T_CASE_GENERATE:
1742
   case T_BLOCK:
1743
   case T_PROCESS:
1744
   case T_CASE:
1745
   case T_FOR:
1746
   case T_SIGNAL_ASSIGN:
1747
   case T_IF:
1748
   case T_WAIT:
1749
   case T_PSL_DIRECT:
1750
   case T_VAR_ASSIGN:
1751
   case T_RETURN:
1752
   case T_ASSERT:
1753
   case T_WHILE:
1754
   case T_LOOP:
1755
   case T_SEQUENCE:
1756
   case T_PCALL:
1757
      dump_stmt(t, indent);
7✔
1758
      break;
7✔
1759
   case T_CONST_DECL:
10✔
1760
   case T_VAR_DECL:
1761
   case T_SIGNAL_DECL:
1762
   case T_TYPE_DECL:
1763
   case T_FIELD_DECL:
1764
   case T_FUNC_DECL:
1765
   case T_PROC_BODY:
1766
   case T_FUNC_BODY:
1767
   case T_PROC_DECL:
1768
   case T_ATTR_DECL:
1769
   case T_ATTR_SPEC:
1770
   case T_ENUM_LIT:
1771
   case T_COMPONENT:
1772
   case T_BLOCK_CONFIG:
1773
   case T_SPEC:
1774
   case T_ALIAS:
1775
   case T_FUNC_INST:
1776
   case T_PROC_INST:
1777
   case T_SUBTYPE_DECL:
1778
   case T_VIEW_DECL:
1779
      dump_decl(t, indent);
10✔
1780
      break;
10✔
1781
   case T_PORT_DECL:
×
1782
   case T_GENERIC_DECL:
1783
   case T_PARAM_DECL:
1784
      dump_port(t, indent);
×
1785
      break;
×
1786
   case T_RANGE:
×
1787
      dump_range(t);
×
1788
      break;
×
1789
   case T_BINDING:
×
1790
      dump_binding(t, indent);
×
1791
      break;
×
1792
   case T_PARAM:
×
1793
      dump_param(t);
×
1794
      break;
×
1795
   case T_CONSTRAINT:
×
1796
      dump_constraint(t);
×
1797
      break;
×
1798
   case T_ELEM_CONSTRAINT:
×
1799
      dump_record_elem_constraint(t);
×
1800
      break;
×
1801
   case T_ALTERNATIVE:
×
1802
      dump_alternative(t, indent);
×
1803
      break;
×
1804
   default:
×
1805
      cannot_dump(t, "tree");
×
1806
   }
1807
}
49✔
1808

1809
void dump(tree_t t)
22✔
1810
{
1811
   vhdl_dump(t, 0);
22✔
1812
   print_syntax("\r");
22✔
1813
}
22✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc