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

nickg / nvc / 12854971287

19 Jan 2025 03:39PM UTC coverage: 92.194% (+0.002%) from 92.192%
12854971287

push

github

nickg
Implement PSL prev() built-in function. Fixes #1135

48 of 53 new or added lines in 3 files covered. (90.57%)

419 existing lines in 12 files now uncovered.

64159 of 69591 relevant lines covered (92.19%)

508771.0 hits per line

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

319
   case T_REF:
54✔
320
      if (tree_has_ref(t)) {
54✔
321
         tree_t decl = tree_ref(t);
54✔
322
         dump_address(decl);
54✔
323
         print_syntax("%s", istr(tree_ident(decl)));
54✔
324
      }
325
      else
326
         print_syntax("%s", istr(tree_ident(t)));
×
327
      break;
328

329
   case T_ATTR_REF:
2✔
330
      dump_expr(tree_name(t));
2✔
331
      print_syntax("'%s", istr(tree_ident(t)));
2✔
332
      if (tree_params(t) > 0)
2✔
333
         dump_params(t, tree_param, tree_params(t), NULL);
×
334
      break;
335

336
   case T_EXTERNAL_NAME:
2✔
337
      dump_external_name(t);
2✔
338
      break;
2✔
339

340
   case T_ARRAY_REF:
1✔
341
      dump_expr(tree_value(t));
1✔
342
      dump_params(t, tree_param, tree_params(t), NULL);
1✔
343
      break;
1✔
344

345
   case T_ARRAY_SLICE:
×
346
      dump_expr(tree_value(t));
×
347
      print_syntax("(");
×
348
      dump_range(tree_range(t, 0));
×
349
      print_syntax(")");
×
350
      break;
×
351

352
   case T_RECORD_REF:
×
353
      dump_expr(tree_value(t));
×
354
      print_syntax(".%s", istr(tree_ident(t)));
×
355
      break;
×
356

357
   case T_TYPE_CONV:
4✔
358
      dump_type(tree_type(t));
4✔
359
      print_syntax("(");
4✔
360
      dump_expr(tree_value(t));
4✔
361
      print_syntax(")");
4✔
362
      break;
4✔
363

364
   case T_QUALIFIED:
×
365
      if (tree_has_value(t)) {
×
366
         print_syntax("%s'(", istr(type_ident(tree_type(t))));
×
367
         dump_expr(tree_value(t));
×
368
         print_syntax(")");
×
369
      }
370
      else
371
         dump_type(tree_type(t));
×
372
      break;
373

374
   case T_OPEN:
1✔
375
      print_syntax("#open");
1✔
376
      break;
1✔
377

378
   case T_BOX:
80✔
379
      print_syntax("<>");
80✔
380
      break;
80✔
381

382
   case T_WAVEFORM:
×
383
      dump_waveform(t);
×
384
      break;
×
385

386
   case T_PACKAGE_MAP:
×
387
      print_syntax("%s ", istr(tree_ident(t)));
×
388
      switch (tree_subkind(t)) {
×
389
      case PACKAGE_MAP_BOX:
×
390
         print_syntax("#generic #map (<>)");
×
391
         break;
×
392
      case PACKAGE_MAP_DEFAULT:
×
393
         print_syntax("#generic map (#default)");
×
394
         break;
×
395
      case PACKAGE_MAP_MATCHING:
×
396
         dump_params(t, tree_genmap, tree_genmaps(t), "#generic #map");
×
397
         break;
×
398
      }
399
      return;
400

401
   case T_COND_VALUE:
402
      for (int i = 0; i < tree_conds(t); i++) {
×
403
         tree_t c = tree_cond(t, i);
×
404
         if (i > 0)
×
405
            print_syntax(" #else ");
×
406
         if (tree_has_result(c))
×
407
            dump_expr(tree_result(c));
×
408
         else
409
            print_syntax("#unaffected");
×
410
         if (tree_has_value(c)) {
×
411
            print_syntax(" #when ");
×
412
            dump_expr(tree_value(c));
×
413
         }
414
      }
415
      break;
416

417
   case T_INERTIAL:
1✔
418
      print_syntax("#inertial ");
1✔
419
      dump_expr(tree_value(t));
1✔
420
      break;
1✔
421

422
   default:
×
423
      cannot_dump(t, "expr");
×
424
   }
425

426
   dump_type_hint(t);
201✔
427
}
428

429
static void dump_record_elem_constraint(tree_t t)
×
430
{
431
   print_syntax("%s", istr(tree_ident(t)));
×
432

433
   type_t ftype = tree_type(t);
×
434
   const int ncon = type_constraints(ftype);
×
435
   for (int i = 0; i < ncon; i++)
×
436
      dump_constraint(type_constraint(ftype, i));
×
437

438
   dump_elem_constraints(ftype);
×
439
}
×
440

441
static void dump_constraint(tree_t t)
5✔
442
{
443
   const int nranges = tree_ranges(t);
5✔
444

445
   switch (tree_subkind(t)) {
5✔
446
   case C_RANGE:
1✔
447
      print_syntax(" #range ");
1✔
448
      dump_range(tree_range(t, 0));
1✔
449
      break;
1✔
450
   case C_INDEX:
4✔
451
      print_syntax("(");
4✔
452
      for (int i = 0; i < nranges; i++) {
8✔
453
         if (i > 0) print_syntax(", ");
4✔
454
         dump_range(tree_range(t, i));
4✔
455
      }
456
      print_syntax(")");
4✔
457
      break;
4✔
458
   case C_OPEN:
×
459
      print_syntax("(#open)");
×
460
      break;
×
461
   case C_RECORD:
×
462
      print_syntax("(");
×
463
      for (int i = 0; i < nranges; i++) {
×
464
         if (i > 0) print_syntax(", ");
×
465
         dump_record_elem_constraint(tree_range(t, i));
×
466
      }
467
      print_syntax(")");
×
468
      break;
×
469
   }
470
}
5✔
471

472
static void dump_elem_constraints(type_t type)
5✔
473
{
474
   if (type_is_array(type) && type_has_elem(type)) {
5✔
475
      type_t elem = type_elem(type);
×
476
      if (is_anonymous_subtype(elem)) {
×
477
         // Anonymous subtype created for element constraints
478
         assert(type_constraints(elem) == 1);
×
479
         dump_constraint(type_constraint(elem, 0));
×
480
         dump_elem_constraints(elem);
×
481
      }
482
   }
483
}
5✔
484

