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

nickg / nvc / 16099227452

06 Jul 2025 12:45PM UTC coverage: 92.335% (+0.05%) from 92.284%
16099227452

push

github

nickg
Handle underscores in Verilog decimal literals

Fixes #1230

18 of 20 new or added lines in 1 file covered. (90.0%)

598 existing lines in 16 files now uncovered.

71069 of 76969 relevant lines covered (92.33%)

564781.41 hits per line

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

59.38
/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 "psl/psl-phase.h"
24
#include "tree.h"
25
#include "type.h"
26
#include "vlog/vlog-node.h"
27
#include "vlog/vlog-phase.h"
28

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

323
   case T_REF:
54✔
324
      if (tree_has_ref(t)) {
54✔
325
         tree_t decl = tree_ref(t);
54✔
326
         dump_address(decl);
54✔
327
         print_syntax("%s", istr(tree_ident(decl)));
54✔
328
      }
329
      else
330
         print_syntax("%s", istr(tree_ident(t)));
×
331
      break;
332

333
   case T_ATTR_REF:
2✔
334
      dump_expr(tree_name(t));
2✔
335
      print_syntax("'%s", istr(tree_ident(t)));
2✔
336
      if (tree_params(t) > 0)
2✔
337
         dump_params(t, tree_param, tree_params(t), NULL);
×
338
      break;
339

340
   case T_EXTERNAL_NAME:
2✔
341
      dump_external_name(t);
2✔
342
      break;
2✔
343

344
   case T_ARRAY_REF:
1✔
345
      dump_expr(tree_value(t));
1✔
346
      dump_params(t, tree_param, tree_params(t), NULL);
1✔
347
      break;
1✔
348

349
   case T_ARRAY_SLICE:
×
350
      dump_expr(tree_value(t));
×
351
      print_syntax("(");
×
352
      dump_range(tree_range(t, 0));
×
353
      print_syntax(")");
×
354
      break;
×
355

356
   case T_RECORD_REF:
×
357
      dump_expr(tree_value(t));
×
358
      print_syntax(".%s", istr(tree_ident(t)));
×
359
      break;
×
360

361
   case T_TYPE_CONV:
4✔
362
      dump_type(tree_type(t));
4✔
363
      print_syntax("(");
4✔
364
      dump_expr(tree_value(t));
4✔
365
      print_syntax(")");
4✔
366
      break;
4✔
367

368
   case T_QUALIFIED:
×
369
      if (tree_has_value(t)) {
×
370
         print_syntax("%s'(", istr(type_ident(tree_type(t))));
×
371
         dump_expr(tree_value(t));
×
372
         print_syntax(")");
×
373
      }
374
      else
375
         dump_type(tree_type(t));
×
376
      break;
377

378
   case T_OPEN:
1✔
379
      print_syntax("#open");
1✔
380
      break;
1✔
381

382
   case T_BOX:
80✔
383
      print_syntax("<>");
80✔
384
      break;
80✔
385

386
   case T_WAVEFORM:
×
387
      dump_waveform(t);
×
388
      break;
×
389

390
   case T_PACKAGE_MAP:
×
391
      print_syntax("%s ", istr(tree_ident(t)));
×
392
      switch (tree_subkind(t)) {
×
393
      case PACKAGE_MAP_BOX:
×
394
         print_syntax("#generic #map (<>)");
×
395
         break;
×
396
      case PACKAGE_MAP_DEFAULT:
×
397
         print_syntax("#generic map (#default)");
×
398
         break;
×
399
      case PACKAGE_MAP_MATCHING:
×
400
         dump_params(t, tree_genmap, tree_genmaps(t), "#generic #map");
×
401
         break;
×
402
      }
403
      return;
404

405
   case T_COND_VALUE:
406
      for (int i = 0; i < tree_conds(t); i++) {
×
407
         tree_t c = tree_cond(t, i);
×
408
         if (i > 0)
×
409
            print_syntax(" #else ");
×
410
         if (tree_has_result(c))
×
411
            dump_expr(tree_result(c));
×
412
         else
413
            print_syntax("#unaffected");
×
414
         if (tree_has_value(c)) {
×
415
            print_syntax(" #when ");
×
416
            dump_expr(tree_value(c));
×
417
         }
418
      }
419
      break;
420

421
   case T_INERTIAL:
1✔
422
      print_syntax("#inertial ");
1✔
423
      dump_expr(tree_value(t));
1✔
424
      break;
1✔
425

426
   default:
×
427
      cannot_dump(t, "expr");
×
428
   }
429

430
   dump_type_hint(t);
201✔
431
}
432

433
static void dump_record_elem_constraint(tree_t t)
×
434
{
435
   print_syntax("%s", istr(tree_ident(t)));
×
436

437
   type_t ftype = tree_type(t);
×
438
   if (type_has_constraint(ftype))
×
439
      dump_constraint(type_constraint(ftype));
×
440

441
   dump_elem_constraints(ftype);
×
442
}
×
443

444
static void dump_constraint(tree_t t)
5✔
445
{
446
   const int nranges = tree_ranges(t);
5✔
447

448
   switch (tree_subkind(t)) {
5✔
449
   case C_RANGE:
1✔
450
      print_syntax(" #range ");
1✔
451
      dump_range(tree_range(t, 0));
1✔
452
      break;
1✔
453
   case C_INDEX:
4✔
454
      print_syntax("(");
4✔
455
      for (int i = 0; i < nranges; i++) {
8✔
456
         if (i > 0) print_syntax(", ");
4✔
457
         dump_range(tree_range(t, i));
4✔
458
      }
459
      print_syntax(")");
4✔
460
      break;
4✔
461
   case C_RECORD:
×
462
      print_syntax("(");
×
463
      for (int i = 0; i < nranges; i++) {
×
464
         if (i > 0) print_syntax(", ");
×
465
         dump_record_elem_constraint(tree_range(t, i));
×
466
      }
467
      print_syntax(")");
×
468
      break;
×
469
   }
470
}
5✔
471

472
static void dump_elem_constraints(type_t type)
5✔
473
{
474
   if (type_is_array(type) && type_has_elem(type)) {
5✔
475
      type_t elem = type_elem(type);
×
476
      if (is_anonymous_subtype(elem)) {
×
477
         // Anonymous subtype created for element constraints
478
         if (type_has_constraint(elem))
×
479
            dump_constraint(type_constraint(elem));
×
480
         else
481
            print_syntax("(#open)");
×
482
         dump_elem_constraints(elem);
×
483
      }
484
   }
485
}
5✔
486

