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

nickg / nvc / 6599333226

21 Oct 2023 07:46PM UTC coverage: 90.886% (-0.004%) from 90.89%
6599333226

push

github

nickg
Create implicit aliases for predefined operators of a type

120 of 120 new or added lines in 5 files covered. (100.0%)

49594 of 54567 relevant lines covered (90.89%)

583373.64 hits per line

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

55.63
/src/dump.c
1
//
2
//  Copyright (C) 2011-2023  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-phase.h"
27

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

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

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

49
typedef tree_t (*get_fn_t)(tree_t, unsigned);
50

51
static void tab(int indent)
201✔
52
{
53
   print_syntax("%*s", indent, "");
201✔
54
}
201✔
55

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

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

76
static void dump_params(tree_t t, get_fn_t get, int n, const char *prefix)
13✔
77
{
78
   if (n > 0) {
13✔
79
      if (prefix != NULL) {
12✔
80
         print_syntax(prefix, "");
2✔
81
         print_syntax(" ");
2✔
82
      }
83
      print_syntax("(");
12✔
84
      for (int i = 0; i < n; i++) {
35✔
85
         if (i > 0)
23✔
86
            print_syntax(", ");
11✔
87
         dump_param((*get)(t, i));
23✔
88
      }
89
      print_syntax(")");
12✔
90
   }
91
}
13✔
92

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

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

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

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

141
   const int color = 16 + 36*r + 6*g + b;
142

143
   char *LOCAL fmt = xasprintf("$!#%d${%%p}$$", color);
144
   color_printf(fmt, t);
145
#endif
146
}
147

148
static void dump_waveform(tree_t w)
3✔
149
{
150
   if (tree_has_value(w))
3✔
151
      dump_expr(tree_value(w));
3✔
152
   else
153
      print_syntax("#null");
×
154

155
   if (tree_has_delay(w)) {
3✔
156
      print_syntax(" #after ");
3✔
157
      dump_expr(tree_delay(w));
3✔
158
   }
159
}
3✔
160

161
static void dump_expr(tree_t t)
162✔
162
{
163
   switch (tree_kind(t)) {
162✔
164
   case T_PROT_FCALL:
1✔
165
      dump_expr(tree_name(t));
1✔
166
      print_syntax(".");
1✔
167
      // Fall-through
168
   case T_FCALL:
10✔
169
      if (tree_has_ref(t)) {
10✔
170
         tree_t decl = tree_ref(t);
10✔
171
         dump_address(decl);
10✔
172
         print_syntax("%s", istr(tree_ident(decl)));
10✔
173
      }
174
      else
175
         print_syntax("%s", istr(tree_ident(t)));
×
176
      dump_params(t, tree_param, tree_params(t), NULL);
10✔
177
#if DUMP_STATICNESS
178
      if (tree_flags(t) & TREE_F_LOCALLY_STATIC)
179
         color_printf("$red$/* locally static */$$");
180
      else if (tree_flags(t) & TREE_F_GLOBALLY_STATIC)
181
         color_printf("$red$/* globally static */$$");
182
#endif
183
      break;
10✔
184

185
   case T_CONV_FUNC:
×
186
      if (tree_has_ref(t)) {
×
187
         tree_t decl = tree_ref(t);
×
188
         dump_address(decl);
×
189
         print_syntax("%s", istr(tree_ident(decl)));
×
190
      }
191
      else
192
         print_syntax("%s", istr(tree_ident(t)));
×
193
      print_syntax("(");
×
194
      dump_expr(tree_value(t));
×
195
      print_syntax(")");
×
196
      break;
×
197

198
   case T_LITERAL:
29✔
199
      switch (tree_subkind(t)) {
29✔
200
      case L_INT:
23✔
201
         print_syntax("%"PRIi64, tree_ival(t));
23✔
202
         break;
23✔
203
      case L_PHYSICAL:
4✔
204
         if (tree_has_ident(t))
4✔
205
            print_syntax("%"PRIi64" %s", tree_ival(t), istr(tree_ident(t)));
4✔
206
         else
207
            print_syntax("%"PRIi64, tree_ival(t));
×
208
         break;
209
      case L_REAL:
2✔
210
         print_syntax("%lf", tree_dval(t));
2✔
211
         break;
2✔
212
      case L_NULL:
×
213
         print_syntax("#null");
×
214
         break;
×
215
      default:
216
         assert(false);
×
217
      }
218
      break;
219

220
   case T_STRING:
1✔
221
      {
222
         print_syntax("\"");
1✔
223
         const int nchars = tree_chars(t);
1✔
224
         for (int i = 0; i < nchars; i++) {
7✔
225
            ident_t rune = tree_ident(tree_char(t, i));
6✔
226
            if (ident_char(rune, 0) == '\'')
6✔
227
               print_syntax("%c", ident_char(rune, 1));
6✔
228
            else
229
               print_syntax("\" & %s & \"", istr(rune));
×
230
         }
231
         print_syntax("\"");
1✔
232
      }
233
      break;
1✔
234

235
   case T_NEW:
×
236
      print_syntax("#new ");
×
237
      dump_expr(tree_value(t));
×
238
      break;
×
239

240
   case T_ALL:
×
241
      if (tree_has_value(t)) {
×
242
         dump_expr(tree_value(t));
×
243
         print_syntax(".#all");
×
244
      }
245
      else
246
         print_syntax("#all");
×
247
      break;
248

249
   case T_TYPE_REF:
1✔
250
      dump_type(tree_type(t));
1✔
251
      break;
1✔
252

253
   case T_AGGREGATE:
3✔
254
      print_syntax("(");
3✔
255
      for (unsigned i = 0; i < tree_assocs(t); i++) {
7✔
256
         if (i > 0)
4✔
257
            print_syntax(", ");
1✔
258
         tree_t a = tree_assoc(t, i);
4✔
259
         tree_t value = tree_value(a);
4✔
260
         switch (tree_subkind(a)) {
4✔
261
         case A_POS:
×
262
            dump_expr(value);
×
263
            break;
×
264
         case A_NAMED:
1✔
265
            dump_expr(tree_name(a));
1✔
266
            print_syntax(" => ");
1✔
267
            dump_expr(value);
1✔
268
            break;
1✔
269
         case A_OTHERS:
3✔
270
            print_syntax("#others => ");
3✔
271
            dump_expr(value);
3✔
272
            break;
3✔
273
         case A_RANGE:
×
274
            dump_range(tree_range(a, 0));
×
275
            print_syntax(" => ");
×
276
            dump_expr(value);
×
277
            break;
×
278
         default:
279
            assert(false);
×
280
         }
281
      }
282
      print_syntax(")");
3✔
283
      break;
3✔
284

285
   case T_REF:
37✔
286
      if (tree_has_ref(t)) {
37✔
287
         tree_t decl = tree_ref(t);
37✔
288
         dump_address(decl);
37✔
289
         print_syntax("%s", istr(tree_ident(decl)));
37✔
290
      }
291
      else
292
         print_syntax("%s", istr(tree_ident(t)));
×
293
      break;
294

295
   case T_ATTR_REF:
1✔
296
      dump_expr(tree_name(t));
1✔
297
      print_syntax("'%s", istr(tree_ident(t)));
1✔
298
      if (tree_params(t) > 0)
1✔
299
         dump_params(t, tree_param, tree_params(t), NULL);
×
300
      break;
301

302
   case T_EXTERNAL_NAME:
×
303
      {
304
         print_syntax("<< #%s ", class_str(tree_class(t)));
×
305
         const int nparts = tree_parts(t);
×
306
         for (int i = 0; i < nparts; i++) {
×
307
            tree_t part = tree_part(t, i);
×
308
            if (i > 0 || tree_subkind(part) == PE_SIMPLE)
×
309
               print_syntax(".");
×
310
            switch (tree_subkind(part)) {
×
311
            case PE_SIMPLE:
×
312
               print_syntax("%s", istr(tree_ident(part)));
×
313
               break;
×
314
            case PE_ABSOLUTE:
×
315
               print_syntax(".");
×
316
               break;
×
317
            case PE_CARET:
×
318
               print_syntax("^");
×
319
               break;
×
320
            }
321
         }
×
322
         print_syntax(" : ");
×
323
         dump_type(tree_type(t));
×
324
         print_syntax(" >>");
×
325
      }
326
      break;
×
327

328
   case T_ARRAY_REF:
1✔
329
      dump_expr(tree_value(t));
1✔
330
      dump_params(t, tree_param, tree_params(t), NULL);
1✔
331
      break;
1✔
332

333
   case T_ARRAY_SLICE:
×
334
      dump_expr(tree_value(t));
×
335
      print_syntax("(");
×
336
      dump_range(tree_range(t, 0));
×
337
      print_syntax(")");
×
338
      break;
×
339

340
   case T_RECORD_REF:
×
341
      dump_expr(tree_value(t));
×
342
      print_syntax(".%s", istr(tree_ident(t)));
×
343
      break;
×
344

345
   case T_TYPE_CONV:
×
346
      print_syntax("%s(", istr(type_ident(tree_type(t))));
×
347
      dump_expr(tree_value(t));
×
348
      print_syntax(")");
×
349
      break;
×
350

351
   case T_QUALIFIED:
×
352
      if (tree_has_value(t)) {
×
353
         print_syntax("%s'(", istr(type_ident(tree_type(t))));
×
354
         dump_expr(tree_value(t));
×
355
         print_syntax(")");
×
356
      }
357
      else
358
         dump_type(tree_type(t));
×
359
      break;
360

361
   case T_OPEN:
1✔
362
      print_syntax("#open");
1✔
363
      break;
1✔
364

365
   case T_BOX:
78✔
366
      print_syntax("<>");
78✔
367
      break;
78✔
368

369
   case T_WAVEFORM:
×
370
      dump_waveform(t);
×
371
      break;
×
372

373
   case T_PACKAGE_MAP:
×
374
      print_syntax("%s ", istr(tree_ident(t)));
×
375
      switch (tree_subkind(t)) {
×
376
      case PACKAGE_MAP_BOX:
×
377
         print_syntax("#generic #map (<>)");
×
378
         break;
×
379
      case PACKAGE_MAP_DEFAULT:
×
380
         print_syntax("#generic map (#default)");
×
381
         break;
×
382
      case PACKAGE_MAP_MATCHING:
×
383
         dump_params(t, tree_genmap, tree_genmaps(t), "#generic #map");
×
384
         break;
×
385
      }
386
      break;
387

388
   case T_COND_VALUE:
389
      for (int i = 0; i < tree_conds(t); i++) {
×
390
         tree_t c = tree_cond(t, i);
×
391
         if (i > 0)
×
392
            print_syntax(" #else ");
×
393
         if (tree_has_result(c))
×
394
            dump_expr(tree_result(c));
×
395
         else
396
            print_syntax("#unaffected");
×
397
         if (tree_has_value(c)) {
×
398
            print_syntax(" #when ");
×
399
            dump_expr(tree_value(c));
×
400
         }
401
      }
402
      break;
403

404
   default:
×
405
      cannot_dump(t, "expr");
×
406
   }
407

408
   dump_type_hint(t);
162✔
409
}
162✔
410