485
static void dump_type(type_t type)
123✔
486
{
487
   if (is_anonymous_subtype(type)) {
123✔
488
      // Anonymous subtype
489
      print_syntax("%s", type_pp(type));
4✔
490
      if (type_ident(type) == type_ident(type_base(type))) {
4✔
491
         const int ncon = type_constraints(type);
4✔
492
         for (int i = 0; i < ncon; i++)
8✔
493
            dump_constraint(type_constraint(type, i));
4✔
494
      }
495
      dump_elem_constraints(type);
4✔
496
   }
497
   else if (type_is_none(type))
119✔
498
      print_syntax("/* error */");
×
499
   else
500
      print_syntax("%s", type_pp(type));
119✔
501
}
123✔
502

503
static void dump_arguments(tree_t t, int indent, const char *trailer)
7✔
504
{
505
   const int nports = tree_ports(t);
7✔
506
   if (nports > 0) {
7✔
507
      print_syntax(" (");
3✔
508
      if (nports > 1) {
3✔
509
         print_syntax("\n");
1✔
510
         for (int i = 0; i < nports; i++) {
3✔
511
            if (i > 0) print_syntax(";\n");
2✔
512
            dump_port(tree_port(t, i), indent + 4);
2✔
513
         }
514
      }
515
      else
516
         dump_port(tree_port(t, 0), 1);
2✔
517
      print_syntax(" )%s", trailer);
3✔
518
   }
519
}
7✔
520

521
static void dump_ports(tree_t t, int indent)
5✔
522
{
523
   const int nports = tree_ports(t);
5✔
524
   if (nports > 0) {
5✔
525
      tab(indent);
4✔
526
      print_syntax("#port (");
4✔
527
      if (nports > 1) {
4✔
528
         print_syntax("\n");
3✔
529
         for (unsigned i = 0; i < nports; i++) {
9✔
530
            if (i > 0) print_syntax(";\n");
6✔
531
            dump_port(tree_port(t, i), indent + 2);
6✔
532
         }
533
      }
534
      else
535
         dump_port(tree_port(t, 0), 1);
1✔
536
      print_syntax(" );\n");
4✔
537
   }
538
}
5✔
539

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

565
static void dump_port_map(tree_t t, int indent, const char *trailer)
3✔
566
{
567
   const int nparams = tree_params(t);
3✔
568
   if (nparams > 0) {
3✔
569
      tab(indent);
3✔
570
      dump_params(t, tree_param, nparams, "#port #map");
3✔
571
      print_syntax("%s", trailer);
3✔
572
   }
573
}
3✔
574

575
static void dump_generic_map(tree_t t, int indent, const char *trailer)
4✔
576
{
577
   const int ngenmaps = tree_genmaps(t);
4✔
578
   if (ngenmaps > 0) {
4✔
579
      tab(indent);
1✔
580
      dump_params(t, tree_genmap, ngenmaps, "#generic #map");
1✔
581
      print_syntax("%s", trailer);
1✔
582
   }
583
}
4✔
584

585
static void dump_binding(tree_t t, int indent)
×
586
{
587
   dump_address(t);
×
588
   print_syntax("#use %s", istr(tree_ident(t)));
×
589
   if (tree_has_ident2(t))
×
590
      print_syntax("(%s)", istr(tree_ident2(t)));
×
591
   if (tree_genmaps(t) > 0 || tree_params(t) > 0)
×
592
      print_syntax("\n");
×
593
   dump_generic_map(t, indent + 2, tree_params(t) > 0 ? "\n" : "");
×
594
   dump_port_map(t, indent + 2, "");
×
595
   print_syntax(";\n");
×
596
}
×
597

598
static void dump_stmts(tree_t t, int indent)
13✔
599
{
600
   bool last_was_newline = false;
13✔
601
   const int nstmts = tree_stmts(t);
13✔
602
   for (int i = 0; i < nstmts; i++) {
25✔
603
      tree_t s = tree_stmt(t, i);
12✔
604
      const tree_kind_t kind = tree_kind(s);
12✔
605

606
      bool needs_newline;
12✔
607
      if (kind == T_VERILOG) {
12✔
608
         const vlog_kind_t vkind = vlog_kind(tree_vlog(s));
×
609
         needs_newline = (vkind == V_ALWAYS || vkind == V_INITIAL);
×
610
      }
611
      else
612
         needs_newline = (kind == T_BLOCK || kind == T_PROCESS
12✔
613
                          || kind == T_INSTANCE);
614

615
      if (needs_newline && i > 0 && !last_was_newline)
12✔
616
         print_syntax("\n");
×
617

618
      dump_stmt(s, indent);
12✔
619

620
      if (needs_newline && i + 1 < nstmts) {
12✔
621
         print_syntax("\n");
×
622
         last_was_newline = true;
×
623
      }
624
      else
625
         last_was_newline = false;
626
   }
627
}
13✔
628

629
static void dump_block(tree_t t, int indent)
7✔
630
{
631
   dump_decls(t, indent + 2);
7✔
632
   tab(indent);
7✔
633
   print_syntax("#begin\n");
7✔
634
   dump_stmts(t, indent + 2);
7✔
635
}
7✔
636

637
static void dump_wait_level(tree_t t)
3✔
638
{
639
   const tree_flags_t flags = tree_flags(t);
3✔
640
   if (flags & TREE_F_NEVER_WAITS)
3✔
641
      print_syntax("   -- Never waits");
3✔
642
   else if (flags & TREE_F_HAS_WAIT)
×
643
      print_syntax("   -- Contains wait statement");
×
644
}
3✔
645

646
static void dump_type_decl(tree_t t, int indent)
2✔
647
{
648
   type_t type = tree_type(t);
2✔
649
   const type_kind_t kind = type_kind(type);
2✔
650

651
   print_syntax("#type %s", istr(tree_ident(t)));
2✔
652

653
   if (kind == T_INCOMPLETE) {
2✔
654
      print_syntax(";\n");
×
655
      return;
×
656
   }
657

658
   print_syntax(" #is ");
2✔
659

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

733
   print_syntax(";\n");
2✔
734
}
735

736
static void dump_subtype_decl(tree_t t, int indent)
1✔
737
{
738
   type_t type = tree_type(t);
1✔
739

740
   print_syntax("#subtype %s #is ", istr(tree_ident(t)));
1✔
741
   if (type_has_resolution(type)) {
1✔
742
      dump_expr(type_resolution(type));
×
743
      print_syntax(" ");
×
744
   }
745
   print_syntax("%s", type_pp(type_base(type)));
1✔
746

747
   const int ncon = type_constraints(type);
1✔
748
   for (int i = 0; i < ncon; i++)
2✔
749
      dump_constraint(type_constraint(type, i));
1✔
750

751
   dump_elem_constraints(type);
1✔
752

753
   print_syntax(";\n");
1✔
754
}
1✔
755