487
static void dump_type(type_t type)
123✔
488
{
489
   if (is_anonymous_subtype(type)) {
123✔
490
      // Anonymous subtype
491
      print_syntax("%s", type_pp(type));
4✔
492
      if (type_ident(type) == type_ident(type_base(type))) {
4✔
493
         if (type_has_constraint(type))
4✔
494
            dump_constraint(type_constraint(type));
4✔
495
      }
496
      dump_elem_constraints(type);
4✔
497
   }
498
   else if (type_is_none(type))
119✔
499
      print_syntax("/* error */");
×
500
   else
501
      print_syntax("%s", type_pp(type));
119✔
502
}
123✔
503

504
static void dump_arguments(tree_t t, int indent, const char *trailer)
7✔
505
{
506
   const int nports = tree_ports(t);
7✔
507
   if (nports > 0) {
7✔
508
      print_syntax(" (");
3✔
509
      if (nports > 1) {
3✔
510
         print_syntax("\n");
1✔
511
         for (int i = 0; i < nports; i++) {
3✔
512
            if (i > 0) print_syntax(";\n");
2✔
513
            dump_port(tree_port(t, i), indent + 4);
2✔
514
         }
515
      }
516
      else
517
         dump_port(tree_port(t, 0), 1);
2✔
518
      print_syntax(" )%s", trailer);
3✔
519
   }
520
}
7✔
521

522
static void dump_ports(tree_t t, int indent)
5✔
523
{
524
   const int nports = tree_ports(t);
5✔
525
   if (nports > 0) {
5✔
526
      tab(indent);
4✔
527
      print_syntax("#port (");
4✔
528
      if (nports > 1) {
4✔
529
         print_syntax("\n");
3✔
530
         for (unsigned i = 0; i < nports; i++) {
9✔
531
            if (i > 0) print_syntax(";\n");
6✔
532
            dump_port(tree_port(t, i), indent + 2);
6✔
533
         }
534
      }
535
      else
536
         dump_port(tree_port(t, 0), 1);
1✔
537
      print_syntax(" );\n");
4✔
538
   }
539
}
5✔
540

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

566
static void dump_port_map(tree_t t, int indent, const char *trailer)
3✔
567
{
568
   const int nparams = tree_params(t);
3✔
569
   if (nparams > 0) {
3✔
570
      tab(indent);
3✔
571
      dump_params(t, tree_param, nparams, "#port #map");
3✔
572
      print_syntax("%s", trailer);
3✔
573
   }
574
}
3✔
575

576
static void dump_generic_map(tree_t t, int indent, const char *trailer)
4✔
577
{
578
   const int ngenmaps = tree_genmaps(t);
4✔
579
   if (ngenmaps > 0) {
4✔
580
      tab(indent);
1✔
581
      dump_params(t, tree_genmap, ngenmaps, "#generic #map");
1✔
582
      print_syntax("%s", trailer);
1✔
583
   }
584
}
4✔
585

586
static void dump_binding(tree_t t, int indent)
×
587
{
588
   dump_address(t);
×
589
   print_syntax("#use %s", istr(tree_ident(t)));
×
590
   if (tree_has_ident2(t))
×
591
      print_syntax("(%s)", istr(tree_ident2(t)));
×
592
   if (tree_genmaps(t) > 0 || tree_params(t) > 0)
×
593
      print_syntax("\n");
×
594
   dump_generic_map(t, indent + 2, tree_params(t) > 0 ? "\n" : "");
×
595
   dump_port_map(t, indent + 2, "");
×
596
   print_syntax(";\n");
×
597
}
×
598

599
static void dump_stmts(tree_t t, int indent)
13✔
600
{
601
   bool last_was_newline = false;
13✔
602
   const int nstmts = tree_stmts(t);
13✔
603
   for (int i = 0; i < nstmts; i++) {
25✔
604
      tree_t s = tree_stmt(t, i);
12✔
605
      const tree_kind_t kind = tree_kind(s);
12✔
606

607
      bool needs_newline;
12✔
608
      if (kind == T_VERILOG) {
12✔
609
         const vlog_kind_t vkind = vlog_kind(tree_vlog(s));
×
610
         needs_newline = (vkind == V_ALWAYS || vkind == V_INITIAL);
×
611
      }
612
      else
613
         needs_newline = (kind == T_BLOCK || kind == T_PROCESS
12✔
614
                          || kind == T_INSTANCE);
615

616
      if (needs_newline && i > 0 && !last_was_newline)
12✔
617
         print_syntax("\n");
×
618

619
      dump_stmt(s, indent);
12✔
620

621
      if (needs_newline && i + 1 < nstmts) {
12✔
622
         print_syntax("\n");
×
623
         last_was_newline = true;
×
624
      }
625
      else
626
         last_was_newline = false;
627
   }
628
}
13✔
629

630
static void dump_block(tree_t t, int indent)
7✔
631
{
632
   dump_decls(t, indent + 2);
7✔
633
   tab(indent);
7✔
634
   print_syntax("#begin\n");
7✔
635
   dump_stmts(t, indent + 2);
7✔
636
}
7✔
637

638
static void dump_wait_level(tree_t t)
3✔
639
{
640
   const tree_flags_t flags = tree_flags(t);
3✔
641
   if (flags & TREE_F_NEVER_WAITS)
3✔
642
      print_syntax("   -- Never waits");
3✔
643
   else if (flags & TREE_F_HAS_WAIT)
×
644
      print_syntax("   -- Contains wait statement");
×
645
}
3✔
646

647
static void dump_type_decl(tree_t t, int indent)
2✔
648
{
649
   type_t type = tree_type(t);
2✔
650
   const type_kind_t kind = type_kind(type);
2✔
651

652
   print_syntax("#type %s", istr(tree_ident(t)));
2✔
653

654
   if (kind == T_INCOMPLETE) {
2✔
655
      print_syntax(";\n");
×
656
      return;
×
657
   }
658

659
   print_syntax(" #is ");
2✔
660

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

733
   print_syntax(";\n");
2✔
734
}
735