411
static void dump_record_elem_constraint(tree_t t)
×
412
{
413
   print_syntax("%s", istr(tree_ident(t)));
×
414

415
   type_t ftype = tree_type(t);
×
416
   const int ncon = type_constraints(ftype);
×
417
   for (int i = 0; i < ncon; i++)
×
418
      dump_constraint(type_constraint(ftype, i));
×
419

420
   dump_elem_constraints(ftype);
×
421
}
×
422

423
static void dump_constraint(tree_t t)
5✔
424
{
425
   const int nranges = tree_ranges(t);
5✔
426

427
   switch (tree_subkind(t)) {
5✔
428
   case C_RANGE:
1✔
429
      print_syntax(" #range ");
1✔
430
      dump_range(tree_range(t, 0));
1✔
431
      break;
1✔
432
   case C_INDEX:
4✔
433
      print_syntax("(");
4✔
434
      for (int i = 0; i < nranges; i++) {
8✔
435
         if (i > 0) print_syntax(", ");
4✔
436
         dump_range(tree_range(t, i));
4✔
437
      }
438
      print_syntax(")");
4✔
439
      break;
4✔
440
   case C_OPEN:
×
441
      print_syntax("(#open)");
×
442
      break;
×
443
   case C_RECORD:
×
444
      print_syntax("(");
×
445
      for (int i = 0; i < nranges; i++) {
×
446
         if (i > 0) print_syntax(", ");
×
447
         dump_record_elem_constraint(tree_range(t, i));
×
448
      }
449
      print_syntax(")");
×
450
      break;
×
451
   }
452
}
5✔
453

454
static void dump_elem_constraints(type_t type)
5✔
455
{
456
   if (type_is_array(type) && type_has_elem(type)) {
5✔
457
      type_t elem = type_elem(type);
×
458
      if (type_kind(elem) == T_SUBTYPE && !type_has_ident(elem)) {
×
459
         // Anonymous subtype created for element constraints
460
         assert(type_constraints(elem) == 1);
×
461
         dump_constraint(type_constraint(elem, 0));
×
462
         dump_elem_constraints(elem);
×
463
      }
464
   }
465
}
5✔
466

467
static void dump_type(type_t type)
111✔
468
{
469
   if (type_kind(type) == T_SUBTYPE && !type_has_ident(type)) {
111✔
470
      // Anonymous subtype
471
      print_syntax("%s", type_pp(type));
4✔
472
      if (type_ident(type) == type_ident(type_base(type))) {
4✔
473
         const int ncon = type_constraints(type);
4✔
474
         for (int i = 0; i < ncon; i++)
8✔
475
            dump_constraint(type_constraint(type, i));
4✔
476
      }
477
      dump_elem_constraints(type);
4✔
478
   }
479
   else if (type_is_none(type))
107✔
480
      print_syntax("/* error */");
×
481
   else
482
      print_syntax("%s", type_pp(type));
107✔
483
}
111✔
484

485
static void dump_arguments(tree_t t, int indent, const char *trailer)
6✔
486
{
487
   const int nports = tree_ports(t);
6✔
488
   if (nports > 0) {
6✔
489
      print_syntax(" (");
3✔
490
      if (nports > 1) {
3✔
491
         print_syntax("\n");
1✔
492
         for (int i = 0; i < nports; i++) {
3✔
493
            if (i > 0) print_syntax(";\n");
2✔
494
            dump_port(tree_port(t, i), indent + 4);
2✔
495
         }
496
      }
497
      else
498
         dump_port(tree_port(t, 0), 1);
2✔
499
      print_syntax(" )%s", trailer);
3✔
500
   }
501
}
6✔
502

503
static void dump_ports(tree_t t, int indent)
4✔
504
{
505
   const int nports = tree_ports(t);
4✔
506
   if (nports > 0) {
4✔
507
      tab(indent);
2✔
508
      print_syntax("#port (");
2✔
509
      if (nports > 1) {
2✔
510
         print_syntax("\n");
2✔
511
         for (unsigned i = 0; i < nports; i++) {
6✔
512
            if (i > 0) print_syntax(";\n");
4✔
513
            dump_port(tree_port(t, i), indent + 2);
4✔
514
         }
515
      }
516
      else
517
         dump_port(tree_port(t, 0), 1);
×
518
      print_syntax(" );\n");
2✔
519
   }
520
}
4✔
521

