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

nickg / nvc / 16099227452

06 Jul 2025 12:45PM UTC coverage: 92.335% (+0.05%) from 92.284%
16099227452

push

github

nickg
Handle underscores in Verilog decimal literals

Fixes #1230

18 of 20 new or added lines in 1 file covered. (90.0%)

598 existing lines in 16 files now uncovered.

71069 of 76969 relevant lines covered (92.33%)

564781.41 hits per line

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

94.66
/src/elab.c
1
//
2
//  Copyright (C) 2011-2025  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 "array.h"
20
#include "common.h"
21
#include "diag.h"
22
#include "driver.h"
23
#include "eval.h"
24
#include "hash.h"
25
#include "inst.h"
26
#include "lib.h"
27
#include "lower.h"
28
#include "mask.h"
29
#include "object.h"
30
#include "option.h"
31
#include "phase.h"
32
#include "psl/psl-phase.h"
33
#include "rt/model.h"
34
#include "rt/structs.h"
35
#include "thread.h"
36
#include "type.h"
37
#include "vlog/vlog-defs.h"
38
#include "vlog/vlog-node.h"
39
#include "vlog/vlog-phase.h"
40
#include "vlog/vlog-util.h"
41

42
#include <assert.h>
43
#include <stdarg.h>
44
#include <stdlib.h>
45
#include <inttypes.h>
46

47
#define MAX_DEPTH 127    // Limited by vcode type indexes
48

49
typedef A(tree_t) tree_list_t;
50

51
typedef struct _elab_ctx elab_ctx_t;
52
typedef struct _generic_list generic_list_t;
53
typedef struct _elab_instance elab_instance_t;
54

55
typedef struct _elab_ctx {
56
   const elab_ctx_t *parent;
57
   tree_t            out;
58
   object_t         *root;
59
   tree_t            inst;
60
   tree_t            config;
61
   ident_t           dotted;
62
   ident_t           prefix[2];
63
   lib_t             library;
64
   hash_t           *generics;
65
   jit_t            *jit;
66
   unit_registry_t  *registry;
67
   mir_context_t    *mir;
68
   lower_unit_t     *lowered;
69
   cover_data_t     *cover;
70
   sdf_file_t       *sdf;
71
   driver_set_t     *drivers;
72
   hash_t           *modcache;
73
   rt_model_t       *model;
74
   rt_scope_t       *scope;
75
   unsigned          depth;
76
} elab_ctx_t;
77

78
typedef struct {
79
   ident_t     search;
80
   ident_t     chosen;
81
   timestamp_t mtime;
82
} lib_search_params_t;
83

84
typedef struct {
85
   tree_t  comp;
86
   tree_t *result;
87
} synth_binding_params_t;
88

89
typedef struct _generic_list {
90
   generic_list_t *next;
91
   ident_t         name;
92
   char           *value;
93
} generic_list_t;
94

95
typedef struct {
96
   tree_t           wrap;
97
   tree_t           entity;
98
   vlog_node_t      module;
99
   elab_instance_t *instances;
100
} mod_cache_t;
101

102
typedef struct _elab_instance {
103
   elab_instance_t *next;
104
   mod_cache_t     *module;
105
   vlog_node_t      body;
106
   tree_t           block;
107
   tree_t           wrap;
108
} elab_instance_t;
109

110
static void elab_block(tree_t t, const elab_ctx_t *ctx);
111
static void elab_stmts(tree_t t, const elab_ctx_t *ctx);
112
static void elab_decls(tree_t t, const elab_ctx_t *ctx);
113
static void elab_push_scope(tree_t t, elab_ctx_t *ctx);
114
static void elab_pop_scope(elab_ctx_t *ctx);
115
static void elab_verilog_stmts(vlog_node_t v, const elab_ctx_t *ctx);
116

117
static generic_list_t *generic_override = NULL;
118

119
static lib_t elab_find_lib(ident_t name, const elab_ctx_t *ctx)
7,663✔
120
{
121
   ident_t lib_name = ident_until(name, '.');
7,663✔
122
   if (lib_name == well_known(W_WORK))
7,663✔
123
      return ctx->library;
7,621✔
124
   else
125
      return lib_require(lib_name);
42✔
126
}
127

128
static void elab_find_arch_cb(lib_t lib, ident_t name, int kind, void *context)
29,165✔
129
{
130
   lib_search_params_t *params = context;
29,165✔
131

132
   ident_t prefix = ident_until(name, '-');
29,165✔
133

134
   if (kind != T_ARCH || prefix != params->search)
29,165✔
135
      return;
136

137
   const timestamp_t new_mtime = lib_get_mtime(lib, name);
7,687✔
138

139
   if (params->chosen == NULL) {
7,687✔
140
      params->chosen = name;
7,663✔
141
      params->mtime  = new_mtime;
7,663✔
142
   }
143
   else if (new_mtime > params->mtime) {
24✔
144
      params->chosen = name;
20✔
145
      params->mtime  = new_mtime;
20✔
146
   }
147
   else if (new_mtime == params->mtime) {
4✔
148
      // Use source file line numbers to break the tie
149
      tree_t old_unit = lib_get(lib, params->chosen);
4✔
150
      tree_t new_unit = lib_get(lib, name);
4✔
151

152
      if (old_unit == NULL)
4✔
153
         params->chosen = name;
×
154
      else if (new_unit != NULL) {
4✔
155
         const loc_t *old_loc = tree_loc(old_unit);
4✔
156
         const loc_t *new_loc = tree_loc(new_unit);
4✔
157

158
         if (old_loc->file_ref != new_loc->file_ref)
4✔
159
            warnf("cannot determine which of %s and %s is most recently "
×
160
                  "modified", istr(params->chosen), istr(name));
161
         else if (new_loc->first_line >= old_loc->first_line)
4✔
162
            params->chosen = name;
4✔
163
      }
164
   }
165
}
166

167
static tree_t elab_pick_arch(const loc_t *loc, tree_t entity,
7,663✔
168
                             const elab_ctx_t *ctx)
169
{
170
   // When an explicit architecture name is not given select the most
171
   // recently analysed architecture of this entity
172

173
   ident_t name = tree_ident(entity);
7,663✔
174
   lib_t lib = elab_find_lib(name, ctx);
7,663✔
175
   ident_t search_name =
7,663✔
176
      ident_prefix(lib_name(lib), ident_rfrom(name, '.'), '.');
7,663✔
177

178
   lib_search_params_t params = {
7,663✔
179
      .search = search_name
180
   };
181
   lib_walk_index(lib, elab_find_arch_cb, &params);
7,663✔
182

183
   if (params.chosen == NULL)
7,663✔
184
      fatal_at(loc, "no suitable architecture for %s", istr(search_name));
×
185

186
   return lib_get(lib, params.chosen);
7,663✔
187
}
188

189
static tree_t elab_copy(tree_t t, const elab_ctx_t *ctx)
8,135✔
190
{
191
   tree_list_t roots = AINIT;
8,135✔
192
   switch (tree_kind(t)) {
8,135✔
193
   case T_ARCH:
7,950✔
194
      APUSH(roots, tree_primary(t));
7,950✔
195
      APUSH(roots, t);    // Architecture must be processed last
7,950✔
196
      break;
7,950✔
197
   case T_BLOCK_CONFIG:
185✔
198
      {
199
         tree_t arch = tree_ref(t);
185✔
200
         assert(tree_kind(arch) == T_ARCH);
185✔
201

202
         APUSH(roots, tree_primary(arch));
185✔
203
         APUSH(roots, arch);
185✔
204
         APUSH(roots, t);
185✔
205
      }
206
      break;
185✔
207
   default:
×
208
      fatal_trace("unexpected %s in elab_copy", tree_kind_str(tree_kind(t)));
209
   }
210

211
   tree_global_flags_t gflags = 0;
212
   for (int i = 0; i < roots.count; i++)
24,590✔
213
      gflags |= tree_global_flags(roots.items[i]);
16,455✔
214

215
   new_instance(roots.items, roots.count, ctx->dotted, ctx->prefix,
8,135✔
216
                ARRAY_LEN(ctx->prefix));
217

218
   tree_t copy = roots.items[roots.count - 1];
8,135✔
219
   ACLEAR(roots);
8,135✔
220

221
   tree_set_global_flags(copy, gflags);
8,135✔
222
   return copy;
8,135✔
223
}
224

225
static void elab_subprogram_prefix(tree_t arch, elab_ctx_t *ctx)
8,135✔
226
{
227
   // Get the prefix of unit that will need to be rewritten in
228
   // subprogram names
229

230
   assert(tree_kind(arch) == T_ARCH);
8,135✔
231

232
   // The order is important here because the architecture name is
233
   // prefixed with the entity
234
   ctx->prefix[0] = tree_ident(arch);
8,135✔
235
   ctx->prefix[1] = tree_ident(tree_primary(arch));
8,135✔
236
}
8,135✔
237

238
static mod_cache_t *elab_cached_module(vlog_node_t mod, const elab_ctx_t *ctx)
217✔
239
{
240
   assert(is_top_level(mod));
217✔
241

242
   mod_cache_t *mc = hash_get(ctx->modcache, mod);
217✔
243
   if (mc != NULL)
217✔
244
      return mc;
245

246
   mc = xcalloc(sizeof(mod_cache_t));
167✔
247
   mc->module = mod;
167✔
248

249
   mc->wrap = tree_new(T_VERILOG);
167✔
250
   tree_set_loc(mc->wrap, vlog_loc(mod));
167✔
251
   tree_set_ident(mc->wrap, vlog_ident(mod));
167✔
252
   tree_set_vlog(mc->wrap, mod);
167✔
253

254
   hash_put(ctx->modcache, mod, mc);
167✔
255
   return mc;
167✔
256
}
257

258
static elab_instance_t *elab_new_instance(vlog_node_t mod, vlog_node_t inst,
182✔
259
                                          const elab_ctx_t *ctx)
260
{
261
   assert(is_top_level(mod));
182✔
262

263
   mod_cache_t *mc = elab_cached_module(mod, ctx);
182✔
264

265
   elab_instance_t *ei = xcalloc(sizeof(elab_instance_t));
182✔
266
   ei->next   = mc->instances;
182✔
267
   ei->module = mc;
182✔
268
   ei->body   = vlog_new_instance(mod, inst, ctx->dotted);
182✔
269

270
   ei->wrap = tree_new(T_VERILOG);
182✔
271
   tree_set_loc(ei->wrap, vlog_loc(mod));
182✔
272
   tree_set_ident(ei->wrap, vlog_ident(mod));
182✔
273
   tree_set_vlog(ei->wrap, ei->body);
182✔
274

275
   ei->block = tree_new(T_BLOCK);
182✔
276
   tree_set_loc(ei->block, vlog_loc(inst));
182✔
277
   tree_set_ident(ei->block, vlog_ident(inst));
182✔
278

279
   vlog_trans(ei->body, ei->block);
182✔
280

281
   mc->instances = ei;
182✔
282

283
   return ei;
182✔
284
}
285

286
static bool elab_synth_binding_cb(lib_t lib, void *__ctx)
37✔
287
{
288
   synth_binding_params_t *params = __ctx;
37✔
289

290
   ident_t name = ident_prefix(lib_name(lib), tree_ident(params->comp), '.');
37✔
291
   *(params->result) = lib_get(lib, name);
37✔
292

293
   return *(params->result) == NULL;
37✔
294
}
295

296
static tree_t elab_to_vhdl(type_t from, type_t to)
34✔
297
{
298
   static struct {
34✔
299
      const verilog_type_t from_id;
300
      const ieee_type_t    to_id;
301
      const char *const    func;
302
      type_t               from;
303
      type_t               to;
304
      tree_t               decl;
305
   } table[] = {
306
      { VERILOG_LOGIC, IEEE_STD_LOGIC, "NVC.VERILOG.TO_VHDL(" T_LOGIC ")U" },
307
      { VERILOG_NET_VALUE, IEEE_STD_LOGIC,
308
        "NVC.VERILOG.TO_VHDL(" T_NET_VALUE ")U" },
309
      { VERILOG_WIRE_ARRAY, IEEE_STD_ULOGIC_VECTOR,
310
        "NVC.VERILOG.TO_VHDL(" T_WIRE_ARRAY ")Y" },
311
      { VERILOG_WIRE_ARRAY, IEEE_STD_LOGIC_VECTOR,
312
        "NVC.VERILOG.TO_VHDL(" T_WIRE_ARRAY ")Y" },
313
   };
314

315
   INIT_ONCE({
134✔
316
         for (int i = 0; i < ARRAY_LEN(table); i++) {
317
            table[i].from = verilog_type(table[i].from_id);
318
            table[i].to   = ieee_type(table[i].to_id);
319
            table[i].decl = verilog_func(ident_new(table[i].func));
320
         }
321
      });
322

323
   for (int i = 0; i < ARRAY_LEN(table); i++) {
71✔
324
      if (type_eq(table[i].from, from) && type_eq(table[i].to, to))
70✔
325
         return table[i].decl;
33✔
326
   }
327

328
   return NULL;
329
}
330