736
static void dump_subtype_decl(tree_t t, int indent)
1✔
737
{
738
   type_t type = tree_type(t);
1✔
739

740
   print_syntax("#subtype %s #is ", istr(tree_ident(t)));
1✔
741
   if (type_has_resolution(type)) {
1✔
742
      dump_expr(type_resolution(type));
×
743
      print_syntax(" ");
×
744
   }
745
   print_syntax("%s", type_pp(type_base(type)));
1✔
746

747
   if (type_has_constraint(type))
1✔
748
      dump_constraint(type_constraint(type));
1✔
749

750
   dump_elem_constraints(type);
1✔
751

752
   print_syntax(";\n");
1✔
753
}
1✔
754

755
static void dump_component(tree_t t, int indent)
1✔
756
{
757
   print_syntax("#component %s #is\n", istr(tree_ident(t)));
1✔
758
   dump_generics(t, indent + 2, ";\n");
1✔
759
   dump_ports(t, indent + 2);
1✔
760
   print_syntax("#end #component;\n");
1✔
761
}
1✔
762

763
static void dump_use(tree_t t)
7✔
764
{
765
   print_syntax("#use %s", istr(tree_ident(t)));
7✔
766
   if (tree_has_ident2(t))
7✔
767
      print_syntax(".%s", istr(tree_ident2(t)));
7✔
768
   print_syntax(";\n");
7✔
769
}
7✔
770

771
static void dump_attr_spec(tree_t t)
4✔
772
{
773
   print_syntax("#attribute %s #of ", istr(tree_ident(t)));
4✔
774

775
   switch (tree_subkind(t)) {
4✔
776
   case SPEC_EXACT:
2✔
777
      print_syntax("%s", istr(tree_ident2(t)));
2✔
778
      break;
2✔
779
   case SPEC_ALL:
1✔
780
      print_syntax("#all");
1✔
781
      break;
1✔
782
   case SPEC_OTHERS:
1✔
783
      print_syntax("#others");
1✔
784
      break;
1✔
785
   }
786

787
   print_syntax(" : #%s #is ", class_str(tree_class(t)));
4✔
788
   dump_expr(tree_value(t));
4✔
789
   print_syntax(";\n");
4✔
790
}
4✔
791

792
static void dump_view_decl(tree_t t, int indent)
1✔
793
{
794
   type_t type = tree_type(t);
1✔
795
   print_syntax("#view %s #of ", istr(tree_ident(t)));
1✔
796
   dump_type(type_designated(type));
1✔
797
   print_syntax(" #is\n");
1✔
798

799
   const int nfields = type_fields(type);
1✔
800
   for (int i = 0; i < nfields; i++) {
3✔
801
      tree_t elem = type_field(type, i);
2✔
802
      tab(indent + 2);
2✔
803
      print_syntax("%s : #%s;\n", istr(tree_ident(elem)),
2✔
804
                   port_mode_str(tree_subkind(elem)));
2✔
805
   }
806

807
   tab(indent);
1✔
808
   print_syntax("#end #view;\n");
1✔
809
}
1✔
810