522
static void dump_generics(tree_t t, int indent, const char *trailer)
11✔
523
{
524
   const int ngenerics = tree_generics(t);
11✔
525
   if (ngenerics > 0) {
11✔
526
      tab(indent);
3✔
527
      print_syntax("#generic (");
3✔
528
      if (ngenerics > 1) {
3✔
529
         print_syntax("\n");
2✔
530
         for (int i = 0; i < ngenerics; i++) {
93✔
531
            tree_t g = tree_generic(t, i);
91✔
532
            dump_port(g, indent + 2);
91✔
533
            if (i + 1 == ngenerics && (tree_flags(g) & TREE_F_PREDEFINED)) {
91✔
534
               print_syntax(";\n");
2✔
535
               tab(indent - 1);
2✔
536
            }
537
            else if (i + 1 < ngenerics)
89✔
538
               print_syntax(";\n");
89✔
539
         }
540
      }
541
      else
542
         dump_port(tree_generic(t, 0), 1);
1✔
543
      print_syntax(" )%s", trailer);
3✔
544
   }
545
}
11✔
546

547
static void dump_port_map(tree_t t, int indent, const char *trailer)
2✔
548
{
549
   const int nparams = tree_params(t);
2✔
550
   if (nparams > 0) {
2✔
551
      tab(indent);
1✔
552
      dump_params(t, tree_param, nparams, "#port #map");
1✔
553
      print_syntax("%s", trailer);
1✔
554
   }
555
}
2✔
556

557
static void dump_generic_map(tree_t t, int indent, const char *trailer)
3✔
558
{
559
   const int ngenmaps = tree_genmaps(t);
3✔
560
   if (ngenmaps > 0) {
3✔
561
      tab(indent);
1✔
562
      dump_params(t, tree_genmap, ngenmaps, "#generic #map");
1✔
563
      print_syntax("%s", trailer);
1✔
564
   }
565
}
3✔
566

567
static void dump_binding(tree_t t, int indent)
×
568
{
569
   print_syntax("#use %s", istr(tree_ident(t)));
×
570
   if (tree_has_ident2(t))
×
571
      print_syntax("(%s)", istr(tree_ident2(t)));
×
572
   if (tree_genmaps(t) > 0 || tree_params(t) > 0)
×
573
      print_syntax("\n");
×
574
   dump_generic_map(t, indent + 2, tree_params(t) > 0 ? "\n" : "");
×
575
   dump_port_map(t, indent + 2, "");
×
576
   print_syntax(";\n");
×
577
}
×
578

579
static void dump_stmts(tree_t t, int indent)
10✔
580
{
581
   const int nstmts = tree_stmts(t);
10✔
582
   for (int i = 0; i < nstmts; i++) {
19✔
583
      tree_t s = tree_stmt(t, i);
9✔
584
      const tree_kind_t kind = tree_kind(s);
9✔
585
      const bool needs_newline =
18✔
586
         kind == T_BLOCK || kind == T_PROCESS || kind == T_INSTANCE;
9✔
587
      if (needs_newline && i > 0)
9✔
588
         print_syntax("\n");
×
589
      dump_stmt(s, indent);
9✔
590
   }
591
}
10✔
592

593
static void dump_block(tree_t t, int indent)
5✔
594
{
595
   dump_decls(t, indent + 2);
5✔
596
   tab(indent);
5✔
597
   print_syntax("#begin\n");
5✔
598
   dump_stmts(t, indent + 2);
5✔
599
}
5✔
600

601
static void dump_wait_level(tree_t t)
2✔
602
{
603
   const tree_flags_t flags = tree_flags(t);
2✔
604
   if (flags & TREE_F_NEVER_WAITS)
2✔
605
      print_syntax("   -- Never waits");
2✔
606
   else if (flags & TREE_F_HAS_WAIT)
×
607
      print_syntax("   -- Contains wait statement");
×
608
}
2✔
609

610
static void dump_type_decl(tree_t t, int indent)
2✔
611
{
612
   type_t type = tree_type(t);
2✔
613
   const type_kind_t kind = type_kind(type);
2✔
614

615
   print_syntax("#type %s", istr(tree_ident(t)));
2✔
616

617
   if (kind == T_INCOMPLETE) {
2✔
618
      print_syntax(";\n");
×
619
      return;
×
620
   }
621

622
   print_syntax(" #is ");
2✔
623

624
   if (type_is_integer(type) || type_is_real(type)) {
2✔
625
      print_syntax("#range ");
×
626
      dump_range(type_dim(type, 0));
×
627
   }
628
   else if (type_is_physical(type)) {
2✔
629
      print_syntax("#range ");
×
630
      dump_range(type_dim(type, 0));
×
631
      print_syntax("\n");
×
632
      tab(indent + 2);
×
633
      print_syntax("#units\n");
×
634
      {
635
         const int nunits = type_units(type);
×
636
         for (int i = 0; i < nunits; i++) {
×
637
            tree_t u = type_unit(type, i);
×
638
            tab(indent + 4);
×
639
            print_syntax("%s = ", istr(tree_ident(u)));
×
640
            dump_expr(tree_value(u));
×
641
            print_syntax(";\n");
×
642
         }
643
      }
644
      tab(indent + 2);
×
645
      print_syntax("#end #units");
×
646
   }
647
   else if (type_is_array(type)) {
2✔
648
      print_syntax("#array ");
1✔
649
      if (kind == T_ARRAY) {
1✔
650
         print_syntax("(");
1✔
651
         const int nindex = type_indexes(type);
1✔
652
         for (int i = 0; i < nindex; i++) {
2✔
653
            if (i > 0) print_syntax(", ");
1✔
654
            dump_type(type_index(type, i));
1✔
655
            print_syntax(" #range <>");
1✔
656
         }
657
         print_syntax(")");
1✔
658
      }
659
      else if (kind == T_SUBTYPE) {
×
660
         const int ncon = type_constraints(type);
×
661
         for (int i = 0; i < ncon; i++)
×
662
            dump_constraint(type_constraint(type, i));
×
663
      }
664
      else {
665
         print_syntax("(");
×
666
         const int ndims = type_dims(type);
×
667
         for (int i = 0; i < ndims; i++) {
×
668
            if (i > 0) print_syntax(", ");
×
669
            dump_range(type_dim(type, i));
×
670
         }
671
         print_syntax(")");
×
672
      }
673
      print_syntax(" #of ");
1✔
674
      dump_type(type_elem(type));
1✔
675
   }
676
   else if (type_is_record(type)) {
1✔
677
      print_syntax("#record\n");
1✔
678
      const int nfields = type_fields(type);
1✔
679
      for (int i = 0; i < nfields; i++)
3✔
680
         dump_decl(type_field(type, i), indent + 2);
2✔
681
      tab(indent);
1✔
682
      print_syntax("#end #record");
1✔
683
   }
684
   else if (kind == T_ENUM) {
×
685
      print_syntax("(");
×
686
      for (unsigned i = 0; i < type_enum_literals(type); i++) {
×
687
         if (i > 0) print_syntax(", ");
×
688
         print_syntax("%s", istr(tree_ident(type_enum_literal(type, i))));
×
689
      }
690
      print_syntax(")");
×
691
   }
692
   else if (kind == T_INCOMPLETE)
×
693
      ;
694
   else
695
      dump_type(type);
×
696

697
   print_syntax(";\n");
2✔
698
}
699

700
static void dump_subtype_decl(tree_t t, int indent)
701
{
702
   type_t type = tree_type(t);
703

704
   print_syntax("#subtype %s #is ", istr(tree_ident(t)));
705
   if (type_has_resolution(type)) {
706
      dump_expr(type_resolution(type));
707
      print_syntax(" ");
708
   }
709
   print_syntax("%s", type_pp(type_base(type)));
710

711
   const int ncon = type_constraints(type);
712
   for (int i = 0; i < ncon; i++)
713
      dump_constraint(type_constraint(type, i));
714

715
   dump_elem_constraints(type);
716

717
   print_syntax(";\n");
718
}
719

720
static void dump_component(tree_t t, int indent)
1✔
721
{
722
   print_syntax("#component %s #is\n", istr(tree_ident(t)));
1✔
723
   dump_generics(t, indent + 2, ";\n");
1✔
724
   dump_ports(t, indent + 2);
1✔
725
   print_syntax("#end #component;\n");
1✔
726
}
1✔
727