331
static tree_t elab_to_verilog(type_t from, type_t to)
77✔
332
{
333
   static struct {
77✔
334
      const ieee_type_t    from_id;
335
      const verilog_type_t to_id;
336
      const char *const    func;
337
      type_t               from;
338
      type_t               to;
339
      tree_t               decl;
340
   } table[] = {
341
      { IEEE_STD_ULOGIC, VERILOG_LOGIC, "NVC.VERILOG.TO_VERILOG(U)" T_LOGIC },
342
      { IEEE_STD_ULOGIC, VERILOG_NET_VALUE,
343
        "NVC.VERILOG.TO_VERILOG(U)" T_NET_VALUE },
344
      { IEEE_STD_ULOGIC_VECTOR, VERILOG_WIRE_ARRAY,
345
        "NVC.VERILOG.TO_VERILOG(Y)" T_NET_ARRAY },
346
   };
347

348
   INIT_ONCE({
152✔
349
         for (int i = 0; i < ARRAY_LEN(table); i++) {
350
           table[i].from = ieee_type(table[i].from_id);
351
           table[i].to   = verilog_type(table[i].to_id);
352
           table[i].decl = verilog_func(ident_new(table[i].func));
353
         }
354
      });
355

356
   for (int i = 0; i < ARRAY_LEN(table); i++) {
154✔
357
      if (type_eq(table[i].from, from) && type_eq(table[i].to, to))
154✔
358
         return table[i].decl;
77✔
359
   }
360

361
   return NULL;
362
}
363

364
static tree_t elab_mixed_binding(tree_t comp, mod_cache_t *mc)
35✔
365
{
366
   assert(tree_kind(comp) == T_COMPONENT);
35✔
367

368
   if (mc->entity == NULL) {
35✔
369
      mc->entity = tree_new(T_ENTITY);
29✔
370
      tree_set_ident(mc->entity, vlog_ident(mc->module));
29✔
371
      tree_set_loc(mc->entity, vlog_loc(mc->module));
29✔
372

373
      vlog_trans(mc->module, mc->entity);
29✔
374
   }
375

376
   tree_t bind = tree_new(T_BINDING);
35✔
377
   tree_set_ident(bind, vlog_ident(mc->module));
35✔
378
   tree_set_loc(bind, tree_loc(comp));
35✔
379
   tree_set_ref(bind, mc->wrap);
35✔
380
   tree_set_class(bind, C_ENTITY);
35✔
381

382
   const int vhdl_nports = tree_ports(comp);
35✔
383
   const int vlog_nports = vlog_ports(mc->module);
35✔
384

385
   bit_mask_t have;
35✔
386
   mask_init(&have, vhdl_nports);
35✔
387

388
   bool have_named = false;
35✔
389
   for (int i = 0; i < vlog_nports; i++) {
145✔
390
      vlog_node_t ref = vlog_port(mc->module, i);
112✔
391
      assert(vlog_kind(ref) == V_REF);
112✔
392

393
      vlog_node_t mport = vlog_ref(ref);
112✔
394
      assert(vlog_kind(mport) == V_PORT_DECL);
112✔
395

396
      ident_t name = vlog_ident2(mport);
112✔
397

398
      tree_t vport = tree_port(mc->entity, i);
112✔
399
      assert(tree_ident(vport) == vlog_ident(mport));
112✔
400

401
      tree_t cport = NULL;
248✔
402
      for (int j = 0; j < vhdl_nports; j++) {
248✔
403
         tree_t pj = tree_port(comp, j);
247✔
404
         if (ident_casecmp(tree_ident(pj), name)) {
247✔
405
            cport = pj;
111✔
406
            mask_set(&have, j);
111✔
407
            break;
408
         }
409
      }
410

411
      if (cport == NULL) {
112✔
412
         error_at(tree_loc(comp), "missing matching VHDL port declaration for "
1✔
413
                  "Verilog port '%s' in component %s", istr(vlog_ident(mport)),
414
                  istr(tree_ident(comp)));
415
         return NULL;
1✔
416
      }
417

418
      type_t btype = tree_type(cport);
111✔
419
      type_t vtype = tree_type(vport);
111✔
420

421
      if (vlog_subkind(mport) == V_PORT_INPUT) {
111✔
422
         tree_t func = elab_to_verilog(btype, vtype);
77✔
423
         if (func == NULL) {
77✔
UNCOV
424
            error_at(tree_loc(cport), "cannot connect VHDL signal with type "
×
425
                     "%s to Verilog input port '%s'", type_pp(btype),
426
                     istr(vlog_ident(mport)));
UNCOV
427
            return NULL;
×
428
         }
429

430
         tree_t conv = tree_new(T_CONV_FUNC);
77✔
431
         tree_set_loc(conv, tree_loc(cport));
77✔
432
         tree_set_ref(conv, func);
77✔
433
         tree_set_ident(conv, tree_ident(func));
77✔
434
         tree_set_type(conv, type_result(tree_type(func)));
77✔
435
         tree_set_value(conv, make_ref(cport));
77✔
436

437
         if (have_named)
77✔
438
            add_param(bind, conv, P_NAMED, make_ref(vport));
20✔
439
         else
440
            add_param(bind, conv, P_POS, NULL);
57✔
441
      }
442
      else {
443
         tree_t func = elab_to_vhdl(vtype, btype);
34✔
444
         if (func == NULL) {
34✔
445
            error_at(tree_loc(cport), "cannot connect VHDL signal with type "
1✔
446
                     "%s to Verilog output port '%s'", type_pp(btype),
447
                     istr(vlog_ident(mport)));
448
            return NULL;
1✔
449
         }
450

451
         tree_t conv = tree_new(T_CONV_FUNC);
33✔
452
         tree_set_loc(conv, tree_loc(cport));
33✔
453
         tree_set_ref(conv, func);
33✔
454
         tree_set_ident(conv, tree_ident(func));
33✔
455
         tree_set_type(conv, type_result(tree_type(func)));
33✔
456
         tree_set_value(conv, make_ref(vport));
33✔
457

458
         add_param(bind, make_ref(cport), P_NAMED, conv);
33✔
459
         have_named = true;
33✔
460
      }
461
   }
462

463
   for (int i = 0; i < vhdl_nports; i++) {
141✔
464
      if (!mask_test(&have, i)) {
108✔
465
         tree_t p = tree_port(comp, i);
1✔
466
         diag_t *d = diag_new(DIAG_ERROR, tree_loc(p));
1✔
467
         diag_printf(d, "port %s not found in Verilog module %s",
1✔
468
                     istr(tree_ident(p)), istr(vlog_ident2(mc->module)));
469
         diag_emit(d);
1✔
470
      }
471
   }
472

473
   mask_free(&have);
33✔
474

475
   const int vhdl_ngenerics = tree_generics(comp);
33✔
476
   const int vlog_ndecls = vlog_decls(mc->module);
33✔
477

478
   mask_init(&have, vhdl_ngenerics);
33✔
479

480
   for (int i = 0, nth = 0; i < vlog_ndecls; i++) {
256✔
481
      vlog_node_t d = vlog_decl(mc->module, i);
225✔
482
      if (vlog_kind(d) != V_PARAM_DECL)
225✔
483
         continue;
216✔
484

485
      ident_t name = vlog_ident(d);
9✔
486

487
      tree_t eg = tree_generic(mc->entity, nth++);
9✔
488
      assert(tree_ident(eg) == name);
9✔
489

490
      tree_t cg = NULL;
9✔
491
      for (int j = 0; j < vhdl_ngenerics; j++) {
9✔
492
         tree_t gj = tree_generic(comp, j);
8✔
493
         if (ident_casecmp(tree_ident(gj), name)) {
8✔
494
            cg = gj;
8✔
495
            mask_set(&have, j);
8✔
496
            break;
497
         }
498
      }
499

500
      if (cg == NULL) {
9✔
501
         error_at(tree_loc(comp), "missing matching VHDL generic declaration "
1✔
502
                  "for Verilog parameter '%s' in component %s", istr(name),
503
                  istr(tree_ident(comp)));
504
         return NULL;
1✔
505
      }
506

507
      type_t ctype = tree_type(cg);
8✔
508
      type_t etype = tree_type(eg);
8✔
509
      assert(type_eq(etype, std_type(NULL, STD_INTEGER)));
8✔
510

511
      if (!type_eq(ctype, etype)) {
8✔
512
         error_at(tree_loc(cg), "generic %s should have type %s to match "
1✔
513
                  "corresponding Verilog parameter", istr(tree_ident(cg)),
514
                  type_pp(etype));
515
         return NULL;
1✔
516
      }
517

518
      tree_t map = tree_new(T_PARAM);
7✔
519
      tree_set_subkind(map, P_POS);
7✔
520
      tree_set_pos(map, tree_genmaps(bind));
7✔
521
      tree_set_value(map, make_ref(cg));
7✔
522

523
      tree_add_genmap(bind, map);
7✔
524
   }
525

526
   for (int i = 0; i < vhdl_ngenerics; i++) {
39✔
527
      if (!mask_test(&have, i)) {
8✔
528
         tree_t g = tree_generic(comp, i);
1✔
529
         diag_t *d = diag_new(DIAG_ERROR, tree_loc(g));
1✔
530
         diag_printf(d, "generic %s not found in Verilog module %s",
1✔
531
                     istr(tree_ident(g)), istr(vlog_ident2(mc->module)));
532
         diag_emit(d);
1✔
533
      }
534
   }
535

536
   mask_free(&have);
31✔
537
   return bind;
31✔
538
}
539

540
static tree_t elab_verilog_conversion(type_t from, type_t to)
24✔
541
{
542
   static struct {
24✔
543
      const verilog_type_t from_id;
544
      const verilog_type_t to_id;
545
      const char *const    func;
546
      type_t               from;
547
      type_t               to;
548
      tree_t               decl;
549
   } table[] = {
550
      { VERILOG_NET_VALUE, VERILOG_LOGIC,
551
        "NVC.VERILOG.TO_LOGIC(" T_NET_VALUE ")" T_LOGIC },
552
      { VERILOG_NET_ARRAY, VERILOG_LOGIC_ARRAY,
553
        "NVC.VERILOG.TO_LOGIC(" T_NET_ARRAY ")" T_LOGIC_ARRAY },
554
      { VERILOG_WIRE_ARRAY, VERILOG_LOGIC_ARRAY,
555
        "NVC.VERILOG.TO_LOGIC(" T_WIRE_ARRAY ")" T_LOGIC_ARRAY },
556
      { VERILOG_LOGIC, VERILOG_NET_VALUE,
557
        "NVC.VERILOG.TO_NET(" T_LOGIC ")" T_NET_VALUE },
558
      { VERILOG_LOGIC_ARRAY, VERILOG_NET_ARRAY,
559
        "NVC.VERILOG.TO_NET(" T_LOGIC_ARRAY ")" T_NET_ARRAY },
560
      { VERILOG_LOGIC_ARRAY, VERILOG_WIRE_ARRAY,
561
        "NVC.VERILOG.TO_NET(" T_LOGIC_ARRAY ")" T_WIRE_ARRAY },
562
   };
563

564
   INIT_ONCE({
72✔
565
         for (int i = 0; i < ARRAY_LEN(table); i++) {
566
            table[i].from = verilog_type(table[i].from_id);
567
            table[i].to   = verilog_type(table[i].to_id);
568
            table[i].decl = verilog_func(ident_new(table[i].func));
569
         }
570
      });
571

572
   for (int i = 0; i < ARRAY_LEN(table); i++) {
104✔
573
      if (type_eq(table[i].from, from) && type_eq(table[i].to, to))
104✔
574
         return table[i].decl;
24✔
575
   }
576

577
   return NULL;
578
}
579

580
static tree_t elab_verilog_binding(vlog_node_t inst, elab_instance_t *ei,
36✔
581
                                   const elab_ctx_t *ctx)
582
{
583
   assert(vlog_kind(inst) == V_MOD_INST);
36✔
584

585
   tree_t bind = tree_new(T_BINDING);
36✔
586
   tree_set_ident(bind, vlog_ident(ei->body));
36✔
587
   tree_set_loc(bind, vlog_loc(inst));
36✔
588
   tree_set_ref(bind, ei->module->wrap);
36✔
589
   tree_set_class(bind, C_ENTITY);
36✔
590

591
   const int nports = vlog_ports(ei->body);
36✔
592
   const int nparams = vlog_params(inst);
36✔
593
   const int outports = tree_ports(ctx->out);
36✔
594
   const int outdecls = tree_decls(ctx->out);
36✔
595

596
   if (nports != nparams) {
36✔
597
      error_at(vlog_loc(inst), "expected %d port connections for module %s "
1✔
598
               "but found %d", nports, istr(vlog_ident2(ei->body)), nparams);
599
      return NULL;
1✔
600
   }
601

602
   bool have_named = false;
603
   for (int i = 0; i < nports; i++) {
89✔
604
      vlog_node_t conn = vlog_param(inst, i);
54✔
605
      assert(vlog_kind(conn) == V_PORT_CONN);
54✔
606

607
      vlog_node_t expr = vlog_value(conn);
54✔
608

609
      ident_t id = vlog_ident(expr);
54✔
610
      tree_t decl = NULL;
54✔
611

612
      for (int j = 0; j < outports; j++) {
54✔
UNCOV
613
         tree_t p = tree_port(ctx->out, j);
×
UNCOV
614
         if (tree_ident(p) == id) {
×
615
            decl = p;
616
            break;
617
         }
618
      }
619

620
      if (decl == NULL) {
54✔
621
         for (int j = 0; j < outdecls; j++) {
159✔
622
            tree_t d = tree_decl(ctx->out, j);
159✔
623
            if (tree_ident(d) == id) {
159✔
624
               decl = d;
625
               break;
626
            }
627
         }
628
      }
629

630
      assert(decl != NULL);
54✔
631

632
      tree_t port = tree_port(ei->block, i);
54✔
633

634
      type_t dtype = tree_type(decl);
54✔
635
      type_t ptype = tree_type(port);
54✔
636

637
      if (type_eq(dtype, ptype)) {
54✔
638
         if (have_named)
30✔
UNCOV
639
            add_param(bind, make_ref(decl), P_NAMED, make_ref(port));
×
640
         else
641
            add_param(bind, make_ref(decl), P_POS, NULL);
30✔
642
      }
643
      else if (tree_subkind(port) == PORT_IN) {
24✔
644
         tree_t func = elab_verilog_conversion(dtype, ptype);
16✔
645
         assert(func != NULL);
16✔
646

647
         tree_t conv = tree_new(T_CONV_FUNC);
16✔
648
         tree_set_loc(conv, vlog_loc(conn));
16✔
649
         tree_set_ref(conv, func);
16✔
650
         tree_set_ident(conv, tree_ident(func));
16✔
651
         tree_set_type(conv, type_result(tree_type(func)));
16✔
652
         tree_set_value(conv, make_ref(decl));
16✔
653

654
         if (have_named)
16✔
655
            add_param(bind, conv, P_NAMED, make_ref(port));
8✔
656
         else
657
            add_param(bind, conv, P_POS, NULL);
8✔
658
      }
659
      else {
660
         tree_t func = elab_verilog_conversion(ptype, dtype);
8✔
661
         assert(func != NULL);
8✔
662

663
         tree_t conv = tree_new(T_CONV_FUNC);
8✔
664
         tree_set_loc(conv, vlog_loc(conn));
8✔
665
         tree_set_ref(conv, func);
8✔
666
         tree_set_ident(conv, tree_ident(func));
8✔
667
         tree_set_type(conv, type_result(tree_type(func)));
8✔
668
         tree_set_value(conv, make_ref(port));
8✔
669

670
         add_param(bind, make_ref(decl), P_NAMED, conv);
8✔
671
         have_named = true;
8✔
672
      }
673
   }
674

675
   return bind;
676
}
677

