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

nickg / nvc / 6916114419

18 Nov 2023 08:26PM UTC coverage: 91.225% (+0.04%) from 91.187%
6916114419

push

github

nickg
Add basic support for PSL cover directives

Issue #795

107 of 120 new or added lines in 10 files covered. (89.17%)

4 existing lines in 3 files now uncovered.

50609 of 55477 relevant lines covered (91.23%)

609275.9 hits per line

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

57.49
/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
static void dump_psl(tree_t t, int indent);
49

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

210
   case T_CONV_FUNC:
×
211
      if (tree_has_ref(t)) {
×
212
         tree_t decl = tree_ref(t);
×
213
         dump_address(decl);
×
214
         print_syntax("%s", istr(tree_ident(decl)));
×
215
      }
216
      else
217
         print_syntax("%s", istr(tree_ident(t)));
×
218
      print_syntax("(");
×
219
      dump_expr(tree_value(t));
×
220
      print_syntax(")");
×
221
      break;
×
222

223
   case T_LITERAL:
30✔
224
      switch (tree_subkind(t)) {
30✔
225
      case L_INT:
24✔
226
         print_syntax("%"PRIi64, tree_ival(t));
24✔
227
         break;
24✔
228
      case L_PHYSICAL:
4✔
229
         if (tree_has_ident(t))
4✔
230
            print_syntax("%"PRIi64" %s", tree_ival(t), istr(tree_ident(t)));
4✔
231
         else
232
            print_syntax("%"PRIi64, tree_ival(t));
×
233
         break;
234
      case L_REAL:
2✔
235
         print_syntax("%lf", tree_dval(t));
2✔
236
         break;
2✔
237
      case L_NULL:
×
238
         print_syntax("#null");
×
239
         break;
×
240
      default:
241
         assert(false);
×
242
      }
243
      break;
244

245
   case T_STRING:
2✔
246
      {
247
         print_syntax("\"");
2✔
248
         const int nchars = tree_chars(t);
2✔
249
         for (int i = 0; i < nchars; i++) {
11✔
250
            ident_t rune = tree_ident(tree_char(t, i));
9✔
251
            if (ident_char(rune, 0) == '\'')
9✔
252
               print_syntax("%c", ident_char(rune, 1));
9✔
253
            else
254
               print_syntax("\" & %s & \"", istr(rune));
×
255
         }
256
         print_syntax("\"");
2✔
257
      }
258
      break;
2✔
259

260
   case T_NEW:
×
261
      print_syntax("#new ");
×
262
      dump_expr(tree_value(t));
×
263
      break;
×
264

265
   case T_ALL:
×
266
      if (tree_has_value(t)) {
×
267
         dump_expr(tree_value(t));
×
268
         print_syntax(".#all");
×
269
      }
270
      else
271
         print_syntax("#all");
×
272
      break;
273

274
   case T_TYPE_REF:
1✔
275
      dump_type(tree_type(t));
1✔
276
      break;
1✔
277

278
   case T_AGGREGATE:
3✔
279
      print_syntax("(");
3✔
280
      for (unsigned i = 0; i < tree_assocs(t); i++) {
7✔
281
         if (i > 0)
4✔
282
            print_syntax(", ");
1✔
283
         tree_t a = tree_assoc(t, i);
4✔
284
         tree_t value = tree_value(a);
4✔
285
         switch (tree_subkind(a)) {
4✔
286
         case A_POS:
×
287
            dump_expr(value);
×
288
            break;
×
289
         case A_NAMED:
1✔
290
            dump_expr(tree_name(a));
1✔
291
            print_syntax(" => ");
1✔
292
            dump_expr(value);
1✔
293
            break;
1✔
294
         case A_OTHERS:
3✔
295
            print_syntax("#others => ");
3✔
296
            dump_expr(value);
3✔
297
            break;
3✔
298
         case A_RANGE:
×
299
            dump_range(tree_range(a, 0));
×
300
            print_syntax(" => ");
×
301
            dump_expr(value);
×
302
            break;
×
303
         default:
304
            assert(false);
×
305
         }
306
      }
307
      print_syntax(")");
3✔
308
      break;
3✔
309

310
   case T_REF:
38✔
311
      if (tree_has_ref(t)) {
38✔
312
         tree_t decl = tree_ref(t);
38✔
313
         dump_address(decl);
38✔
314
         print_syntax("%s", istr(tree_ident(decl)));
38✔
315
      }
316
      else
317
         print_syntax("%s", istr(tree_ident(t)));
×
318
      break;
319

320
   case T_ATTR_REF:
1✔
321
      dump_expr(tree_name(t));