728
static void dump_use(tree_t t)
6✔
729
{
730
   print_syntax("#use %s", istr(tree_ident(t)));
6✔
731
   if (tree_has_ident2(t))
6✔
732
      print_syntax(".%s", istr(tree_ident2(t)));
6✔
733
   print_syntax(";\n");
6✔
734
}
6✔
735

736
static void dump_decl(tree_t t, int indent)
25✔
737
{
738
   tab(indent);
25✔
739
   if (tree_kind(t) != T_HIER) dump_address(t);
25✔
740

741
   switch (tree_kind(t)) {
25✔
742
   case T_IMPLICIT_SIGNAL:
×
743
      print_syntax("/* implicit */ ");
×
744
      // Fall-through
745
   case T_SIGNAL_DECL:
3✔
746
      print_syntax("#signal %s : ", istr(tree_ident(t)));
3✔
747
      break;
3✔
748

749
   case T_VAR_DECL:
3✔
750
      print_syntax("#variable %s : ", istr(tree_ident(t)));
3✔
751
      break;
3✔
752

753
   case T_CONST_DECL:
2✔
754
      print_syntax("#constant %s : ", istr(tree_ident(t)));
2✔
755
      break;
2✔
756

757
   case T_GENERIC_DECL:
1✔
758
      // Loop variable in for-generate statement
759
      print_syntax("/* loop variable */ %s : ", istr(tree_ident(t)));
1✔
760
      break;
1✔
761

762
   case T_FIELD_DECL:
2✔
763
      print_syntax("%s : ", istr(tree_ident(t)));
2✔
764
      break;
2✔
765

766
   case T_TYPE_DECL:
2✔
767
      dump_type_decl(t, indent);
2✔
768
      return;
2✔
769

770
   case T_SUBTYPE_DECL:
1✔
771
      dump_subtype_decl(t, indent);
1✔
772
      return;
1✔
773

774
   case T_SPEC:
×
775
      print_syntax("#for %s", istr(tree_ident(t)));
×
776
      if (tree_has_ref(t))
×
777
         print_syntax(" : %s", istr(tree_ident(tree_ref(t))));
×
778
      print_syntax("\n");
×
779
      tab(indent + 2);
×
780
      dump_binding(tree_value(t), indent + 2);
×
781
      dump_decls(t, indent + 2);
×
782
      tab(indent);
×
783
      print_syntax("#end #for;\n");
×
784
      return;
×
785

786
   case T_BLOCK_CONFIG:
×
787
      print_syntax("#for %s\n", istr(tree_ident(t)));
×
788
      dump_decls(t, indent + 2);
×
789
      tab(indent);
×
790
      print_syntax("#end #for;\n");
×
791
      return;
×
792

793
   case T_ENUM_LIT:
×
794
      print_syntax("%s", istr(tree_ident(t)));
×
795
      return;
×
796

797
   case T_ALIAS:
×
798
      if (tree_flags(t) & TREE_F_PREDEFINED)
×
799
         print_syntax("-- predefined ");
×
800
      print_syntax("#alias %s", istr(tree_ident(t)));
×
801
      if (tree_has_type(t)) {
×
802
         print_syntax(" : ");
×
803
         dump_type(tree_type(t));
×
804
      }
805
      print_syntax(" #is ");
×
806
      dump_expr(tree_value(t));
×
807
      print_syntax(";\n");
×
808
      return;
×
809

810
   case T_ATTR_SPEC:
1✔
811
      print_syntax("#attribute %s #of %s : #%s #is ", istr(tree_ident(t)),
1✔
812
             istr(tree_ident2(t)), class_str(tree_class(t)));
813
      dump_expr(tree_value(t));
1✔
814
      print_syntax(";\n");
1✔
815
      return;
1✔
816

817
   case T_ATTR_DECL:
1✔
818
      print_syntax("#attribute %s : ", istr(tree_ident(t)));
1✔
819
      dump_type(tree_type(t));
1✔
820
      print_syntax(";\n");
1✔
821
      return;
1✔
822

823
   case T_FUNC_DECL:
2✔
824
      if (tree_flags(t) & TREE_F_PREDEFINED)
2✔
825
         print_syntax("-- predefined %s\n", type_pp(tree_type(t)));
×
826
      else {
827
         print_syntax("#function %s", istr(tree_ident(t)));
2✔
828
         dump_generics(t, indent + 2, "");
2✔
829
         dump_arguments(t, indent, "");
2✔
830
         print_syntax(" #return ");
2✔
831
         dump_type(type_result(tree_type(t)));
2✔
832
         print_syntax(";\n");
2✔
833
         if (tree_has_ident2(t)) {
2✔
834
            tab(indent + 2);
2✔
835
            print_syntax("-- %s\n", istr(tree_ident2(t)));
2✔
836
         }
837
      }
838
      return;
839

840
   case T_FUNC_INST:
2✔
841
   case T_FUNC_BODY:
842
      print_syntax("#function %s", istr(tree_ident(t)));
2✔
843
      dump_type_hint(t);
2✔
844
      dump_generics(t, indent + 2, tree_ports(t) > 0 ? "\n" : "");
3✔
845
      if (tree_kind(t) == T_FUNC_INST)
2✔
846
         dump_generic_map(t, indent + 2, tree_ports(t) > 0 ? "\n" : "");
×
847
      dump_arguments(t, indent, "");
2✔
848
      print_syntax(" #return ");
2✔
849
      dump_type(type_result(tree_type(t)));
2✔
850
      print_syntax(" #is\n");
2✔
851
      if (tree_has_ident2(t)) {
2✔
852
         tab(indent + 2);
2✔
853
         print_syntax("-- %s\n", istr(tree_ident2(t)));
2✔
854
      }
855
      dump_block(t, indent);
2✔
856
      tab(indent);
2✔
857
      print_syntax("#end #function;\n");
2✔
858
      return;
2✔
859

860
   case T_PROC_DECL:
×
861
      if (tree_flags(t) & TREE_F_PREDEFINED)
×
862
         print_syntax("-- predefined %s\n", type_pp(tree_type(t)));
×
863
      else {
864
         print_syntax("#procedure %s", istr(tree_ident(t)));
×
865
         dump_generics(t, indent + 2, tree_ports(t) > 0 ? "\n" : "");
×
866
         dump_arguments(t, indent, "");
×
867
         print_syntax(";");
×
868
         dump_wait_level(t);
×
869
         print_syntax("\n");
×
870
         if (tree_has_ident2(t)) {
×
871
            tab(indent + 2);
×
872
            print_syntax("-- %s\n", istr(tree_ident2(t)));
×
873
         }
874
      }
875
      return;
876

877
   case T_PROC_INST:
2✔
878
   case T_PROC_BODY:
879
      print_syntax("#procedure %s", istr(tree_ident(t)));
2✔
880
      dump_type_hint(t);
2✔
881
      dump_generics(t, indent + 2, tree_ports(t) > 0 ? "\n" : "");
3✔
882
      if (tree_kind(t) == T_PROC_INST)
2✔
883
         dump_generic_map(t, indent + 2, tree_ports(t) > 0 ? "\n" : "");
×
884
      dump_arguments(t, indent, "");
2✔
885
      print_syntax(" #is");
2✔
886
      dump_wait_level(t);
2✔
887
      print_syntax("\n");
2✔
888
      if (tree_has_ident2(t)) {
2✔
889
         tab(indent + 2);
2✔
890
         print_syntax("-- %s\n", istr(tree_ident2(t)));
2✔
891
      }
892
      dump_block(t, indent);
2✔
893
      tab(indent);
2✔
894
      print_syntax("#end #procedure;\n");
2✔
895
      return;
2✔
896

897
   case T_HIER:
×
898
      {
899
         const char *kind = "Scope";
×
900
         switch (tree_subkind(t)) {
×
901
         case T_ARCH: kind = "Instance"; break;
×
902
         case T_IF_GENERATE: kind = "If generate"; break;
×
903
         case T_FOR_GENERATE: kind = "For generate"; break;
×
904
         case T_BLOCK: kind = "Block"; break;
×
905
         }
906
         print_syntax("-- %s %s\n", kind, istr(tree_ident2(t)));
×
907
      }
908
      return;
×
909

910
   case T_COMPONENT:
1✔
911
      dump_component(t, indent);
1✔
912
      return;
1✔
913

914
   case T_PROT_DECL:
1✔
915
      print_syntax("#type %s #is #protected\n", istr(tree_ident(t)));
1✔
916
      dump_decls(t, indent + 2);
1✔
917
      tab(indent);
1✔
918
      print_syntax("#end #protected;\n");
1✔
919
      return;
1✔
920

921
   case T_PROT_BODY:
1✔
922
      print_syntax("#type %s #is #protected #body\n", istr(tree_ident(t)));
1✔
923
      dump_decls(t, indent + 2);
1✔
924
      tab(indent);
1✔
925
      print_syntax("#end #protected #body;\n");
1✔
926
      return;
1✔
927

928
   case T_FILE_DECL:
×
929
      print_syntax("#file %s : ", istr(tree_ident(t)));
×
930
      dump_type(tree_type(t));
×
931
      if (tree_has_value(t)) {
×
932
         print_syntax(" #open ");
×
933
         dump_expr(tree_file_mode(t));
×
934
         print_syntax(" #is ");
×
935
         dump_expr(tree_value(t));
×
936
      }
937
      print_syntax(";\n");
×
938
      return;
×
939

940
   case T_USE:
×
941
      dump_use(t);
×
942
      return;
×
943

944
   case T_PACKAGE:
×
945
   case T_PACK_INST:
946
      dump_package(t, indent);
×
947
      return;
×
948

949
   case T_PACK_BODY:
×
950
      dump_package_body(t, indent);
×
951
      return;
×
952

953
   default:
×
954
      cannot_dump(t, "decl");
×
955
   }
956

957
   dump_type(tree_type(t));
11✔
958

959
   if (tree_kind(t) != T_FIELD_DECL && tree_has_value(t)) {
11✔
960
      print_syntax(" := ");
5✔
961
      dump_expr(tree_value(t));
5✔
962
   }
963
   print_syntax(";\n");
11✔
964
}
965