678
static tree_t elab_default_binding(tree_t inst, const elab_ctx_t *ctx)
819✔
679
{
680
   // Default binding indication is described in LRM 93 section 5.2.2
681

682
   tree_t comp = tree_ref(inst);
819✔
683

684
   ident_t full_i = tree_ident(comp);
819✔
685
   ident_t lib_i = ident_until(full_i, '.');
819✔
686

687
   lib_t lib = NULL;
819✔
688
   bool synth_binding = true;
819✔
689
   if (lib_i == full_i) {
819✔
690
      lib    = ctx->library;
819✔
691
      full_i = ident_prefix(lib_name(lib), full_i, '.');
819✔
692
   }
693
   else {
694
      synth_binding = false;
×
UNCOV
695
      lib = elab_find_lib(lib_i, ctx);
×
696

697
      // Strip out the component package name, if any
UNCOV
698
      full_i = ident_prefix(lib_i, ident_rfrom(full_i, '.'), '.');
×
699
   }
700

701
   object_t *obj = lib_get_generic(lib, full_i, NULL);
819✔
702

703
   vlog_node_t mod = vlog_from_object(obj);
819✔
704
   if (mod != NULL) {
819✔
705
      mod_cache_t *mc = elab_cached_module(mod, ctx);
35✔
706
      return elab_mixed_binding(comp, mc);
35✔
707
   }
708

709
   tree_t entity = tree_from_object(obj);
784✔
710

711
   if (entity == NULL && synth_binding) {
784✔
712
      // This is not correct according to the LRM but matches the
713
      // behaviour of many synthesis tools
714
      synth_binding_params_t params = {
16✔
715
         .comp     = comp,
716
         .result   = &entity
717
      };
718
      lib_for_all(elab_synth_binding_cb, &params);
16✔
719
   }
720

721
   if (entity == NULL) {
784✔
722
      warn_at(tree_loc(inst), "cannot find entity for component %s "
8✔
723
              "without binding indication", istr(tree_ident(comp)));
724
      return NULL;
8✔
725
   }
726

727
   tree_t arch = elab_pick_arch(tree_loc(comp), entity, ctx);
776✔
728

729
   // Check entity is compatible with component declaration
730

731
   tree_t bind = tree_new(T_BINDING);
776✔
732
   tree_set_ident(bind, tree_ident(arch));
776✔
733
   tree_set_loc(bind, tree_loc(arch));
776✔
734
   tree_set_ref(bind, arch);
776✔
735
   tree_set_class(bind, C_ENTITY);
776✔
736

737
   const int c_ngenerics = tree_generics(comp);
776✔
738
   const int e_ngenerics = tree_generics(entity);
776✔
739

740
   for (int i = 0; i < e_ngenerics; i++) {
1,535✔
741
      tree_t eg = tree_generic(entity, i);
762✔
742

743
      tree_t match = NULL;
762✔
744
      for (int j = 0; j < c_ngenerics; j++) {
1,136✔
745
         tree_t cg = tree_generic(comp, j);
1,133✔
746
         if (ident_casecmp(tree_ident(eg), tree_ident(cg))) {
1,133✔
747
            match = cg;
748
            break;
749
         }
750
      }
751

752
      tree_t value;
762✔
753
      if (match != NULL) {
762✔
754
         const class_t class = tree_class(eg);
759✔
755

756
         if (class != tree_class(match)) {
759✔
757
            diag_t *d = diag_new(DIAG_ERROR, tree_loc(inst));
1✔
758
            diag_printf(d, "generic %s in component %s has class %s which is "
1✔
759
                        "incompatible with class %s in entity %s",
760
                        istr(tree_ident(match)), istr(tree_ident(comp)),
761
                        class_str(tree_class(match)), class_str(class),
762
                        istr(tree_ident(entity)));
763
            diag_hint(d, tree_loc(match), "declaration of generic %s in "
1✔
764
                      "component", istr(tree_ident(match)));
765
            diag_hint(d, tree_loc(eg), "declaration of generic %s in entity",
1✔
766
                      istr(tree_ident(eg)));
767
            diag_emit(d);
1✔
768
            return NULL;
1✔
769
         }
770
         else if (class == C_PACKAGE) {
758✔
771
            value = tree_new(T_REF);
1✔
772
            tree_set_ident(value, tree_ident(match));
1✔
773
            tree_set_ref(value, match);
1✔
774
         }
775
         else {
776
            type_t ctype = tree_type(match);
757✔
777
            type_t etype = tree_type(eg);
757✔
778
            if (!type_eq(ctype, etype)) {
757✔
779
               diag_t *d = diag_new(DIAG_ERROR, tree_loc(inst));
1✔
780
               diag_printf(d, "generic %s in component %s has type %s which is "
1✔
781
                           "incompatible with type %s in entity %s",
782
                           istr(tree_ident(match)), istr(tree_ident(comp)),
783
                           type_pp2(ctype, etype), type_pp2(etype, ctype),
784
                           istr(tree_ident(entity)));
785
               diag_hint(d, tree_loc(match), "declaration of generic %s in "
1✔
786
                         "component", istr(tree_ident(match)));
787
               diag_hint(d, tree_loc(eg), "declaration of generic %s in entity",
1✔
788
                         istr(tree_ident(eg)));
789
               diag_emit(d);
1✔
790
               return NULL;
1✔
791
            }
792

793
            value = make_ref(match);
756✔
794
         }
795
      }
796
      else if (tree_has_value(eg)) {
3✔
797
         tree_t def = tree_value(eg);
2✔
798
         if (is_literal(def))
2✔
799
            value = def;
800
         else {
801
            tree_t open = tree_new(T_OPEN);
×
UNCOV
802
            tree_set_loc(open, tree_loc(eg));
×
UNCOV
803
            tree_set_type(open, tree_type(eg));
×
804

UNCOV
805
            value = open;
×
806
         }
807
      }
808
      else {
809
         diag_t *d = diag_new(DIAG_ERROR, tree_loc(inst));
1✔
810
         diag_printf(d, "generic %s in entity %s without a default value "
1✔
811
                     "has no corresponding generic in component %s",
812
                     istr(tree_ident(eg)),  istr(tree_ident(entity)),
813
                     istr(tree_ident(comp)));
814
         diag_hint(d, tree_loc(eg), "declaration of generic %s in entity",
1✔
815
                   istr(tree_ident(eg)));
816
         diag_emit(d);
1✔
817
         return NULL;
1✔
818
      }
819

820
      tree_t map = tree_new(T_PARAM);
759✔
821
      tree_set_loc(map, tree_loc(inst));
759✔
822
      tree_set_value(map, value);
759✔
823
      tree_set_subkind(map, P_POS);
759✔
824
      tree_set_pos(map, i);
759✔
825

826
      tree_add_genmap(bind, map);
759✔
827
   }
828

829
   const int c_nports = tree_ports(comp);
773✔
830
   const int e_nports = tree_ports(entity);
773✔
831

832
   for (int i = 0; i < e_nports; i++) {
2,256✔
833
      tree_t ep = tree_port(entity, i);
1,486✔
834

835
      tree_t match = NULL;
1,486✔
836
      for (int j = 0; j < c_nports; j++) {
2,273✔
837
         tree_t cp = tree_port(comp, j);
2,271✔
838
         if (ident_casecmp(tree_ident(ep), tree_ident(cp))) {
2,271✔
839
            match = cp;
840
            break;
841
         }
842
      }
843

844
      tree_t value;
1,486✔
845
      if (match != NULL) {
1,486✔
846
         type_t ctype = tree_type(match);
1,484✔
847
         type_t etype = tree_type(ep);
1,484✔
848
         if (!type_eq(ctype, etype)) {
1,484✔
849
            diag_t *d = diag_new(DIAG_ERROR, tree_loc(inst));
1✔
850
            diag_printf(d, "port %s in component %s has type %s which is "
1✔
851
                        "incompatible with type %s in entity %s",
852
                        istr(tree_ident(match)), istr(tree_ident(comp)),
853
                        type_pp2(ctype, etype), type_pp2(etype, ctype),
854
                        istr(tree_ident(entity)));
855
            diag_hint(d, tree_loc(match), "declaration of port %s in component",
1✔
856
                      istr(tree_ident(match)));
857
            diag_hint(d, tree_loc(ep), "declaration of port %s in entity",
1✔
858
                      istr(tree_ident(ep)));
859
            diag_emit(d);
1✔
860
            return NULL;
1✔
861
         }
862

863
         value = make_ref(match);
1,483✔
864
      }
865
      else {
866
         const bool open_ok =
4✔
867
            tree_has_value(ep)
2✔
868
            || (tree_subkind(ep) == PORT_OUT
2✔
869
                && !type_is_unconstrained(tree_type(ep)));
×
870

871
          if (open_ok) {
2✔
872
             tree_t open = tree_new(T_OPEN);
×
UNCOV
873
             tree_set_loc(open, tree_loc(ep));
×
UNCOV
874
             tree_set_type(open, tree_type(ep));
×
875

UNCOV
876
             value = open;
×
877
          }
878
          else {
879
            diag_t *d = diag_new(DIAG_ERROR, tree_loc(inst));
2✔
880
            diag_printf(d, "port %s in entity %s without a default value "
2✔
881
                        "has no corresponding port in component %s",
882
                        istr(tree_ident(ep)), istr(tree_ident(entity)),
883
                        istr(tree_ident(comp)));
884
            diag_hint(d, tree_loc(ep), "port %s declared here",
2✔
885
                      istr(tree_ident(ep)));
886
            diag_emit(d);
2✔
887
            return NULL;
2✔
888
         }
889
      }
890

891
      add_param(bind, value, P_POS, NULL);
1,483✔
892
   }
893

894
   return bind;
895
}
896

897
static void elab_write_generic(text_buf_t *tb, tree_t value)
23✔
898
{
899
   switch (tree_kind(value)) {
23✔
900
   case T_LITERAL:
10✔
901
      switch (tree_subkind(value)) {
10✔
902
      case L_INT:  tb_printf(tb, "%"PRIi64, tree_ival(value)); break;
9✔
UNCOV
903
      case L_REAL: tb_printf(tb, "%lf", tree_dval(value)); break;
×
904
      case L_PHYSICAL:
1✔
905
         tb_printf(tb, "%"PRIi64" %s", tree_ival(value),
1✔
906
                   istr(tree_ident(value)));
907
         break;
1✔
908
      }
909
      break;
910
   case T_STRING:
1✔
911
      {
912
         tb_printf(tb, "\"");
1✔
913
         const int nchars = tree_chars(value);
1✔
914
         for (int i = 0; i < nchars; i++)
6✔
915
            tb_append(tb, ident_char(tree_ident(tree_char(value, i)), 1));
5✔
916
         tb_printf(tb, "\"");
1✔
917
      }
918
      break;
1✔
919
   case T_AGGREGATE:
1✔
920
      {
921
         tb_append(tb, '(');
1✔
922
         const int nassocs = tree_assocs(value);
1✔
923
         for (int i = 0; i < nassocs; i++) {
4✔
924
            if (i > 0) tb_cat(tb, ", ");
3✔
925
            elab_write_generic(tb, tree_value(tree_assoc(value, i)));
3✔
926
         }
927
         tb_append(tb, ')');
1✔
928
      }
929
      break;
1✔
930
   case T_REF:
7✔
931
      if (is_subprogram(tree_ref(value)))
7✔
932
         tb_printf(tb, "%s", type_pp(tree_type(value)));
2✔
933
      else
934
         tb_printf(tb, "%s", istr(tree_ident(value)));
5✔
935
      break;
UNCOV
936
   case T_TYPE_CONV:
×
937
   case T_QUALIFIED:
UNCOV
938
      elab_write_generic(tb, tree_value(value));
×
UNCOV
939
      break;
×
940
   case T_TYPE_REF:
1✔
941
      tb_printf(tb, "%s", type_pp(tree_type(value)));
1✔
942
      break;
1✔
943
   case T_OPEN:
3✔
944
      tb_cat(tb, "OPEN");
3✔
945
      break;
3✔
UNCOV
946
   default:
×
UNCOV
947
      tb_printf(tb, "...");
×
UNCOV
948
      DEBUG_ONLY(tb_cat(tb, tree_kind_str(tree_kind(value))));
×
949
   }
950
}
23✔
951