1✔
322
      print_syntax("'%s", istr(tree_ident(t)));
1✔
323
      if (tree_params(t) > 0)
1✔
324
         dump_params(t, tree_param, tree_params(t), NULL);
×
325
      break;
326

327
   case T_EXTERNAL_NAME:
1✔
328
      dump_external_name(t);
1✔
329
      break;
1✔
330

331
   case T_ARRAY_REF:
1✔
332
      dump_expr(tree_value(t));
1✔
333
      dump_params(t, tree_param, tree_params(t), NULL);
1✔
334
      break;
1✔
335

336
   case T_ARRAY_SLICE:
×
337
      dump_expr(tree_value(t));
×
338
      print_syntax("(");
×
339
      dump_range(tree_range(t, 0));
×
340
      print_syntax(")");
×
341
      break;
×
342

343
   case T_RECORD_REF:
×
344
      dump_expr(tree_value(t));
×
345
      print_syntax(".%s", istr(tree_ident(t)));
×
346
      break;
×
347

348
   case T_TYPE_CONV:
4✔
349
      dump_type(tree_type(t));
4✔
350
      print_syntax("(");
4✔
351
      dump_expr(tree_value(t));
4✔
352
      print_syntax(")");
4✔
353
      break;
4✔
354

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

365
   case T_OPEN:
1✔
366
      print_syntax("#open");
1✔
367
      break;
1✔
368

369
   case T_BOX:
78✔
370
      print_syntax("<>");
78✔
371
      break;
78✔
372

373
   case T_WAVEFORM:
×
374
      dump_waveform(t);
×
375
      break;
×
376

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

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

408
   default:
×
409
      cannot_dump(t, "expr");
×
410
   }
411

412
   dump_type_hint(t);
170✔
413
}
170✔
414

415
static void dump_record_elem_constraint(tree_t t)
×
416
{
417
   print_syntax("%s", istr(tree_ident(t)));
×
418

419
   type_t ftype = tree_type(t);
×
420
   const int ncon = type_constraints(ftype);
×
421
   for (int i = 0; i < ncon; i++)
×
422
      dump_constraint(type_constraint(ftype, i));
×
423

424
   dump_elem_constraints(ftype);
×
425
}
×
426