966
static void dump_waveforms(tree_t t)
2✔
967
{
968
   const int nwaves = tree_waveforms(t);
2✔
969
   for (int i = 0; i < nwaves; i++) {
5✔
970
      if (i > 0) print_syntax(", ");
3✔
971
      dump_waveform(tree_waveform(t, i));
3✔
972
   }
973
}
2✔
974

975
static void dump_alternative(tree_t t, int indent)
×
976
{
977
   tab(indent);
×
978
   print_syntax("#when ");
×
979
   if (tree_has_ident(t))
×
980
      print_syntax("%s: ", istr(tree_ident(t)));
×
981
   for (unsigned i = 0; i < tree_assocs(t); i++) {
×
982
      if (i > 0) print_syntax("| ");
×
983
      tree_t a = tree_assoc(t, i);
×
984
      switch (tree_subkind(a)) {
×
985
      case A_NAMED:
×
986
         dump_expr(tree_name(a));
×
987
         break;
×
988
      case A_OTHERS:
×
989
         print_syntax("#others");
×
990
         break;
×
991
      case A_RANGE:
×
992
         dump_range(tree_range(a, 0));
×
993
         break;
×
994
      }
995
   }
×
996
   print_syntax(" =>\n");
×
997
   if (tree_decls(t) > 0) {
×
998
      dump_decls(t, indent + 4);
×
999
      tab(indent + 2);
×
1000
      print_syntax("#begin\n");
×
1001
      dump_stmts(t, indent + 4);
×
1002
      tab(indent + 2);
×
1003
      print_syntax("#end;\n");
×
1004
   }
1005
   else
1006
      dump_stmts(t, indent + 2);
×
1007
}
×
1008

1009
static void dump_psl(tree_t t, int indent)
1010
{
1011
   if (standard() < STD_08)
1012
      print_syntax("-- psl ");
1013
   psl_dump(tree_psl(t));
1014
}
1015

1016
static void dump_instance(tree_t t, int indent)
1✔
1017
{
1018
   switch (tree_class(t)) {
1✔
1019
   case C_ENTITY:        print_syntax("#entity "); break;
×
1020
   case C_COMPONENT:     print_syntax("#component "); break;
1✔
1021
   case C_CONFIGURATION: print_syntax("#configuration "); break;
×
1022
   default: break;
1023
   }
1024

1025
   print_syntax("%s", istr(tree_ident2(t)));
1✔
1026

1027
   const int nparams = tree_params(t);
1✔
1028
   const int ngenmaps = tree_genmaps(t);
1✔
1029

1030
   if (tree_has_spec(t)) {
1✔
1031
      tree_t spec = tree_spec(t);
×
1032
      if (tree_has_value(spec)) {
×
1033
         tree_t bind = tree_value(spec);
×
1034
         LOCAL_TEXT_BUF tb = tb_new();
×
1035
         tb_cat(tb, istr(tree_ident(bind)));
×
1036
         if (tree_has_ident2(bind))
×
1037
            tb_printf(tb, "(%s)", istr(tree_ident2(bind)));
×
1038
         print_syntax("  -- bound to %s\n", tb_get(tb));
×
1039
      }
1040
   }
1041
   else if (nparams > 0 || ngenmaps > 0)
1✔
1042
      print_syntax("\n");
1✔
1043

1044
   dump_generic_map(t, indent + 2, nparams > 0 ? "\n" : "");
1✔
1045
   dump_port_map(t, indent + 2, "");
1✔
1046
   print_syntax(";\n");
1✔
1047
}
1✔
1048