952
static void elab_hint_fn(diag_t *d, void *arg)
16✔
953
{
954
   tree_t t = arg;
16✔
955

956
   diag_hint(d, tree_loc(t), "while elaborating instance %s",
16✔
957
             istr(tree_ident(t)));
958

959
   tree_t unit = tree_ref(t);
16✔
960
   const tree_kind_t kind = tree_kind(unit);
16✔
961
   if (kind == T_CONFIGURATION || kind == T_ARCH)
16✔
UNCOV
962
      unit = tree_primary(unit);
×
963

964
   const int ngenerics = tree_genmaps(t);
16✔
965
   for (int i = 0; i < ngenerics; i++) {
36✔
966
      tree_t p = tree_genmap(t, i);
20✔
967
      ident_t name = NULL;
20✔
968
      switch (tree_subkind(p)) {
20✔
969
      case P_POS:
20✔
970
         name = tree_ident(tree_generic(unit, tree_pos(p)));
20✔
971
         break;
20✔
972
      case P_NAMED:
×
UNCOV
973
         name = tree_ident(tree_name(p));
×
UNCOV
974
         break;
×
UNCOV
975
      default:
×
UNCOV
976
         continue;
×
977
      }
978

979
      LOCAL_TEXT_BUF tb = tb_new();
40✔
980
      elab_write_generic(tb, tree_value(p));
20✔
981
      diag_hint(d, NULL, "generic %s => %s", istr(name), tb_get(tb));
20✔
982
   }
983
}
16✔
984

985
static void elab_ports(tree_t entity, tree_t bind, const elab_ctx_t *ctx)
10,819✔
986
{
987
   const int nports = tree_ports(entity);
10,819✔
988
   const int nparams = tree_params(bind);
10,819✔
989
   bool have_named = false;
10,819✔
990

991
   for (int i = 0; i < nports; i++) {
23,075✔
992
      tree_t p = tree_port(entity, i), map = NULL;
12,256✔
993
      ident_t pname = tree_ident(p);
12,256✔
994

995
      if (i < nparams && !have_named) {
12,256✔
996
         tree_t m = tree_param(bind, i);
11,762✔
997
         if (tree_subkind(m) == P_POS) {
11,762✔
998
            assert(tree_pos(m) == i);
7,727✔
999
            tree_add_param(ctx->out, m);
7,727✔
1000
            map = m;
7,727✔
1001
         }
1002
      }
1003

1004
      if (map == NULL) {
7,727✔
1005
         for (int j = 0; j < nparams; j++) {
18,839✔
1006
            tree_t m = tree_param(bind, j);
18,099✔
1007
            if (tree_subkind(m) == P_NAMED) {
18,099✔
1008
               tree_t name = tree_name(m), ref;
18,033✔
1009
               bool is_conv = false;
18,033✔
1010

1011
               switch (tree_kind(name)) {
18,033✔
1012
               case T_TYPE_CONV:
309✔
1013
               case T_CONV_FUNC:
1014
                  is_conv = true;
309✔
1015
                  ref = name_to_ref(tree_value(name));
309✔
1016
                  break;
309✔
1017
               default:
17,724✔
1018
                  ref = name_to_ref(name);
17,724✔
1019
                  break;
17,724✔
1020
               }
1021
               assert(ref != NULL);
18,033✔
1022

1023
               if (tree_ident(ref) != pname)
18,033✔
1024
                  continue;
13,285✔
1025

1026
               map = tree_new(T_PARAM);
4,748✔
1027
               tree_set_loc(map, tree_loc(m));
4,748✔
1028
               tree_set_value(map, tree_value(m));
4,748✔
1029

1030
               tree_add_param(ctx->out, map);
4,748✔
1031

1032
               if (!have_named && !is_conv && ref == name) {
4,748✔
1033
                  tree_set_subkind(map, P_POS);
3,789✔
1034
                  tree_set_pos(map, i);
3,789✔
1035
                  break;
3,789✔
1036
               }
1037
               else {
1038
                  tree_set_subkind(map, P_NAMED);
959✔
1039
                  tree_set_name(map, change_ref(tree_name(m), p));
959✔
1040
                  have_named = true;
959✔
1041
               }
1042
            }
1043
         }
1044
      }
1045

1046
      if (map == NULL) {
12,256✔
1047
         map = tree_new(T_PARAM);
306✔
1048
         tree_set_loc(map, tree_loc(p));
306✔
1049

1050
         if (have_named) {
306✔
UNCOV
1051
            tree_set_subkind(map, P_NAMED);
×
UNCOV
1052
            tree_set_name(map, make_ref(p));
×
1053
         }
1054
         else {
1055
            tree_set_subkind(map, P_POS);
306✔
1056
            tree_set_pos(map, i);
306✔
1057
         }
1058

1059
         tree_t open = tree_new(T_OPEN);
306✔
1060
         tree_set_type(open, tree_type(p));
306✔
1061
         tree_set_loc(open, tree_loc(p));
306✔
1062

1063
         tree_set_value(map, open);
306✔
1064

1065
         tree_add_param(ctx->out, map);
306✔
1066
      }
1067

1068
      tree_add_port(ctx->out, p);
12,256✔
1069
   }
1070
}
10,819✔
1071

1072
static tree_t elab_parse_generic_string(tree_t generic, const char *str)
84✔
1073
{
1074
   type_t type = tree_type(generic);
84✔
1075

1076
   parsed_value_t value;
84✔
1077
   if (!parse_value(type, str, &value))
84✔
UNCOV
1078
      fatal("failed to parse \"%s\" as type %s for generic %s",
×
1079
            str, type_pp(type), istr(tree_ident(generic)));
1080

1081
   if (type_is_enum(type)) {
84✔
1082
      type_t base = type_base_recur(type);
9✔
1083
      tree_t lit = type_enum_literal(base, value.integer);
9✔
1084

1085
      tree_t result = tree_new(T_REF);
9✔
1086
      tree_set_type(result, type);
9✔
1087
      tree_set_ident(result, ident_new(str));
9✔
1088
      tree_set_ref(result, lit);
9✔
1089
      tree_set_loc(result, tree_loc(generic));
9✔
1090

1091
      return result;
9✔
1092
   }
1093
   else if (type_is_integer(type)) {
75✔
1094
      tree_t result = tree_new(T_LITERAL);
62✔
1095
      tree_set_subkind(result, L_INT);
62✔
1096
      tree_set_type(result, type);
62✔
1097
      tree_set_ival(result, value.integer);
62✔
1098
      tree_set_loc(result, tree_loc(generic));
62✔
1099

1100
      return result;
62✔
1101
   }
1102
   else if (type_is_real(type)) {
13✔
1103
      tree_t result = tree_new(T_LITERAL);
1✔
1104
      tree_set_subkind(result, L_REAL);
1✔
1105
      tree_set_type(result, type);
1✔
1106
      tree_set_dval(result, value.real);
1✔
1107
      tree_set_loc(result, tree_loc(generic));
1✔
1108

1109
      return result;
1✔
1110
   }
1111
   else if (type_is_physical(type)) {
12✔
1112
      tree_t result = tree_new(T_LITERAL);
1✔
1113
      tree_set_subkind(result, L_PHYSICAL);
1✔
1114
      tree_set_type(result, type);
1✔
1115
      tree_set_ival(result, value.integer);
1✔
1116
      tree_set_loc(result, tree_loc(generic));
1✔
1117

1118
      return result;
1✔
1119
   }
1120
   else if (type_is_character_array(type)) {
11✔
1121
      tree_t t = tree_new(T_STRING);
11✔
1122
      tree_set_loc(t, tree_loc(generic));
11✔
1123

1124
      type_t elem = type_base_recur(type_elem(type));
11✔
1125
      for (int i = 0; i < value.enums->count; i++) {
32✔
1126
         tree_t lit = type_enum_literal(elem, value.enums->values[i]);
21✔
1127

1128
         tree_t ref = tree_new(T_REF);
21✔
1129
         tree_set_ident(ref, tree_ident(lit));
21✔
1130
         tree_set_ref(ref, lit);
21✔
1131
         tree_add_char(t, ref);
21✔
1132
      }
1133
      free(value.enums);
11✔
1134

1135
      tree_set_type(t, subtype_for_string(t, type));
11✔
1136
      return t;
11✔
1137
   }
1138
   else
UNCOV
1139
      fatal("cannot override generic %s of type %s", istr(tree_ident(generic)),
×
1140
            type_pp(type));
1141
}
1142

1143
static tree_t elab_find_generic_override(tree_t g, const elab_ctx_t *ctx)
5,687✔
1144
{
1145
   if (generic_override == NULL)
5,687✔
1146
      return NULL;
1147

1148
   ident_t qual = tree_ident(g);
88✔
1149
   for (const elab_ctx_t *e = ctx; e->inst; e = e->parent)
96✔
1150
      qual = ident_prefix(tree_ident(e->inst), qual, '.');
8✔
1151

1152
   generic_list_t **it, *tmp;
1153
   for (it = &generic_override;
1154
        *it && (*it)->name != qual;
105✔
1155
        it = &((*it)->next))
17✔
1156
      ;
1157

1158
   if (*it == NULL)
88✔
1159
      return NULL;
1160

1161
   tree_t value = elab_parse_generic_string(g, (*it)->value);
84✔
1162

1163
   *it = (tmp = (*it))->next;
84✔
1164
   free(tmp->value);
84✔
1165
   free(tmp);
84✔
1166

1167
   return value;
84✔
1168
}
1169

1170
static void elab_generics(tree_t entity, tree_t bind, elab_ctx_t *ctx)
10,760✔
1171
{
1172
   const int ngenerics = tree_generics(entity);
10,760✔
1173
   const int ngenmaps = tree_genmaps(bind);
10,760✔
1174

1175
   for (int i = 0; i < ngenerics; i++) {
15,775✔
1176
      tree_t g = tree_generic(entity, i);
5,015✔
1177
      tree_add_generic(ctx->out, g);
5,015✔
1178

1179
      tree_t map = NULL;
5,015✔
1180
      if (i < ngenmaps) {
5,015✔
1181
         map = tree_genmap(bind, i);
5,015✔
1182
         assert(tree_subkind(map) == P_POS);
5,015✔
1183
         assert(tree_pos(map) == i);
5,015✔
1184
      }
1185
      else if (tree_has_value(g)) {
×
1186
         map = tree_new(T_PARAM);
×
UNCOV
1187
         tree_set_loc(map, tree_loc(g));
×
UNCOV
1188
         tree_set_subkind(map, P_POS);
×
UNCOV
1189
         tree_set_pos(map, i);
×
UNCOV
1190
         tree_set_value(map, tree_value(g));
×
1191
      }
1192

1193
      tree_t override = elab_find_generic_override(g, ctx);
5,015✔
1194
      if (override != NULL) {
5,015✔
1195
         map = tree_new(T_PARAM);
8✔
1196
         tree_set_subkind(map, P_POS);
8✔
1197
         tree_set_pos(map, i);
8✔
1198
         tree_set_value(map, override);
8✔
1199
      }
1200

1201
      if (map == NULL) {
5,015✔
UNCOV
1202
         error_at(tree_loc(bind), "missing value for generic %s with no "
×
1203
                  "default", istr(tree_ident(g)));
UNCOV
1204
         continue;
×
1205
      }
1206

1207
      tree_t value = tree_value(map);
5,015✔
1208

1209
      switch (tree_kind(value)) {
5,015✔
1210
      case T_REF:
1,924✔
1211
         if (tree_kind(tree_ref(value)) == T_ENUM_LIT)
1,924✔
1212
            break;
1213
         else if (tree_class(g) == C_PACKAGE)
1,590✔
1214
            break;
1215
         // Fall-through
1216
      case T_ARRAY_REF:
1217
      case T_RECORD_REF:
1218
      case T_FCALL:
1219
         if (type_is_scalar(tree_type(value))) {
1,667✔
1220
            void *context = NULL;
1,036✔
1221
            if (ctx->parent->scope->kind != SCOPE_ROOT)
1,036✔
1222
               context = *mptr_get(ctx->parent->scope->privdata);
1,032✔
1223

1224
            tree_t folded = eval_try_fold(ctx->jit, value,
2,072✔
1225
                                          ctx->registry,
1226
                                          ctx->parent->lowered,
1,036✔
1227
                                          context);
1228

1229
            if (folded != value) {
1,036✔
1230
               tree_t m = tree_new(T_PARAM);
1,016✔
1231
               tree_set_loc(m, tree_loc(map));
1,016✔
1232
               tree_set_subkind(m, P_POS);
1,016✔
1233
               tree_set_pos(m, tree_pos(map));
1,016✔
1234
               tree_set_value(m, (value = folded));
1,016✔
1235

1236
               map = m;
1,016✔
1237
            }
1238
         }
1239
         break;
1240

1241
      default:
1242
         break;
1243
      }
1244

1245
      tree_add_genmap(ctx->out, map);
5,015✔
1246

1247
      if (is_literal(value)) {
5,015✔
1248
         // These values can be safely substituted for all references to
1249
         // the generic name
1250
         if (ctx->generics == NULL)
3,860✔
1251
            ctx->generics = hash_new(ngenerics * 2);
2,268✔
1252
         hash_put(ctx->generics, g, value);
3,860✔
1253
      }
1254
   }
1255
}
10,760✔
1256