756
static void dump_component(tree_t t, int indent)
1✔
757
{
758
   print_syntax("#component %s #is\n", istr(tree_ident(t)));
1✔
759
   dump_generics(t, indent + 2, ";\n");
1✔
760
   dump_ports(t, indent + 2);
1✔
761
   print_syntax("#end #component;\n");
1✔
762
}
1✔
763

764
static void dump_use(tree_t t)
7✔
765
{
766
   print_syntax("#use %s", istr(tree_ident(t)));
7✔
767
   if (tree_has_ident2(t))
7✔
768
      print_syntax(".%s", istr(tree_ident2(t)));
7✔
769
   print_syntax(";\n");
7✔
770
}
7✔
771

772
static void dump_attr_spec(tree_t t)
4✔
773
{
774
   print_syntax("#attribute %s #of ", istr(tree_ident(t)));
4✔
775

776
   switch (tree_subkind(t)) {
4✔
777
   case SPEC_EXACT:
2✔
778
      print_syntax("%s", istr(tree_ident2(t)));
2✔
779
      break;
2✔
780
   case SPEC_ALL:
1✔
781
      print_syntax("#all");
1✔
782
      break;
1✔
783
   case SPEC_OTHERS:
1✔
784
      print_syntax("#others");
1✔
785
      break;
1✔
786
   }
787

788
   print_syntax(" : #%s #is ", class_str(tree_class(t)));
4✔
789
   dump_expr(tree_value(t));
4✔
790
   print_syntax(";\n");
4✔
791
}
4✔
792

793
static void dump_view_decl(tree_t t, int indent)
1✔
794
{
795
   type_t type = tree_type(t);
1✔
796
   print_syntax("#view %s #of ", istr(tree_ident(t)));
1✔
797
   dump_type(type_designated(type));
1✔
798
   print_syntax(" #is\n");
1✔
799

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

808
   tab(indent);
1✔
809
   print_syntax("#end #view;\n");
1✔
810
}
1✔
811