811
static void dump_decl(tree_t t, int indent)
35✔
812
{
813
   tab(indent);
35✔
814

815
   const tree_kind_t kind = tree_kind(t);
35✔
816
   if (kind != T_HIER)
35✔
817
      dump_address(t);
818

819
   switch (kind) {
35✔
UNCOV
820
   case T_IMPLICIT_SIGNAL:
×
UNCOV
821
      print_syntax("/* implicit */ ");
×
822
      // Fall-through
823
   case T_SIGNAL_DECL:
5✔
824
      print_syntax("#signal %s : ", istr(tree_ident(t)));
5✔
825
      break;
5✔
826

827
   case T_VAR_DECL:
3✔
828
      print_syntax("#variable %s : ", istr(tree_ident(t)));
3✔
829
      break;
3✔
830

831
   case T_CONST_DECL:
3✔
832
      print_syntax("#constant %s : ", istr(tree_ident(t)));
3✔
833
      break;
3✔
834

835
   case T_GENERIC_DECL:
1✔
836
      // Loop variable in for-generate statement
837
      print_syntax("/* loop variable */ %s : ", istr(tree_ident(t)));
1✔
838
      break;
1✔
839

840
   case T_FIELD_DECL:
2✔
841
      print_syntax("%s : ", istr(tree_ident(t)));
2✔
842
      break;
2✔
843

844
   case T_TYPE_DECL:
2✔
845
      dump_type_decl(t, indent);
2✔
846
      return;
2✔
847

848
   case T_SUBTYPE_DECL:
1✔
849
      dump_subtype_decl(t, indent);
1✔
850
      return;
1✔
851

UNCOV
852
   case T_SPEC:
×
853
      if (tree_has_ident(t))
×
854
         print_syntax("#for %s", istr(tree_ident(t)));
×
855
      else
856
         print_syntax("#for #others");
×
857
      if (tree_has_ref(t))
×
858
         print_syntax(" : %s", istr(tree_ident(tree_ref(t))));
×
859
      print_syntax("\n");
×
860
      tab(indent + 2);
×
861
      dump_binding(tree_value(t), indent + 2);
×
862
      dump_decls(t, indent + 2);
×
UNCOV
863
      tab(indent);
×
864
      print_syntax("#end #for;\n");
×
865
      return;
×
866

867
   case T_BLOCK_CONFIG:
×
868
      print_syntax("#for %s\n", istr(tree_ident(t)));
×
869
      dump_decls(t, indent + 2);
×
UNCOV
870
      tab(indent);
×
871
      print_syntax("#end #for;\n");
×
872
      return;
×
873

UNCOV
874
   case T_ENUM_LIT:
×
875
      print_syntax("%s", istr(tree_ident(t)));
×
876
      return;
×
877

878
   case T_ALIAS:
×
879
      if (tree_flags(t) & TREE_F_PREDEFINED)
×
880
         print_syntax("-- predefined ");
×
881
      print_syntax("#alias %s", istr(tree_ident(t)));
×
UNCOV
882
      if (tree_has_type(t)) {
×
883
         print_syntax(" : ");
×
884
         dump_type(tree_type(t));
×
885
      }
886
      print_syntax(" #is ");
×
UNCOV
887
      dump_expr(tree_value(t));
×
UNCOV
888
      print_syntax(";\n");
×
UNCOV
889
      return;
×
890

891
   case T_ATTR_SPEC:
4✔
892
      dump_attr_spec(t);
4✔
893
      return;
4✔
894

895
   case T_ATTR_DECL:
2✔
896
      print_syntax("#attribute %s : ", istr(tree_ident(t)));
2✔
897
      dump_type(tree_type(t));
2✔
898
      print_syntax(";\n");
2✔
899
      return;
2✔
900

901
   case T_FUNC_DECL:
2✔
902
      if (tree_flags(t) & TREE_F_PREDEFINED)
2✔
UNCOV
903
         print_syntax("-- predefined %s\n", type_pp(tree_type(t)));
×
904
      else {
905
         print_syntax("#function %s", istr(tree_ident(t)));
2✔
906
         dump_generics(t, indent + 2, "");
2✔
907
         dump_arguments(t, indent, "");
2✔
908
         print_syntax(" #return ");
2✔
909
         dump_type(type_result(tree_type(t)));
2✔
910
         print_syntax(";\n");
2✔
911
         if (tree_has_ident2(t)) {
2✔
912
            tab(indent + 2);
2✔
913
            print_syntax("-- %s\n", istr(tree_ident2(t)));
2✔
914
         }
915
      }
916
      return;
917

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

UNCOV
938
   case T_PROC_DECL:
×
939
      if (tree_flags(t) & TREE_F_PREDEFINED)
×
940
         print_syntax("-- predefined %s\n", type_pp(tree_type(t)));
×
941
      else {
942
         print_syntax("#procedure %s", istr(tree_ident(t)));
×
943
         dump_generics(t, indent + 2, tree_ports(t) > 0 ? "\n" : "");
×
944
         dump_arguments(t, indent, "");
×
945
         print_syntax(";");
×
946
         dump_wait_level(t);
×
947
         print_syntax("\n");
×
UNCOV
948
         if (tree_has_ident2(t)) {
×
UNCOV
949
            tab(indent + 2);
×
UNCOV
950
            print_syntax("-- %s\n", istr(tree_ident2(t)));
×
951
         }
952
      }
953
      return;
954

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

975
   case T_HIER:
×
976
      {
977
         const char *kind = "Scope";
×
978
         switch (tree_subkind(t)) {
×
979
         case T_ARCH: kind = "Instance"; break;
×
UNCOV
980
         case T_IF_GENERATE: kind = "If generate"; break;
×
981
         case T_FOR_GENERATE: kind = "For generate"; break;
×
UNCOV
982
         case T_BLOCK: kind = "Block"; break;
×
983
         }
UNCOV
984
         print_syntax("-- %s %s\n", kind, istr(tree_ident2(t)));
×
985
      }
UNCOV
986
      return;
×
987

988
   case T_COMPONENT:
1✔
989
      dump_component(t, indent);
1✔
990
      return;
1✔
991

992
   case T_PROT_DECL:
1✔
993
      print_syntax("#type %s #is #protected\n", istr(tree_ident(t)));
1✔
994
      dump_decls(t, indent + 2);
1✔
995
      tab(indent);
1✔
996
      print_syntax("#end #protected;\n");
1✔
997
      return;
1✔
998

999
   case T_PROT_BODY:
1✔
1000
      print_syntax("#type %s #is #protected #body\n", istr(tree_ident(t)));
1✔
1001
      dump_decls(t, indent + 2);
1✔
1002
      tab(indent);
1✔
1003
      print_syntax("#end #protected #body;\n");
1✔
1004
      return;
1✔
1005

1006
   case T_FILE_DECL:
×
1007
      print_syntax("#file %s : ", istr(tree_ident(t)));
×
1008
      dump_type(tree_type(t));
×
1009
      if (tree_has_value(t)) {
×
1010
         print_syntax(" #open ");
×
UNCOV
1011
         dump_expr(tree_file_mode(t));
×
1012
         print_syntax(" #is ");
×
1013
         dump_expr(tree_value(t));
×
1014
      }
1015
      print_syntax(";\n");
×
1016
      return;
×
1017

UNCOV
1018
   case T_USE:
×
1019
      dump_use(t);
×
UNCOV
1020
      return;
×
1021

1022
   case T_PACKAGE:
×
1023
   case T_PACK_INST:
1024
      dump_package(t, indent);
×
1025
      return;
×
1026

UNCOV
1027
   case T_PACK_BODY:
×
UNCOV
1028
      dump_package_body(t, indent);
×
UNCOV
1029
      return;
×
1030

1031
   case T_PSL_DECL:
1✔
1032
   case T_PSL_DIRECT:
1033
      dump_psl(t, 0);
1✔
1034
      print_syntax(";\n");
1✔
1035
      return;
1✔
1036

1037
   case T_VIEW_DECL:
1✔
1038
      dump_view_decl(t, 0);
1✔
1039
      return;
1✔
1040

UNCOV
1041
   case T_VERILOG:
×
UNCOV
1042
      vlog_dump(tree_vlog(t), indent);
×
UNCOV
1043
      return;
×
1044

UNCOV
1045
   default:
×
UNCOV
1046
      cannot_dump(t, "decl");
×
1047
   }
1048

1049
   dump_type(tree_type(t));
14✔
1050

1051
   if (tree_kind(t) != T_FIELD_DECL && tree_has_value(t)) {
14✔
1052
      print_syntax(" := ");
6✔
1053
      dump_expr(tree_value(t));
6✔
1054
   }
1055
   print_syntax(";\n");
14✔
1056
}
1057

1058
static void dump_waveforms(tree_t t)
3✔
1059
{
1060
   const int nwaves = tree_waveforms(t);
3✔
1061
   for (int i = 0; i < nwaves; i++) {
7✔
1062
      if (i > 0) print_syntax(", ");
4✔
1063
      dump_waveform(tree_waveform(t, i));
4✔
1064
   }
1065
}
3✔
1066