1257
static void elab_map_generic_type(type_t generic, type_t actual, hash_t *map)
74✔
1258
{
1259
   assert(type_kind(generic) == T_GENERIC);
74✔
1260

1261
   switch (type_subkind(generic)) {
74✔
1262
   case GTYPE_ARRAY:
2✔
1263
      {
1264
         type_t gelem = type_elem(generic);
2✔
1265
         if (type_kind(gelem) == T_GENERIC && !type_has_ident(gelem))
2✔
1266
            elab_map_generic_type(gelem, type_elem(actual), map);
1✔
1267

1268
         const int ndims = type_indexes(generic);
2✔
1269
         for (int i = 0; i < ndims; i++) {
4✔
1270
            type_t index = type_index(generic, i);
2✔
1271
            if (type_kind(index) == T_GENERIC && !type_has_ident(index))
2✔
UNCOV
1272
               elab_map_generic_type(index, index_type_of(actual, i), map);
×
1273
         }
1274
      }
1275
      break;
1276
   }
1277

1278
   hash_put(map, generic, actual);
74✔
1279
}
74✔
1280

1281
static void elab_instance_fixup(tree_t arch, const elab_ctx_t *ctx)
10,484✔
1282
{
1283
   if (standard() < STD_08)
10,484✔
1284
      return;
1285

1286
   hash_t *map = NULL;
2,748✔
1287

1288
   const int ngenerics = tree_generics(ctx->out);
2,748✔
1289
   assert(tree_genmaps(ctx->out) == ngenerics);
2,748✔
1290

1291
   for (int i = 0; i < ngenerics; i++) {
4,026✔
1292
      tree_t g = tree_generic(ctx->out, i);
1,278✔
1293

1294
      const class_t class = tree_class(g);
1,278✔
1295
      if (class == C_CONSTANT)
1,278✔
1296
         continue;
919✔
1297
      else if (map == NULL)
359✔
1298
         map = hash_new(64);
150✔
1299

1300
      tree_t value = tree_value(tree_genmap(ctx->out, i));
359✔
1301

1302
      switch (class) {
359✔
1303
      case C_TYPE:
73✔
1304
         elab_map_generic_type(tree_type(g), tree_type(value), map);
73✔
1305
         break;
73✔
1306

1307
      case C_PACKAGE:
70✔
1308
         {
1309
            tree_t formal = tree_ref(tree_value(g));
70✔
1310
            tree_t actual = tree_ref(value);
70✔
1311

1312
            const int ndecls = tree_decls(formal);
70✔
1313
            for (int i = 0; i < ndecls; i++) {
316✔
1314
               tree_t gd = tree_decl(formal, i);
246✔
1315
               tree_t ad = tree_decl(actual, i);
246✔
1316
               assert(tree_kind(gd) == tree_kind(ad));
246✔
1317

1318
               hash_put(map, gd, ad);
246✔
1319

1320
               if (is_type_decl(gd))
246✔
1321
                  hash_put(map, tree_type(gd), tree_type(ad));
28✔
1322
            }
1323

1324
            const int ngenerics = tree_generics(formal);
70✔
1325
            for (int i = 0; i < ngenerics; i++) {
388✔
1326
               tree_t fg = tree_generic(formal, i);
318✔
1327
               tree_t ag = tree_generic(actual, i);
318✔
1328

1329
               switch (tree_class(fg)) {
318✔
1330
               case C_FUNCTION:
244✔
1331
               case C_PROCEDURE:
1332
                  {
1333
                     // Get the actual subprogram from the generic map
1334
                     assert(ngenerics == tree_genmaps(actual));
244✔
1335
                     tree_t ref = tree_value(tree_genmap(actual, i));
244✔
1336
                     assert(tree_kind(ref) == T_REF);
244✔
1337

1338
                     hash_put(map, fg, tree_ref(ref));
244✔
1339
                  }
1340
                  break;
244✔
1341
               case C_TYPE:
62✔
1342
                  hash_put(map, tree_type(fg), tree_type(ag));
62✔
1343
                  break;
62✔
1344
               case C_PACKAGE:
12✔
1345
                  // TODO: this should be processed recursively
1346
               default:
1347
                  hash_put(map, fg, ag);
12✔
1348
                  break;
12✔
1349
               }
1350
            }
1351

1352
            hash_put(map, g, actual);
70✔
1353
         }
1354
         break;
70✔
1355

1356
      case C_FUNCTION:
216✔
1357
      case C_PROCEDURE:
1358
         hash_put(map, g, tree_ref(value));
216✔
1359
         break;
216✔
1360

1361
      default:
1362
         break;
1363
      }
1364
   }
1365

1366
   if (map == NULL)
2,748✔
1367
      return;
1368

1369
   instance_fixup(arch, map);
150✔
1370
   hash_free(map);
150✔
1371
}
1372

1373
static void elab_context(tree_t t)
16,270✔
1374
{
1375
   const int nctx = tree_contexts(t);
16,270✔
1376
   for (int i = 0; i < nctx; i++) {
69,986✔
1377
      // Make sure any referenced libraries are loaded to allow synth
1378
      // binding to search for entities in them
1379
      tree_t c = tree_context(t, i);
53,716✔
1380
      if (tree_kind(c) == T_LIBRARY)
53,716✔
1381
         lib_require(tree_ident(c));
33,901✔
1382
   }
1383
}
16,270✔
1384

1385
static void elab_inherit_context(elab_ctx_t *ctx, const elab_ctx_t *parent)
12,935✔
1386
{
1387
   ctx->parent    = parent;
12,935✔
1388
   ctx->jit       = parent->jit;
12,935✔
1389
   ctx->registry  = parent->registry;
12,935✔
1390
   ctx->mir       = parent->mir;
12,935✔
1391
   ctx->root      = parent->root;
12,935✔
1392
   ctx->dotted    = ctx->dotted ?: parent->dotted;
12,935✔
1393
   ctx->library   = ctx->library ?: parent->library;
12,935✔
1394
   ctx->out       = ctx->out ?: parent->out;
12,935✔
1395
   ctx->cover     = parent->cover;
12,935✔
1396
   ctx->sdf       = parent->sdf;
12,935✔
1397
   ctx->inst      = ctx->inst ?: parent->inst;
12,935✔
1398
   ctx->modcache  = parent->modcache;
12,935✔
1399
   ctx->depth     = parent->depth + 1;
12,935✔
1400
   ctx->model     = parent->model;
12,935✔
1401
}
12,935✔
1402

1403
static driver_set_t *elab_driver_set(const elab_ctx_t *ctx)
24,691✔
1404
{
1405
   if (ctx->drivers != NULL)
27,170✔
1406
      return ctx->drivers;
1407
   else if (ctx->parent != NULL)
2,479✔
1408
      return elab_driver_set(ctx->parent);
1409
   else
1410
      return NULL;
1411
}
1412

1413
static void elab_lower(tree_t b, const elab_instance_t *ei, elab_ctx_t *ctx)
12,909✔
1414
{
1415
   if (ei != NULL)
12,909✔
1416
      vlog_lower_block(ctx->mir, ctx->parent->dotted, b);
179✔
1417
   else
1418
      ctx->lowered = lower_instance(ctx->registry, ctx->parent->lowered,
12,730✔
1419
                                    elab_driver_set(ctx), ctx->cover, b);
1420

1421
   if (ctx->inst != NULL)
12,909✔
1422
      diag_add_hint_fn(elab_hint_fn, ctx->inst);
6,855✔
1423

1424
   ctx->scope = create_scope(ctx->model, b, ctx->parent->scope);
12,909✔
1425

1426
   if (ctx->inst != NULL)
12,909✔
1427
      diag_remove_hint_fn(elab_hint_fn);
6,855✔
1428
}
12,909✔
1429

1430
static void elab_verilog_module(tree_t bind, ident_t label,
181✔
1431
                                const elab_instance_t *ei,
1432
                                const elab_ctx_t *ctx)
1433
{
1434
   ident_t ndotted = ident_prefix(ctx->dotted, label, '.');
181✔
1435

1436
   elab_ctx_t new_ctx = {
181✔
1437
      .dotted    = ndotted,
1438
   };
1439
   elab_inherit_context(&new_ctx, ctx);
181✔
1440

1441
   tree_t b = tree_new(T_BLOCK);
181✔
1442
   tree_set_ident(b, label);
181✔
1443
   tree_set_loc(b, tree_loc(ctx->out));
181✔
1444

1445
   tree_add_stmt(ctx->out, b);
181✔
1446
   new_ctx.out = b;
181✔
1447

1448
   elab_push_scope(ei->wrap, &new_ctx);
181✔
1449

1450
   if (bind != NULL)
181✔
1451
      elab_ports(ei->block, bind, &new_ctx);
64✔
1452

1453
   if (error_count() == 0)
181✔
1454
      elab_decls(ei->block, &new_ctx);
179✔
1455

1456
   if (error_count() == 0) {
181✔
1457
      new_ctx.drivers = find_drivers(ei->block);
179✔
1458
      elab_lower(b, ei, &new_ctx);
179✔
1459
   }
1460

1461
   if (error_count() == 0)
181✔
1462
      elab_verilog_stmts(ei->body, &new_ctx);
179✔
1463

1464
   elab_pop_scope(&new_ctx);
181✔
1465
}
181✔
1466

1467
static void elab_verilog_instance_list(vlog_node_t v, const elab_ctx_t *ctx)
38✔
1468
{
1469
   ident_t modname = vlog_ident(v);
38✔
1470
   ident_t libname = lib_name(ctx->library);
38✔
1471

1472
   text_buf_t *tb = tb_new();
38✔
1473
   tb_istr(tb, libname);
38✔
1474
   tb_append(tb, '.');
38✔
1475
   tb_istr(tb, modname);
38✔
1476
   tb_upcase(tb);
38✔
1477

1478
   ident_t qual = ident_new(tb_get(tb));
38✔
1479

1480
   object_t *obj = lib_get_generic(ctx->library, qual, NULL);
38✔
1481
   if (obj == NULL) {
38✔
1482
      error_at(vlog_loc(v), "module %s not found in library %s",
1✔
1483
               istr(modname), istr(libname));
1484
      return;
1✔
1485
   }
1486

1487
   vlog_node_t mod = vlog_from_object(obj);
37✔
1488
   if (mod == NULL) {
37✔
UNCOV
1489
      error_at(&obj->loc, "unit %s is not a Verilog module", istr(qual));
×
UNCOV
1490
      return;
×
1491
   }
1492
   else if (vlog_ident2(mod) != modname) {
37✔
1493
      diag_t *d = diag_new(DIAG_ERROR, vlog_loc(v));
1✔
1494
      diag_printf(d, "name of Verilog module %s in library unit %s "
1✔
1495
                  "does not match name %s in module instance %s",
1496
                  istr(vlog_ident2(mod)), istr(qual), istr(modname),
1497
                  istr(vlog_ident(vlog_stmt(v, 0))));
1498
      diag_hint(d, NULL, "this tool does not preserve case sensitivity "
1✔
1499
                "in module names");
1500
      diag_emit(d);
1✔
1501
      return;
1✔
1502
   }
1503

1504
   elab_instance_t *ei = elab_new_instance(mod, v, ctx);
36✔
1505

1506
   const int nstmts = vlog_stmts(v);
36✔
1507
   for (int i = 0; i < nstmts; i++) {
72✔
1508
      vlog_node_t inst = vlog_stmt(v, i);
36✔
1509
      assert(vlog_kind(inst) == V_MOD_INST);
36✔
1510

1511
      tree_t bind = elab_verilog_binding(inst, ei, ctx);
36✔
1512
      if (bind != NULL)
36✔
1513
         elab_verilog_module(bind, vlog_ident(inst), ei, ctx);
35✔
1514
   }
1515
}
1516

1517
static void elab_verilog_stmts(vlog_node_t v, const elab_ctx_t *ctx)
191✔
1518
{
1519
   const int nstmts = vlog_stmts(v);
191✔
1520
   for (int i = 0; i < nstmts; i++) {
609✔
1521
      vlog_node_t s = vlog_stmt(v, i);
418✔
1522

1523
      const vlog_kind_t kind = vlog_kind(s);
418✔
1524
      switch (kind) {
418✔
1525
      case V_INST_LIST:
38✔
1526
         elab_verilog_instance_list(s, ctx);
38✔
1527
         break;
38✔
1528
      case V_INITIAL:
368✔
1529
      case V_ALWAYS:
1530
      case V_ASSIGN:
1531
      case V_UDP_TABLE:
1532
      case V_GATE_INST:
1533
         {
1534
            ident_t name = vlog_ident(s);
368✔
1535
            ident_t sym = ident_prefix(ctx->dotted, name, '.');
368✔
1536

1537
            tree_t w = tree_new(T_VERILOG);
368✔
1538
            tree_set_ident(w, name);
368✔
1539
            tree_set_loc(w, vlog_loc(s));
368✔
1540
            tree_set_vlog(w, s);
368✔
1541

1542
            tree_add_stmt(ctx->out, w);
368✔
1543

1544
            if (kind == V_UDP_TABLE)
368✔
1545
               mir_defer(ctx->mir, sym, ctx->dotted, MIR_UNIT_PROCESS,
12✔
1546
                         vlog_lower_udp, vlog_to_object(v));
1547
            else
1548
               mir_defer(ctx->mir, sym, ctx->dotted, MIR_UNIT_PROCESS,
356✔
1549
                         vlog_lower_deferred, vlog_to_object(s));
1550
         }
1551
         break;
1552
      case V_BLOCK:
12✔
1553
         // TODO: should create a block in hierarchy
1554
         elab_verilog_stmts(s, ctx);
12✔
1555
         break;
12✔
UNCOV
1556
      case V_IF_GENERATE:
×
UNCOV
1557
         error_at(vlog_loc(s), "if-generate construct could not be "
×
1558
                  "evaluated at elaboration time");
UNCOV
1559
         break;
×
UNCOV
1560
      default:
×
UNCOV
1561
         fatal_at(vlog_loc(s), "sorry, this Verilog statement is not "
×
1562
                  "currently supported");
1563
      }
1564
   }
1565
}
191✔
1566