812
static void dump_decl(tree_t t, int indent)
35✔
813
{
814
   tab(indent);
35✔
815
   if (tree_kind(t) != T_HIER) dump_address(t);
35✔
816

817
   switch (tree_kind(t)) {
35✔
818
   case T_IMPLICIT_SIGNAL:
×
819
      print_syntax("/* implicit */ ");
×
820
      // Fall-through
821
   case T_SIGNAL_DECL:
5✔
822
      print_syntax("#signal %s : ", istr(tree_ident(t)));
5✔
823
      break;
5✔
824

825
   case T_VAR_DECL:
3✔
826
      print_syntax("#variable %s : ", istr(tree_ident(t)));
3✔
827
      break;
3✔
828

829
   case T_CONST_DECL:
3✔
830
      print_syntax("#constant %s : ", istr(tree_ident(t)));
3✔
831
      break;
3✔
832

833
   case T_GENERIC_DECL:
1✔
834
      // Loop variable in for-generate statement
835
      print_syntax("/* loop variable */ %s : ", istr(tree_ident(t)));
1✔
836
      break;
1✔
837

838
   case T_FIELD_DECL:
2✔
839
      print_syntax("%s : ", istr(tree_ident(t)));
2✔
840
      break;
2✔
841

842
   case T_TYPE_DECL:
2✔
843
      dump_type_decl(t, indent);
2✔
844
      return;
2✔
845

846
   case T_SUBTYPE_DECL:
1✔
847
      dump_subtype_decl(t, indent);
1✔
848
      return;
1✔
849

850
   case T_SPEC:
×
851
      if (tree_has_ident(t))
×
852
         print_syntax("#for %s", istr(tree_ident(t)));
×
853
      else
854
         print_syntax("#for #others");
×
855
      if (tree_has_ref(t))
×
856
         print_syntax(" : %s", istr(tree_ident(tree_ref(t))));
×
857
      print_syntax("\n");
×
858
      tab(indent + 2);
×
859
      dump_binding(tree_value(t), indent + 2);
×
860
      dump_decls(t, indent + 2);
×
861
      tab(indent);
×
862
      print_syntax("#end #for;\n");
×
863
      return;
×
864

865
   case T_BLOCK_CONFIG:
×
866
      print_syntax("#for %s\n", istr(tree_ident(t)));
×
867
      dump_decls(t, indent + 2);
×
868
      tab(indent);
×
869
      print_syntax("#end #for;\n");
×
870
      return;
×
871

872
   case T_ENUM_LIT:
×
873
      print_syntax("%s", istr(tree_ident(t)));
×
874
      return;
×
875

876
   case T_ALIAS:
×
877
      if (tree_flags(t) & TREE_F_PREDEFINED)
×
878
         print_syntax("-- predefined ");
×
879
      print_syntax("#alias %s", istr(tree_ident(t)));
×
880
      if (tree_has_type(t)) {
×
881
         print_syntax(" : ");
×
882
         dump_type(tree_type(t));
×
883
      }
884
      print_syntax(" #is ");
×
885
      dump_expr(tree_value(t));
×
886
      print_syntax(";\n");
×
887
      return;
×
888

889
   case T_ATTR_SPEC:
4✔
890
      dump_attr_spec(t);
4✔
891
      return;
4✔
892

893
   case T_ATTR_DECL:
2✔
894
      print_syntax("#attribute %s : ", istr(tree_ident(t)));
2✔
895
      dump_type(tree_type(t));
2✔
896
      print_syntax(";\n");
2✔
897
      return;
2✔
898

899
   case T_FUNC_DECL:
2✔
900
      if (tree_flags(t) & TREE_F_PREDEFINED)
2✔
901
         print_syntax("-- predefined %s\n", type_pp(tree_type(t)));
×
902
      else {
903
         print_syntax("#function %s", istr(tree_ident(t)));
2✔
904
         dump_generics(t, indent + 2, "");
2✔
905
         dump_arguments(t, indent, "");
2✔
906
         print_syntax(" #return ");
2✔
907
         dump_type(type_result(tree_type(t)));
2✔
908
         print_syntax(";\n");
2✔
909
         if (tree_has_ident2(t)) {
2✔
910
            tab(indent + 2);
2✔
911
            print_syntax("-- %s\n", istr(tree_ident2(t)));
2✔
912
         }
913
      }
914
      return;
915

916
   case T_FUNC_INST:
2✔
917
   case T_FUNC_BODY:
918
      print_syntax("#function %s", istr(tree_ident(t)));
2✔
919
      dump_type_hint(t);
2✔
920
      dump_generics(t, indent + 2, tree_ports(t) > 0 ? "\n" : "");
3✔
921
      if (tree_kind(t) == T_FUNC_INST)
2✔
922
         dump_generic_map(t, indent + 2, tree_ports(t) > 0 ? "\n" : "");
×
923
      dump_arguments(t, indent, "");
2✔
924
      print_syntax(" #return ");
2✔
925
      dump_type(type_result(tree_type(t)));
2✔
926
      print_syntax(" #is\n");
2✔
927
      if (tree_has_ident2(t)) {
2✔
928
         tab(indent + 2);
2✔
929
         print_syntax("-- %s\n", istr(tree_ident2(t)));
2✔
930
      }
931
      dump_block(t, indent);
2✔
932
      tab(indent);
2✔
933
      print_syntax("#end #function;\n");
2✔
934
      return;
2✔
935

936
   case T_PROC_DECL:
×
937
      if (tree_flags(t) & TREE_F_PREDEFINED)
×
938
         print_syntax("-- predefined %s\n", type_pp(tree_type(t)));
×
939
      else {
940
         print_syntax("#procedure %s", istr(tree_ident(t)));
×
941
         dump_generics(t, indent + 2, tree_ports(t) > 0 ? "\n" : "");
×
942
         dump_arguments(t, indent, "");
×
943
         print_syntax(";");
×
944
         dump_wait_level(t);
×
945
         print_syntax("\n");
×
946
         if (tree_has_ident2(t)) {
×
947
            tab(indent + 2);
×
948
            print_syntax("-- %s\n", istr(tree_ident2(t)));
×
949
         }
950
      }
951
      return;
952

953
   case T_PROC_INST:
3✔
954
   case T_PROC_BODY:
955
      print_syntax("#procedure %s", istr(tree_ident(t)));
3✔
956
      dump_type_hint(t);
3✔
957
      dump_generics(t, indent + 2, tree_ports(t) > 0 ? "\n" : "");
5✔
958
      if (tree_kind(t) == T_PROC_INST)
3✔
959
         dump_generic_map(t, indent + 2, tree_ports(t) > 0 ? "\n" : "");
×
960
      dump_arguments(t, indent, "");
3✔
961
      print_syntax(" #is");
3✔
962
      dump_wait_level(t);
3✔
963
      print_syntax("\n");
3✔
964
      if (tree_has_ident2(t)) {
3✔
965
         tab(indent + 2);
3✔
966
         print_syntax("-- %s\n", istr(tree_ident2(t)));
3✔
967
      }
968
      dump_block(t, indent);
3✔
969
      tab(indent);
3✔
970
      print_syntax("#end #procedure;\n");
3✔
971
      return;
3✔
972

973
   case T_HIER:
×
974
      {
975
         const char *kind = "Scope";
×
976
         switch (tree_subkind(t)) {
×
977
         case T_ARCH: kind = "Instance"; break;
×
978
         case T_IF_GENERATE: kind = "If generate"; break;
×
979
         case T_FOR_GENERATE: kind = "For generate"; break;
×
980
         case T_BLOCK: kind = "Block"; break;
×
981
         }
982
         print_syntax("-- %s %s\n", kind, istr(tree_ident2(t)));
×
983
      }
984
      return;
×
985

986
   case T_COMPONENT:
1✔
987
      dump_component(t, indent);
1✔
988
      return;
1✔
989

990
   case T_PROT_DECL:
1✔
991
      print_syntax("#type %s #is #protected\n", istr(tree_ident(t)));
1✔
992
      dump_decls(t, indent + 2);
1✔
993
      tab(indent);
1✔
994
      print_syntax("#end #protected;\n");
1✔
995
      return;
1✔
996

997
   case T_PROT_BODY:
1✔
998
      print_syntax("#type %s #is #protected #body\n", istr(tree_ident(t)));
1✔
999
      dump_decls(t, indent + 2);
1✔
1000
      tab(indent);
1✔
1001
      print_syntax("#end #protected #body;\n");
1✔
1002
      return;
1✔
1003

1004
   case T_FILE_DECL:
×
1005
      print_syntax("#file %s : ", istr(tree_ident(t)));
×
1006
      dump_type(tree_type(t));
×
1007
      if (tree_has_value(t)) {
×
1008
         print_syntax(" #open ");
×
1009
         dump_expr(tree_file_mode(t));
×
1010
         print_syntax(" #is ");
×
1011
         dump_expr(tree_value(t));
×
1012
      }
1013
      print_syntax(";\n");
×
1014
      return;
×
1015

1016
   case T_USE:
×
1017
      dump_use(t);
×
1018
      return;
×
1019

1020
   case T_PACKAGE:
×
1021
   case T_PACK_INST:
1022
      dump_package(t, indent);
×
1023
      return;
×
1024

1025
   case T_PACK_BODY:
×
1026
      dump_package_body(t, indent);
×
1027
      return;
×
1028

1029
   case T_PSL_DECL:
1✔
1030
   case T_PSL_DIRECT:
1031
      dump_psl(t, 0);
1✔
1032
      print_syntax(";\n");
1✔
1033
      return;
1✔
1034

1035
   case T_VIEW_DECL:
1✔
1036
      dump_view_decl(t, 0);
1✔
1037
      return;
1✔
1038

1039
   default:
×
UNCOV
1040
      cannot_dump(t, "decl");
×
1041
   }
1042

1043
   dump_type(tree_type(t));
14✔
1044

1045
   if (tree_kind(t) != T_FIELD_DECL && tree_has_value(t)) {
14✔
1046
      print_syntax(" := ");
6✔
1047
      dump_expr(tree_value(t));
6✔
1048
   }
1049
   print_syntax(";\n");
14✔
1050
}
1051

1052
static void dump_waveforms(tree_t t)
3✔
1053
{
1054
   const int nwaves = tree_waveforms(t);
3✔
1055
   for (int i = 0; i < nwaves; i++) {
7✔
1056
      if (i > 0) print_syntax(", ");
4✔
1057
      dump_waveform(tree_waveform(t, i));
4✔
1058
   }
1059
}
3✔
1060

