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

nickg / nvc / 19789834065

29 Nov 2025 09:53PM UTC coverage: 92.566% (-0.009%) from 92.575%
19789834065

push

github

nickg
Avoid code generation for processes in cloned blocks

38 of 49 new or added lines in 4 files covered. (77.55%)

595 existing lines in 10 files now uncovered.

75316 of 81365 relevant lines covered (92.57%)

421911.4 hits per line

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

59.06
/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
            if (tree_ranges(a) > 0) {
3✔
307
               print_syntax("/*");
×
308
               dump_range(tree_range(a, 0));
×
309
               print_syntax("*/ ");
×
310
            }
311
            print_syntax("=> ");
3✔
312
            dump_expr(value);
3✔
313
            break;
3✔
314
         case A_SLICE:
×
315
            print_syntax("/* slice */");
×
316
            // Fall-through
317
         case A_RANGE:
×
318
            dump_range(tree_range(a, 0));
×
319
            print_syntax(" => ");
×
320
            dump_expr(value);
×
321
            break;
×
322
         default:
×
323
            should_not_reach_here();
324
         }
325
      }
326
      print_syntax(")");
3✔
327
      break;
3✔
328

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

436
   dump_type_hint(t);
201✔
437
}
438

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

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

447
   dump_elem_constraints(ftype);
×
448
}
×
449

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

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

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

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

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

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

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

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

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

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

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

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

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

625
      dump_stmt(s, indent);
12✔
626

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

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

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

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

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

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

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

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

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

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

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

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

756
   dump_elem_constraints(type);
1✔
757

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1080
static void dump_alternative(tree_t t, int indent)
×
1081
{
1082
   tab(indent);
×
1083
   print_syntax("#when ");
×
1084
   if (tree_has_ident(t))
×
1085
      print_syntax("%s: ", istr(tree_ident(t)));
×
1086
   for (unsigned i = 0; i < tree_assocs(t); i++) {
×
1087
      if (i > 0) print_syntax("| ");
×
1088
      tree_t a = tree_assoc(t, i);
×
1089
      switch (tree_subkind(a)) {
×
1090
      case A_NAMED:
×
1091
         dump_expr(tree_name(a));
×
1092
         break;
×
1093
      case A_OTHERS:
×
1094
         print_syntax("#others");
×
1095
         break;
×
1096
      case A_RANGE:
×
1097
         dump_range(tree_range(a, 0));
×
1098
         break;
×
1099
      }
1100
   }
1101
   print_syntax(" =>\n");
×
1102
   if (tree_decls(t) > 0) {
×
1103
      dump_decls(t, indent + 4);
×
1104
      tab(indent + 2);
×
1105
      print_syntax("#begin\n");
×
1106
      dump_stmts(t, indent + 4);
×
1107
      tab(indent + 2);
×
1108
      print_syntax("#end;\n");
×
1109
   }
1110
   else
1111
      dump_stmts(t, indent + 2);
×
1112
}
×
1113

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

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

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

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

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

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

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

1162
   tab(indent);
21✔
1163

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1441
   case T_NULL:
×
1442
      print_syntax("#null");
×
1443
      break;
×
1444

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

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

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

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

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

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

1486
   print_syntax(";\n");
14✔
1487
}
1488

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

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

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

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

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

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

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

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

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

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

1592
      default:
1593
         break;
1594
      }
1595

1596
      tab(indent);
21✔
1597
   }
1598

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

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

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

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

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

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

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

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

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

1808
void dump(tree_t t)
21✔
1809
{
1810
   vhdl_dump(t, 0);
21✔
1811
   print_syntax("\r");
21✔
1812
}
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