1049
static void dump_stmt(tree_t t, int indent)
13✔
1050
{
1051
   tab(indent);
15✔
1052

1053
   if (tree_has_ident(t)) {
15✔
1054
      const char *label = istr(tree_ident(t));
6✔
1055
#if !DUMP_GEN_NAMES
1056
      if (label[0] != '_')   // Skip generated labels
6✔
1057
#endif
1058
         print_syntax("%s: ", label);
4✔
1059
   }
1060

1061
   switch (tree_kind(t)) {
15✔
1062
   case T_PROCESS:
1✔
1063
      dump_address(t);
1✔
1064
      if (tree_flags(t) & TREE_F_POSTPONED)
1✔
1065
         print_syntax("#postponed ");
×
1066
      print_syntax("#process ");
1✔
1067
      if (tree_triggers(t) > 0) {
1✔
1068
         print_syntax("(");
1✔
1069
         for (unsigned i = 0; i < tree_triggers(t); i++) {
2✔
1070
            if (i > 0)
1✔
1071
               print_syntax(", ");
×
1072
            dump_expr(tree_trigger(t, i));
1✔
1073
         }
1074
         print_syntax(") ");
1✔
1075
      }
1076
      print_syntax("#is\n");
1✔
1077
      dump_decls(t, indent + 2);
1✔
1078
      tab(indent);
1✔
1079
      print_syntax("#begin\n");
1✔
1080
      dump_stmts(t, indent + 2);
1✔
1081
      tab(indent);
1✔
1082
      print_syntax("#end #process;\n");
1✔
1083
      return;
1✔
1084

1085
   case T_SIGNAL_ASSIGN:
1✔
1086
      dump_expr(tree_target(t));
1✔
1087
      print_syntax(" <= #reject ");
1✔
1088
      if (tree_has_reject(t))
1✔
1089
         dump_expr(tree_reject(t));
1✔
1090
      else
1091
         print_syntax("0 ps");
×
1092
      print_syntax(" #inertial ");
1✔
1093
      dump_waveforms(t);
1✔
1094
      break;
1✔
1095

1096
   case T_FORCE:
×
1097
      dump_expr(tree_target(t));
×
1098
      print_syntax(" <= #force ");
×
1099
      dump_expr(tree_value(t));
×
1100
      break;
×
1101

1102
   case T_RELEASE:
×
1103
      dump_expr(tree_target(t));
×
1104
      print_syntax(" <= #release");
×
1105
      break;
×
1106

1107
   case T_VAR_ASSIGN:
2✔
1108
      dump_expr(tree_target(t));
2✔
1109
      print_syntax(" := ");
2✔
1110
      dump_expr(tree_value(t));
2✔
1111
      break;
2✔
1112

1113
   case T_WAIT:
×
1114
      print_syntax("#wait");
×
1115
      if (tree_triggers(t) > 0) {
×
1116
         print_syntax(" #on ");
×
1117
         for (unsigned i = 0; i < tree_triggers(t); i++) {
×
1118
            if (i > 0)
×
1119
               print_syntax(", ");
×
1120
            dump_expr(tree_trigger(t, i));
×
1121
         }
1122
      }
1123
      if (tree_has_value(t)) {
×
1124
         print_syntax(" #until ");
×
1125
         dump_expr(tree_value(t));
×
1126
      }
1127
      if (tree_has_delay(t)) {
×
1128
         print_syntax(" #for ");
×
1129
         dump_expr(tree_delay(t));
×
1130
      }
1131
      print_syntax(";");
×
1132
      if (tree_flags(t) & TREE_F_STATIC_WAIT)
×
1133
         print_syntax("   -- static");
×
1134
      print_syntax("\n");
×
1135
      return;
×
1136

1137
   case T_BLOCK:
1✔
1138
      dump_address(t);
1✔
1139
      print_syntax("#block #is\n");
1✔
1140
      dump_generics(t, indent + 2, ";\n");
1✔
1141
      dump_generic_map(t, indent + 2, ";\n");
1✔
1142
      dump_ports(t, indent + 2);
1✔
1143
      dump_port_map(t, indent + 2, ";\n");
1✔
1144
      dump_block(t, indent);
1✔
1145
      tab(indent);
1✔
1146
      print_syntax("#end #block;\n");
1✔
1147
      return;
1✔
1148

1149
   case T_SEQUENCE:
×
1150
      print_syntax("#block #is\n");
×
1151
      dump_block(t, indent);
×
1152
      tab(indent);
×
1153
      print_syntax("#end #block;\n");
×
1154
      return;
×
1155

1156
   case T_ASSERT:
1✔
1157
      if (tree_has_value(t)) {
1✔
1158
         print_syntax("#assert ");
1✔
1159
         dump_expr(tree_value(t));
1✔
1160
         print_syntax(" ");
1✔
1161
      }
1162
      if (tree_has_message(t)) {
1✔
1163
         print_syntax("#report ");
×
1164
         dump_expr(tree_message(t));
×
1165
         print_syntax(" ");
×
1166
      }
1167
      print_syntax("#severity ");
1✔
1168
      dump_expr(tree_severity(t));
1✔
1169
      break;
1✔
1170

1171
   case T_WHILE:
×
1172
      if (tree_has_value(t)) {
×
1173
         print_syntax("#while ");
×
1174
         dump_expr(tree_value(t));
×
1175
         print_syntax(" ");
×
1176
      }
1177
      print_syntax("#loop\n");
×
1178
      dump_stmts(t, indent + 2);
×
1179
      tab(indent);
×
1180
      print_syntax("#end #loop");
×
1181
      break;
×
1182

1183
   case T_IF:
1184
      for (unsigned i = 0; i < tree_conds(t); i++) {
3✔
1185
         tree_t c = tree_cond(t, i);
2✔
1186
         if (tree_has_value(c)) {
2✔
1187
            if (i > 0)
1✔
1188
               tab(indent);
×
1189
            print_syntax(i > 0 ? "#elsif " : "#if ");
2✔
1190
            dump_expr(tree_value(c));
1✔
1191
            print_syntax(" #then\n");
1✔
1192
         }
1193
         else {
1194
            tab(indent);
1✔
1195
            print_syntax("#else\n");
1✔
1196
         }
1197
         dump_stmts(c, indent + 2);
2✔
1198
      }
1199
      tab(indent);
1✔
1200
      print_syntax("#end #if");
1✔
1201
      break;
1✔
1202

1203
   case T_EXIT:
×
1204
      print_syntax("#exit %s", istr(tree_ident2(t)));
×
1205
      if (tree_has_value(t)) {
×
1206
         print_syntax(" #when ");
×
1207
         dump_expr(tree_value(t));
×
1208
      }
1209
      break;
1210

1211
   case T_CASE:
×
1212
   case T_MATCH_CASE:
1213
      {
1214
         const char *suffix = tree_kind(t) == T_MATCH_CASE ? "?" : "";
×
1215
         print_syntax("#case%s ", suffix);
×
1216
         dump_expr(tree_value(t));
×
1217
         print_syntax(" #is\n");
×
1218
         const int nstmts = tree_stmts(t);
×
1219
         for (int i = 0; i < nstmts; i++)
×
1220
            dump_alternative(tree_stmt(t, i), indent + 2);
×
1221
         tab(indent);
×
1222
         print_syntax("#end #case%s", suffix);
×
1223
      }
1224
      break;
×
1225

1226
   case T_RETURN:
3✔
1227
      print_syntax("#return");
3✔
1228
      if (tree_has_value(t)) {
3✔
1229
         print_syntax(" ");
3✔
1230
         dump_expr(tree_value(t));
3✔
1231
      }
1232
      break;
1233

1234
   case T_COND_RETURN:
×
1235
      print_syntax("#return #when ");
×
1236
      dump_expr(tree_value(t));
×
1237
      break;
×
1238

1239
   case T_FOR:
×
1240
      print_syntax("#for %s #in ", istr(tree_ident(tree_decl(t, 0))));
×
1241
      dump_range(tree_range(t, 0));
×
1242
      print_syntax(" #loop\n");
×
1243
      dump_stmts(t, indent + 2);
×
1244
      tab(indent);
×
1245
      print_syntax("#end #for");
×
1246
      break;
×
1247

1248
   case T_PROT_PCALL:
×
1249
      dump_expr(tree_name(t));
×
1250
      print_syntax(".");
×
1251
      // Fall-through
1252
   case T_PCALL:
×
1253
      if (tree_has_ref(t)) {
×
1254
         tree_t decl = tree_ref(t);
×
1255
         dump_address(decl);
×
1256
         print_syntax("%s", istr(tree_ident(decl)));
×
1257
      }
1258
      else
1259
         print_syntax("%s", istr(tree_ident(t)));
×
1260
      dump_params(t, tree_param, tree_params(t), NULL);
×
1261
      break;
×
1262

1263
   case T_FOR_GENERATE:
1✔
1264
      print_syntax("#for %s #in ", istr(tree_ident(tree_decl(t, 0))));
1✔
1265
      dump_range(tree_range(t, 0));
1✔
1266
      print_syntax(" #generate\n");
1✔
1267
      dump_decls(t, indent + 2);
1✔
1268
      tab(indent);
1✔
1269
      print_syntax("#begin\n");
1✔
1270
      dump_stmts(t, indent + 2);
1✔
1271
      tab(indent);
1✔
1272
      print_syntax("#end #generate");
1✔
1273
      break;
1✔
1274

1275
   case T_CASE_GENERATE:
×
1276
      print_syntax("#case ");
×
1277
      dump_expr(tree_value(t));
×
1278
      print_syntax(" #generate\n");
×
1279
      dump_stmts(t, indent + 2);
×
1280
      print_syntax("#end #generate");
×
1281
      break;
×
1282

1283
   case T_IF_GENERATE:
1284
      for (unsigned i = 0; i < tree_conds(t); i++) {
×
1285
         tree_t c = tree_cond(t, i);
×
1286
         if (tree_has_value(c)) {
×
1287
            if (i > 0)
×
1288
               tab(indent);
×
1289
            print_syntax(i > 0 ? "#elsif " : "#if ");
×
1290
            dump_expr(tree_value(c));
×
1291
            print_syntax(" #generate\n");
×
1292
         }
1293
         else {
1294
            tab(indent);
×
1295
            print_syntax("#else\n");
×
1296
         }
1297
         for (unsigned i = 0; i < tree_stmts(c); i++)
×
1298
            dump_stmt(tree_stmt(c, i), indent + 2);
×
1299
      }
1300
      tab(indent);
×
1301
      print_syntax("#end #generate");
×
1302
      break;
×
1303

1304
   case T_INSTANCE:
1✔
1305
      dump_instance(t, indent);
1✔
1306
      return;
1✔
1307

1308
   case T_NEXT:
×
1309
      print_syntax("#next");
×
1310
      if (tree_has_value(t)) {
×
1311
         print_syntax(" #when ");
×
1312
         dump_expr(tree_value(t));
×
1313
      }
1314
      break;
1315

1316
   case T_NULL:
×
1317
      print_syntax("#null");
×
1318
      break;
×
1319

1320
   case T_COND_ASSIGN:
1✔
1321
      dump_expr(tree_target(t));
1✔
1322
      print_syntax(" <= ");
1✔
1323
      for (int i = 0; i < tree_conds(t); i++) {
2✔
1324
         tree_t c = tree_cond(t, i);
1✔
1325
         dump_waveforms(tree_stmt(c, 0));
1✔
1326
         if (tree_has_value(c)) {
1✔
1327
            print_syntax(" #when ");
×
1328
            dump_expr(tree_value(c));
×
1329
         }
1330
      }
1331
      break;
1332

1333
   case T_SELECT:
×
1334
      print_syntax(" <= ");
×
1335
      if (tree_has_guard(t)) print_syntax("#guarded ");
×
1336
      color_printf("$red$/* TODO: T_SELECT */$$");
×
1337
      break;
×
1338

1339
   case T_CONCURRENT:
2✔
1340
      if (tree_flags(t) & TREE_F_POSTPONED)
2✔
1341
         print_syntax("#postponed ");
×
1342
      if (tree_has_guard(t))
2✔
1343
         print_syntax("#guarded ");
×
1344
      dump_stmt(tree_stmt(t, 0), 0);
2✔
1345
      return;
2✔
1346

1347
   case T_PSL:
×
1348
      dump_psl(t, 0);
×
1349
      break;
×
1350

1351
   case T_VERILOG:
×
1352
      print_syntax("#block #is\n");
×
1353
      dump_generic_map(t, indent + 2, ";\n");
×
1354
      dump_port_map(t, indent + 2, ";\n");
×
1355
      tab(indent);
×
1356
      print_syntax("#begin\n");
×
1357
      vlog_dump(tree_vlog(t), indent + 2);
×
1358
      tab(indent);
×
1359
      print_syntax("#end #block");
×
1360
      break;
×
1361

1362
   default:
×
1363
      cannot_dump(t, "stmt");
×
1364
   }
1365

1366
   print_syntax(";\n");
10✔
1367
}
1368