UNCOV
1061
static void dump_alternative(tree_t t, int indent)
×
1062
{
1063
   tab(indent);
×
1064
   print_syntax("#when ");
×
1065
   if (tree_has_ident(t))
×
1066
      print_syntax("%s: ", istr(tree_ident(t)));
×
1067
   for (unsigned i = 0; i < tree_assocs(t); i++) {
×
1068
      if (i > 0) print_syntax("| ");
×
1069
      tree_t a = tree_assoc(t, i);
×
1070
      switch (tree_subkind(a)) {
×
1071
      case A_NAMED:
×
1072
         dump_expr(tree_name(a));
×
1073
         break;
×
1074
      case A_OTHERS:
×
1075
         print_syntax("#others");
×
1076
         break;
×
1077
      case A_RANGE:
×
1078
         dump_range(tree_range(a, 0));
×
UNCOV
1079
         break;
×
1080
      }
1081
   }
1082
   print_syntax(" =>\n");
×
1083
   if (tree_decls(t) > 0) {
×
1084
      dump_decls(t, indent + 4);
×
1085
      tab(indent + 2);
×
1086
      print_syntax("#begin\n");
×
1087
      dump_stmts(t, indent + 4);
×
1088
      tab(indent + 2);
×
UNCOV
1089
      print_syntax("#end;\n");
×
1090
   }
1091
   else
1092
      dump_stmts(t, indent + 2);
×
UNCOV
1093
}
×
1094

1095
static void dump_psl(tree_t t, int indent)
2✔
1096
{
1097
   if (standard() < STD_08)
2✔
UNCOV
1098
      print_syntax("-- psl ");
×
1099
   psl_dump(tree_psl(t));
2✔
1100
}
2✔
1101

1102
static void dump_instance(tree_t t, int indent)
1✔
1103
{
1104
   switch (tree_class(t)) {
1✔
UNCOV
1105
   case C_ENTITY:        print_syntax("#entity "); break;
×
1106
   case C_COMPONENT:     print_syntax("#component "); break;
1✔
UNCOV
1107
   case C_CONFIGURATION: print_syntax("#configuration "); break;
×
1108
   default: break;
1109
   }
1110

1111
   print_syntax("%s", istr(tree_ident2(t)));
1✔
1112

1113
   const int nparams = tree_params(t);
1✔
1114
   const int ngenmaps = tree_genmaps(t);
1✔
1115

1116
   if (tree_has_spec(t)) {
1✔
1117
      tree_t spec = tree_spec(t);
×
1118
      if (tree_has_value(spec)) {
×
1119
         tree_t bind = tree_value(spec);
×
1120
         LOCAL_TEXT_BUF tb = tb_new();
×
1121
         tb_cat(tb, istr(tree_ident(bind)));
×
1122
         if (tree_has_ident2(bind))
×
1123
            tb_printf(tb, "(%s)", istr(tree_ident2(bind)));
×
UNCOV
1124
         print_syntax("  -- bound to %s\n", tb_get(tb));
×
1125
      }
1126
   }
1127
   else if (nparams > 0 || ngenmaps > 0)
1✔
1128
      print_syntax("\n");
1✔
1129

1130
   dump_generic_map(t, indent + 2, nparams > 0 ? "\n" : "");
1✔
1131
   dump_port_map(t, indent + 2, "");
1✔
1132
   print_syntax(";\n");
1✔
1133
}
1✔
1134