1567
static void elab_architecture(tree_t bind, tree_t arch, tree_t config,
8,135✔
1568
                              const elab_ctx_t *ctx)
1569
{
1570
   tree_t inst = NULL;
8,135✔
1571
   ident_t label;
8,135✔
1572
   switch (tree_kind(bind)) {
8,135✔
1573
   case T_BINDING:
5,869✔
1574
      label = ident_rfrom(tree_ident(tree_primary(arch)), '.');
5,869✔
1575
      break;
5,869✔
1576
   case T_INSTANCE:
2,266✔
1577
      label = tree_ident(bind);
2,266✔
1578
      inst = bind;
2,266✔
1579
      break;
2,266✔
UNCOV
1580
   default:
×
1581
      fatal_trace("unexpected binding kind %s in elab_architecture",
1582
                  tree_kind_str(tree_kind(bind)));
1583
   }
1584

1585
   ident_t ndotted = ident_prefix(ctx->dotted, label, '.');
8,135✔
1586

1587
   elab_ctx_t new_ctx = {
8,135✔
1588
      .dotted = ndotted,
1589
      .inst   = inst,
1590
   };
1591
   elab_inherit_context(&new_ctx, ctx);
8,135✔
1592

1593
   tree_t b = tree_new(T_BLOCK);
8,135✔
1594
   tree_set_ident(b, label);
8,135✔
1595
   tree_set_loc(b, tree_loc(bind));
8,135✔
1596

1597
   tree_add_stmt(ctx->out, b);
8,135✔
1598
   new_ctx.out = b;
8,135✔
1599

1600
   new_ctx.library = lib_require(ident_until(tree_ident(arch), '.'));
8,135✔
1601

1602
   elab_subprogram_prefix(arch, &new_ctx);
8,135✔
1603

1604
   tree_t arch_copy;
8,135✔
1605
   if (config != NULL) {
8,135✔
1606
      assert(tree_ref(config) == arch);
185✔
1607
      new_ctx.config = elab_copy(config, &new_ctx);
185✔
1608
      arch_copy = tree_ref(new_ctx.config);
185✔
1609
   }
1610
   else
1611
      arch_copy = elab_copy(arch, &new_ctx);
7,950✔
1612

1613
   tree_t entity = tree_primary(arch_copy);
8,135✔
1614

1615
   elab_push_scope(arch, &new_ctx);
8,135✔
1616
   elab_context(entity);
8,135✔
1617
   elab_context(arch_copy);
8,135✔
1618
   elab_generics(entity, bind, &new_ctx);
8,135✔
1619
   elab_instance_fixup(arch_copy, &new_ctx);
8,135✔
1620
   simplify_global(arch_copy, new_ctx.generics, ctx->jit, ctx->registry,
8,135✔
1621
                   ctx->mir);
8,135✔
1622
   elab_ports(entity, bind, &new_ctx);
8,130✔
1623
   elab_decls(entity, &new_ctx);
8,130✔
1624

1625
   if (error_count() == 0)
8,130✔
1626
      elab_decls(arch_copy, &new_ctx);
8,123✔
1627

1628
   if (error_count() == 0) {
8,130✔
1629
      new_ctx.drivers = find_drivers(arch_copy);
8,123✔
1630
      elab_lower(b, NULL, &new_ctx);
8,123✔
1631
      elab_stmts(entity, &new_ctx);
8,123✔
1632
      elab_stmts(arch_copy, &new_ctx);
8,123✔
1633
   }
1634

1635
   elab_pop_scope(&new_ctx);
8,130✔
1636
}
8,130✔
1637

1638
static tree_t elab_find_spec(tree_t inst, const elab_ctx_t *ctx)
1,186✔
1639
{
1640
   if (tree_has_spec(inst))
1,186✔
1641
      return tree_spec(inst);
166✔
1642
   else if (ctx->config == NULL)
1,020✔
1643
      return NULL;
1644

1645
   assert(tree_kind(ctx->config) == T_BLOCK_CONFIG);
201✔
1646

1647
   tree_t spec = NULL;
201✔
1648
   const int ndecls = tree_decls(ctx->config);
201✔
1649
   for (int i = 0; i < ndecls; i++) {
436✔
1650
      tree_t d = tree_decl(ctx->config, i);
235✔
1651
      if (tree_kind(d) != T_SPEC)
235✔
1652
         continue;
24✔
1653
      else if (tree_ident2(d) != tree_ident2(inst))
211✔
1654
         continue;
10✔
1655

1656
      bool apply = false;
201✔
1657
      if (tree_has_ident(d)) {
201✔
1658
         ident_t match = tree_ident(d);
197✔
1659
         apply = (match == tree_ident(inst) || match == well_known(W_ALL));
197✔
1660
      }
1661
      else if (spec == NULL)
4✔
1662
         apply = true;
1663

1664
      if (apply) spec = d;
197✔
1665
   }
1666

1667
   return spec;
1668
}
1669

1670
static void elab_component(tree_t inst, tree_t comp, const elab_ctx_t *ctx)
1,186✔
1671
{
1672
   tree_t arch = NULL, config = NULL, bind = NULL, spec;
1,186✔
1673
   if ((spec = elab_find_spec(inst, ctx)) && tree_has_value(spec)) {
1,186✔
1674
      bind = tree_value(spec);
362✔
1675
      assert(tree_kind(bind) == T_BINDING);
362✔
1676

1677
      const int ndecls = tree_decls(spec);
362✔
1678
      if (ndecls == 0) {
362✔
1679
         tree_t unit = tree_ref(bind);
360✔
1680
         switch (tree_kind(unit)) {
360✔
1681
         case T_ENTITY:
77✔
1682
            arch = elab_pick_arch(tree_loc(inst), unit, ctx);
77✔
1683
            break;
77✔
1684
         case T_CONFIGURATION:
95✔
1685
            config = tree_decl(unit, 0);
95✔
1686
            assert(tree_kind(config) == T_BLOCK_CONFIG);
95✔
1687
            arch = tree_ref(config);
95✔
1688
            break;
95✔
1689
         case T_ARCH:
1690
            arch = unit;
1691
            break;
UNCOV
1692
         default:
×
UNCOV
1693
            fatal_at(tree_loc(bind), "sorry, this form of binding indication "
×
1694
                     "is not supported yet");
1695
         }
1696
      }
1697
      else {
1698
         assert(ndecls == 1);
2✔
1699

1700
         config = tree_decl(spec, 0);
2✔
1701
         assert(tree_kind(config) == T_BLOCK_CONFIG);
2✔
1702

1703
         arch = tree_ref(config);
2✔
1704
      }
1705
   }
1706
   else if (spec == NULL && (bind = elab_default_binding(inst, ctx)))
824✔
1707
      arch = tree_ref(bind);
801✔
1708

1709
   // Must create a unique instance if type or package generics present
1710
   const int ngenerics = tree_generics(comp);
1,186✔
1711
   for (int i = 0; i < ngenerics; i++) {
2,263✔
1712
      if (tree_class(tree_generic(comp, i)) != C_CONSTANT) {
1,111✔
1713
         tree_t roots[] = { comp, bind };
34✔
1714
         new_instance(roots, bind ? 2 : 1, ctx->dotted, ctx->prefix,
36✔
1715
                      ARRAY_LEN(ctx->prefix));
1716

1717
         comp = roots[0];
34✔
1718
         bind = roots[1];
34✔
1719

1720
         break;
34✔
1721
      }
1722
   }
1723

1724
   ident_t ndotted = ident_prefix(ctx->dotted, tree_ident(inst), '.');
1,186✔
1725

1726
   elab_ctx_t new_ctx = {
1,186✔
1727
      .dotted    = ndotted,
1728
      .inst      = inst,
1729
   };
1730
   elab_inherit_context(&new_ctx, ctx);
1,186✔
1731

1732
   tree_t b = tree_new(T_BLOCK);
1,186✔
1733
   tree_set_ident(b, tree_ident(inst));
1,186✔
1734
   tree_set_loc(b, tree_loc(inst));
1,186✔
1735

1736
   tree_add_stmt(ctx->out, b);
1,186✔
1737
   new_ctx.out = b;
1,186✔
1738

1739
   elab_push_scope(comp, &new_ctx);
1,186✔
1740
   elab_generics(comp, inst, &new_ctx);
1,186✔
1741
   if (bind != NULL) elab_instance_fixup(bind, &new_ctx);
1,186✔
1742
   elab_instance_fixup(comp, &new_ctx);
1,186✔
1743
   elab_ports(comp, inst, &new_ctx);
1,186✔
1744

1745
   if (bind != NULL && tree_kind(arch) != T_VERILOG)
1,186✔
1746
      new_ctx.drivers = find_drivers(bind);
1,132✔
1747

1748
   if (error_count() == 0)
1,186✔
1749
      elab_lower(b, NULL, &new_ctx);
1,174✔
1750

1751
   if (error_count() > 0 || arch == NULL)
1,186✔
1752
      ;   // Unbound architecture
1753
   else if (tree_kind(arch) == T_VERILOG) {
1,161✔
1754
      vlog_node_t mod = tree_vlog(arch);
29✔
1755

1756
      vlog_node_t stmt = vlog_new(V_MOD_INST);
29✔
1757
      vlog_set_ident(stmt, vlog_ident2(mod));
29✔
1758

1759
      vlog_node_t list = vlog_new(V_INST_LIST);
29✔
1760
      vlog_set_ident(list, vlog_ident2(mod));
29✔
1761
      vlog_add_stmt(list, stmt);
29✔
1762

1763
      const int ngenmaps = tree_genmaps(bind);
29✔
1764
      for (int i = 0; i < ngenmaps; i++) {
34✔
1765
         tree_t decl = tree_ref(tree_value(tree_genmap(bind, i)));
5✔
1766
         assert(tree_kind(decl) == T_GENERIC_DECL);
5✔
1767

1768
         tree_t map = hash_get(new_ctx.generics, decl);
5✔
1769
         if (map == NULL)
5✔
UNCOV
1770
            fatal_at(tree_loc(inst), "cannot get value of generic %s",
×
1771
                     istr(tree_ident(decl)));
1772

1773
         // TODO: have some better way of constructing these
1774
         char buf[64];
5✔
1775
         checked_sprintf(buf, sizeof(buf), "32'd%"PRIi64, assume_int(map));
5✔
1776

1777
         vlog_node_t num = vlog_new(V_NUMBER);
5✔
1778
         vlog_set_number(num, number_new(buf, NULL));
5✔
1779

1780
         vlog_node_t pa = vlog_new(V_PARAM_ASSIGN);
5✔
1781
         vlog_set_value(pa, num);
5✔
1782

1783
         vlog_add_param(list, pa);
5✔
1784
      }
1785

1786
      elab_instance_t *ei = elab_new_instance(mod, list, &new_ctx);
29✔
1787
      elab_verilog_module(bind, vlog_ident2(mod), ei, &new_ctx);
29✔
1788
   }
1789
   else
1790
      elab_architecture(bind, arch, config, &new_ctx);
1,132✔
1791

1792
   elab_pop_scope(&new_ctx);
1,186✔
1793
}
1,186✔
1794

1795
static tree_t elab_block_config(tree_t block, const elab_ctx_t *ctx)
3,417✔
1796
{
1797
   if (ctx->config == NULL)
3,417✔
1798
      return NULL;
1799

1800
   ident_t label = tree_ident(block);
116✔
1801

1802
   const int ndecls = tree_decls(ctx->config);
116✔
1803
   for (int i = 0; i < ndecls; i++) {
220✔
1804
      tree_t d = tree_decl(ctx->config, i);
208✔
1805
      if (tree_kind(d) != T_BLOCK_CONFIG)
208✔
1806
         continue;
76✔
1807
      else if (tree_ident(d) == label)
132✔
1808
         return d;
104✔
1809
   }
1810

1811
   return NULL;
1812
}
1813