1067
static void dump_alternative(tree_t t, int indent)
×
1068
{
1069
   tab(indent);
×
1070
   print_syntax("#when ");
×
1071
   if (tree_has_ident(t))
×
1072
      print_syntax("%s: ", istr(tree_ident(t)));
×
1073
   for (unsigned i = 0; i < tree_assocs(t); i++) {
×
1074
      if (i > 0) print_syntax("| ");
×
1075
      tree_t a = tree_assoc(t, i);
×
1076
      switch (tree_subkind(a)) {
×
1077
      case A_NAMED:
×
1078
         dump_expr(tree_name(a));
×
UNCOV
1079
         break;
×
UNCOV
1080
      case A_OTHERS:
×
1081
         print_syntax("#others");
×
1082
         break;
×
1083
      case A_RANGE:
×
1084
         dump_range(tree_range(a, 0));
×
1085
         break;
×
1086
      }
1087
   }
1088
   print_syntax(" =>\n");
×
UNCOV
1089
   if (tree_decls(t) > 0) {
×
UNCOV
1090
      dump_decls(t, indent + 4);
×
1091
      tab(indent + 2);
×
1092
      print_syntax("#begin\n");
×
UNCOV
1093
      dump_stmts(t, indent + 4);
×
UNCOV
1094
      tab(indent + 2);
×
UNCOV
1095
      print_syntax("#end;\n");
×
1096
   }
1097
   else
UNCOV
1098
      dump_stmts(t, indent + 2);
×
UNCOV
1099
}
×
1100

1101
static void dump_psl(tree_t t, int indent)
2✔
1102
{
1103
   if (standard() < STD_08)
2✔
1104
      print_syntax("-- psl ");
×
1105
   psl_dump(tree_psl(t));
2✔
1106
}
2✔
1107

1108
static void dump_instance(tree_t t, int indent)
1✔
1109
{
1110
   switch (tree_class(t)) {
1✔
UNCOV
1111
   case C_ENTITY:        print_syntax("#entity "); break;
×
1112
   case C_COMPONENT:     print_syntax("#component "); break;
1✔
UNCOV
1113
   case C_CONFIGURATION: print_syntax("#configuration "); break;
×
1114
   default: break;
1115
   }
1116

1117
   print_syntax("%s", istr(tree_ident2(t)));
1✔
1118

1119
   const int nparams = tree_params(t);
1✔
1120
   const int ngenmaps = tree_genmaps(t);
1✔
1121

1122
   if (tree_has_spec(t)) {
1✔
1123
      tree_t spec = tree_spec(t);
×
UNCOV
1124
      if (tree_has_value(spec)) {
×
UNCOV
1125
         tree_t bind = tree_value(spec);
×
UNCOV
1126
         LOCAL_TEXT_BUF tb = tb_new();
×
UNCOV
1127
         tb_cat(tb, istr(tree_ident(bind)));
×
UNCOV
1128
         if (tree_has_ident2(bind))
×
UNCOV
1129
            tb_printf(tb, "(%s)", istr(tree_ident2(bind)));
×
UNCOV
1130
         print_syntax("  -- bound to %s\n", tb_get(tb));
×
1131
      }
1132
   }
1133
   else if (nparams > 0 || ngenmaps > 0)
1✔
1134
      print_syntax("\n");
1✔
1135

1136
   dump_generic_map(t, indent + 2, nparams > 0 ? "\n" : "");
1✔
1137
   dump_port_map(t, indent + 2, "");
1✔
1138
   print_syntax(";\n");
1✔
1139
}
1✔
1140

