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

nickg / nvc / 25986469887

17 May 2026 08:44AM UTC coverage: 92.22% (-0.04%) from 92.258%
25986469887

push

github

nickg
Add PicoRV32 to regression tests

78454 of 85073 relevant lines covered (92.22%)

648774.32 hits per line

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

61.48
/src/dump.c
1
//
2
//  Copyright (C) 2011-2024  Nick Gasson
3
//
4
//  This program is free software: you can redistribute it and/or modify
5
//  it under the terms of the GNU General Public License as published by
6
//  the Free Software Foundation, either version 3 of the License, or
7
//  (at your option) any later version.
8
//
9
//  This program is distributed in the hope that it will be useful,
10
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
//  GNU General Public License for more details.
13
//
14
//  You should have received a copy of the GNU General Public License
15
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
//
17

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

433
   case T_PSL_FCALL:
×
434
   case T_PSL_UNION:
435
      psl_dump(tree_psl(t));
×
436
      break;
×
437

438
   default:
×
439
      cannot_dump(t, "expr");
×
440
   }
441

442
   dump_type_hint(t);
206✔
443
}
444

445
static void dump_record_elem_constraint(tree_t t)
×
446
{
447
   print_syntax("%s", istr(tree_ident(t)));
×
448

449
   type_t ftype = tree_type(t);
×
450
   if (type_has_constraint(ftype))
×
451
      dump_constraint(type_constraint(ftype));
×
452

453
   dump_elem_constraints(ftype);
×
454
}
×
455