1814
static void elab_instance(tree_t t, const elab_ctx_t *ctx)
3,453✔
1815
{
1816
   if (ctx->depth == MAX_DEPTH) {
3,453✔
1817
      diag_t *d = diag_new(DIAG_ERROR, tree_loc(t));
1✔
1818
      diag_printf(d, "maximum instantiation depth of %d reached", MAX_DEPTH);
1✔
1819
      diag_hint(d, NULL, "this is likely caused by unbounded recursion");
1✔
1820
      diag_emit(d);
1✔
1821
      return;
1✔
1822
   }
1823

1824
   tree_t ref = tree_ref(t);
3,452✔
1825
   switch (tree_kind(ref)) {
3,452✔
1826
   case T_ENTITY:
2,169✔
1827
      {
1828
         tree_t arch = elab_pick_arch(tree_loc(t), ref, ctx);
2,169✔
1829
         elab_architecture(t, arch, NULL, ctx);
2,169✔
1830
      }
1831
      break;
2,169✔
1832

1833
   case T_ARCH:
81✔
1834
      elab_architecture(t, ref, NULL, ctx);
81✔
1835
      break;
81✔
1836

1837
   case T_COMPONENT:
1,186✔
1838
      elab_component(t, ref, ctx);
1,186✔
1839
      break;
1,186✔
1840

1841
   case T_CONFIGURATION:
16✔
1842
      {
1843
         tree_t config = tree_decl(ref, 0);
16✔
1844
         assert(tree_kind(config) == T_BLOCK_CONFIG);
16✔
1845

1846
         tree_t arch = tree_ref(config);
16✔
1847
         elab_architecture(t, arch, config, ctx);
16✔
1848
      }
1849
      break;
16✔
1850

UNCOV
1851
   default:
×
1852
      fatal_trace("unexpected tree kind %s in elab_instance",
1853
                  tree_kind_str(tree_kind(ref)));
1854
   }
1855
}
1856

1857
static void elab_decls(tree_t t, const elab_ctx_t *ctx)
19,865✔
1858
{
1859
   const int ndecls = tree_decls(t);
19,865✔
1860
   for (int i = 0; i < ndecls; i++) {
56,974✔
1861
      tree_t d = tree_decl(t, i);
37,109✔
1862

1863
      switch (tree_kind(d)) {
37,109✔
1864
      case T_SIGNAL_DECL:
17,195✔
1865
      case T_IMPLICIT_SIGNAL:
1866
      case T_ALIAS:
1867
      case T_FILE_DECL:
1868
      case T_VAR_DECL:
1869
      case T_CONST_DECL:
1870
      case T_FUNC_BODY:
1871
      case T_PROC_BODY:
1872
      case T_FUNC_INST:
1873
      case T_PROC_INST:
1874
      case T_PROT_DECL:
1875
      case T_PROT_BODY:
1876
      case T_TYPE_DECL:
1877
      case T_SUBTYPE_DECL:
1878
      case T_PACK_BODY:
1879
      case T_PACKAGE:
1880
      case T_PACK_INST:
1881
      case T_PSL_DECL:
1882
      case T_ATTR_SPEC:
1883
      case T_VERILOG:
1884
         tree_add_decl(ctx->out, d);
17,195✔
1885
         break;
17,195✔
1886
      case T_FUNC_DECL:
16,748✔
1887
      case T_PROC_DECL:
1888
         if (!is_open_coded_builtin(tree_subkind(d)))
16,748✔
1889
            tree_add_decl(ctx->out, d);
8,611✔
1890
         break;
1891
      default:
1892
         break;
1893
      }
1894
   }
1895
}
19,865✔
1896

1897
static void elab_push_scope(tree_t t, elab_ctx_t *ctx)
12,935✔
1898
{
1899
   tree_t h = tree_new(T_HIER);
12,935✔
1900
   tree_set_loc(h, tree_loc(t));
12,935✔
1901
   tree_set_subkind(h, tree_kind(t));
12,935✔
1902
   tree_set_ref(h, t);
12,935✔
1903

1904
   tree_set_ident(h, ctx->dotted);
12,935✔
1905
   tree_set_ident2(h, ctx->dotted);
12,935✔
1906

1907
   tree_add_decl(ctx->out, h);
12,935✔
1908
}
12,935✔
1909

1910
static void elab_pop_scope(elab_ctx_t *ctx)
12,930✔
1911
{
1912
   if (ctx->generics != NULL)
12,930✔
1913
      hash_free(ctx->generics);
4,215✔
1914

1915
   if (ctx->drivers != NULL)
12,930✔
1916
      free_drivers(ctx->drivers);
11,428✔
1917

1918
   if (ctx->lowered != NULL)
12,930✔
1919
      unit_registry_finalise(ctx->registry, ctx->lowered);
12,730✔
1920
}
12,930✔
1921

1922
static inline tree_t elab_eval_expr(tree_t t, const elab_ctx_t *ctx)
163✔
1923
{
1924
   void *context = *mptr_get(ctx->scope->privdata);
163✔
1925
   return eval_must_fold(ctx->jit, t, ctx->registry, ctx->lowered, context);
163✔
1926
}
1927

1928
static bool elab_copy_genvar_cb(tree_t t, void *ctx)
63,340✔
1929
{
1930
   tree_t genvar = ctx;
63,340✔
1931
   return tree_kind(t) == T_REF && tree_ref(t) == genvar;
63,340✔
1932
}
1933

1934
static void elab_generate_range(tree_t r, int64_t *low, int64_t *high,
385✔
1935
                                const elab_ctx_t *ctx)
1936
{
1937
   if (tree_subkind(r) == RANGE_EXPR) {
385✔
1938
      tree_t value = tree_value(r);
45✔
1939
      assert(tree_kind(value) == T_ATTR_REF);
45✔
1940

1941
      tree_t tmp = tree_new(T_ATTR_REF);
45✔
1942
      tree_set_name(tmp, tree_name(value));
45✔
1943
      tree_set_type(tmp, tree_type(r));
45✔
1944
      tree_set_subkind(tmp, ATTR_LOW);
45✔
1945

1946
      tree_t tlow = elab_eval_expr(tmp, ctx);
45✔
1947
      if (folded_int(tlow, low)) {
45✔
1948
         tree_set_subkind(tmp, ATTR_HIGH);
45✔
1949

1950
         tree_t thigh = elab_eval_expr(tmp, ctx);
45✔
1951
         if (folded_int(thigh, high))
45✔
1952
            return;
1953
      }
1954

UNCOV
1955
      error_at(tree_loc(r), "generate range is not static");
×
UNCOV
1956
      *low = *high = 0;
×
1957
   }
1958
   else if (!folded_bounds(r, low, high)) {
340✔
1959
      tree_t left  = elab_eval_expr(tree_left(r), ctx);
14✔
1960
      tree_t right = elab_eval_expr(tree_right(r), ctx);
14✔
1961

1962
      int64_t ileft, iright;
14✔
1963
      if (folded_int(left, &ileft) && folded_int(right, &iright)) {
14✔
1964
         const bool asc = (tree_subkind(r) == RANGE_TO);
14✔
1965
         *low = asc ? ileft : iright;
14✔
1966
         *high = asc ? iright : ileft;
14✔
1967
      }
1968
      else {
UNCOV
1969
         error_at(tree_loc(r), "generate range is not static");
×
UNCOV
1970
         *low = *high = 0;
×
1971
      }
1972
   }
1973
}
1974

1975
static void elab_for_generate(tree_t t, const elab_ctx_t *ctx)
385✔
1976
{
1977
   int64_t low, high;
385✔
1978
   elab_generate_range(tree_range(t, 0), &low, &high, ctx);
385✔
1979

1980
   tree_t g = tree_decl(t, 0);
385✔
1981
   assert(tree_kind(g) == T_GENERIC_DECL);
385✔
1982

1983
   ident_t base = tree_ident(t);
385✔
1984

1985
   for (int64_t i = low; i <= high; i++) {
2,332✔
1986
      LOCAL_TEXT_BUF tb = tb_new();
3,894✔
1987
      tb_cat(tb, istr(base));
1,947✔
1988
      tb_printf(tb, "(%"PRIi64")", i);
1,947✔
1989

1990
      ident_t id = ident_new(tb_get(tb));
1,947✔
1991

1992
      tree_t b = tree_new(T_BLOCK);
1,947✔
1993
      tree_set_loc(b, tree_loc(t));
1,947✔
1994
      tree_set_ident(b, id);
1,947✔
1995
      tree_set_loc(b, tree_loc(t));
1,947✔
1996

1997
      tree_add_stmt(ctx->out, b);
1,947✔
1998

1999
      tree_t map = tree_new(T_PARAM);
1,947✔
2000
      tree_set_subkind(map, P_POS);
1,947✔
2001
      tree_set_loc(map, tree_loc(g));
1,947✔
2002
      tree_set_value(map, get_int_lit(g, NULL, i));
1,947✔
2003

2004
      tree_add_generic(b, g);
1,947✔
2005
      tree_add_genmap(b, map);
1,947✔
2006

2007
      ident_t ndotted = ident_prefix(ctx->dotted, id, '.');
1,947✔
2008

2009
      elab_ctx_t new_ctx = {
1,947✔
2010
         .out       = b,
2011
         .dotted    = ndotted,
2012
         .generics  = hash_new(16),
1,947✔
2013
         .config    = elab_block_config(t, ctx),
1,947✔
2014
      };
2015
      elab_inherit_context(&new_ctx, ctx);
1,947✔
2016

2017
      new_ctx.prefix[0] = ident_prefix(ctx->dotted, base, '.');
1,947✔
2018

2019
      tree_t roots[] = { t };
1,947✔
2020
      copy_with_renaming(roots, 1, elab_copy_genvar_cb, NULL, g, ndotted,
1,947✔
2021
                         new_ctx.prefix, ARRAY_LEN(new_ctx.prefix));
2022

2023
      tree_t copy = roots[0];
1,947✔
2024

2025
      elab_push_scope(t, &new_ctx);
1,947✔
2026
      hash_put(new_ctx.generics, g, tree_value(map));
1,947✔
2027

2028
      simplify_global(copy, new_ctx.generics, new_ctx.jit, new_ctx.registry,
1,947✔
2029
                      new_ctx.mir);
2030

2031
      new_ctx.drivers = find_drivers(copy);
1,947✔
2032

2033
      if (error_count() == 0)
1,947✔
2034
         elab_decls(copy, &new_ctx);
1,947✔
2035

2036
      if (error_count() == 0) {
1,947✔
2037
         elab_lower(b, NULL, &new_ctx);
1,947✔
2038
         elab_stmts(copy, &new_ctx);
1,947✔
2039
      }
2040

2041
      elab_pop_scope(&new_ctx);
1,947✔
2042
   }
2043
}
385✔
2044

2045
static bool elab_generate_test(tree_t value, const elab_ctx_t *ctx)
45✔
2046
{
2047
   bool test;
45✔
2048
   if (folded_bool(value, &test))
45✔
UNCOV
2049
      return test;
×
2050

2051
   tree_t folded = elab_eval_expr(value, ctx);
45✔
2052

2053
   if (folded_bool(folded, &test))
45✔
2054
      return test;
44✔
2055

2056
   error_at(tree_loc(value), "generate expression is not static");
1✔
2057
   return false;
1✔
2058
}
2059

2060
static void elab_if_generate(tree_t t, const elab_ctx_t *ctx)
45✔
2061
{
2062
   const int nconds = tree_conds(t);
45✔
2063
   for (int i = 0; i < nconds; i++) {
59✔
2064
      tree_t cond = tree_cond(t, i);
45✔
2065
      if (!tree_has_value(cond) || elab_generate_test(tree_value(cond), ctx)) {
45✔
2066
         tree_t b = tree_new(T_BLOCK);
31✔
2067
         tree_set_loc(b, tree_loc(cond));
31✔
2068
         tree_set_ident(b, tree_ident(cond));
31✔
2069

2070
         tree_add_stmt(ctx->out, b);
31✔
2071

2072
         ident_t name = tree_ident(cond);
31✔
2073
         ident_t ndotted = ident_prefix(ctx->dotted, name, '.');
31✔
2074

2075
         elab_ctx_t new_ctx = {
31✔
2076
            .out    = b,
2077
            .dotted = ndotted,
2078
            .config = elab_block_config(cond, ctx),
31✔
2079
         };
2080
         elab_inherit_context(&new_ctx, ctx);
31✔
2081

2082
         elab_push_scope(t, &new_ctx);
31✔
2083
         elab_decls(cond, &new_ctx);
31✔
2084

2085
         new_ctx.drivers = find_drivers(cond);
31✔
2086

2087
         if (error_count() == 0) {
31✔
2088
            elab_lower(b, NULL, &new_ctx);
31✔
2089
            elab_stmts(cond, &new_ctx);
31✔
2090
         }
2091

2092
         elab_pop_scope(&new_ctx);
31✔
2093
         return;
31✔
2094
      }
2095
   }
2096
}
2097

2098
static void elab_case_generate(tree_t t, const elab_ctx_t *ctx)
16✔
2099
{
2100
   void *context = *mptr_get(ctx->scope->privdata);
16✔
2101
   tree_t chosen = eval_case(ctx->jit, t, ctx->lowered, context);
16✔
2102
   if (chosen == NULL)
16✔
UNCOV
2103
      return;
×
2104

2105
   ident_t id = tree_has_ident(chosen) ? tree_ident(chosen) : tree_ident(t);
16✔
2106

2107
   tree_t b = tree_new(T_BLOCK);
16✔
2108
   tree_set_loc(b, tree_loc(chosen));
16✔
2109
   tree_set_ident(b, id);
16✔
2110

2111
   tree_add_stmt(ctx->out, b);
16✔
2112

2113
   ident_t ndotted = ident_prefix(ctx->dotted, id, '.');
16✔
2114

2115
   elab_ctx_t new_ctx = {
16✔
2116
      .out    = b,
2117
      .dotted = ndotted,
2118
   };
2119
   elab_inherit_context(&new_ctx, ctx);
16✔
2120

2121
   elab_push_scope(t, &new_ctx);
16✔
2122
   elab_decls(chosen, &new_ctx);
16✔
2123

2124
   new_ctx.drivers = find_drivers(chosen);
16✔
2125

2126
   if (error_count() == 0) {
16✔
2127
      elab_lower(b, NULL, &new_ctx);
16✔
2128
      elab_stmts(chosen, &new_ctx);
16✔
2129
   }
2130

2131
   elab_pop_scope(&new_ctx);
16✔
2132
}
2133