1141
static void dump_stmt(tree_t t, int indent)
18✔
1142
{
1143
   const tree_kind_t kind = tree_kind(t);
21✔
1144
   if (kind == T_VERILOG) {
21✔
UNCOV
1145
      vlog_dump(tree_vlog(t), indent);
×
UNCOV
1146
      return;
×
1147
   }
1148

1149
   tab(indent);
21✔
1150

1151
   if (tree_has_ident(t)) {
21✔
1152
      const char *label = istr(tree_ident(t));
9✔
1153
#if !DUMP_GEN_NAMES
1154
      if (label[0] != '_')   // Skip generated labels
9✔
1155
#endif
1156
         print_syntax("%s: ", label);
5✔
1157
   }
1158

1159
   switch (tree_kind(t)) {
21✔
1160
   case T_PROCESS:
1✔
1161
      dump_address(t);
1✔
1162
      if (tree_flags(t) & TREE_F_POSTPONED)
1✔
UNCOV
1163
         print_syntax("#postponed ");
×
1164
      print_syntax("#process ");
1✔
1165
      if (tree_triggers(t) > 0) {
1✔
1166
         print_syntax("(");
1✔
1167
         for (unsigned i = 0; i < tree_triggers(t); i++) {
2✔
1168
            if (i > 0)
1✔
UNCOV
1169
               print_syntax(", ");
×
1170
            dump_expr(tree_trigger(t, i));
1✔
1171
         }
1172
         print_syntax(") ");
1✔
1173
      }
1174
      print_syntax("#is\n");
1✔
1175
      dump_decls(t, indent + 2);
1✔
1176
      tab(indent);
1✔
1177
      print_syntax("#begin\n");
1✔
1178
      dump_stmts(t, indent + 2);
1✔
1179
      tab(indent);
1✔
1180
      print_syntax("#end #process;\n");
1✔
1181
      return;
1✔
1182

1183
   case T_SIGNAL_ASSIGN:
2✔
1184
      dump_expr(tree_target(t));
2✔
1185
      print_syntax(" <= #reject ");
2✔
1186
      if (tree_has_reject(t))
2✔
1187
         dump_expr(tree_reject(t));
1✔
1188
      else
1189
         print_syntax("0 ps");
1✔
1190
      print_syntax(" #inertial ");
2✔
1191
      dump_waveforms(t);
2✔
1192
      break;
2✔
1193

1194
   case T_FORCE:
×
1195
      dump_expr(tree_target(t));
×
1196
      print_syntax(" <= #force ");
×
UNCOV
1197
      dump_expr(tree_value(t));
×
UNCOV
1198
      break;
×
1199

UNCOV
1200
   case T_RELEASE:
×
UNCOV
1201
      dump_expr(tree_target(t));
×
UNCOV
1202
      print_syntax(" <= #release");
×
UNCOV
1203
      break;
×
1204

1205
   case T_VAR_ASSIGN:
2✔
1206
      dump_expr(tree_target(t));
2✔
1207
      print_syntax(" := ");
2✔
1208
      dump_expr(tree_value(t));
2✔
1209
      break;
2✔
1210

1211
   case T_WAIT:
×
UNCOV
1212
      print_syntax("#wait");
×
UNCOV
1213
      if (tree_triggers(t) > 0) {
×
1214
         print_syntax(" #on ");
×
1215
         for (unsigned i = 0; i < tree_triggers(t); i++) {
×
1216
            if (i > 0)
×
UNCOV
1217
               print_syntax(", ");
×
1218
            dump_expr(tree_trigger(t, i));
×
1219
         }
1220
      }
UNCOV
1221
      if (tree_has_value(t)) {
×
1222
         print_syntax(" #until ");
×
1223
         dump_expr(tree_value(t));
×
1224
      }
1225
      if (tree_has_delay(t)) {
×
1226
         print_syntax(" #for ");
×
UNCOV
1227
         dump_expr(tree_delay(t));
×
1228
      }
UNCOV
1229
      print_syntax(";");
×
UNCOV
1230
      if (tree_flags(t) & TREE_F_STATIC_WAIT)
×
UNCOV
1231
         print_syntax("   -- static");
×
UNCOV
1232
      print_syntax("\n");
×
UNCOV
1233
      return;
×
1234

1235
   case T_BLOCK:
2✔
1236
      dump_address(t);
2✔
1237
      print_syntax("#block #is\n");
2✔
1238
      dump_generics(t, indent + 2, ";\n");
2✔
1239
      dump_generic_map(t, indent + 2, ";\n");
2✔
1240
      dump_ports(t, indent + 2);
2✔
1241
      dump_port_map(t, indent + 2, ";\n");
2✔
1242
      dump_block(t, indent);
2✔
1243
      tab(indent);
2✔
1244
      print_syntax("#end #block;\n");
2✔
1245
      return;
2✔
1246

UNCOV
1247
   case T_SEQUENCE:
×
UNCOV
1248
      print_syntax("#block #is\n");
×
UNCOV
1249
      dump_block(t, indent);
×
UNCOV
1250
      tab(indent);
×
1251
      print_syntax("#end #block;\n");
×
1252
      return;
×
1253

1254
   case T_ASSERT:
2✔
1255
      print_syntax("#assert ");
2✔
1256
      dump_expr(tree_value(t));
2✔
1257
      if (tree_has_message(t)) {
2✔
UNCOV
1258
         print_syntax(" #report ");
×
UNCOV
1259
         dump_expr(tree_message(t));
×
1260
      }
1261
      if (tree_has_severity(t)) {
2✔
UNCOV
1262
         print_syntax(" #severity ");
×
UNCOV
1263
         dump_expr(tree_severity(t));
×
1264
      }
1265
      break;
1266

1267
   case T_REPORT:
1✔
1268
      print_syntax("#report ");
1✔
1269
      dump_expr(tree_message(t));
1✔
1270
      if (tree_has_severity(t)) {
1✔
1271
         print_syntax(" #severity ");
×
1272
         dump_expr(tree_severity(t));
×
1273
      }
1274
      break;
1275

1276
   case T_WHILE:
×
1277
      print_syntax("#while ");
×
1278
      dump_expr(tree_value(t));
×
1279
      print_syntax(" ");
×
1280
      // Fall-through
UNCOV
1281
   case T_LOOP:
×
UNCOV
1282
      print_syntax("#loop\n");
×
UNCOV
1283
      dump_stmts(t, indent + 2);
×
UNCOV
1284
      tab(indent);
×
UNCOV
1285
      print_syntax("#end #loop");
×
1286
      break;
×
1287

1288
   case T_IF:
1289
      for (unsigned i = 0; i < tree_conds(t); i++) {
3✔
1290
         tree_t c = tree_cond(t, i);
2✔
1291
         if (tree_has_value(c)) {
2✔
1292
            if (i > 0)
1✔
UNCOV
1293
               tab(indent);
×
1294
            print_syntax(i > 0 ? "#elsif " : "#if ");
2✔
1295
            dump_expr(tree_value(c));
1✔
1296
            print_syntax(" #then\n");
1✔
1297
         }
1298
         else {
1299
            tab(indent);
1✔
1300
            print_syntax("#else\n");
1✔
1301
         }
1302
         dump_stmts(c, indent + 2);
2✔
1303
      }
1304
      tab(indent);
1✔
1305
      print_syntax("#end #if");
1✔
1306
      break;
1✔
1307

UNCOV
1308
   case T_EXIT:
×
1309
      print_syntax("#exit %s", istr(tree_ident2(t)));
×
UNCOV
1310
      if (tree_has_value(t)) {
×
UNCOV
1311
         print_syntax(" #when ");
×
1312
         dump_expr(tree_value(t));
×
1313
      }
1314
      break;
1315

1316
   case T_CASE:
×
1317
   case T_MATCH_CASE:
1318
      {
1319
         const char *suffix = tree_kind(t) == T_MATCH_CASE ? "?" : "";
×
1320
         print_syntax("#case%s ", suffix);
×
UNCOV
1321
         dump_expr(tree_value(t));
×
1322
         print_syntax(" #is\n");
×
UNCOV
1323
         const int nstmts = tree_stmts(t);
×
UNCOV
1324
         for (int i = 0; i < nstmts; i++)
×
UNCOV
1325
            dump_alternative(tree_stmt(t, i), indent + 2);
×
UNCOV
1326
         tab(indent);
×
UNCOV
1327
         print_syntax("#end #case%s", suffix);
×
1328
      }
UNCOV
1329
      break;
×
1330

1331
   case T_RETURN:
3✔
1332
      print_syntax("#return");
3✔
1333
      if (tree_has_value(t)) {
3✔
1334
         print_syntax(" ");
3✔
1335
         dump_expr(tree_value(t));
3✔
1336
      }
1337
      break;
1338

1339
   case T_COND_RETURN:
×
1340
      print_syntax("#return #when ");
×
1341
      dump_expr(tree_value(t));
×
1342
      break;
×
1343

1344
   case T_FOR:
×
UNCOV
1345
      print_syntax("#for %s #in ", istr(tree_ident(tree_decl(t, 0))));
×
1346
      dump_range(tree_range(t, 0));
×
1347
      print_syntax(" #loop\n");
×
1348
      dump_stmts(t, indent + 2);
×
UNCOV
1349
      tab(indent);
×
1350
      print_syntax("#end #for");
×
1351
      break;
×
1352

1353
   case T_PROT_PCALL:
×
1354
      dump_expr(tree_name(t));
×
UNCOV
1355
      print_syntax(".");
×
1356
      // Fall-through
1357
   case T_PCALL:
×
1358
      if (tree_has_ref(t)) {
×
1359
         tree_t decl = tree_ref(t);
×
UNCOV
1360
         dump_address(decl);
×
UNCOV
1361
         print_syntax("%s", istr(tree_ident(decl)));
×
1362
      }
1363
      else
UNCOV
1364
         print_syntax("%s", istr(tree_ident2(t)));
×
UNCOV
1365
      dump_params(t, tree_param, tree_params(t), NULL);
×
UNCOV
1366
      break;
×
1367

1368
   case T_FOR_GENERATE:
1✔
1369
      print_syntax("#for %s #in ", istr(tree_ident(tree_decl(t, 0))));
1✔
1370
      dump_range(tree_range(t, 0));
1✔
1371
      print_syntax(" #generate\n");
1✔
1372
      dump_decls(t, indent + 2);
1✔
1373
      tab(indent);
1✔
1374
      print_syntax("#begin\n");
1✔
1375
      dump_stmts(t, indent + 2);
1✔
1376
      tab(indent);
1✔
1377
      print_syntax("#end #generate");
1✔
1378
      break;
1✔
1379

1380
   case T_CASE_GENERATE:
×
1381
      {
UNCOV
1382
         print_syntax("#case ");
×
1383
         dump_expr(tree_value(t));
×
1384
         print_syntax(" #generate\n");
×
1385

1386
         const int nstmts = tree_stmts(t);
×
UNCOV
1387
         for (int i = 0; i < nstmts; i++)
×
UNCOV
1388
            dump_alternative(tree_stmt(t, i), indent + 2);
×
1389

1390
         print_syntax("#end #generate");
×
1391
         tab(indent);
×
1392
      }
1393
      break;
×
1394

1395
   case T_IF_GENERATE:
1396
      for (unsigned i = 0; i < tree_conds(t); i++) {
×
UNCOV
1397
         tree_t c = tree_cond(t, i);
×
UNCOV
1398
         if (tree_has_value(c)) {
×
1399
            if (i > 0)
×
1400
               tab(indent);
×
UNCOV
1401
            print_syntax(i > 0 ? "#elsif " : "#if ");
×
1402
            dump_expr(tree_value(c));
×
1403
            print_syntax(" #generate\n");
×
1404
         }
1405
         else {
1406
            tab(indent);
×
1407
            print_syntax("#else\n");
×
1408
         }
UNCOV
1409
         for (unsigned i = 0; i < tree_stmts(c); i++)
×
UNCOV
1410
            dump_stmt(tree_stmt(c, i), indent + 2);
×
1411
      }
UNCOV
1412
      tab(indent);
×
1413
      print_syntax("#end #generate");
×
1414
      break;
×
1415

1416
   case T_INSTANCE:
1✔
1417
      dump_instance(t, indent);
1✔
1418
      return;
1✔
1419

UNCOV
1420
   case T_NEXT:
×
1421
      print_syntax("#next");
×
1422
      if (tree_has_value(t)) {
×
1423
         print_syntax(" #when ");
×
UNCOV
1424
         dump_expr(tree_value(t));
×
1425
      }
1426
      break;
1427

UNCOV
1428
   case T_NULL:
×
1429
      print_syntax("#null");
×
UNCOV
1430
      break;
×
1431

1432
   case T_COND_ASSIGN:
1✔
1433
      dump_expr(tree_target(t));
1✔
1434
      print_syntax(" <= ");
1✔
1435
      if (tree_has_guard(t))
1✔
UNCOV
1436
         print_syntax("#guarded ");
×
1437
      for (int i = 0; i < tree_conds(t); i++) {
2✔
1438
         tree_t c = tree_cond(t, i);
1✔
1439
         dump_waveforms(tree_stmt(c, 0));
1✔
1440
         if (tree_has_value(c)) {
1✔
1441
            print_syntax(" #when ");
×
1442
            dump_expr(tree_value(c));
×
1443
         }
1444
      }
1445
      break;
1446

UNCOV
1447
   case T_SELECT:
×
1448
      print_syntax(" <= ");
×
UNCOV
1449
      if (tree_has_guard(t)) print_syntax("#guarded ");
×
UNCOV
1450
      color_printf("$red$/* TODO: T_SELECT */$$");
×
UNCOV
1451
      break;
×
1452

1453
   case T_CONCURRENT:
3✔
1454
      if (tree_flags(t) & TREE_F_POSTPONED)
3✔
1455
         print_syntax("#postponed ");
×
1456
      dump_stmt(tree_stmt(t, 0), 0);
3✔
1457
      return;
3✔
1458

UNCOV
1459
   case T_DUMMY_DRIVER:
×
UNCOV
1460
      print_syntax("-- dummy driver for ");
×
UNCOV
1461
      dump_expr(tree_target(t));
×
1462
      print_syntax("\n");
×
1463
      return;
×
1464

1465
   case T_PSL_DIRECT:
1✔
1466
      dump_psl(t, indent);
1✔
1467
      break;
1✔
1468

UNCOV
1469
   default:
×
UNCOV
1470
      cannot_dump(t, "stmt");
×
1471
   }
1472

1473
   print_syntax(";\n");
14✔
1474
}
1475