1135
static void dump_stmt(tree_t t, int indent)
18✔
1136
{
1137
   const tree_kind_t kind = tree_kind(t);
21✔
1138
   if (kind == T_VERILOG) {
21✔
1139
      vlog_dump(tree_vlog(t), indent);
×
UNCOV
1140
      return;
×
1141
   }
1142

1143
   tab(indent);
21✔
1144

1145
   if (tree_has_ident(t)) {
21✔
1146
      const char *label = istr(tree_ident(t));
9✔
1147
#if !DUMP_GEN_NAMES
1148
      if (label[0] != '_')   // Skip generated labels
9✔
1149
#endif
1150
         print_syntax("%s: ", label);
5✔
1151
   }
1152

1153
   switch (tree_kind(t)) {
21✔
1154
   case T_PROCESS:
1✔
1155
      dump_address(t);
1✔
1156
      if (tree_flags(t) & TREE_F_POSTPONED)
1✔
UNCOV
1157
         print_syntax("#postponed ");
×
1158
      print_syntax("#process ");
1✔
1159
      if (tree_triggers(t) > 0) {
1✔
1160
         print_syntax("(");
1✔
1161
         for (unsigned i = 0; i < tree_triggers(t); i++) {
2✔
1162
            if (i > 0)
1✔
UNCOV
1163
               print_syntax(", ");
×
1164
            dump_expr(tree_trigger(t, i));
1✔
1165
         }
1166
         print_syntax(") ");
1✔
1167
      }
1168
      print_syntax("#is\n");
1✔
1169
      dump_decls(t, indent + 2);
1✔
1170
      tab(indent);
1✔
1171
      print_syntax("#begin\n");
1✔
1172
      dump_stmts(t, indent + 2);
1✔
1173
      tab(indent);
1✔
1174
      print_syntax("#end #process;\n");
1✔
1175
      return;
1✔
1176

1177
   case T_SIGNAL_ASSIGN:
2✔
1178
      dump_expr(tree_target(t));
2✔
1179
      print_syntax(" <= #reject ");
2✔
1180
      if (tree_has_reject(t))
2✔
1181
         dump_expr(tree_reject(t));
1✔
1182
      else
1183
         print_syntax("0 ps");
1✔
1184
      print_syntax(" #inertial ");
2✔
1185
      dump_waveforms(t);
2✔
1186
      break;
2✔
1187

1188
   case T_FORCE:
×
1189
      dump_expr(tree_target(t));
×
1190
      print_syntax(" <= #force ");
×
1191
      dump_expr(tree_value(t));
×
UNCOV
1192
      break;
×
1193

1194
   case T_RELEASE:
×
1195
      dump_expr(tree_target(t));
×
1196
      print_syntax(" <= #release");
×
UNCOV
1197
      break;
×
1198

1199
   case T_VAR_ASSIGN:
2✔
1200
      dump_expr(tree_target(t));
2✔
1201
      print_syntax(" := ");
2✔
1202
      dump_expr(tree_value(t));
2✔
1203
      break;
2✔
1204

1205
   case T_WAIT:
×
1206
      print_syntax("#wait");
×
1207
      if (tree_triggers(t) > 0) {
×
1208
         print_syntax(" #on ");
×
1209
         for (unsigned i = 0; i < tree_triggers(t); i++) {
×
1210
            if (i > 0)
×
1211
               print_syntax(", ");
×
UNCOV
1212
            dump_expr(tree_trigger(t, i));
×
1213
         }
1214
      }
1215
      if (tree_has_value(t)) {
×
1216
         print_syntax(" #until ");
×
UNCOV
1217
         dump_expr(tree_value(t));
×
1218
      }
1219
      if (tree_has_delay(t)) {
×
1220
         print_syntax(" #for ");
×
UNCOV
1221
         dump_expr(tree_delay(t));
×
1222
      }
1223
      print_syntax(";");
×
1224
      if (tree_flags(t) & TREE_F_STATIC_WAIT)
×
1225
         print_syntax("   -- static");
×
1226
      print_syntax("\n");
×
UNCOV
1227
      return;
×
1228

1229
   case T_BLOCK:
2✔
1230
      dump_address(t);
2✔
1231
      print_syntax("#block #is\n");
2✔
1232
      dump_generics(t, indent + 2, ";\n");
2✔
1233
      dump_generic_map(t, indent + 2, ";\n");
2✔
1234
      dump_ports(t, indent + 2);
2✔
1235
      dump_port_map(t, indent + 2, ";\n");
2✔
1236
      dump_block(t, indent);
2✔
1237
      tab(indent);
2✔
1238
      print_syntax("#end #block;\n");
2✔
1239
      return;
2✔
1240

1241
   case T_SEQUENCE:
×
1242
      print_syntax("#block #is\n");
×
1243
      dump_block(t, indent);
×
1244
      tab(indent);
×
1245
      print_syntax("#end #block;\n");
×
UNCOV
1246
      return;
×
1247

1248
   case T_ASSERT:
2✔
1249
      print_syntax("#assert ");
2✔
1250
      dump_expr(tree_value(t));
2✔
1251
      if (tree_has_message(t)) {
2✔
1252
         print_syntax(" #report ");
×
UNCOV
1253
         dump_expr(tree_message(t));
×
1254
      }
1255
      if (tree_has_severity(t)) {
2✔
1256
         print_syntax(" #severity ");
×
UNCOV
1257
         dump_expr(tree_severity(t));
×
1258
      }
1259
      break;
1260

1261
   case T_REPORT:
1✔
1262
      print_syntax("#report ");
1✔
1263
      dump_expr(tree_message(t));
1✔
1264
      if (tree_has_severity(t)) {
1✔
1265
         print_syntax(" #severity ");
×
UNCOV
1266
         dump_expr(tree_severity(t));
×
1267
      }
1268
      break;
1269

1270
   case T_WHILE:
×
1271
      print_syntax("#while ");
×
1272
      dump_expr(tree_value(t));
×
UNCOV
1273
      print_syntax(" ");
×
1274
      // Fall-through
1275
   case T_LOOP:
×
1276
      print_syntax("#loop\n");
×
1277
      dump_stmts(t, indent + 2);
×
1278
      tab(indent);
×
1279
      print_syntax("#end #loop");
×
UNCOV
1280
      break;
×
1281

1282
   case T_IF:
1283
      for (unsigned i = 0; i < tree_conds(t); i++) {
3✔
1284
         tree_t c = tree_cond(t, i);
2✔
1285
         if (tree_has_value(c)) {
2✔
1286
            if (i > 0)
1✔
UNCOV
1287
               tab(indent);
×
1288
            print_syntax(i > 0 ? "#elsif " : "#if ");
2✔
1289
            dump_expr(tree_value(c));
1✔
1290
            print_syntax(" #then\n");
1✔
1291
         }
1292
         else {
1293
            tab(indent);
1✔
1294
            print_syntax("#else\n");
1✔
1295
         }
1296
         dump_stmts(c, indent + 2);
2✔
1297
      }
1298
      tab(indent);
1✔
1299
      print_syntax("#end #if");
1✔
1300
      break;
1✔
1301

1302
   case T_EXIT:
×
1303
      print_syntax("#exit %s", istr(tree_ident2(t)));
×
1304
      if (tree_has_value(t)) {
×
1305
         print_syntax(" #when ");
×
UNCOV
1306
         dump_expr(tree_value(t));
×
1307
      }
1308
      break;
1309

UNCOV
1310
   case T_CASE:
×
1311
   case T_MATCH_CASE:
1312
      {
1313
         const char *suffix = tree_kind(t) == T_MATCH_CASE ? "?" : "";
×
1314
         print_syntax("#case%s ", suffix);
×
1315
         dump_expr(tree_value(t));
×
1316
         print_syntax(" #is\n");
×
1317
         const int nstmts = tree_stmts(t);
×
1318
         for (int i = 0; i < nstmts; i++)
×
1319
            dump_alternative(tree_stmt(t, i), indent + 2);
×
1320
         tab(indent);
×
UNCOV
1321
         print_syntax("#end #case%s", suffix);
×
1322
      }
UNCOV
1323
      break;
×
1324

1325
   case T_RETURN:
3✔
1326
      print_syntax("#return");
3✔
1327
      if (tree_has_value(t)) {
3✔
1328
         print_syntax(" ");
3✔
1329
         dump_expr(tree_value(t));
3✔
1330
      }
1331
      break;
1332

1333
   case T_COND_RETURN:
×
1334
      print_syntax("#return #when ");
×
1335
      dump_expr(tree_value(t));
×
UNCOV
1336
      break;
×
1337

1338
   case T_FOR:
×
1339
      print_syntax("#for %s #in ", istr(tree_ident(tree_decl(t, 0))));
×
1340
      dump_range(tree_range(t, 0));
×
1341
      print_syntax(" #loop\n");
×
1342
      dump_stmts(t, indent + 2);
×
1343
      tab(indent);
×
1344
      print_syntax("#end #for");
×
UNCOV
1345
      break;
×
1346

1347
   case T_PROT_PCALL:
×
1348
      dump_expr(tree_name(t));
×
UNCOV
1349
      print_syntax(".");
×
1350
      // Fall-through
1351
   case T_PCALL:
×
1352
      if (tree_has_ref(t)) {
×
1353
         tree_t decl = tree_ref(t);
×
1354
         dump_address(decl);
×
UNCOV
1355
         print_syntax("%s", istr(tree_ident(decl)));
×
1356
      }
1357
      else
1358
         print_syntax("%s", istr(tree_ident2(t)));
×
1359
      dump_params(t, tree_param, tree_params(t), NULL);
×
UNCOV
1360
      break;
×
1361

1362
   case T_FOR_GENERATE:
1✔
1363
      print_syntax("#for %s #in ", istr(tree_ident(tree_decl(t, 0))));
1✔
1364
      dump_range(tree_range(t, 0));
1✔
1365
      print_syntax(" #generate\n");
1✔
1366
      dump_decls(t, indent + 2);
1✔
1367
      tab(indent);
1✔
1368
      print_syntax("#begin\n");
1✔
1369
      dump_stmts(t, indent + 2);
1✔
1370
      tab(indent);
1✔
1371
      print_syntax("#end #generate");
1✔
1372
      break;
1✔
1373

UNCOV
1374
   case T_CASE_GENERATE:
×
1375
      {
1376
         print_syntax("#case ");
×
1377
         dump_expr(tree_value(t));
×
UNCOV
1378
         print_syntax(" #generate\n");
×
1379

1380
         const int nstmts = tree_stmts(t);
×
1381
         for (int i = 0; i < nstmts; i++)
×
UNCOV
1382
            dump_alternative(tree_stmt(t, i), indent + 2);
×
1383

1384
         print_syntax("#end #generate");
×
UNCOV
1385
         tab(indent);
×
1386
      }
UNCOV
1387
      break;
×
1388

1389
   case T_IF_GENERATE:
1390
      for (unsigned i = 0; i < tree_conds(t); i++) {
×
1391
         tree_t c = tree_cond(t, i);
×
1392
         if (tree_has_value(c)) {
×
1393
            if (i > 0)
×
1394
               tab(indent);
×
1395
            print_syntax(i > 0 ? "#elsif " : "#if ");
×
1396
            dump_expr(tree_value(c));
×
UNCOV
1397
            print_syntax(" #generate\n");
×
1398
         }
1399
         else {
1400
            tab(indent);
×
UNCOV
1401
            print_syntax("#else\n");
×
1402
         }
1403
         for (unsigned i = 0; i < tree_stmts(c); i++)
×
UNCOV
1404
            dump_stmt(tree_stmt(c, i), indent + 2);
×
1405
      }
1406
      tab(indent);
×
1407
      print_syntax("#end #generate");
×
UNCOV
1408
      break;
×
1409

1410
   case T_INSTANCE:
1✔
1411
      dump_instance(t, indent);
1✔
1412
      return;
1✔
1413

1414
   case T_NEXT:
×
1415
      print_syntax("#next");
×
1416
      if (tree_has_value(t)) {
×
1417
         print_syntax(" #when ");
×
UNCOV
1418
         dump_expr(tree_value(t));
×
1419
      }
1420
      break;
1421

1422
   case T_NULL:
×
1423
      print_syntax("#null");
×
UNCOV
1424
      break;
×
1425

1426
   case T_COND_ASSIGN:
1✔
1427
      dump_expr(tree_target(t));
1✔
1428
      print_syntax(" <= ");
1✔
1429
      if (tree_has_guard(t))
1✔
UNCOV
1430
         print_syntax("#guarded ");
×
1431
      for (int i = 0; i < tree_conds(t); i++) {
2✔
1432
         tree_t c = tree_cond(t, i);
1✔
1433
         dump_waveforms(tree_stmt(c, 0));
1✔
1434
         if (tree_has_value(c)) {
1✔
1435
            print_syntax(" #when ");
×
UNCOV
1436
            dump_expr(tree_value(c));
×
1437
         }
1438
      }
1439
      break;
1440

1441
   case T_SELECT:
×
1442
      print_syntax(" <= ");
×
1443
      if (tree_has_guard(t)) print_syntax("#guarded ");
×
1444
      color_printf("$red$/* TODO: T_SELECT */$$");
×
UNCOV
1445
      break;
×
1446

1447
   case T_CONCURRENT:
3✔
1448
      if (tree_flags(t) & TREE_F_POSTPONED)
3✔
UNCOV
1449
         print_syntax("#postponed ");
×
1450
      dump_stmt(tree_stmt(t, 0), 0);
3✔
1451
      return;
3✔
1452

1453
   case T_DUMMY_DRIVER:
×
1454
      print_syntax("-- dummy driver for ");
×
1455
      dump_expr(tree_target(t));
×
1456
      print_syntax("\n");
×
UNCOV
1457
      return;
×
1458

1459
   case T_PSL_DIRECT:
1✔
1460
      dump_psl(t, indent);
1✔
1461
      break;
1✔
1462

1463
   default:
×
UNCOV
1464
      cannot_dump(t, "stmt");
×
1465
   }
1466

1467
   print_syntax(";\n");
14✔
1468
}
1469