1369
static void dump_port(tree_t t, int indent)
100✔
1370
{
1371
   tab(indent);
100✔
1372
   dump_address(t);
100✔
1373

1374
   if (tree_flags(t) & TREE_F_PREDEFINED)
100✔
1375
      print_syntax("-- predefined ");
80✔
1376

1377
   const class_t class = tree_class(t);
100✔
1378
   print_syntax("#%s %s", class_str(class), istr(tree_ident(t)));
100✔
1379

1380
   type_t type = get_type_or_null(t);
100✔
1381
   if (class == C_PACKAGE) {
100✔
1382
      print_syntax(" #is #new ");
×
1383
      dump_expr(tree_value(t));
×
1384
   }
1385
   else if (class == C_TYPE && type_kind(type) == T_GENERIC) {
100✔
1386
      print_syntax(" #is ");
10✔
1387

1388
      switch (type_subkind(type)) {
10✔
1389
      case GTYPE_PRIVATE:
2✔
1390
         print_syntax("#private");
2✔
1391
         break;
2✔
1392
      case GTYPE_SCALAR:
1✔
1393
         print_syntax("<>");
1✔
1394
         break;
1✔
1395
      case GTYPE_DISCRETE:
1✔
1396
         print_syntax("(<>)");
1✔
1397
         break;
1✔
1398
      case GTYPE_INTEGER:
1✔
1399
         print_syntax("#range <>");
1✔
1400
         break;
1✔
1401
      case GTYPE_PHYSICAL:
1✔
1402
         print_syntax("#units <>");
1✔
1403
         break;
1✔
1404
      case GTYPE_FLOATING:
1✔
1405
         print_syntax("#range <> . <>");
1✔
1406
         break;
1✔
1407
      case GTYPE_ARRAY:
1✔
1408
         {
1409
            print_syntax("#array (");
1✔
1410
            const int nindex = type_indexes(type);
1✔
1411
            for (int i = 0; i < nindex; i++) {
2✔
1412
               if (i > 0) print_syntax(", ");
1✔
1413
               dump_type(type_index(type, i));
1✔
1414
               print_syntax(" #range <>");
1✔
1415
            }
1416
            print_syntax(") #of ");
1✔
1417
            dump_type(type_elem(type));
1✔
1418
         }
1419
         break;
1✔
1420
      case GTYPE_ACCESS:
1✔
1421
         print_syntax("#access ..");
1✔
1422
         break;
1✔
1423
      case GTYPE_FILE:
1✔
1424
         print_syntax("#file #of ..");
1✔
1425
         break;
1✔
1426
      }
1427
   }
1428
   else {
1429
      const char *dir = NULL;
90✔
1430
      switch (tree_subkind(t)) {
90✔
1431
      case PORT_IN:      dir = "in";     break;
86✔
1432
      case PORT_OUT:     dir = "out";    break;
4✔
1433
      case PORT_INOUT:   dir = "inout";  break;
×
1434
      case PORT_BUFFER:  dir = "buffer"; break;
×
1435
      case PORT_INVALID: dir = "??";     break;
×
1436
      }
1437
      print_syntax(" : #%s ", dir);
90✔
1438
      dump_type(type);
90✔
1439

1440
      if (tree_has_value(t)) {
90✔
1441
         print_syntax(" := ");
79✔
1442
         dump_expr(tree_value(t));
79✔
1443
      }
1444
   }
1445
}
100✔
1446

1447
static void dump_context(tree_t t, int indent)
6✔
1448
{
1449
   const int nctx = tree_contexts(t);
6✔
1450
   for (int i = 0; i < nctx; i++) {
24✔
1451
      tree_t c = tree_context(t, i);
18✔
1452
      switch (tree_kind(c)) {
18✔
1453
      case T_LIBRARY:
12✔
1454
         switch (is_well_known(tree_ident(c))) {
12✔
1455
         case W_STD:
1456
         case W_WORK:
1457
            break;
1458
         default:
×
1459
            print_syntax("#library %s;\n", istr(tree_ident(c)));
×
1460
         }
1461
         break;
1462

1463
      case T_USE:
6✔
1464
         dump_use(c);
6✔
1465
         break;
6✔
1466

1467
      case T_CONTEXT_REF:
×
1468
         print_syntax("#context %s;\n", istr(tree_ident(t)));
×
1469
         break;
×
1470

1471
      default:
1472
         break;
1473
      }
1474

1475
      tab(indent);
18✔
1476
   }
1477

1478
   if (nctx > 0) {
6✔
1479
      print_syntax("\n");
6✔
1480
      tab(indent);
6✔
1481
   }
1482
}
6✔
1483

1484
static void dump_elab(tree_t t)
×
1485
{
1486
   dump_context(t, 0);
×
1487
   dump_address(t);
×
1488
   print_syntax("#entity %s #is\n#end #entity;\n\n", istr(tree_ident(t)));
×
1489
   print_syntax("#architecture #elab #of %s #is\n", istr(tree_ident(t)));
×
1490
   dump_decls(t, 2);
×
1491
   print_syntax("#begin\n");
×
1492
   for (unsigned i = 0; i < tree_stmts(t); i++)
×
1493
      dump_stmt(tree_stmt(t, i), 2);
×
1494
   print_syntax("#end #architecture;\n\n");
×
1495
}
×
1496