1476
static void dump_port(tree_t t, int indent)
103✔
1477
{
1478
   tab(indent);
103✔
1479
   dump_address(t);
103✔
1480

1481
   if (tree_flags(t) & TREE_F_PREDEFINED)
103✔
1482
      print_syntax("-- predefined ");
80✔
1483

1484
   const class_t class = tree_class(t);
103✔
1485
   print_syntax("#%s %s", class_str(class), istr(tree_ident(t)));
103✔
1486

1487
   const port_mode_t mode = tree_subkind(t);
103✔
1488

1489
   type_t type = get_type_or_null(t);
103✔
1490
   if (class == C_PACKAGE) {
103✔
UNCOV
1491
      print_syntax(" #is #new ");
×
UNCOV
1492
      dump_expr(tree_value(t));
×
1493
   }
1494
   else if (class == C_TYPE && type_kind(type) == T_GENERIC) {
103✔
1495
      print_syntax(" #is ");
10✔
1496

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

1548
      if (tree_has_value(t)) {
91✔
1549
         print_syntax(" := ");
81✔
1550
         dump_expr(tree_value(t));
81✔
1551
      }
1552
   }
1553
}
103✔
1554

1555
static void dump_context(tree_t t, int indent)
7✔
1556
{
1557
   const int nctx = tree_contexts(t);
7✔
1558
   for (int i = 0; i < nctx; i++) {
28✔
1559
      tree_t c = tree_context(t, i);
21✔
1560
      switch (tree_kind(c)) {
21✔
1561
      case T_LIBRARY:
14✔
1562
         switch (is_well_known(tree_ident(c))) {
14✔
1563
         case W_STD:
1564
         case W_WORK:
1565
            break;
UNCOV
1566
         default:
×
UNCOV
1567
            print_syntax("#library %s;\n", istr(tree_ident(c)));
×
1568
         }
1569
         break;
1570

1571
      case T_USE:
7✔
1572
         dump_use(c);
7✔
1573
         break;
7✔
1574

UNCOV
1575
      case T_CONTEXT_REF:
×
UNCOV
1576
         print_syntax("#context %s;\n", istr(tree_ident(t)));
×
UNCOV
1577
         break;
×
1578

1579
      default:
1580
         break;
1581
      }
1582

1583
      tab(indent);
21✔
1584
   }
1585

1586
   if (nctx > 0) {
7✔
1587
      print_syntax("\n");
7✔
1588
      tab(indent);
7✔
1589
   }
1590
}
7✔
1591