456
static void dump_constraint(tree_t t)
5✔
457
{
458
   const int nranges = tree_ranges(t);
5✔
459

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

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

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

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

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

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

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

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

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

611
static void dump_stmts(tree_t t, int indent)
16✔
612
{
613
   bool last_was_newline = false;
16✔
614
   const int nstmts = tree_stmts(t);
16✔
615
   for (int i = 0; i < nstmts; i++) {
31✔
616
      tree_t s = tree_stmt(t, i);
15✔
617
      const tree_kind_t kind = tree_kind(s);
15✔
618

619
      bool needs_newline;
15✔
620
      if (kind == T_VERILOG) {
15✔
621
         const vlog_kind_t vkind = vlog_kind(tree_vlog(s));
×
622
         needs_newline = (vkind == V_ALWAYS || vkind == V_INITIAL
×
623
                          || vkind == V_FINAL);
×
624
      }
625
      else
626
         needs_newline = (kind == T_BLOCK || kind == T_PROCESS
15✔
627
                          || kind == T_INSTANCE);
628

629
      if (needs_newline && i > 0 && !last_was_newline)
15✔
630
         print_syntax("\n");
×
631

632
      dump_stmt(s, indent);
15✔
633

634
      if (needs_newline && i + 1 < nstmts) {
15✔
635
         print_syntax("\n");
×
636
         last_was_newline = true;
×
637
      }
638
      else
639
         last_was_newline = false;
640
   }
641
}
16✔
642

643
static void dump_block(tree_t t, int indent)
7✔
644
{
645
   dump_decls(t, indent + 2);
7✔
646
   tab(indent);
7✔
647
   print_syntax("#begin\n");
7✔
648
   dump_stmts(t, indent + 2);
7✔
649
}
7✔
650

651
static void dump_wait_level(tree_t t)
3✔
652
{
653
   const tree_flags_t flags = tree_flags(t);
3✔
654
   if (flags & TREE_F_NEVER_WAITS)
3✔
655
      print_syntax("   -- Never waits");
3✔
656
   else if (flags & TREE_F_HAS_WAIT)
×
657
      print_syntax("   -- Contains wait statement");
×
658
}
3✔
659

660
static void dump_type_decl(tree_t t, int indent)
2✔
661
{
662
   type_t type = tree_type(t);
2✔
663
   const type_kind_t kind = type_kind(type);
2✔
664

665
   print_syntax("#type %s", istr(tree_ident(t)));
2✔
666

667
   if (kind == T_INCOMPLETE) {
2✔
668
      print_syntax(";\n");
×
669
      return;
×
670
   }
671

672
   print_syntax(" #is ");
2✔
673

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

746
   print_syntax(";\n");
2✔
747
}
748

749
static void dump_subtype_decl(tree_t t, int indent)
1✔
750
{
751
   type_t type = tree_type(t);
1✔
752

753
   print_syntax("#subtype %s #is ", istr(tree_ident(t)));
1✔
754
   if (type_has_resolution(type)) {
1✔
755
      dump_expr(type_resolution(type));
×
756
      print_syntax(" ");
×
757
   }
758
   print_syntax("%s", type_pp(type_base(type)));
1✔
759

760
   if (type_has_constraint(type))
1✔
761
      dump_constraint(type_constraint(type));
1✔
762

763
   dump_elem_constraints(type);
1✔
764

765
   print_syntax(";\n");
1✔
766
}
1✔
767

768
static void dump_component(tree_t t, int indent)
1✔
769
{
770
   print_syntax("#component %s #is\n", istr(tree_ident(t)));
1✔
771
   dump_generics(t, indent + 2, ";\n");
1✔
772
   dump_ports(t, indent + 2);
1✔
773
   print_syntax("#end #component;\n");
1✔
774
}
1✔
775

776
static void dump_use(tree_t t)
7✔
777
{
778
   print_syntax("#use %s", istr(tree_ident(t)));
7✔
779
   if (tree_has_ident2(t))
7✔
780
      print_syntax(".%s", istr(tree_ident2(t)));
7✔
781
   print_syntax(";\n");
7✔
782
}
7✔
783

784
static void dump_attr_spec(tree_t t)
4✔
785
{
786
   print_syntax("#attribute %s #of ", istr(tree_ident(t)));
4✔
787

788
   switch (tree_subkind(t)) {
4✔
789
   case SPEC_EXACT:
2✔
790
      print_syntax("%s", istr(tree_ident2(t)));
2✔
791
      break;
2✔
792
   case SPEC_ALL:
1✔
793
      print_syntax("#all");
1✔
794
      break;
1✔
795
   case SPEC_OTHERS:
1✔
796
      print_syntax("#others");
1✔
797
      break;
1✔
798
   }
799

800
   print_syntax(" : #%s #is ", class_str(tree_class(t)));
4✔
801
   dump_expr(tree_value(t));
4✔
802
   print_syntax(";\n");
4✔
803
}
4✔
804

805
static void dump_view_decl(tree_t t, int indent)
1✔
806
{
807
   type_t type = tree_type(t);
1✔
808
   print_syntax("#view %s #of ", istr(tree_ident(t)));
1✔
809
   dump_type(type_designated(type));
1✔
810
   print_syntax(" #is\n");
1✔
811

812
   const int nfields = type_fields(type);
1✔
813
   for (int i = 0; i < nfields; i++) {
3✔
814
      tree_t elem = type_field(type, i);
2✔
815
      tab(indent + 2);
2✔
816
      print_syntax("%s : #%s;\n", istr(tree_ident(elem)),
2✔
817
                   port_mode_str(tree_subkind(elem)));
2✔
818
   }
819

820
   tab(indent);
1✔
821
   print_syntax("#end #view;\n");
1✔
822
}
1✔
823

824
static void dump_decl(tree_t t, int indent)
35✔
825
{
826
   tab(indent);
35✔
827

828
   const tree_kind_t kind = tree_kind(t);
35✔
829
   if (kind != T_HIER)
35✔
830
      dump_address(t);
831

832
   switch (kind) {
35✔
833
   case T_IMPLICIT_SIGNAL:
×
834
      print_syntax("/* implicit */ ");
×
835
      // Fall-through
836
   case T_SIGNAL_DECL:
5✔
837
      print_syntax("#signal %s : ", istr(tree_ident(t)));
5✔
838
      break;
5✔
839

840
   case T_VAR_DECL:
3✔
841
      print_syntax("#variable %s : ", istr(tree_ident(t)));
3✔
842
      break;
3✔
843

844
   case T_CONST_DECL:
3✔
845
      print_syntax("#constant %s : ", istr(tree_ident(t)));
3✔
846
      break;
3✔
847

848
   case T_GENERIC_DECL:
1✔
849
      // Loop variable in for-generate statement
850
      print_syntax("/* loop variable */ %s : ", istr(tree_ident(t)));
1✔
851
      break;
1✔
852

853
   case T_FIELD_DECL:
2✔
854
      print_syntax("%s : ", istr(tree_ident(t)));
2✔
855
      break;
2✔
856

857
   case T_TYPE_DECL:
2✔
858
      dump_type_decl(t, indent);
2✔
859
      return;
2✔
860

861
   case T_SUBTYPE_DECL:
1✔
862
      dump_subtype_decl(t, indent);
1✔
863
      return;
1✔
864

865
   case T_SPEC:
×
866
      if (tree_has_ident(t))
×
867
         print_syntax("#for %s", istr(tree_ident(t)));
×
868
      else
869
         print_syntax("#for #others");
×
870
      if (tree_has_ref(t))
×
871
         print_syntax(" : %s", istr(tree_ident(tree_ref(t))));
×
872
      print_syntax("\n");
×
873
      tab(indent + 2);
×
874
      if (tree_has_value(t))
×
875
         dump_binding(tree_value(t), indent + 2);
×
876
      else
877
         print_syntax("#use #open;\n");
×
878
      dump_decls(t, indent + 2);
×
879
      tab(indent);
×
880
      print_syntax("#end #for;\n");
×
881
      return;
×
882

883
   case T_BLOCK_CONFIG:
×
884
      print_syntax("#for %s\n", istr(tree_ident(t)));
×
885
      dump_decls(t, indent + 2);
×
886
      tab(indent);
×
887
      print_syntax("#end #for;\n");
×
888
      return;
×
889

890
   case T_ENUM_LIT:
×
891
      print_syntax("%s", istr(tree_ident(t)));
×
892
      return;
×
893

894
   case T_ALIAS:
×
895
      if (tree_flags(t) & TREE_F_PREDEFINED)
×
896
         print_syntax("-- predefined ");
×
897
      print_syntax("#alias %s", istr(tree_ident(t)));
×
898
      if (tree_has_type(t)) {
×
899
         print_syntax(" : ");
×
900
         dump_type(tree_type(t));
×
901
      }
902
      print_syntax(" #is ");
×
903
      dump_expr(tree_value(t));
×
904
      print_syntax(";\n");
×
905
      return;
×
906

907
   case T_ATTR_SPEC:
4✔
908
      dump_attr_spec(t);
4✔
909
      return;
4✔
910

911
   case T_ATTR_DECL:
2✔
912
      print_syntax("#attribute %s : ", istr(tree_ident(t)));
2✔
913
      dump_type(tree_type(t));
2✔
914
      print_syntax(";\n");
2✔
915
      return;
2✔
916

917
   case T_FUNC_DECL:
2✔
918
      if (tree_flags(t) & TREE_F_PREDEFINED)
2✔
919
         print_syntax("-- predefined %s\n", type_pp(tree_type(t)));
×
920
      else {
921
         print_syntax("#function %s", istr(tree_ident(t)));
2✔
922
         dump_generics(t, indent + 2, "");
2✔
923
         dump_arguments(t, indent, "");
2✔
924
         print_syntax(" #return ");
2✔
925
         dump_type(type_result(tree_type(t)));
2✔
926
         print_syntax(";\n");
2✔
927
         if (tree_has_ident2(t)) {
2✔
928
            tab(indent + 2);
2✔
929
            print_syntax("-- %s\n", istr(tree_ident2(t)));
2✔
930
         }
931
      }
932
      return;
933

934
   case T_FUNC_INST:
2✔
935
   case T_FUNC_BODY:
936
      print_syntax("#function %s", istr(tree_ident(t)));
2✔
937
      dump_type_hint(t);
2✔
938
      dump_generics(t, indent + 2, tree_ports(t) > 0 ? "\n" : "");
3✔
939
      if (tree_kind(t) == T_FUNC_INST)
2✔
940
         dump_generic_map(t, indent + 2, tree_ports(t) > 0 ? "\n" : "");
×
941
      dump_arguments(t, indent, "");
2✔
942
      print_syntax(" #return ");
2✔
943
      dump_type(type_result(tree_type(t)));
2✔
944
      print_syntax(" #is\n");
2✔
945
      if (tree_has_ident2(t)) {
2✔
946
         tab(indent + 2);
2✔
947
         print_syntax("-- %s\n", istr(tree_ident2(t)));
2✔
948
      }
949
      dump_block(t, indent);
2✔
950
      tab(indent);
2✔
951
      print_syntax("#end #function;\n");
2✔
952
      return;
2✔
953

954
   case T_PROC_DECL:
×
955
      if (tree_flags(t) & TREE_F_PREDEFINED)
×
956
         print_syntax("-- predefined %s\n", type_pp(tree_type(t)));
×
957
      else {
958
         print_syntax("#procedure %s", istr(tree_ident(t)));
×
959
         dump_generics(t, indent + 2, tree_ports(t) > 0 ? "\n" : "");
×
960
         dump_arguments(t, indent, "");
×
961
         print_syntax(";");
×
962
         dump_wait_level(t);
×
963
         print_syntax("\n");
×
964
         if (tree_has_ident2(t)) {
×
965
            tab(indent + 2);
×
966
            print_syntax("-- %s\n", istr(tree_ident2(t)));
×
967
         }
968
      }
969
      return;
970

971
   case T_PROC_INST:
3✔
972
   case T_PROC_BODY:
973
      print_syntax("#procedure %s", istr(tree_ident(t)));
3✔
974
      dump_type_hint(t);
3✔
975
      dump_generics(t, indent + 2, tree_ports(t) > 0 ? "\n" : "");
5✔
976
      if (tree_kind(t) == T_PROC_INST)
3✔
977
         dump_generic_map(t, indent + 2, tree_ports(t) > 0 ? "\n" : "");
×
978
      dump_arguments(t, indent, "");
3✔
979
      print_syntax(" #is");
3✔
980
      dump_wait_level(t);
3✔
981
      print_syntax("\n");
3✔
982
      if (tree_has_ident2(t)) {
3✔
983
         tab(indent + 2);
3✔
984
         print_syntax("-- %s\n", istr(tree_ident2(t)));
3✔
985
      }
986
      dump_block(t, indent);
3✔
987
      tab(indent);
3✔
988
      print_syntax("#end #procedure;\n");
3✔
989
      return;
3✔
990

991
   case T_HIER:
×
992
      {
993
         const char *kind = "Scope";
×
994
         switch (tree_subkind(t)) {
×
995
         case T_ARCH: kind = "Instance"; break;
×
996
         case T_IF_GENERATE: kind = "If generate"; break;
×
997
         case T_FOR_GENERATE: kind = "For generate"; break;
×
998
         case T_BLOCK: kind = "Block"; break;
×
999
         }
1000

1001
         ident_t dotted = tree_ident(t);
×
1002
         ident_t symbol = tree_ident2(t);
×
1003

1004
         print_syntax("-- %s %s", kind, istr(dotted));
×
1005
         if (dotted != symbol)
×
1006
            print_syntax(" (clone of %s)", istr(symbol));
×
1007
         print_syntax("\n");
×
1008
      }
1009
      return;
×
1010

1011
   case T_COMPONENT:
1✔
1012
      dump_component(t, indent);
1✔
1013
      return;
1✔
1014

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

1022
   case T_PROT_BODY:
1✔
1023
      print_syntax("#type %s #is #protected #body\n", istr(tree_ident(t)));
1✔
1024
      dump_decls(t, indent + 2);
1✔
1025
      tab(indent);
1✔
1026
      print_syntax("#end #protected #body;\n");
1✔
1027
      return;
1✔
1028

1029
   case T_FILE_DECL:
×
1030
      print_syntax("#file %s : ", istr(tree_ident(t)));
×
1031
      dump_type(tree_type(t));
×
1032
      if (tree_has_value(t)) {
×
1033
         print_syntax(" #open ");
×
1034
         dump_expr(tree_file_mode(t));
×
1035
         print_syntax(" #is ");
×
1036
         dump_expr(tree_value(t));
×
1037
      }
1038
      print_syntax(";\n");
×
1039
      return;
×
1040

1041
   case T_USE:
×
1042
      dump_use(t);
×
1043
      return;
×
1044

1045
   case T_PACKAGE:
×
1046
   case T_PACK_INST:
1047
      dump_package(t, indent);
×
1048
      return;
×
1049

1050
   case T_PACK_BODY:
×
1051
      dump_package_body(t, indent);
×
1052
      return;
×
1053

1054
   case T_PSL_DECL:
1✔
1055
   case T_PSL_DIRECT:
1056
      dump_psl(t, 0);
1✔
1057
      print_syntax(";\n");
1✔
1058
      return;
1✔
1059

1060
   case T_VIEW_DECL:
1✔
1061
      dump_view_decl(t, 0);
1✔
1062
      return;
1✔
1063

1064
   case T_VERILOG:
×
1065
      vlog_dump(tree_vlog(t), indent);
×
1066
      return;
×
1067

1068
   default:
×
1069
      cannot_dump(t, "decl");
×
1070
   }
1071

1072
   dump_type(tree_type(t));
14✔
1073

1074
   if (tree_kind(t) != T_FIELD_DECL && tree_has_value(t)) {
14✔
1075
      print_syntax(" := ");
6✔
1076
      dump_expr(tree_value(t));
6✔
1077
   }
1078
   print_syntax(";\n");
14✔
1079
}
1080

1081
static void dump_waveforms(tree_t t)
3✔
1082
{
1083
   const int nwaves = tree_waveforms(t);
3✔
1084
   for (int i = 0; i < nwaves; i++) {
7✔
1085
      if (i > 0) print_syntax(", ");
4✔
1086
      dump_waveform(tree_waveform(t, i));
4✔
1087
   }
1088
}
3✔
1089

1090
static void dump_alternative(tree_t t, int indent)
2✔
1091
{
1092
   tab(indent);
2✔
1093
   print_syntax("#when ");
2✔
1094

1095
   if (tree_has_ident(t))
2✔
1096
      print_syntax("%s: ", istr(tree_ident(t)));
×
1097

1098
   const int nchoices = tree_choices(t);
2✔
1099
   for (int i = 0; i < nchoices; i++) {
5✔
1100
      if (i > 0) print_syntax(" | ");
3✔
1101
      tree_t a = tree_choice(t, i);
3✔
1102
      if (tree_has_name(a))
3✔
1103
         dump_expr(tree_name(a));
1✔
1104
      else if (tree_ranges(a) > 0)
2✔
1105
         dump_range(tree_range(a, 0));
1✔
1106
      else
1107
         print_syntax("#others");
1✔
1108
   }
1109

1110
   print_syntax(" =>\n");
2✔
1111

1112
   if (tree_decls(t) > 0) {
2✔
1113
      dump_decls(t, indent + 4);
×
1114
      tab(indent + 2);
×
1115
      print_syntax("#begin\n");
×
1116
      dump_stmts(t, indent + 4);
×
1117
      tab(indent + 2);
×
1118
      print_syntax("#end;\n");
×
1119
   }
1120
   else
1121
      dump_stmts(t, indent + 2);
2✔
1122
}
2✔
1123

1124
static void dump_psl(tree_t t, int indent)
2✔
1125
{
1126
   if (standard() < STD_08)
2✔
1127
      print_syntax("-- psl ");
×
1128
   psl_dump(tree_psl(t));
2✔
1129
}
2✔
1130

1131
static void dump_instance(tree_t t, int indent)
1✔
1132
{
1133
   switch (tree_class(t)) {
1✔
1134
   case C_ENTITY:        print_syntax("#entity "); break;
×
1135
   case C_COMPONENT:     print_syntax("#component "); break;
1✔
1136
   case C_CONFIGURATION: print_syntax("#configuration "); break;
×
1137
   default: break;
1138
   }
1139

1140
   print_syntax("%s", istr(tree_ident2(t)));
1✔
1141

1142
   const int nparams = tree_params(t);
1✔
1143
   const int ngenmaps = tree_genmaps(t);
1✔
1144

1145
   if (tree_has_spec(t)) {
1✔
1146
      tree_t spec = tree_spec(t);
×
1147
      if (tree_has_value(spec)) {
×
1148
         tree_t bind = tree_value(spec);
×
1149
         LOCAL_TEXT_BUF tb = tb_new();
×
1150
         tb_cat(tb, istr(tree_ident(bind)));
×
1151
         if (tree_has_ident2(bind))
×
1152
            tb_printf(tb, "(%s)", istr(tree_ident2(bind)));
×
1153
         print_syntax("  -- bound to %s\n", tb_get(tb));
×
1154
      }
1155
   }
1156
   else if (nparams > 0 || ngenmaps > 0)
1✔
1157
      print_syntax("\n");
1✔
1158

1159
   dump_generic_map(t, indent + 2, nparams > 0 ? "\n" : "");
1✔
1160
   dump_port_map(t, indent + 2, "");
1✔
1161
   print_syntax(";\n");
1✔
1162
}
1✔
1163

1164
static void dump_stmt(tree_t t, int indent)
22✔
1165
{
1166
   const tree_kind_t kind = tree_kind(t);
25✔
1167
   if (kind == T_VERILOG) {
25✔
1168
      vlog_dump(tree_vlog(t), indent);
×
1169
      return;
×
1170
   }
1171

1172
   tab(indent);
25✔
1173

1174
   if (tree_has_ident(t)) {
25✔
1175
      const char *label = istr(tree_ident(t));
10✔
1176
#if !DUMP_GEN_NAMES
1177
      if (label[0] != '_')   // Skip generated labels
10✔
1178
#endif
1179
         print_syntax("%s: ", label);
6✔
1180
   }
1181

1182
   switch (tree_kind(t)) {
25✔
1183
   case T_PROCESS:
2✔
1184
      dump_address(t);
2✔
1185
      if (tree_flags(t) & TREE_F_POSTPONED)
2✔
1186
         print_syntax("#postponed ");
×
1187
      print_syntax("#process ");
2✔
1188
      if (tree_triggers(t) > 0) {
2✔
1189
         print_syntax("(");
2✔
1190
         for (unsigned i = 0; i < tree_triggers(t); i++) {
4✔
1191
            if (i > 0)
2✔
1192
               print_syntax(", ");
×
1193
            dump_expr(tree_trigger(t, i));
2✔
1194
         }
1195
         print_syntax(") ");
2✔
1196
      }
1197
      print_syntax("#is\n");
2✔
1198
      dump_decls(t, indent + 2);
2✔
1199
      tab(indent);
2✔
1200
      print_syntax("#begin\n");
2✔
1201
      dump_stmts(t, indent + 2);
2✔
1202
      tab(indent);
2✔
1203
      print_syntax("#end #process;\n");
2✔
1204
      return;
2✔
1205

1206
   case T_SIGNAL_ASSIGN:
2✔
1207
      dump_expr(tree_target(t));
2✔
1208
      print_syntax(" <= #reject ");
2✔
1209
      if (tree_has_reject(t))
2✔
1210
         dump_expr(tree_reject(t));
1✔
1211
      else
1212
         print_syntax("0 ps");
1✔
1213
      print_syntax(" #inertial ");
2✔
1214
      dump_waveforms(t);
2✔
1215
      break;
2✔
1216

1217
   case T_FORCE:
×
1218
      dump_expr(tree_target(t));
×
1219
      print_syntax(" <= #force ");
×
1220
      dump_expr(tree_value(t));
×
1221
      break;
×
1222

1223
   case T_RELEASE:
×
1224
      dump_expr(tree_target(t));
×
1225
      print_syntax(" <= #release");
×
1226
      break;
×
1227

1228
   case T_VAR_ASSIGN:
2✔
1229
      dump_expr(tree_target(t));
2✔
1230
      print_syntax(" := ");
2✔
1231
      dump_expr(tree_value(t));
2✔
1232
      break;
2✔
1233

1234
   case T_WAIT:
×
1235
      print_syntax("#wait");
×
1236
      if (tree_triggers(t) > 0) {
×
1237
         print_syntax(" #on ");
×
1238
         for (unsigned i = 0; i < tree_triggers(t); i++) {
×
1239
            if (i > 0)
×
1240
               print_syntax(", ");
×
1241
            dump_expr(tree_trigger(t, i));
×
1242
         }
1243
      }
1244
      if (tree_has_value(t)) {
×
1245
         print_syntax(" #until ");
×
1246
         dump_expr(tree_value(t));
×
1247
      }
1248
      if (tree_has_delay(t)) {
×
1249
         print_syntax(" #for ");
×
1250
         dump_expr(tree_delay(t));
×
1251
      }
1252
      print_syntax(";");
×
1253
      if (tree_flags(t) & TREE_F_STATIC_WAIT)
×
1254
         print_syntax("   -- static");
×
1255
      print_syntax("\n");
×
1256
      return;
×
1257

1258
   case T_BLOCK:
2✔
1259
      dump_address(t);
2✔
1260
      print_syntax("#block #is\n");
2✔
1261
      dump_generics(t, indent + 2, ";\n");
2✔
1262
      dump_generic_map(t, indent + 2, ";\n");
2✔
1263
      dump_ports(t, indent + 2);
2✔
1264
      dump_port_map(t, indent + 2, ";\n");
2✔
1265
      dump_block(t, indent);
2✔
1266
      tab(indent);
2✔
1267
      print_syntax("#end #block;\n");
2✔
1268
      return;
2✔
1269

1270
   case T_SEQUENCE:
×
1271
      print_syntax("#block #is\n");
×
1272
      dump_block(t, indent);
×
1273
      tab(indent);
×
1274
      print_syntax("#end #block;\n");
×
1275
      return;
×
1276

1277
   case T_ASSERT:
2✔
1278
      print_syntax("#assert ");
2✔
1279
      dump_expr(tree_value(t));
2✔
1280
      if (tree_has_message(t)) {
2✔
1281
         print_syntax(" #report ");
×
1282
         dump_expr(tree_message(t));
×
1283
      }
1284
      if (tree_has_severity(t)) {
2✔
1285
         print_syntax(" #severity ");
×
1286
         dump_expr(tree_severity(t));
×
1287
      }
1288
      break;
1289

1290
   case T_REPORT:
1✔
1291
      print_syntax("#report ");
1✔
1292
      dump_expr(tree_message(t));
1✔
1293
      if (tree_has_severity(t)) {
1✔
1294
         print_syntax(" #severity ");
×
1295
         dump_expr(tree_severity(t));
×
1296
      }
1297
      break;
1298

1299
   case T_WHILE:
×
1300
      print_syntax("#while ");
×
1301
      dump_expr(tree_value(t));
×
1302
      print_syntax(" ");
×
1303
      // Fall-through
1304
   case T_LOOP:
×
1305
      print_syntax("#loop\n");
×
1306
      dump_stmts(t, indent + 2);
×
1307
      tab(indent);
×
1308
      print_syntax("#end #loop");
×
1309
      break;
×
1310

1311
   case T_IF:
1312
      for (unsigned i = 0; i < tree_conds(t); i++) {
3✔
1313
         tree_t c = tree_cond(t, i);
2✔
1314
         if (tree_has_value(c)) {
2✔
1315
            if (i > 0)
1✔
1316
               tab(indent);
×
1317
            print_syntax(i > 0 ? "#elsif " : "#if ");
2✔
1318
            dump_expr(tree_value(c));
1✔
1319
            print_syntax(" #then\n");
1✔
1320
         }
1321
         else {
1322
            tab(indent);
1✔
1323
            print_syntax("#else\n");
1✔
1324
         }
1325
         dump_stmts(c, indent + 2);
2✔
1326
      }
1327
      tab(indent);
1✔
1328
      print_syntax("#end #if");
1✔
1329
      break;
1✔
1330

1331
   case T_EXIT:
×
1332
      print_syntax("#exit %s", istr(tree_ident2(t)));
×
1333
      if (tree_has_value(t)) {
×
1334
         print_syntax(" #when ");
×
1335
         dump_expr(tree_value(t));
×
1336
      }
1337
      break;
1338

1339
   case T_CASE:
1✔
1340
   case T_MATCH_CASE:
1341
      {
1342
         const char *suffix = tree_kind(t) == T_MATCH_CASE ? "?" : "";
1✔
1343
         print_syntax("#case%s ", suffix);
1✔
1344
         dump_expr(tree_value(t));
1✔
1345
         print_syntax(" #is\n");
1✔
1346
         const int nstmts = tree_stmts(t);
1✔
1347
         for (int i = 0; i < nstmts; i++)
3✔
1348
            dump_alternative(tree_stmt(t, i), indent + 2);
2✔
1349
         tab(indent);
1✔
1350
         print_syntax("#end #case%s", suffix);
1✔
1351
      }
1352
      break;
1✔
1353

1354
   case T_RETURN:
3✔
1355
      print_syntax("#return");
3✔
1356
      if (tree_has_value(t)) {
3✔
1357
         print_syntax(" ");
3✔
1358
         dump_expr(tree_value(t));
3✔
1359
      }
1360
      break;
1361

1362
   case T_COND_RETURN:
×
1363
      print_syntax("#return #when ");
×
1364
      dump_expr(tree_value(t));
×
1365
      break;
×
1366

1367
   case T_FOR:
×
1368
      print_syntax("#for %s #in ", istr(tree_ident(tree_decl(t, 0))));
×
1369
      dump_range(tree_range(t, 0));
×
1370
      print_syntax(" #loop\n");
×
1371
      dump_stmts(t, indent + 2);
×
1372
      tab(indent);
×
1373
      print_syntax("#end #for");
×
1374
      break;
×
1375

1376
   case T_PROT_PCALL:
×
1377
      dump_expr(tree_name(t));
×
1378
      print_syntax(".");
×
1379
      // Fall-through
1380
   case T_PCALL:
×
1381
      if (tree_has_ref(t)) {
×
1382
         tree_t decl = tree_ref(t);
×
1383
         dump_address(decl);
×
1384
         print_syntax("%s", istr(tree_ident(decl)));
×
1385
      }
1386
      else
1387
         print_syntax("%s", istr(tree_ident2(t)));
×
1388
      dump_params(t, tree_param, tree_params(t), NULL);
×
1389
      break;
×
1390

1391
   case T_FOR_GENERATE:
1✔
1392
      print_syntax("#for %s #in ", istr(tree_ident(tree_decl(t, 0))));
1✔
1393
      dump_range(tree_range(t, 0));
1✔
1394
      print_syntax(" #generate\n");
1✔
1395
      dump_decls(t, indent + 2);
1✔
1396
      tab(indent);
1✔
1397
      print_syntax("#begin\n");
1✔
1398
      dump_stmts(t, indent + 2);
1✔
1399
      tab(indent);
1✔
1400
      print_syntax("#end #generate");
1✔
1401
      break;
1✔
1402

1403
   case T_CASE_GENERATE:
×
1404
      {
1405
         print_syntax("#case ");
×
1406
         dump_expr(tree_value(t));
×
1407
         print_syntax(" #generate\n");
×
1408

1409
         const int nstmts = tree_stmts(t);
×
1410
         for (int i = 0; i < nstmts; i++)
×
1411
            dump_alternative(tree_stmt(t, i), indent + 2);
×
1412

1413
         print_syntax("#end #generate");
×
1414
         tab(indent);
×
1415
      }
1416
      break;
×
1417

1418
   case T_IF_GENERATE:
1419
      for (unsigned i = 0; i < tree_conds(t); i++) {
×
1420
         tree_t c = tree_cond(t, i);
×
1421
         if (tree_has_value(c)) {
×
1422
            if (i > 0)
×
1423
               tab(indent);
×
1424
            print_syntax(i > 0 ? "#elsif " : "#if ");
×
1425
            dump_expr(tree_value(c));
×
1426
            print_syntax(" #generate\n");
×
1427
         }
1428
         else {
1429
            tab(indent);
×
1430
            print_syntax("#else\n");
×
1431
         }
1432
         for (unsigned i = 0; i < tree_stmts(c); i++)
×
1433
            dump_stmt(tree_stmt(c, i), indent + 2);
×
1434
      }
1435
      tab(indent);
×
1436
      print_syntax("#end #generate");
×
1437
      break;
×
1438

1439
   case T_INSTANCE:
1✔
1440
      dump_instance(t, indent);
1✔
1441
      return;
1✔
1442

1443
   case T_NEXT:
×
1444
      print_syntax("#next");
×
1445
      if (tree_has_value(t)) {
×
1446
         print_syntax(" #when ");
×
1447
         dump_expr(tree_value(t));
×
1448
      }
1449
      break;
1450

1451
   case T_NULL:
2✔
1452
      print_syntax("#null");
2✔
1453
      break;
2✔
1454

1455
   case T_COND_ASSIGN:
1✔
1456
      dump_expr(tree_target(t));
1✔
1457
      print_syntax(" <= ");
1✔
1458
      if (tree_has_guard(t))
1✔
1459
         print_syntax("#guarded ");
×
1460
      for (int i = 0; i < tree_conds(t); i++) {
2✔
1461
         tree_t c = tree_cond(t, i);
1✔
1462
         dump_waveforms(tree_stmt(c, 0));
1✔
1463
         if (tree_has_value(c)) {
1✔
1464
            print_syntax(" #when ");
×
1465
            dump_expr(tree_value(c));
×
1466
         }
1467
      }
1468
      break;
1469

1470
   case T_SELECT:
×
1471
      print_syntax(" <= ");
×
1472
      if (tree_has_guard(t)) print_syntax("#guarded ");
×
1473
      nvc_printf("$red$/* TODO: T_SELECT */$$");
×
1474
      break;
×
1475

1476
   case T_CONCURRENT:
3✔
1477
      if (tree_flags(t) & TREE_F_POSTPONED)
3✔
1478
         print_syntax("#postponed ");
×
1479
      dump_stmt(tree_stmt(t, 0), 0);
3✔
1480
      return;
3✔
1481

1482
   case T_DUMMY_DRIVER:
×
1483
      print_syntax("-- dummy driver for ");
×
1484
      dump_expr(tree_target(t));
×
1485
      print_syntax("\n");
×
1486
      return;
×
1487

1488
   case T_PSL_DIRECT:
1✔
1489
      dump_psl(t, indent);
1✔
1490
      break;
1✔
1491

1492
   default:
×
1493
      cannot_dump(t, "stmt");
×
1494
   }
1495

1496
   print_syntax(";\n");
17✔
1497
}
1498

1499
static void dump_port(tree_t t, int indent)
103✔
1500
{
1501
   tab(indent);
103✔
1502
   dump_address(t);
103✔
1503

1504
   if (tree_flags(t) & TREE_F_PREDEFINED)
103✔
1505
      print_syntax("-- predefined ");
80✔
1506

1507
   const class_t class = tree_class(t);
103✔
1508
   print_syntax("#%s %s", class_str(class), istr(tree_ident(t)));
103✔
1509

1510
   const port_mode_t mode = tree_subkind(t);
103✔
1511

1512
   type_t type = get_type_or_null(t);
103✔
1513
   if (class == C_PACKAGE) {
103✔
1514
      print_syntax(" #is #new ");
×
1515
      dump_expr(tree_value(t));
×
1516
   }
1517
   else if (class == C_TYPE && type_kind(type) == T_GENERIC) {
103✔
1518
      print_syntax(" #is ");
10✔
1519

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

1571
      if (tree_has_value(t)) {
91✔
1572
         print_syntax(" := ");
81✔
1573
         dump_expr(tree_value(t));
81✔
1574
      }
1575
   }
1576
}
103✔
1577

1578
static void dump_context(tree_t t, int indent)
7✔
1579
{
1580
   const int nctx = tree_contexts(t);
7✔
1581
   for (int i = 0; i < nctx; i++) {
28✔
1582
      tree_t c = tree_context(t, i);
21✔
1583
      switch (tree_kind(c)) {
21✔
1584
      case T_LIBRARY:
14✔
1585
         switch (is_well_known(tree_ident(c))) {
14✔
1586
         case W_STD:
1587
         case W_WORK:
1588
            break;
1589
         default:
×
1590
            print_syntax("#library %s;\n", istr(tree_ident(c)));
×
1591
         }
1592
         break;
1593

1594
      case T_USE:
7✔
1595
         dump_use(c);
7✔
1596
         break;
7✔
1597

1598
      case T_CONTEXT_REF:
×
1599
         print_syntax("#context %s;\n", istr(tree_ident(t)));
×
1600
         break;
×
1601

1602
      default:
1603
         break;
1604
      }
1605

1606
      tab(indent);
21✔
1607
   }
1608

1609
   if (nctx > 0) {
7✔
1610
      print_syntax("\n");
7✔
1611
      tab(indent);
7✔
1612
   }
1613
}
7✔
1614

1615
static void dump_elab(tree_t t)
×
1616
{
1617
   dump_context(t, 0);
×
1618
   dump_address(t);
×
1619
   print_syntax("#entity %s #is\n#end #entity;\n\n", istr(tree_ident(t)));
×
1620
   print_syntax("#architecture #elab #of %s #is\n", istr(tree_ident(t)));
×
1621
   dump_decls(t, 2);
×
1622
   print_syntax("#begin\n");
×
1623
   for (unsigned i = 0; i < tree_stmts(t); i++)
×
1624
      dump_stmt(tree_stmt(t, i), 2);
×
1625
   print_syntax("#end #architecture;\n\n");
×
1626
}
×
1627

1628
static void dump_entity(tree_t t)
2✔
1629
{
1630
   dump_context(t, 0);
2✔
1631
   dump_address(t);
2✔
1632
   print_syntax("#entity %s #is\n", istr(tree_ident(t)));
2✔
1633
   dump_generics(t, 2, ";\n");
2✔
1634
   dump_ports(t, 2);
2✔
1635
   dump_decls(t, 2);
2✔
1636
   if (tree_stmts(t) > 0) {
2✔
1637
      print_syntax("#begin\n");
×
1638
      for (unsigned i = 0; i < tree_stmts(t); i++) {
×
1639
         dump_stmt(tree_stmt(t, i), 2);
×
1640
      }
1641
   }
1642
   print_syntax("#end #entity;\n\n");
2✔
1643
}
2✔
1644

1645
static void dump_decls(tree_t t, int indent)
19✔
1646
{
1647
   const int ndecls = tree_decls(t);
19✔
1648
   bool was_body = false;
19✔
1649
   for (unsigned i = 0; i < ndecls; i++) {
42✔
1650
      tree_t d = tree_decl(t, i);
23✔
1651
      tree_kind_t dkind = tree_kind(d);
23✔
1652
      const bool is_body = dkind == T_FUNC_BODY || dkind == T_PROT_BODY
46✔
1653
         || dkind == T_PROC_BODY;
23✔
1654
      if ((was_body && !is_body) || (is_body && i > 0))
23✔
1655
         print_syntax("\n");
5✔
1656
      was_body = is_body;
23✔
1657
      dump_decl(d, indent);
23✔
1658
   }
1659
}
19✔
1660

1661
static void dump_arch(tree_t t)
2✔
1662
{
1663
   dump_context(t, 0);
2✔
1664
   dump_address(t);
2✔
1665
   print_syntax("#architecture %s #of %s #is\n",
2✔
1666
                istr(tree_ident(t)), istr(tree_ident2(t)));
1667
   dump_decls(t, 2);
2✔
1668
   print_syntax("#begin\n");
2✔
1669
   dump_stmts(t, 2);
2✔
1670
   print_syntax("#end #architecture;\n\n");
2✔
1671
}
2✔
1672

1673
static void dump_package(tree_t t, int indent)
1✔
1674
{
1675
   dump_context(t, indent);
1✔
1676
   dump_address(t);
1✔
1677
   print_syntax("#package %s #is\n", istr(tree_ident(t)));
1✔
1678
   if (tree_kind(t) == T_PACK_INST && tree_has_ref(t)) {
1✔
1679
      tab(indent);
×
1680
      print_syntax("  -- Instantiated from %s\n", istr(tree_ident(tree_ref(t))));
×
1681
   }
1682
   dump_generics(t, indent + 2, ";\n");
1✔
1683
   dump_generic_map(t, indent + 2, ";\n");
1✔
1684
   dump_decls(t, indent + 2);
1✔
1685
   tab(indent);
1✔
1686
   print_syntax("#end #package;\n\n");
1✔
1687
}
1✔
1688

1689
static void dump_package_body(tree_t t, int indent)
2✔
1690
{
1691
   dump_context(t, indent);
2✔
1692
   dump_address(t);
2✔
1693
   print_syntax("#package #body %s #is\n", istr(tree_ident(t)));
2✔
1694
   dump_decls(t, indent + 2);
2✔
1695
   tab(indent);
2✔
1696
   print_syntax("#end #package #body;\n\n");
2✔
1697
}
2✔
1698

1699
static void dump_configuration(tree_t t)
×
1700
{
1701
   dump_address(t);
×
1702
   print_syntax("#configuration %s #of %s #is\n",
×
1703
          istr(tree_ident(t)), istr(tree_ident2(t)));
1704
   dump_decls(t, 2);
×
1705
   print_syntax("#end #configuration\n");
×
1706
}
×
1707

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

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

© 2026 Coveralls, Inc