2134
static void elab_process(tree_t t, const elab_ctx_t *ctx)
11,972✔
2135
{
2136
   if (error_count() == 0)
11,972✔
2137
      lower_process(ctx->lowered, t, elab_driver_set(ctx));
11,961✔
2138

2139
   tree_add_stmt(ctx->out, t);
11,972✔
2140
}
11,972✔
2141

2142
static void elab_psl(tree_t t, const elab_ctx_t *ctx)
296✔
2143
{
2144
   if (error_count() == 0)
296✔
2145
      psl_lower_directive(ctx->registry, ctx->lowered, ctx->cover, t);
296✔
2146

2147
   tree_add_stmt(ctx->out, t);
296✔
2148
}
296✔
2149

2150
static void elab_stmts(tree_t t, const elab_ctx_t *ctx)
19,679✔
2151
{
2152
   const int nstmts = tree_stmts(t);
19,679✔
2153
   for (int i = 0; i < nstmts; i++) {
37,285✔
2154
      tree_t s = tree_stmt(t, i);
17,606✔
2155

2156
      switch (tree_kind(s)) {
17,606✔
2157
      case T_INSTANCE:
3,453✔
2158
         elab_instance(s, ctx);
3,453✔
2159
         break;
3,453✔
2160
      case T_BLOCK:
1,439✔
2161
         elab_block(s, ctx);
1,439✔
2162
         break;
1,439✔
2163
      case T_FOR_GENERATE:
385✔
2164
         elab_for_generate(s, ctx);
385✔
2165
         break;
385✔
2166
      case T_IF_GENERATE:
45✔
2167
         elab_if_generate(s, ctx);
45✔
2168
         break;
45✔
2169
      case T_CASE_GENERATE:
16✔
2170
         elab_case_generate(s, ctx);
16✔
2171
         break;
16✔
2172
      case T_PROCESS:
11,972✔
2173
         elab_process(s, ctx);
11,972✔
2174
         break;
11,972✔
2175
      case T_PSL_DIRECT:
296✔
2176
         elab_psl(s, ctx);
296✔
2177
         break;
296✔
UNCOV
2178
      default:
×
2179
         fatal_trace("unexpected statement %s", tree_kind_str(tree_kind(s)));
2180
      }
2181
   }
2182
}
19,679✔
2183

2184
static void elab_block(tree_t t, const elab_ctx_t *ctx)
1,439✔
2185
{
2186
   ident_t id = tree_ident(t);
1,439✔
2187

2188
   tree_t b = tree_new(T_BLOCK);
1,439✔
2189
   tree_set_ident(b, id);
1,439✔
2190
   tree_set_loc(b, tree_loc(t));
1,439✔
2191

2192
   tree_add_stmt(ctx->out, b);
1,439✔
2193

2194
   ident_t ndotted = ident_prefix(ctx->dotted, id, '.');
1,439✔
2195

2196
   elab_ctx_t new_ctx = {
1,439✔
2197
      .out    = b,
2198
      .dotted = ndotted,
2199
      .config = elab_block_config(t, ctx),
1,439✔
2200
   };
2201
   elab_inherit_context(&new_ctx, ctx);
1,439✔
2202

2203
   const int base_errors = error_count();
1,439✔
2204

2205
   elab_push_scope(t, &new_ctx);
1,439✔
2206
   elab_generics(t, t, &new_ctx);
1,439✔
2207
   elab_ports(t, t, &new_ctx);
1,439✔
2208
   elab_decls(t, &new_ctx);
1,439✔
2209

2210
   if (error_count() == base_errors) {
1,439✔
2211
      elab_lower(b, NULL, &new_ctx);
1,439✔
2212
      elab_stmts(t, &new_ctx);
1,439✔
2213
   }
2214

2215
   elab_pop_scope(&new_ctx);
1,439✔
2216
}
1,439✔
2217

2218
static tree_t elab_top_level_binding(tree_t arch, const elab_ctx_t *ctx)
4,739✔
2219
{
2220
   tree_t bind = tree_new(T_BINDING);
4,739✔
2221
   tree_set_ident(bind, tree_ident(arch));
4,739✔
2222
   tree_set_loc(bind, tree_loc(arch));
4,739✔
2223
   tree_set_ref(bind, arch);
4,739✔
2224
   tree_set_class(bind, C_ENTITY);
4,739✔
2225

2226
   tree_t entity = tree_primary(arch);
4,739✔
2227
   const int ngenerics = tree_generics(entity);
4,739✔
2228

2229
   for (int i = 0; i < ngenerics; i++) {
5,414✔
2230
      tree_t g = tree_generic(entity, i);
675✔
2231
      ident_t name = tree_ident(g);
675✔
2232

2233
      if (tree_flags(g) & TREE_F_PREDEFINED)
675✔
2234
         continue;    // Predefined generic subprograms
2✔
2235
      else if (tree_class(g) != C_CONSTANT) {
673✔
2236
         error_at(tree_loc(g), "only constant top-level generics are "
1✔
2237
                  "supported");
2238
         continue;
1✔
2239
      }
2240

2241
      tree_t value = elab_find_generic_override(g, ctx);
672✔
2242
      if (value == NULL && tree_has_value(g))
672✔
2243
         value = tree_value(g);
595✔
2244
      else if (value == NULL) {
77✔
2245
         error_at(tree_loc(g), "generic %s of top-level entity must have "
1✔
2246
                  "default value or be specified using -gNAME=VALUE",
2247
                  istr(name));
2248
         continue;
1✔
2249
      }
2250

2251
      tree_t map = tree_new(T_PARAM);
671✔
2252
      tree_set_subkind(map, P_POS);
671✔
2253
      tree_set_pos(map, i);
671✔
2254
      tree_set_value(map, value);
671✔
2255

2256
      tree_add_genmap(bind, map);
671✔
2257
   }
2258

2259
   const int nports = tree_ports(entity);
4,739✔
2260
   for (int i = 0; i < nports; i++) {
5,183✔
2261
      tree_t p = tree_port(entity, i);
444✔
2262

2263
      tree_t m = tree_new(T_PARAM);
444✔
2264
      tree_set_subkind(m, P_POS);
444✔
2265
      tree_set_pos(m, i);
444✔
2266

2267
      if (tree_subkind(p) == PORT_IN && tree_has_value(p))
444✔
2268
         tree_set_value(m, tree_value(p));
44✔
2269
      else {
2270
         type_t type = tree_type(p);
400✔
2271
         if (type_is_unconstrained(type))
400✔
2272
            error_at(tree_loc(p), "unconnected top-level port %s cannot have "
1✔
2273
                     "unconstrained type %s", istr(tree_ident(p)),
2274
                     type_pp(type));
2275

2276
         tree_t open = tree_new(T_OPEN);
400✔
2277
         tree_set_type(open, type);
400✔
2278
         tree_set_loc(open, tree_loc(p));
400✔
2279

2280
         tree_set_value(m, open);
400✔
2281
      }
2282

2283
      tree_add_param(bind, m);
444✔
2284
   }
2285

2286
   return bind;
4,739✔
2287
}
2288

2289
void elab_set_generic(const char *name, const char *value)
85✔
2290
{
2291
   ident_t id = ident_new(name);
85✔
2292

2293
   for (generic_list_t *it = generic_override; it != NULL; it = it->next) {
110✔
2294
      if (it->name == id)
25✔
UNCOV
2295
         fatal("generic %s already has value '%s'", name, it->value);
×
2296
   }
2297

2298
   generic_list_t *new = xmalloc(sizeof(generic_list_t));
85✔
2299
   new->name  = id;
85✔
2300
   new->value = xstrdup(value);
85✔
2301
   new->next  = generic_override;
85✔
2302

2303
   generic_override = new;
85✔
2304
}
85✔
2305

2306
static void elab_vhdl_root_cb(void *arg)
4,739✔
2307
{
2308
   elab_ctx_t *ctx = arg;
4,739✔
2309

2310
   tree_t vhdl = tree_from_object(ctx->root);
4,739✔
2311
   assert(vhdl != NULL);
4,739✔
2312

2313
   tree_t arch, config = NULL;
4,739✔
2314
   switch (tree_kind(vhdl)) {
4,739✔
2315
   case T_ENTITY:
4,641✔
2316
      arch = elab_pick_arch(&ctx->root->loc, vhdl, ctx);
4,641✔
2317
      break;
4,641✔
2318
   case T_ARCH:
2319
      arch = vhdl;
2320
      break;
2321
   case T_CONFIGURATION:
72✔
2322
      config = tree_decl(vhdl, 0);
72✔
2323
      assert(tree_kind(config) == T_BLOCK_CONFIG);
72✔
2324
      arch = tree_ref(config);
72✔
2325
      break;
72✔
UNCOV
2326
   default:
×
UNCOV
2327
      fatal("%s is not a suitable top-level unit", istr(tree_ident(vhdl)));
×
2328
   }
2329

2330
   tree_t bind = elab_top_level_binding(arch, ctx);
4,739✔
2331

2332
   if (error_count() == 0)
4,739✔
2333
      elab_architecture(bind, arch, config, ctx);
4,737✔
2334
}
4,734✔
2335

2336
static void elab_verilog_root_cb(void *arg)
117✔
2337
{
2338
   elab_ctx_t *ctx = arg;
117✔
2339

2340
   vlog_node_t vlog = vlog_from_object(ctx->root);
117✔
2341
   assert(vlog != NULL);
117✔
2342

2343
   ident_t label = vlog_ident2(vlog);
117✔
2344

2345
   vlog_node_t stmt = vlog_new(V_MOD_INST);
117✔
2346
   vlog_set_ident(stmt, label);
117✔
2347

2348
   vlog_node_t list = vlog_new(V_INST_LIST);
117✔
2349
   vlog_set_ident(list, label);
117✔
2350
   vlog_add_stmt(list, stmt);
117✔
2351

2352
   elab_instance_t *ei = elab_new_instance(vlog, list, ctx);
117✔
2353
   elab_verilog_module(NULL, label, ei, ctx);
117✔
2354
}
117✔
2355

2356
tree_t elab(object_t *top, jit_t *jit, unit_registry_t *ur, mir_context_t *mc,
4,856✔
2357
            cover_data_t *cover, sdf_file_t *sdf, rt_model_t *m)
2358
{
2359
   make_new_arena();
4,856✔
2360

2361
   ident_t name = NULL;
4,856✔
2362

2363
   tree_t vhdl = tree_from_object(top);
4,856✔
2364
   if (vhdl != NULL)
4,856✔
2365
      name = ident_prefix(tree_ident(vhdl), well_known(W_ELAB), '.');
4,739✔
2366

2367
   vlog_node_t vlog = vlog_from_object(top);
4,856✔
2368
   if (vlog != NULL)
4,856✔
2369
      name = ident_prefix(vlog_ident(vlog), well_known(W_ELAB), '.');
117✔
2370

2371
   if (vhdl == NULL && vlog == NULL)
4,856✔
UNCOV
2372
      fatal("top level is not a VHDL design unit or Verilog module");
×
2373

2374
   tree_t e = tree_new(T_ELAB);
4,856✔
2375
   tree_set_ident(e, name);
4,856✔
2376
   tree_set_loc(e, &(top->loc));
4,856✔
2377

2378
   lib_t work = lib_work();
4,856✔
2379

2380
   elab_ctx_t ctx = {
4,856✔
2381
      .out       = e,
2382
      .root      = top,
2383
      .cover     = cover,
2384
      .library   = work,
2385
      .jit       = jit,
2386
      .sdf       = sdf,
2387
      .registry  = ur,
2388
      .mir       = mc,
2389
      .modcache  = hash_new(16),
4,856✔
2390
      .dotted    = lib_name(work),
4,856✔
2391
      .model     = m,
2392
      .scope     = create_scope(m, e, NULL),
4,856✔
2393
   };
2394

2395
   if (vhdl != NULL)
4,856✔
2396
      call_with_model(m, elab_vhdl_root_cb, &ctx);
4,739✔
2397
   else
2398
      call_with_model(m, elab_verilog_root_cb, &ctx);
117✔
2399

2400
   const void *key;
4,851✔
2401
   void *value;
4,851✔
2402
   for (hash_iter_t it = HASH_BEGIN;
4,851✔
2403
        hash_iter(ctx.modcache, &it, &key, &value); )
5,018✔
2404
      free(value);
167✔
2405

2406
   hash_free(ctx.modcache);
4,851✔
2407

2408
   if (error_count() > 0)
4,851✔
2409
      return NULL;
2410

2411
   if (opt_get_verbose(OPT_ELAB_VERBOSE, NULL))
4,819✔
UNCOV
2412
      dump(e);
×
2413

2414
   for (generic_list_t *it = generic_override; it != NULL; it = it->next)
4,820✔
2415
      warnf("generic value for %s not used", istr(it->name));
1✔
2416

2417
   ident_t b0_name = tree_ident(tree_stmt(e, 0));
4,819✔
2418
   ident_t vu_name = ident_prefix(lib_name(ctx.library), b0_name, '.');
4,819✔
2419
   unit_registry_flush(ur, vu_name);
4,819✔
2420

2421
   freeze_global_arena();
4,819✔
2422
   return e;
4,819✔
2423
}
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