1592
static void dump_elab(tree_t t)
×
1593
{
1594
   dump_context(t, 0);
×
1595
   dump_address(t);
×
1596
   print_syntax("#entity %s #is\n#end #entity;\n\n", istr(tree_ident(t)));
×
UNCOV
1597
   print_syntax("#architecture #elab #of %s #is\n", istr(tree_ident(t)));
×
UNCOV
1598
   dump_decls(t, 2);
×
UNCOV
1599
   print_syntax("#begin\n");
×
UNCOV
1600
   for (unsigned i = 0; i < tree_stmts(t); i++)
×
UNCOV
1601
      dump_stmt(tree_stmt(t, i), 2);
×
UNCOV
1602
   print_syntax("#end #architecture;\n\n");
×
UNCOV
1603
}
×
1604

1605
static void dump_entity(tree_t t)
2✔
1606
{
1607
   dump_context(t, 0);
2✔
1608
   dump_address(t);
2✔
1609
   print_syntax("#entity %s #is\n", istr(tree_ident(t)));
2✔
1610
   dump_generics(t, 2, ";\n");
2✔
1611
   dump_ports(t, 2);
2✔
1612
   dump_decls(t, 2);
2✔
1613
   if (tree_stmts(t) > 0) {
2✔
UNCOV
1614
      print_syntax("#begin\n");
×
UNCOV
1615
      for (unsigned i = 0; i < tree_stmts(t); i++) {
×
UNCOV
1616
         dump_stmt(tree_stmt(t, i), 2);
×
1617
      }
1618
   }
1619
   print_syntax("#end #entity;\n\n");
2✔
1620
}
2✔
1621

1622
static void dump_decls(tree_t t, int indent)
18✔
1623
{
1624
   const int ndecls = tree_decls(t);
18✔
1625
   bool was_body = false;
18✔
1626
   for (unsigned i = 0; i < ndecls; i++) {
41✔
1627
      tree_t d = tree_decl(t, i);
23✔
1628
      tree_kind_t dkind = tree_kind(d);
23✔
1629
      const bool is_body = dkind == T_FUNC_BODY || dkind == T_PROT_BODY
46✔
1630
         || dkind == T_PROC_BODY;
23✔
1631
      if ((was_body && !is_body) || (is_body && i > 0))
23✔
1632
         print_syntax("\n");
5✔
1633
      was_body = is_body;
23✔
1634
      dump_decl(d, indent);
23✔
1635
   }
1636
}
18✔
1637

1638
static void dump_arch(tree_t t)
2✔
1639
{
1640
   dump_context(t, 0);
2✔
1641
   dump_address(t);
2✔
1642
   print_syntax("#architecture %s #of %s #is\n",
2✔
1643
                istr(tree_ident(t)), istr(tree_ident2(t)));
1644
   dump_decls(t, 2);
2✔
1645
   print_syntax("#begin\n");
2✔
1646
   dump_stmts(t, 2);
2✔
1647
   print_syntax("#end #architecture;\n\n");
2✔
1648
}
2✔
1649

1650
static void dump_package(tree_t t, int indent)
1✔
1651
{
1652
   dump_context(t, indent);
1✔
1653
   dump_address(t);
1✔
1654
   print_syntax("#package %s #is\n", istr(tree_ident(t)));
1✔
1655
   if (tree_kind(t) == T_PACK_INST && tree_has_ref(t)) {
1✔
UNCOV
1656
      tab(indent);
×
UNCOV
1657
      print_syntax("  -- Instantiated from %s\n", istr(tree_ident(tree_ref(t))));
×
1658
   }
1659
   dump_generics(t, indent + 2, ";\n");
1✔
1660
   dump_generic_map(t, indent + 2, ";\n");
1✔
1661
   dump_decls(t, indent + 2);
1✔
1662
   tab(indent);
1✔
1663
   print_syntax("#end #package;\n\n");
1✔
1664
}
1✔
1665

1666
static void dump_package_body(tree_t t, int indent)
2✔
1667
{
1668
   dump_context(t, indent);
2✔
1669
   dump_address(t);
2✔
1670
   print_syntax("#package #body %s #is\n", istr(tree_ident(t)));
2✔
1671
   dump_decls(t, indent + 2);
2✔
1672
   tab(indent);
2✔
1673
   print_syntax("#end #package #body;\n\n");
2✔
1674
}
2✔
1675

1676
static void dump_configuration(tree_t t)
×
1677
{
UNCOV
1678
   dump_address(t);
×
UNCOV
1679
   print_syntax("#configuration %s #of %s #is\n",
×
1680
          istr(tree_ident(t)), istr(tree_ident2(t)));
1681
   dump_decls(t, 2);
×
1682
   print_syntax("#end #configuration\n");
×
1683
}
×
1684

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

1795
void dump(tree_t t)
21✔
1796
{
1797
   vhdl_dump(t, 0);
21✔
1798
   print_syntax("\r");
21✔
1799
}
21✔
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