427
static void dump_constraint(tree_t t)
5✔
428
{
429
   const int nranges = tree_ranges(t);
5✔
430

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

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

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

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

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

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

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

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

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

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

597
static void dump_block(tree_t t, int indent)
5✔
598
{
599
   dump_decls(t, indent + 2);
5✔
600
   tab(indent);
5✔
601
   print_syntax("#begin\n");
5✔
602
   dump_stmts(t, indent + 2);
5✔
603
}
5✔
604

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

614
static void dump_type_decl(tree_t t, int indent)
2✔
615
{
616
   type_t type = tree_type(t);
2✔
617
   const type_kind_t kind = type_kind(type);
2✔
618

619
   print_syntax("#type %s", istr(tree_ident(t)));
2✔
620

621
   if (kind == T_INCOMPLETE) {
2✔
622
      print_syntax(";\n");
×
623
      return;
×
624
   }
625

626
   print_syntax(" #is ");
2✔
627

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

701
   print_syntax(";\n");
2✔
702
}
703

704
static void dump_subtype_decl(tree_t t, int indent)
705
{
706
   type_t type = tree_type(t);
707

708
   print_syntax("#subtype %s #is ", istr(tree_ident(t)));
709
   if (type_has_resolution(type)) {
710
      dump_expr(type_resolution(type));
711
      print_syntax(" ");
712
   }
713
   print_syntax("%s", type_pp(type_base(type)));
714

715
   const int ncon = type_constraints(type);
716
   for (int i = 0; i < ncon; i++)
717
      dump_constraint(type_constraint(type, i));
718

719
   dump_elem_constraints(type);
720

721
   print_syntax(";\n");
722
}
723

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

732
static void dump_use(tree_t t)
6✔
733
{
734
   print_syntax("#use %s", istr(tree_ident(t)));
6✔
735
   if (tree_has_ident2(t))
6✔
736
      print_syntax(".%s", istr(tree_ident2(t)));
6✔
737
   print_syntax(";\n");
6✔
738
}
6✔
739

740
static void dump_decl(tree_t t, int indent)
26✔
741
{
742
   tab(indent);
26✔
743
   if (tree_kind(t) != T_HIER) dump_address(t);
26✔
744

745
   switch (tree_kind(t)) {
26✔
746
   case T_IMPLICIT_SIGNAL:
×
747
      print_syntax("/* implicit */ ");
×
748
      // Fall-through
749
   case T_SIGNAL_DECL:
3✔
750
      print_syntax("#signal %s : ", istr(tree_ident(t)));
3✔
751
      break;
3✔
752

753
   case T_VAR_DECL:
3✔
754
      print_syntax("#variable %s : ", istr(tree_ident(t)));
3✔
755
      break;
3✔
756

757
   case T_CONST_DECL:
3✔
758
      print_syntax("#constant %s : ", istr(tree_ident(t)));
3✔
759
      break;
3✔
760

761
   case T_GENERIC_DECL:
1✔
762
      // Loop variable in for-generate statement
763
      print_syntax("/* loop variable */ %s : ", istr(tree_ident(t)));
1✔
764
      break;
1✔
765

766
   case T_FIELD_DECL:
2✔
767
      print_syntax("%s : ", istr(tree_ident(t)));
2✔
768
      break;
2✔
769

770
   case T_TYPE_DECL:
2✔
771
      dump_type_decl(t, indent);
2✔
772
      return;
2✔
773

774
   case T_SUBTYPE_DECL:
1✔
775
      dump_subtype_decl(t, indent);
1✔
776
      return;
1✔
777

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

790
   case T_BLOCK_CONFIG:
×
791
      print_syntax("#for %s\n", istr(tree_ident(t)));
×
792
      dump_decls(t, indent + 2);
×
793
      tab(indent);
×
794
      print_syntax("#end #for;\n");
×
795
      return;
×
796

797
   case T_ENUM_LIT:
×
798
      print_syntax("%s", istr(tree_ident(t)));
×
799
      return;
×
800

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

814
   case T_ATTR_SPEC:
1✔
815
      print_syntax("#attribute %s #of %s : #%s #is ", istr(tree_ident(t)),
1✔
816
             istr(tree_ident2(t)), class_str(tree_class(t)));
817
      dump_expr(tree_value(t));
1✔
818
      print_syntax(";\n");
1✔
819
      return;
1✔
820

821
   case T_ATTR_DECL:
1✔
822
      print_syntax("#attribute %s : ", istr(tree_ident(t)));
1✔
823
      dump_type(tree_type(t));
1✔
824
      print_syntax(";\n");
1✔
825
      return;
1✔
826

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

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

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

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

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

914
   case T_COMPONENT:
1✔
915
      dump_component(t, indent);
1✔
916
      return;
1✔
917

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

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

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

944
   case T_USE:
×
945
      dump_use(t);
×
946
      return;
×
947

948
   case T_PACKAGE:
×
949
   case T_PACK_INST:
950
      dump_package(t, indent);
×
951
      return;
×
952

953
   case T_PACK_BODY:
×
954
      dump_package_body(t, indent);
×
955
      return;
×
956

NEW
957
   case T_PSL:
×
NEW
958
      dump_psl(t, 0);
×
NEW
959
      print_syntax(";\n");
×
NEW
960
      return;
×
961

962
   default:
×
963
      cannot_dump(t, "decl");
×
964
   }
965

966
   dump_type(tree_type(t));
12✔
967

968
   if (tree_kind(t) != T_FIELD_DECL && tree_has_value(t)) {
12✔
969
      print_syntax(" := ");
6✔
970
      dump_expr(tree_value(t));
6✔
971
   }
972
   print_syntax(";\n");
12✔
973
}
974

975
static void dump_waveforms(tree_t t)
2✔
976
{
977
   const int nwaves = tree_waveforms(t);
2✔
978
   for (int i = 0; i < nwaves; i++) {
5✔
979
      if (i > 0) print_syntax(", ");
3✔
980
      dump_waveform(tree_waveform(t, i));
3✔
981
   }
982
}
2✔
983

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

1018
static void dump_psl(tree_t t, int indent)
1019
{
1020
   if (standard() < STD_08)
1021
      print_syntax("-- psl ");
1022
   psl_dump(tree_psl(t));
1023
}
1024

1025
static void dump_instance(tree_t t, int indent)
1✔
1026
{
1027
   switch (tree_class(t)) {
1✔
1028
   case C_ENTITY:        print_syntax("#entity "); break;
×
1029
   case C_COMPONENT:     print_syntax("#component "); break;
1✔
1030
   case C_CONFIGURATION: print_syntax("#configuration "); break;
×
1031
   default: break;
1032
   }
1033

1034
   print_syntax("%s", istr(tree_ident2(t)));
1✔
1035

1036
   const int nparams = tree_params(t);
1✔
1037
   const int ngenmaps = tree_genmaps(t);
1✔
1038

1039
   if (tree_has_spec(t)) {
1✔
1040
      tree_t spec = tree_spec(t);
×
1041
      if (tree_has_value(spec)) {
×
1042
         tree_t bind = tree_value(spec);
×
1043
         LOCAL_TEXT_BUF tb = tb_new();
×
1044
         tb_cat(tb, istr(tree_ident(bind)));
×
1045
         if (tree_has_ident2(bind))
×
1046
            tb_printf(tb, "(%s)", istr(tree_ident2(bind)));
×
1047
         print_syntax("  -- bound to %s\n", tb_get(tb));
×
1048
      }
1049
   }
1050
   else if (nparams > 0 || ngenmaps > 0)
1✔
1051
      print_syntax("\n");
1✔
1052

1053
   dump_generic_map(t, indent + 2, nparams > 0 ? "\n" : "");
1✔
1054
   dump_port_map(t, indent + 2, "");
1✔
1055
   print_syntax(";\n");
1✔
1056
}
1✔
1057

1058
static void dump_stmt(tree_t t, int indent)
13✔
1059
{
1060
   tab(indent);
15✔
1061

1062
   if (tree_has_ident(t)) {
15✔
1063
      const char *label = istr(tree_ident(t));
6✔
1064
#if !DUMP_GEN_NAMES
1065
      if (label[0] != '_')   // Skip generated labels
6✔
1066
#endif
1067
         print_syntax("%s: ", label);
4✔
1068
   }
1069

1070
   switch (tree_kind(t)) {
15✔
1071
   case T_PROCESS:
1✔
1072
      dump_address(t);
1✔
1073
      if (tree_flags(t) & TREE_F_POSTPONED)
1✔
1074
         print_syntax("#postponed ");
×
1075
      print_syntax("#process ");
1✔
1076
      if (tree_triggers(t) > 0) {
1✔
1077
         print_syntax("(");
1✔
1078
         for (unsigned i = 0; i < tree_triggers(t); i++) {
2✔
1079
            if (i > 0)
1✔
1080
               print_syntax(", ");
×
1081
            dump_expr(tree_trigger(t, i));
1✔
1082
         }
1083
         print_syntax(") ");
1✔
1084
      }
1085
      print_syntax("#is\n");
1✔
1086
      dump_decls(t, indent + 2);
1✔
1087
      tab(indent);
1✔
1088
      print_syntax("#begin\n");
1✔
1089
      dump_stmts(t, indent + 2);
1✔
1090
      tab(indent);
1✔
1091
      print_syntax("#end #process;\n");
1✔
1092
      return;
1✔
1093

1094
   case T_SIGNAL_ASSIGN:
1✔
1095
      dump_expr(tree_target(t));
1✔
1096
      print_syntax(" <= #reject ");
1✔
1097
      if (tree_has_reject(t))
1✔
1098
         dump_expr(tree_reject(t));
1✔
1099
      else
1100
         print_syntax("0 ps");
×
1101
      print_syntax(" #inertial ");
1✔
1102
      dump_waveforms(t);
1✔
1103
      break;
1✔
1104

1105
   case T_FORCE:
×
1106
      dump_expr(tree_target(t));
×
1107
      print_syntax(" <= #force ");
×
1108
      dump_expr(tree_value(t));
×
1109
      break;
×
1110

1111
   case T_RELEASE:
×
1112
      dump_expr(tree_target(t));
×
1113
      print_syntax(" <= #release");
×
1114
      break;
×
1115

1116
   case T_VAR_ASSIGN:
2✔
1117
      dump_expr(tree_target(t));
2✔
1118
      print_syntax(" := ");
2✔
1119
      dump_expr(tree_value(t));
2✔
1120
      break;
2✔
1121

1122
   case T_WAIT:
×
1123
      print_syntax("#wait");
×
1124
      if (tree_triggers(t) > 0) {
×
1125
         print_syntax(" #on ");
×
1126
         for (unsigned i = 0; i < tree_triggers(t); i++) {
×
1127
            if (i > 0)
×
1128
               print_syntax(", ");
×
1129
            dump_expr(tree_trigger(t, i));
×
1130
         }
1131
      }
1132
      if (tree_has_value(t)) {
×
1133
         print_syntax(" #until ");
×
1134
         dump_expr(tree_value(t));
×
1135
      }
1136
      if (tree_has_delay(t)) {
×
1137
         print_syntax(" #for ");
×
1138
         dump_expr(tree_delay(t));
×
1139
      }
1140
      print_syntax(";");
×
1141
      if (tree_flags(t) & TREE_F_STATIC_WAIT)
×
1142
         print_syntax("   -- static");
×
1143
      print_syntax("\n");
×
1144
      return;
×
1145

1146
   case T_BLOCK:
1✔
1147
      dump_address(t);
1✔
1148
      print_syntax("#block #is\n");
1✔
1149
      dump_generics(t, indent + 2, ";\n");
1✔
1150
      dump_generic_map(t, indent + 2, ";\n");
1✔
1151
      dump_ports(t, indent + 2);
1✔
1152
      dump_port_map(t, indent + 2, ";\n");
1✔
1153
      dump_block(t, indent);
1✔
1154
      tab(indent);
1✔
1155
      print_syntax("#end #block;\n");
1✔
1156
      return;
1✔
1157

1158
   case T_SEQUENCE:
×
1159
      print_syntax("#block #is\n");
×
1160
      dump_block(t, indent);
×
1161
      tab(indent);
×
1162
      print_syntax("#end #block;\n");
×
1163
      return;
×
1164

1165
   case T_ASSERT:
1✔
1166
      if (tree_has_value(t)) {
1✔
1167
         print_syntax("#assert ");
1✔
1168
         dump_expr(tree_value(t));
1✔
1169
         print_syntax(" ");
1✔
1170
      }
1171
      if (tree_has_message(t)) {
1✔
1172
         print_syntax("#report ");
×
1173
         dump_expr(tree_message(t));
×
1174
         print_syntax(" ");
×
1175
      }
1176
      print_syntax("#severity ");
1✔
1177
      dump_expr(tree_severity(t));
1✔
1178
      break;
1✔
1179

1180
   case T_WHILE:
×
1181
      if (tree_has_value(t)) {
×
1182
         print_syntax("#while ");
×
1183
         dump_expr(tree_value(t));
×
1184
         print_syntax(" ");
×
1185
      }
1186
      print_syntax("#loop\n");
×
1187
      dump_stmts(t, indent + 2);
×
1188
      tab(indent);
×
1189
      print_syntax("#end #loop");
×
1190
      break;
×
1191

1192
   case T_IF:
1193
      for (unsigned i = 0; i < tree_conds(t); i++) {
3✔
1194
         tree_t c = tree_cond(t, i);
2✔
1195
         if (tree_has_value(c)) {
2✔
1196
            if (i > 0)
1✔
1197
               tab(indent);
×
1198
            print_syntax(i > 0 ? "#elsif " : "#if ");
2✔
1199
            dump_expr(tree_value(c));
1✔
1200
            print_syntax(" #then\n");
1✔
1201
         }
1202
         else {
1203
            tab(indent);
1✔
1204
            print_syntax("#else\n");
1✔
1205
         }
1206
         dump_stmts(c, indent + 2);
2✔
1207
      }
1208
      tab(indent);
1✔
1209
      print_syntax("#end #if");
1✔
1210
      break;
1✔
1211

1212
   case T_EXIT:
×
1213
      print_syntax("#exit %s", istr(tree_ident2(t)));
×
1214
      if (tree_has_value(t)) {
×
1215
         print_syntax(" #when ");
×
1216
         dump_expr(tree_value(t));
×
1217
      }
1218
      break;
1219

1220
   case T_CASE:
×
1221
   case T_MATCH_CASE:
1222
      {
1223
         const char *suffix = tree_kind(t) == T_MATCH_CASE ? "?" : "";
×
1224
         print_syntax("#case%s ", suffix);
×
1225
         dump_expr(tree_value(t));
×
1226
         print_syntax(" #is\n");
×
1227
         const int nstmts = tree_stmts(t);
×
1228
         for (int i = 0; i < nstmts; i++)
×
1229
            dump_alternative(tree_stmt(t, i), indent + 2);
×
1230
         tab(indent);
×
1231
         print_syntax("#end #case%s", suffix);
×
1232
      }
1233
      break;
×
1234

1235
   case T_RETURN:
3✔
1236
      print_syntax("#return");
3✔
1237
      if (tree_has_value(t)) {
3✔
1238
         print_syntax(" ");
3✔
1239
         dump_expr(tree_value(t));
3✔
1240
      }
1241
      break;
1242

1243
   case T_COND_RETURN:
×
1244
      print_syntax("#return #when ");
×
1245
      dump_expr(tree_value(t));
×
1246
      break;
×
1247

1248
   case T_FOR:
×
1249
      print_syntax("#for %s #in ", istr(tree_ident(tree_decl(t, 0))));
×
1250
      dump_range(tree_range(t, 0));
×
1251
      print_syntax(" #loop\n");
×
1252
      dump_stmts(t, indent + 2);
×
1253
      tab(indent);
×
1254
      print_syntax("#end #for");
×
1255
      break;
×
1256

1257
   case T_PROT_PCALL:
×
1258
      dump_expr(tree_name(t));
×
1259
      print_syntax(".");
×
1260
      // Fall-through
1261
   case T_PCALL:
×
1262
      if (tree_has_ref(t)) {
×
1263
         tree_t decl = tree_ref(t);
×
1264
         dump_address(decl);
×
1265
         print_syntax("%s", istr(tree_ident(decl)));
×
1266
      }
1267
      else
1268
         print_syntax("%s", istr(tree_ident(t)));
×
1269
      dump_params(t, tree_param, tree_params(t), NULL);
×
1270
      break;
×
1271

1272
   case T_FOR_GENERATE:
1✔
1273
      print_syntax("#for %s #in ", istr(tree_ident(tree_decl(t, 0))));
1✔
1274
      dump_range(tree_range(t, 0));
1✔
1275
      print_syntax(" #generate\n");
1✔
1276
      dump_decls(t, indent + 2);
1✔
1277
      tab(indent);
1✔
1278
      print_syntax("#begin\n");
1✔
1279
      dump_stmts(t, indent + 2);
1✔
1280
      tab(indent);
1✔
1281
      print_syntax("#end #generate");
1✔
1282
      break;
1✔
1283

1284
   case T_CASE_GENERATE:
×
1285
      {
1286
         print_syntax("#case ");
×
1287
         dump_expr(tree_value(t));
×
1288
         print_syntax(" #generate\n");
×
1289

1290
         const int nstmts = tree_stmts(t);
×
1291
         for (int i = 0; i < nstmts; i++)
×
1292
            dump_alternative(tree_stmt(t, i), indent + 2);
×
1293

1294
         print_syntax("#end #generate");
×
1295
         tab(indent);
×
1296
      }
1297
      break;
×
1298

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

1320
   case T_INSTANCE:
1✔
1321
      dump_instance(t, indent);
1✔
1322
      return;
1✔
1323

1324
   case T_NEXT:
×
1325
      print_syntax("#next");
×
1326
      if (tree_has_value(t)) {
×
1327
         print_syntax(" #when ");
×
1328
         dump_expr(tree_value(t));
×
1329
      }
1330
      break;
1331

1332
   case T_NULL:
×
1333
      print_syntax("#null");
×
1334
      break;
×
1335

1336
   case T_COND_ASSIGN:
1✔
1337
      dump_expr(tree_target(t));
1✔
1338
      print_syntax(" <= ");
1✔
1339
      for (int i = 0; i < tree_conds(t); i++) {
2✔
1340
         tree_t c = tree_cond(t, i);
1✔
1341
         dump_waveforms(tree_stmt(c, 0));
1✔
1342
         if (tree_has_value(c)) {
1✔
1343
            print_syntax(" #when ");
×
1344
            dump_expr(tree_value(c));
×
1345
         }
1346
      }
1347
      break;
1348

1349
   case T_SELECT:
×
1350
      print_syntax(" <= ");
×
1351
      if (tree_has_guard(t)) print_syntax("#guarded ");
×
1352
      color_printf("$red$/* TODO: T_SELECT */$$");
×
1353
      break;
×
1354

1355
   case T_CONCURRENT:
2✔
1356
      if (tree_flags(t) & TREE_F_POSTPONED)
2✔
1357
         print_syntax("#postponed ");
×
1358
      if (tree_has_guard(t))
2✔
1359
         print_syntax("#guarded ");
×
1360
      dump_stmt(tree_stmt(t, 0), 0);
2✔
1361
      return;
2✔
1362

1363
   case T_PSL:
×
1364
      dump_psl(t, 0);
×
1365
      break;
×
1366

1367
   case T_VERILOG:
×
1368
      print_syntax("#block #is\n");
×
1369
      dump_generic_map(t, indent + 2, ";\n");
×
1370
      dump_port_map(t, indent + 2, ";\n");
×
1371
      tab(indent);
×
1372
      print_syntax("#begin\n");
×
1373
      vlog_dump(tree_vlog(t), indent + 2);
×
1374
      tab(indent);
×
1375
      print_syntax("#end #block");
×
1376
      break;
×
1377

1378
   default:
×
1379
      cannot_dump(t, "stmt");
×
1380
   }
1381

1382
   print_syntax(";\n");
10✔
1383
}
1384

1385
static void dump_port(tree_t t, int indent)
100✔
1386
{
1387
   tab(indent);
100✔
1388
   dump_address(t);
100✔
1389

1390
   if (tree_flags(t) & TREE_F_PREDEFINED)
100✔
1391
      print_syntax("-- predefined ");
80✔
1392

1393
   const class_t class = tree_class(t);
100✔
1394
   print_syntax("#%s %s", class_str(class), istr(tree_ident(t)));
100✔
1395

1396
   type_t type = get_type_or_null(t);
100✔
1397
   if (class == C_PACKAGE) {
100✔
1398
      print_syntax(" #is #new ");
×
1399
      dump_expr(tree_value(t));
×
1400
   }
1401
   else if (class == C_TYPE && type_kind(type) == T_GENERIC) {
100✔
1402
      print_syntax(" #is ");
10✔
1403

1404
      switch (type_subkind(type)) {
10✔
1405
      case GTYPE_PRIVATE:
2✔
1406
         print_syntax("#private");
2✔
1407
         break;
2✔
1408
      case GTYPE_SCALAR:
1✔
1409
         print_syntax("<>");
1✔
1410
         break;
1✔
1411
      case GTYPE_DISCRETE:
1✔
1412
         print_syntax("(<>)");
1✔
1413
         break;
1✔
1414
      case GTYPE_INTEGER:
1✔
1415
         print_syntax("#range <>");
1✔
1416
         break;
1✔
1417
      case GTYPE_PHYSICAL:
1✔
1418
         print_syntax("#units <>");
1✔
1419
         break;
1✔
1420
      case GTYPE_FLOATING:
1✔
1421
         print_syntax("#range <> . <>");
1✔
1422
         break;
1✔
1423
      case GTYPE_ARRAY:
1✔
1424
         {
1425
            print_syntax("#array (");
1✔
1426
            const int nindex = type_indexes(type);
1✔
1427
            for (int i = 0; i < nindex; i++) {
2✔
1428
               if (i > 0) print_syntax(", ");
1✔
1429
               dump_type(type_index(type, i));
1✔
1430
               print_syntax(" #range <>");
1✔
1431
            }
1432
            print_syntax(") #of ");
1✔
1433
            dump_type(type_elem(type));
1✔
1434
         }
1435
         break;
1✔
1436
      case GTYPE_ACCESS:
1✔
1437
         print_syntax("#access ..");
1✔
1438
         break;
1✔
1439
      case GTYPE_FILE:
1✔
1440
         print_syntax("#file #of ..");
1✔
1441
         break;
1✔
1442
      }
1443
   }
1444
   else {
1445
      const char *dir = NULL;
90✔
1446
      switch (tree_subkind(t)) {
90✔
1447
      case PORT_IN:      dir = "in";     break;
86✔
1448
      case PORT_OUT:     dir = "out";    break;
4✔
1449
      case PORT_INOUT:   dir = "inout";  break;
×
1450
      case PORT_BUFFER:  dir = "buffer"; break;
×
1451
      case PORT_INVALID: dir = "??";     break;
×
1452
      }
1453
      print_syntax(" : #%s ", dir);
90✔
1454
      dump_type(type);
90✔
1455

1456
      if (tree_has_value(t)) {
90✔
1457
         print_syntax(" := ");
79✔
1458
         dump_expr(tree_value(t));
79✔
1459
      }
1460
   }
1461
}
100✔
1462

1463
static void dump_context(tree_t t, int indent)
6✔
1464
{
1465
   const int nctx = tree_contexts(t);
6✔
1466
   for (int i = 0; i < nctx; i++) {
24✔
1467
      tree_t c = tree_context(t, i);
18✔
1468
      switch (tree_kind(c)) {
18✔
1469
      case T_LIBRARY:
12✔
1470
         switch (is_well_known(tree_ident(c))) {
12✔
1471
         case W_STD:
1472
         case W_WORK:
1473
            break;
1474
         default:
×
1475
            print_syntax("#library %s;\n", istr(tree_ident(c)));
×
1476
         }
1477
         break;
1478

1479
      case T_USE:
6✔
1480
         dump_use(c);
6✔
1481
         break;
6✔
1482

1483
      case T_CONTEXT_REF:
×
1484
         print_syntax("#context %s;\n", istr(tree_ident(t)));
×
1485
         break;
×
1486

1487
      default:
1488
         break;
1489
      }
1490

1491
      tab(indent);
18✔
1492
   }
1493

1494
   if (nctx > 0) {
6✔
1495
      print_syntax("\n");
6✔
1496
      tab(indent);
6✔
1497
   }
1498
}
6✔
1499

1500
static void dump_elab(tree_t t)
×
1501
{
1502
   dump_context(t, 0);
×
1503
   dump_address(t);
×
1504
   print_syntax("#entity %s #is\n#end #entity;\n\n", istr(tree_ident(t)));
×
1505
   print_syntax("#architecture #elab #of %s #is\n", istr(tree_ident(t)));
×
1506
   dump_decls(t, 2);
×
1507
   print_syntax("#begin\n");
×
1508
   for (unsigned i = 0; i < tree_stmts(t); i++)
×
1509
      dump_stmt(tree_stmt(t, i), 2);
×
1510
   print_syntax("#end #architecture;\n\n");
×
1511
}
×
1512

1513
static void dump_entity(tree_t t)
2✔
1514
{
1515
   dump_context(t, 0);
2✔
1516
   dump_address(t);
2✔
1517
   print_syntax("#entity %s #is\n", istr(tree_ident(t)));
2✔
1518
   dump_generics(t, 2, ";\n");
2✔
1519
   dump_ports(t, 2);
2✔
1520
   dump_decls(t, 2);
2✔
1521
   if (tree_stmts(t) > 0) {
2✔
1522
      print_syntax("#begin\n");
×
1523
      for (unsigned i = 0; i < tree_stmts(t); i++) {
×
1524
         dump_stmt(tree_stmt(t, i), 2);
×
1525
      }
1526
   }
1527
   print_syntax("#end #entity;\n\n");
2✔
1528
}
2✔
1529

1530
static void dump_decls(tree_t t, int indent)
15✔
1531
{
1532
   const int ndecls = tree_decls(t);
15✔
1533
   bool was_body = false;
15✔
1534
   for (unsigned i = 0; i < ndecls; i++) {
31✔
1535
      tree_t d = tree_decl(t, i);
16✔
1536
      tree_kind_t dkind = tree_kind(d);
16✔
1537
      const bool is_body = dkind == T_FUNC_BODY || dkind == T_PROT_BODY
32✔
1538
         || dkind == T_PROC_BODY;
16✔
1539
      if ((was_body && !is_body) || (is_body && i > 0))
16✔
1540
         print_syntax("\n");
4✔
1541
      was_body = is_body;
16✔
1542
      dump_decl(d, indent);
16✔
1543
   }
1544
}
15✔
1545

1546
static void dump_arch(tree_t t)
1✔
1547
{
1548
   dump_context(t, 0);
1✔
1549
   dump_address(t);
1✔
1550
   print_syntax("#architecture %s #of %s #is\n",
1✔
1551
                istr(tree_ident(t)), istr(tree_ident2(t)));
1552
   dump_decls(t, 2);
1✔
1553
   print_syntax("#begin\n");
1✔
1554
   dump_stmts(t, 2);
1✔
1555
   print_syntax("#end #architecture;\n\n");
1✔
1556
}
1✔
1557

1558
static void dump_package(tree_t t, int indent)
1✔
1559
{
1560
   dump_context(t, indent);
1✔
1561
   dump_address(t);
1✔
1562
   print_syntax("#package %s #is\n", istr(tree_ident(t)));
1✔
1563
   if (tree_kind(t) == T_PACK_INST && tree_has_ref(t)) {
1✔
1564
      tab(indent);
×
1565
      print_syntax("  -- Instantiated from %s\n", istr(tree_ident(tree_ref(t))));
×
1566
   }
1567
   dump_generics(t, indent + 2, ";\n");
1✔
1568
   dump_generic_map(t, indent + 2, ";\n");
1✔
1569
   dump_decls(t, indent + 2);
1✔
1570
   tab(indent);
1✔
1571
   print_syntax("#end #package;\n\n");
1✔
1572
}
1✔
1573

1574
static void dump_package_body(tree_t t, int indent)
2✔
1575
{
1576
   dump_context(t, indent);
2✔
1577
   dump_address(t);
2✔
1578
   print_syntax("#package #body %s #is\n", istr(tree_ident(t)));
2✔
1579
   dump_decls(t, indent + 2);
2✔
1580
   tab(indent);
2✔
1581
   print_syntax("#end #package #body;\n\n");
2✔
1582
}
2✔
1583

1584
static void dump_configuration(tree_t t)
×
1585
{
1586
   dump_address(t);
×
1587
   print_syntax("#configuration %s #of %s #is\n",
×
1588
          istr(tree_ident(t)), istr(tree_ident2(t)));
1589
   dump_decls(t, 2);
×
1590
   print_syntax("#end #configuration\n");
×
1591
}
×
1592

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

1696
void dump(tree_t t)
18✔
1697
{
1698
   vhdl_dump(t, 0);
18✔
1699
   print_syntax("\r");
18✔
1700
}
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