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

nickg / nvc / 18355434486

08 Oct 2025 07:12PM UTC coverage: 92.707% (-0.06%) from 92.769%
18355434486

Pull #1319

github

web-flow
Merge 2b4943c60 into c5bc22845
Pull Request #1319: Partial support of PSL next_a

26 of 84 new or added lines in 3 files covered. (30.95%)

221 existing lines in 2 files now uncovered.

75062 of 80967 relevant lines covered (92.71%)

574372.1 hits per line

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

59.15
/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

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

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

441
   dump_type_hint(t);
201✔
442
}
443

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

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

452
   dump_elem_constraints(ftype);
×
453
}
×
454

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

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

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

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

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

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

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

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

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

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

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

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

627
      if (needs_newline && i > 0 && !last_was_newline)
12✔
628
         print_syntax("\n");
×
629

630
      dump_stmt(s, indent);
12✔
631

632
      if (needs_newline && i + 1 < nstmts) {
12✔
633
         print_syntax("\n");
×
634
         last_was_newline = true;
×
635
      }
636
      else
637
         last_was_newline = false;
638
   }
639
}
13✔
640

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

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

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

663
   print_syntax("#type %s", istr(tree_ident(t)));
2✔
664

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

670
   print_syntax(" #is ");
2✔
671

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

744
   print_syntax(";\n");
2✔
745
}
746

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

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

758
   if (type_has_constraint(type))
1✔
759
      dump_constraint(type_constraint(type));
1✔
760

761
   dump_elem_constraints(type);
1✔
762

763
   print_syntax(";\n");
1✔
764
}
1✔
765

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

855
   case T_TYPE_DECL:
2✔
856
      dump_type_decl(t, indent);
2✔
857
      return;
2✔
858

859
   case T_SUBTYPE_DECL:
1✔
860
      dump_subtype_decl(t, indent);
1✔
861
      return;
1✔
862

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

878
   case T_BLOCK_CONFIG:
×
879
      print_syntax("#for %s\n", istr(tree_ident(t)));
×
880
      dump_decls(t, indent + 2);
×
881
      tab(indent);
×
882
      print_syntax("#end #for;\n");
×
883
      return;
×
884

885
   case T_ENUM_LIT:
×
886
      print_syntax("%s", istr(tree_ident(t)));
×
887
      return;
×
888

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

902
   case T_ATTR_SPEC:
4✔
903
      dump_attr_spec(t);
4✔
904
      return;
4✔
905

906
   case T_ATTR_DECL:
2✔
907
      print_syntax("#attribute %s : ", istr(tree_ident(t)));
2✔
908
      dump_type(tree_type(t));
2✔
909
      print_syntax(";\n");
2✔
910
      return;
2✔
911

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

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

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

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

986
   case T_HIER:
×
987
      {
988
         const char *kind = "Scope";
×
989
         switch (tree_subkind(t)) {
×
990
         case T_ARCH: kind = "Instance"; break;
×
991
         case T_IF_GENERATE: kind = "If generate"; break;
×
992
         case T_FOR_GENERATE: kind = "For generate"; break;
×
993
         case T_BLOCK: kind = "Block"; break;
×
994
         }
995
         print_syntax("-- %s %s\n", kind, istr(tree_ident2(t)));
×
996
      }
997
      return;
×
998

999
   case T_COMPONENT:
1✔
1000
      dump_component(t, indent);
1✔
1001
      return;
1✔
1002

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

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

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

1029
   case T_USE:
×
1030
      dump_use(t);
×
1031
      return;
×
1032

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

1038
   case T_PACK_BODY:
×
1039
      dump_package_body(t, indent);
×
1040
      return;
×
1041

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

1048
   case T_VIEW_DECL:
1✔
1049
      dump_view_decl(t, 0);
1✔
1050
      return;
1✔
1051

1052
   case T_VERILOG:
×
1053
      vlog_dump(tree_vlog(t), indent);
×
1054
      return;
×
1055

1056
   default:
×
1057
      cannot_dump(t, "decl");
×
1058
   }
1059

1060
   dump_type(tree_type(t));
14✔
1061

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

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

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

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

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

1128
   print_syntax("%s", istr(tree_ident2(t)));
1✔
1129

1130
   const int nparams = tree_params(t);
1✔
1131
   const int ngenmaps = tree_genmaps(t);
1✔
1132

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

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

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

1160
   tab(indent);
21✔
1161

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1427
   case T_INSTANCE:
1✔
1428
      dump_instance(t, indent);
1✔
1429
      return;
1✔
1430

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

1439
   case T_NULL:
×
1440
      print_syntax("#null");
×
1441
      break;
×
1442

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

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

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

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

1476
   case T_PSL_DIRECT:
1✔
1477
      dump_psl(t, indent);
1✔
1478
      break;
1✔
1479

1480
   default:
×
1481
      cannot_dump(t, "stmt");
×
1482
   }
1483

1484
   print_syntax(";\n");
14✔
1485
}
1486

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

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

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

1498
   const port_mode_t mode = tree_subkind(t);
103✔
1499

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

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

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

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

1582
      case T_USE:
7✔
1583
         dump_use(c);
7✔
1584
         break;
7✔
1585

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

1590
      default:
1591
         break;
1592
      }
1593

1594
      tab(indent);
21✔
1595
   }
1596

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

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

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

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

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

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

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

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

1696
void vhdl_dump(tree_t t, int indent)
48✔
1697
{
1698
   switch (tree_kind(t)) {
48✔
1699
   case T_ELAB:
×
1700
      dump_elab(t);
×
1701
      break;
×
1702
   case T_ENTITY:
2✔
1703
      dump_entity(t);
2✔
1704
      break;
2✔
1705
   case T_ARCH:
2✔
1706
      dump_arch(t);
2✔
1707
      break;
2✔
1708
   case T_PACKAGE:
1✔
1709
   case T_PACK_INST:
1710
      dump_package(t, indent);
1✔
1711
      break;
1✔
1712
   case T_PACK_BODY:
2✔
1713
      dump_package_body(t, indent);
2✔
1714
      break;
2✔
1715
   case T_CONFIGURATION:
×
1716
      dump_configuration(t);
×
1717
      break;
×
1718
   case T_REF:
25✔
1719
   case T_FCALL:
1720
   case T_PROT_FCALL:
1721
   case T_LITERAL:
1722
   case T_AGGREGATE:
1723
   case T_ARRAY_REF:
1724
   case T_ARRAY_SLICE:
1725
   case T_TYPE_CONV:
1726
   case T_RECORD_REF:
1727
   case T_ATTR_REF:
1728
   case T_CONV_FUNC:
1729
   case T_QUALIFIED:
1730
   case T_EXTERNAL_NAME:
1731
   case T_STRING:
1732
   case T_PACKAGE_MAP:
1733
   case T_TYPE_REF:
1734
   case T_PSL_FCALL:
1735
   case T_PSL_UNION:
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