1470
static void dump_port(tree_t t, int indent)
103✔
1471
{
1472
   tab(indent);
103✔
1473
   dump_address(t);
103✔
1474

1475
   if (tree_flags(t) & TREE_F_PREDEFINED)
103✔
1476
      print_syntax("-- predefined ");
80✔
1477

1478
   const class_t class = tree_class(t);
103✔
1479
   print_syntax("#%s %s", class_str(class), istr(tree_ident(t)));
103✔
1480

1481
   const port_mode_t mode = tree_subkind(t);
103✔
1482

1483
   type_t type = get_type_or_null(t);
103✔
1484
   if (class == C_PACKAGE) {
103✔
1485
      print_syntax(" #is #new ");
×
UNCOV
1486
      dump_expr(tree_value(t));
×
1487
   }
1488
   else if (class == C_TYPE && type_kind(type) == T_GENERIC) {
103✔
1489
      print_syntax(" #is ");
10✔
1490

1491
      switch (type_subkind(type)) {
10✔
1492
      case GTYPE_PRIVATE:
2✔
1493
         print_syntax("#private");
2✔
1494
         break;
2✔
1495
      case GTYPE_SCALAR:
1✔
1496
         print_syntax("<>");
1✔
1497
         break;
1✔
1498
      case GTYPE_DISCRETE:
1✔
1499
         print_syntax("(<>)");
1✔
1500
         break;
1✔
1501
      case GTYPE_INTEGER:
1✔
1502
         print_syntax("#range <>");
1✔
1503
         break;
1✔
1504
      case GTYPE_PHYSICAL:
1✔
1505
         print_syntax("#units <>");
1✔
1506
         break;
1✔
1507
      case GTYPE_FLOATING:
1✔
1508
         print_syntax("#range <> . <>");
1✔
1509
         break;
1✔
1510
      case GTYPE_ARRAY:
1✔
1511
         {
1512
            print_syntax("#array (");
1✔
1513
            const int nindex = type_indexes(type);
1✔
1514
            for (int i = 0; i < nindex; i++) {
2✔
1515
               if (i > 0) print_syntax(", ");
1✔
1516
               dump_type(type_index(type, i));
1✔
1517
               print_syntax(" #range <>");
1✔
1518
            }
1519
            print_syntax(") #of ");
1✔
1520
            dump_type(type_elem(type));
1✔
1521
         }
1522
         break;
1✔
1523
      case GTYPE_ACCESS:
1✔
1524
         print_syntax("#access ..");
1✔
1525
         break;
1✔
1526
      case GTYPE_FILE:
1✔
1527
         print_syntax("#file #of ..");
1✔
1528
         break;
1✔
1529
      }
1530
   }
1531
   else if (mode == PORT_ARRAY_VIEW || mode == PORT_RECORD_VIEW) {
93✔
1532
      print_syntax(" : #view ");
2✔
1533
      dump_expr(tree_value(t));
2✔
1534
   }
1535
   else {
1536
      static const char *map[] = {
91✔
1537
         "??", "in", "out", "inout", "buffer", "linkage"
1538
      };
1539
      print_syntax(" : #%s ", map[mode]);
91✔
1540
      dump_type(type);
91✔
1541

1542
      if (tree_has_value(t)) {
91✔
1543
         print_syntax(" := ");
81✔
1544
         dump_expr(tree_value(t));
81✔
1545
      }
1546
   }
1547
}
103✔
1548