1497
static void dump_entity(tree_t t)
2✔
1498
{
1499
   dump_context(t, 0);
2✔
1500
   dump_address(t);
2✔
1501
   print_syntax("#entity %s #is\n", istr(tree_ident(t)));
2✔
1502
   dump_generics(t, 2, ";\n");
2✔
1503
   dump_ports(t, 2);
2✔
1504
   dump_decls(t, 2);
2✔
1505
   if (tree_stmts(t) > 0) {
2✔
1506
      print_syntax("#begin\n");
×
1507
      for (unsigned i = 0; i < tree_stmts(t); i++) {
×
1508
         dump_stmt(tree_stmt(t, i), 2);
×
1509
      }
1510
   }
1511
   print_syntax("#end #entity;\n\n");
2✔
1512
}
2✔
1513

1514
static void dump_decls(tree_t t, int indent)
15✔
1515
{
1516
   const int ndecls = tree_decls(t);
15✔
1517
   bool was_body = false;
15✔
1518
   for (unsigned i = 0; i < ndecls; i++) {
30✔
1519
      tree_t d = tree_decl(t, i);
15✔
1520
      tree_kind_t dkind = tree_kind(d);
15✔
1521
      const bool is_body = dkind == T_FUNC_BODY || dkind == T_PROT_BODY
30✔
1522
         || dkind == T_PROC_BODY;
15✔
1523
      if ((was_body && !is_body) || (is_body && i > 0))
15✔
1524
         print_syntax("\n");
4✔
1525
      was_body = is_body;
15✔
1526
      dump_decl(d, indent);
15✔
1527
   }
1528
}
15✔
1529

1530
static void dump_arch(tree_t t)
1✔
1531
{
1532
   dump_context(t, 0);
1✔
1533
   dump_address(t);
1✔
1534
   print_syntax("#architecture %s #of %s #is\n",
1✔
1535
                istr(tree_ident(t)), istr(tree_ident2(t)));
1536
   dump_decls(t, 2);
1✔
1537
   print_syntax("#begin\n");
1✔
1538
   dump_stmts(t, 2);
1✔
1539
   print_syntax("#end #architecture;\n\n");
1✔
1540
}
1✔
1541

1542
static void dump_package(tree_t t, int indent)
1✔
1543
{
1544
   dump_context(t, indent);
1✔
1545
   dump_address(t);
1✔
1546
   print_syntax("#package %s #is\n", istr(tree_ident(t)));
1✔
1547
   if (tree_kind(t) == T_PACK_INST && tree_has_ref(t)) {
1✔
1548
      tab(indent);
×
1549
      print_syntax("  -- Instantiated from %s\n", istr(tree_ident(tree_ref(t))));
×
1550
   }
1551
   dump_generics(t, indent + 2, ";\n");
1✔
1552
   dump_generic_map(t, indent + 2, ";\n");
1✔
1553
   dump_decls(t, indent + 2);
1✔
1554
   tab(indent);
1✔
1555
   print_syntax("#end #package;\n\n");
1✔
1556
}
1✔
1557

1558
static void dump_package_body(tree_t t, int indent)
2✔
1559
{
1560
   dump_context(t, indent);
2✔
1561
   dump_address(t);
2✔
1562
   print_syntax("#package #body %s #is\n", istr(tree_ident(t)));
2✔
1563
   dump_decls(t, indent + 2);
2✔
1564
   tab(indent);
2✔
1565
   print_syntax("#end #package #body;\n\n");
2✔
1566
}
2✔
1567

1568
static void dump_configuration(tree_t t)
×
1569
{
1570
   dump_address(t);
×
1571
   print_syntax("#configuration %s #of %s #is\n",
×
1572
          istr(tree_ident(t)), istr(tree_ident2(t)));
1573
   dump_decls(t, 2);
×
1574
   print_syntax("#end #configuration\n");
×
1575
}
×
1576

1577
void vhdl_dump(tree_t t, int indent)
29✔
1578
{
1579
   switch (tree_kind(t)) {
29✔
1580
   case T_ELAB:
×
1581
      dump_elab(t);
×
1582
      break;
×
1583
   case T_ENTITY:
2✔
1584
      dump_entity(t);
2✔
1585
      break;
2✔
1586
   case T_ARCH:
1✔
1587
      dump_arch(t);
1✔
1588
      break;
1✔
1589
   case T_PACKAGE:
1✔
1590
   case T_PACK_INST:
1591
      dump_package(t, indent);
1✔
1592
      break;
1✔
1593
   case T_PACK_BODY:
2✔
1594
      dump_package_body(t, indent);
2✔
1595
      break;
2✔
1596
   case T_CONFIGURATION:
×
1597
      dump_configuration(t);
×
1598
      break;
×
1599
   case T_REF:
10✔
1600
   case T_FCALL:
1601
   case T_PROT_FCALL:
1602
   case T_LITERAL:
1603
   case T_AGGREGATE:
1604
   case T_ARRAY_REF:
1605
   case T_ARRAY_SLICE:
1606
   case T_TYPE_CONV:
1607
   case T_RECORD_REF:
1608
   case T_ATTR_REF:
1609
   case T_CONV_FUNC:
1610
   case T_QUALIFIED:
1611
   case T_EXTERNAL_NAME:
1612
   case T_STRING:
1613
   case T_PACKAGE_MAP:
1614
      dump_expr(t);
10✔
1615
      break;
10✔
1616
   case T_INSTANCE:
4✔
1617
   case T_FOR_GENERATE:
1618
   case T_CASE_GENERATE:
1619
   case T_BLOCK:
1620
   case T_PROCESS:
1621
   case T_CASE:
1622
   case T_FOR:
1623
   case T_SIGNAL_ASSIGN:
1624
   case T_IF:
1625
   case T_WAIT:
1626
   case T_PSL:
1627
   case T_VAR_ASSIGN:
1628
   case T_RETURN:
1629
      dump_stmt(t, indent);
4✔
1630
      break;
4✔
1631
   case T_CONST_DECL:
8✔
1632
   case T_VAR_DECL:
1633
   case T_SIGNAL_DECL:
1634
   case T_TYPE_DECL:
1635
   case T_FIELD_DECL:
1636
   case T_FUNC_DECL:
1637
   case T_PROC_BODY:
1638
   case T_FUNC_BODY:
1639
   case T_PROC_DECL:
1640
   case T_ATTR_DECL:
1641
   case T_ATTR_SPEC:
1642
   case T_ENUM_LIT:
1643
   case T_COMPONENT:
1644
   case T_BLOCK_CONFIG:
1645
   case T_SPEC:
1646
   case T_ALIAS:
1647
   case T_FUNC_INST:
1648
   case T_PROC_INST:
1649
   case T_SUBTYPE_DECL:
1650
      dump_decl(t, indent);
8✔
1651
      break;
8✔
1652
   case T_PORT_DECL:
×
1653
   case T_GENERIC_DECL:
1654
      dump_port(t, indent);
×
1655
      break;
×
1656
   case T_RANGE:
1✔
1657
      dump_range(t);
1✔
1658
      break;
1✔
1659
   case T_BINDING:
×
1660
      dump_binding(t, indent);
×
1661
      break;
×
1662
   case T_PARAM:
×
1663
      dump_param(t);
×
1664
      break;
×
1665
   case T_CONSTRAINT:
×
1666
      dump_constraint(t);
×
1667
      break;
×
1668
   case T_ELEM_CONSTRAINT:
×
1669
      dump_record_elem_constraint(t);
×
1670
      break;
×
1671
   case T_ALTERNATIVE:
×
1672
      dump_alternative(t, indent);
×
1673
      break;
×
1674
   default:
×
1675
      cannot_dump(t, "tree");
×
1676
   }
1677
}
29✔
1678

1679
void dump(tree_t t)
18✔
1680
{
1681
   vhdl_dump(t, 0);
18✔
1682
   print_syntax("\r");
18✔
1683
}
18✔
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