1549
static void dump_context(tree_t t, int indent)
7✔
1550
{
1551
   const int nctx = tree_contexts(t);
7✔
1552
   for (int i = 0; i < nctx; i++) {
28✔
1553
      tree_t c = tree_context(t, i);
21✔
1554
      switch (tree_kind(c)) {
21✔
1555
      case T_LIBRARY:
14✔
1556
         switch (is_well_known(tree_ident(c))) {
14✔
1557
         case W_STD:
1558
         case W_WORK:
1559
            break;
1560
         default:
×
UNCOV
1561
            print_syntax("#library %s;\n", istr(tree_ident(c)));
×
1562
         }
1563
         break;
1564

1565
      case T_USE:
7✔
1566
         dump_use(c);
7✔
1567
         break;
7✔
1568

1569
      case T_CONTEXT_REF:
×
1570
         print_syntax("#context %s;\n", istr(tree_ident(t)));
×
UNCOV
1571
         break;
×
1572

1573
      default:
1574
         break;
1575
      }
1576

1577
      tab(indent);
21✔
1578
   }
1579

1580
   if (nctx > 0) {
7✔
1581
      print_syntax("\n");
7✔
1582
      tab(indent);
7✔
1583
   }
1584
}
7✔
1585

UNCOV
1586
static void dump_elab(tree_t t)
×
1587
{
1588
   dump_context(t, 0);
×
1589
   dump_address(t);
×
1590
   print_syntax("#entity %s #is\n#end #entity;\n\n", istr(tree_ident(t)));
×
1591
   print_syntax("#architecture #elab #of %s #is\n", istr(tree_ident(t)));
×
1592
   dump_decls(t, 2);
×
1593
   print_syntax("#begin\n");
×
1594
   for (unsigned i = 0; i < tree_stmts(t); i++)
×
1595
      dump_stmt(tree_stmt(t, i), 2);
×
1596
   print_syntax("#end #architecture;\n\n");
×
UNCOV
1597
}
×
1598

1599
static void dump_entity(tree_t t)
2✔
1600
{
1601
   dump_context(t, 0);
2✔
1602
   dump_address(t);
2✔
1603
   print_syntax("#entity %s #is\n", istr(tree_ident(t)));
2✔
1604
   dump_generics(t, 2, ";\n");
2✔
1605
   dump_ports(t, 2);
2✔
1606
   dump_decls(t, 2);
2✔
1607
   if (tree_stmts(t) > 0) {
2✔
1608
      print_syntax("#begin\n");
×
1609
      for (unsigned i = 0; i < tree_stmts(t); i++) {
×
UNCOV
1610
         dump_stmt(tree_stmt(t, i), 2);
×
1611
      }
1612
   }
1613
   print_syntax("#end #entity;\n\n");
2✔
1614
}
2✔
1615

1616
static void dump_decls(tree_t t, int indent)
18✔
1617
{
1618
   const int ndecls = tree_decls(t);
18✔
1619
   bool was_body = false;
18✔
1620
   for (unsigned i = 0; i < ndecls; i++) {
41✔
1621
      tree_t d = tree_decl(t, i);
23✔
1622
      tree_kind_t dkind = tree_kind(d);
23✔
1623
      const bool is_body = dkind == T_FUNC_BODY || dkind == T_PROT_BODY
46✔
1624
         || dkind == T_PROC_BODY;
23✔
1625
      if ((was_body && !is_body) || (is_body && i > 0))
23✔
1626
         print_syntax("\n");
5✔
1627
      was_body = is_body;
23✔
1628
      dump_decl(d, indent);
23✔
1629
   }
1630
}
18✔
1631

1632
static void dump_arch(tree_t t)
2✔
1633
{
1634
   dump_context(t, 0);
2✔
1635
   dump_address(t);
2✔
1636
   print_syntax("#architecture %s #of %s #is\n",
2✔
1637
                istr(tree_ident(t)), istr(tree_ident2(t)));
1638
   dump_decls(t, 2);
2✔
1639
   print_syntax("#begin\n");
2✔
1640
   dump_stmts(t, 2);
2✔
1641
   print_syntax("#end #architecture;\n\n");
2✔
1642
}
2✔
1643

1644
static void dump_package(tree_t t, int indent)
1✔
1645
{
1646
   dump_context(t, indent);
1✔
1647
   dump_address(t);
1✔
1648
   print_syntax("#package %s #is\n", istr(tree_ident(t)));
1✔
1649
   if (tree_kind(t) == T_PACK_INST && tree_has_ref(t)) {
1✔
1650
      tab(indent);
×
UNCOV
1651
      print_syntax("  -- Instantiated from %s\n", istr(tree_ident(tree_ref(t))));
×
1652
   }
1653
   dump_generics(t, indent + 2, ";\n");
1✔
1654
   dump_generic_map(t, indent + 2, ";\n");
1✔
1655
   dump_decls(t, indent + 2);
1✔
1656
   tab(indent);
1✔
1657
   print_syntax("#end #package;\n\n");
1✔
1658
}
1✔
1659

1660
static void dump_package_body(tree_t t, int indent)
2✔
1661
{
1662
   dump_context(t, indent);
2✔
1663
   dump_address(t);
2✔
1664
   print_syntax("#package #body %s #is\n", istr(tree_ident(t)));
2✔
1665
   dump_decls(t, indent + 2);
2✔
1666
   tab(indent);
2✔
1667
   print_syntax("#end #package #body;\n\n");
2✔
1668
}
2✔
1669

UNCOV
1670
static void dump_configuration(tree_t t)
×
1671
{
1672
   dump_address(t);
×
UNCOV
1673
   print_syntax("#configuration %s #of %s #is\n",
×
1674
          istr(tree_ident(t)), istr(tree_ident2(t)));
1675
   dump_decls(t, 2);
×
1676
   print_syntax("#end #configuration\n");
×
UNCOV
1677
}
×
1678

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

1789
void dump(tree_t t)
21✔
1790
{
1791
   vhdl_dump(t, 0);
21✔
1792
   print_syntax("\r");
21✔
1793
}
21✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc