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

nickg / nvc / 12293324012

12 Dec 2024 09:18AM UTC coverage: 91.973% (+0.1%) from 91.835%
12293324012

Pull #1081

github

web-flow
Merge c7e642928 into 72b5e72f5
Pull Request #1081: Add PSL 2010 features breakdown to HTML docs.

63217 of 68734 relevant lines covered (91.97%)

621809.29 hits per line

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

98.12
/src/vlog/vlog-node.c
1
//
2
//  Copyright (C) 2022-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 "vlog/vlog-node.h"
20
#include "vlog/vlog-number.h"
21
#include "object.h"
22

23
#include <string.h>
24
#include <inttypes.h>
25
#include <stdlib.h>
26

27
static const imask_t has_map[V_LAST_NODE_KIND] = {
28
   // V_MODULE
29
   (I_IDENT | I_PORTS | I_STMTS | I_DECLS | I_IDENT2),
30

31
   // V_PORT_DECL
32
   (I_IDENT | I_SUBKIND | I_IDENT2 | I_REF | I_RANGES | I_TYPE),
33

34
   // V_REF
35
   (I_IDENT | I_REF),
36

37
   // V_ALWAYS
38
   (I_IDENT | I_STMTS),
39

40
   // V_TIMING
41
   (I_VALUE | I_STMTS),
42

43
   // V_NBASSIGN
44
   (I_TARGET | I_VALUE | I_DELAY),
45

46
   // V_EVENT
47
   (I_SUBKIND | I_VALUE),
48

49
   // V_INITIAL
50
   (I_IDENT | I_STMTS),
51

52
   // V_SEQ_BLOCK
53
   (I_IDENT | I_STMTS),
54

55
   // V_SYS_TCALL
56
   (I_IDENT | I_PARAMS),
57

58
   // V_STRING
59
   (I_TEXT),
60

61
   // V_NUMBER
62
   (I_NUMBER),
63

64
   // V_NET_DECL
65
   (I_IDENT | I_SUBKIND | I_TYPE | I_RANGES | I_VALUE),
66

67
   // V_ASSIGN
68
   (I_TARGET | I_VALUE | I_IDENT | I_DELAY),
69

70
   // V_DIMENSION
71
   (I_SUBKIND | I_LEFT | I_RIGHT),
72

73
   // V_IF
74
   (I_CONDS),
75

76
   // V_COND
77
   (I_VALUE | I_STMTS),
78

79
   // V_VAR_DECL
80
   (I_IDENT | I_TYPE | I_RANGES | I_VALUE),
81

82
   // V_DELAY_CONTROL
83
   (I_VALUE),
84

85
   // V_BINARY
86
   (I_LEFT | I_RIGHT | I_SUBKIND),
87

88
   // V_BASSIGN
89
   (I_TARGET | I_VALUE | I_SUBKIND | I_DELAY),
90

91
   // V_UNARY
92
   (I_VALUE | I_SUBKIND),
93

94
   // V_GATE_INST
95
   (I_SUBKIND | I_PARAMS | I_IDENT | I_REF | I_TARGET),
96

97
   // V_STRENGTH
98
   (I_SUBKIND),
99

100
   // V_MOD_INST
101
   (I_IDENT | I_IDENT2 | I_PARAMS),
102

103
   // V_BIT_SELECT
104
   (I_IDENT | I_REF | I_PARAMS),
105

106
   // V_SYS_FCALL
107
   (I_IDENT | I_PARAMS),
108

109
   // V_FOREVER
110
   (I_STMTS),
111

112
   // V_SPECIFY
113
   (0),
114

115
   // V_PRIMITIVE
116
   (I_IDENT | I_IDENT2 | I_PORTS | I_DECLS | I_STMTS),
117

118
   // V_UDP_TABLE
119
   (I_IDENT | I_PARAMS | I_SUBKIND | I_STMTS),
120

121
   // V_UDP_ENTRY
122
   (I_TEXT),
123

124
   // V_DATA_TYPE
125
   (I_SUBKIND | I_RANGES),
126

127
   // V_TYPE_DECL
128
   (I_IDENT | I_TYPE),
129

130
   // V_ENUM_DECL
131
   (I_IDENT | I_TYPE | I_RANGES | I_DECLS),
132

133
   // V_ENUM_NAME
134
   (I_IDENT | I_TYPE),
135

136
   // V_UNION_DECL
137
   (I_IDENT | I_DECLS),
138

139
   // V_STRUCT_DECL
140
   (I_IDENT | I_DECLS),
141

142
   // V_EVENT_CONTROL
143
   (I_PARAMS),
144

145
   // V_EMPTY
146
   (0),
147

148
   // V_REPEAT
149
   (I_VALUE | I_STMTS),
150

151
   // V_WHILE
152
   (I_VALUE | I_STMTS),
153

154
   // V_DO_WHILE
155
   (I_VALUE | I_STMTS),
156

157
   // V_TASK_DECL
158
   (I_IDENT | I_STMTS | I_DECLS),
159

160
   // V_FUNC_DECL
161
   (I_IDENT | I_STMTS | I_DECLS | I_TYPE),
162
};
163

164
static const char *kind_text_map[V_LAST_NODE_KIND] = {
165
   "V_MODULE",     "V_PORT_DECL",   "V_REF",           "V_ALWAYS",
166
   "V_TIMING",     "V_NBASSIGN",    "V_EVENT",         "V_INITIAL",
167
   "V_SEQ_BLOCK",  "V_SYS_TCALL",   "V_STRING",        "V_NUMBER",
168
   "V_NET_DECL",   "V_ASSIGN",      "V_DIMENSION",     "V_IF",
169
   "V_COND",       "V_VAR_DECL",    "V_DELAY_CONTROL", "V_BINARY",
170
   "V_BASSIGN",    "V_UNARY",       "V_GATE_INST",     "V_STRENGTH",
171
   "V_MOD_INST",   "V_BIT_SELECT",  "V_SYS_FCALL",     "V_FOREVER",
172
   "V_SPECIFY",    "V_PRIMITIVE",   "V_UDP_TABLE",     "V_UDP_ENTRY",
173
   "V_DATA_TYPE",  "V_TYPE_DECL",   "V_ENUM_DECL",     "V_ENUM_NAME",
174
   "V_UNION_DECL", "V_STRUCT_DECL", "V_EVENT_CONTROL", "V_EMPTY",
175
   "V_REPEAT",     "V_WHILE",       "V_DO_WHILE",      "V_TASK_DECL",
176
   "V_FUNC_DECL",
177
};
178

179
static const change_allowed_t change_allowed[] = {
180
   { -1, -1 }
181
};
182

183
object_class_t vlog_object = {
184
   .name           = "vlog",
185
   .change_allowed = change_allowed,
186
   .has_map        = has_map,
187
   .kind_text_map  = kind_text_map,
188
   .tag            = OBJECT_TAG_VLOG,
189
   .last_kind      = V_LAST_NODE_KIND,
190
   .has_loc        = true,
191
   .gc_roots       = { V_MODULE, V_PRIMITIVE },
192
   .gc_num_roots   = 2
193
};
194

195
struct _vlog_node {
196
   object_t object;
197
};
198

199
static inline vlog_node_t vlog_array_nth(item_t *item, unsigned n)
7,081✔
200
{
201
   object_t *o = obj_array_nth(item->obj_array, n);
7,081✔
202
   return container_of(o, struct _vlog_node, object);
7,081✔
203
}
204

205
static inline void vlog_array_add(item_t *item, vlog_node_t v)
2,959✔
206
{
207
   obj_array_add(&(item->obj_array), &(v->object));
2,959✔
208
}
2,959✔
209

210
vlog_node_t vlog_new(vlog_kind_t kind)
5,338✔
211
{
212
   object_t *o = object_new(NULL, &vlog_object, kind);
5,338✔
213
   return container_of(o, struct _vlog_node, object);
5,338✔
214
}
215

216
vlog_kind_t vlog_kind(vlog_node_t v)
24,310✔
217
{
218
   return v->object.kind;
24,310✔
219
}
220

221
const char *vlog_kind_str(vlog_kind_t kind)
×
222
{
223
   return kind_text_map[kind];
×
224
}
225

226
ident_t vlog_ident(vlog_node_t v)
4,302✔
227
{
228
   item_t *item = lookup_item(&vlog_object, v, I_IDENT);
4,302✔
229
   assert(item->ident != NULL);
4,302✔
230
   return item->ident;
4,302✔
231
}
232

233
void vlog_set_ident(vlog_node_t v, ident_t i)
2,458✔
234
{
235
   lookup_item(&vlog_object, v, I_IDENT)->ident = i;
2,458✔
236
}
2,458✔
237

238
bool vlog_has_ident(vlog_node_t v)
32✔
239
{
240
   return lookup_item(&vlog_object, v, I_IDENT)->ident != NULL;
32✔
241
}
242

243
ident_t vlog_ident2(vlog_node_t v)
199✔
244
{
245
   item_t *item = lookup_item(&vlog_object, v, I_IDENT2);
199✔
246
   assert(item->ident != NULL);
199✔
247
   return item->ident;
199✔
248
}
249

250
void vlog_set_ident2(vlog_node_t v, ident_t i)
300✔
251
{
252
   lookup_item(&vlog_object, v, I_IDENT2)->ident = i;
300✔
253
}
300✔
254

255
const loc_t *vlog_loc(vlog_node_t v)
3,976✔
256
{
257
   assert(v != NULL);
3,976✔
258
   return &(v->object.loc);
3,976✔
259
}
260

261
void vlog_set_loc(vlog_node_t v, const loc_t *loc)
5,792✔
262
{
263
   assert(v != NULL);
5,792✔
264
   assert(loc != NULL);
5,792✔
265
   v->object.loc = *loc;
5,792✔
266
}
5,792✔
267

268
vlog_node_t vlog_ref(vlog_node_t v)
2,505✔
269
{
270
   item_t *item = lookup_item(&vlog_object, v, I_REF);
2,505✔
271
   assert(item->object != NULL);
2,505✔
272
   return container_of(item->object, struct _vlog_node, object);
2,505✔
273
}
274

275
bool vlog_has_ref(vlog_node_t v)
905✔
276
{
277
   return lookup_item(&vlog_object, v, I_REF)->object != NULL;
905✔
278
}
279

280
void vlog_set_ref(vlog_node_t v, vlog_node_t d)
1,289✔
281
{
282
   lookup_item(&vlog_object, v, I_REF)->object = &(d->object);
1,289✔
283
   object_write_barrier(&(v->object), &(d->object));
1,289✔
284
}
1,289✔
285

286
unsigned vlog_stmts(vlog_node_t v)
1,388✔
287
{
288
   item_t *item = lookup_item(&vlog_object, v, I_STMTS);
1,388✔
289
   return obj_array_count(item->obj_array);
1,388✔
290
}
291

292
vlog_node_t vlog_stmt(vlog_node_t v, unsigned n)
2,706✔
293
{
294
   item_t *item = lookup_item(&vlog_object, v, I_STMTS);
2,706✔
295
   return vlog_array_nth(item, n);
2,706✔
296
}
297

298
void vlog_add_stmt(vlog_node_t v, vlog_node_t s)
1,307✔
299
{
300
   assert(s != NULL);
1,307✔
301
   vlog_array_add(lookup_item(&vlog_object, v, I_STMTS), s);
1,307✔
302
   object_write_barrier(&(v->object), &(s->object));
1,307✔
303
}
1,307✔
304

305
unsigned vlog_ports(vlog_node_t v)
301✔
306
{
307
   item_t *item = lookup_item(&vlog_object, v, I_PORTS);
301✔
308
   return obj_array_count(item->obj_array);
301✔
309
}
310

311
vlog_node_t vlog_port(vlog_node_t v, unsigned n)
410✔
312
{
313
   item_t *item = lookup_item(&vlog_object, v, I_PORTS);
410✔
314
   return vlog_array_nth(item, n);
410✔
315
}
316

317
void vlog_add_port(vlog_node_t v, vlog_node_t p)
172✔
318
{
319
   assert(p != NULL);
172✔
320
   assert(p->object.kind == V_REF);
172✔
321
   vlog_array_add(lookup_item(&vlog_object, v, I_PORTS), p);
172✔
322
   object_write_barrier(&(v->object), &(p->object));
172✔
323
}
172✔
324

325
unsigned vlog_params(vlog_node_t v)
1,252✔
326
{
327
   item_t *item = lookup_item(&vlog_object, v, I_PARAMS);
1,252✔
328
   return obj_array_count(item->obj_array);
1,252✔
329
}
330

331
vlog_node_t vlog_param(vlog_node_t v, unsigned n)
2,067✔
332
{
333
   item_t *item = lookup_item(&vlog_object, v, I_PARAMS);
2,067✔
334
   return vlog_array_nth(item, n);
2,067✔
335
}
336

337
void vlog_add_param(vlog_node_t v, vlog_node_t p)
816✔
338
{
339
   assert(p != NULL);
816✔
340
   vlog_array_add(lookup_item(&vlog_object, v, I_PARAMS), p);
816✔
341
   object_write_barrier(&(v->object), &(p->object));
816✔
342
}
816✔
343

344
unsigned vlog_ranges(vlog_node_t v)
2,807✔
345
{
346
   item_t *item = lookup_item(&vlog_object, v, I_RANGES);
2,807✔
347
   return obj_array_count(item->obj_array);
2,807✔
348
}
349

350
vlog_node_t vlog_range(vlog_node_t v, unsigned n)
255✔
351
{
352
   item_t *item = lookup_item(&vlog_object, v, I_RANGES);
255✔
353
   return vlog_array_nth(item, n);
255✔
354
}
355

356
void vlog_add_range(vlog_node_t v, vlog_node_t r)
41✔
357
{
358
   assert(r != NULL);
41✔
359
   assert(r->object.kind == V_DIMENSION);
41✔
360
   vlog_array_add(lookup_item(&vlog_object, v, I_RANGES), r);
41✔
361
   object_write_barrier(&(v->object), &(r->object));
41✔
362
}
41✔
363

364
unsigned vlog_decls(vlog_node_t v)
332✔
365
{
366
   item_t *item = lookup_item(&vlog_object, v, I_DECLS);
332✔
367
   return obj_array_count(item->obj_array);
332✔
368
}
369

370
vlog_node_t vlog_decl(vlog_node_t v, unsigned n)
1,428✔
371
{
372
   item_t *item = lookup_item(&vlog_object, v, I_DECLS);
1,428✔
373
   return vlog_array_nth(item, n);
1,428✔
374
}
375

376
void vlog_add_decl(vlog_node_t v, vlog_node_t d)
508✔
377
{
378
   assert(d != NULL);
508✔
379
   vlog_array_add(lookup_item(&vlog_object, v, I_DECLS), d);
508✔
380
   object_write_barrier(&(v->object), &(d->object));
508✔
381
}
508✔
382

383
unsigned vlog_conds(vlog_node_t v)
188✔
384
{
385
   item_t *item = lookup_item(&vlog_object, v, I_CONDS);
188✔
386
   return obj_array_count(item->obj_array);
188✔
387
}
388

389
vlog_node_t vlog_cond(vlog_node_t v, unsigned n)
215✔
390
{
391
   item_t *item = lookup_item(&vlog_object, v, I_CONDS);
215✔
392
   return vlog_array_nth(item, n);
215✔
393
}
394

395
void vlog_add_cond(vlog_node_t v, vlog_node_t c)
115✔
396
{
397
   assert(c != NULL && c->object.kind == V_COND);
115✔
398
   vlog_array_add(lookup_item(&vlog_object, v, I_CONDS), c);
115✔
399
   object_write_barrier(&(v->object), &(c->object));
115✔
400
}
115✔
401

402
unsigned vlog_subkind(vlog_node_t v)
812✔
403
{
404
   return lookup_item(&vlog_object, v, I_SUBKIND)->ival;
812✔
405
}
406

407
void vlog_set_subkind(vlog_node_t v, unsigned sub)
1,161✔
408
{
409
   lookup_item(&vlog_object, v, I_SUBKIND)->ival = sub;
1,161✔
410
}
1,161✔
411

412
vlog_node_t vlog_value(vlog_node_t v)
1,990✔
413
{
414
   item_t *item = lookup_item(&vlog_object, v, I_VALUE);
1,990✔
415
   assert(item->object != NULL);
1,990✔
416
   return container_of(item->object, struct _vlog_node, object);
1,990✔
417
}
418

419
bool vlog_has_value(vlog_node_t v)
366✔
420
{
421
   return lookup_item(&vlog_object, v, I_VALUE)->object != NULL;
366✔
422
}
423

424
void vlog_set_value(vlog_node_t v, vlog_node_t e)
976✔
425
{
426
   lookup_item(&vlog_object, v, I_VALUE)->object = &(e->object);
976✔
427
   object_write_barrier(&(v->object), &(e->object));
976✔
428
}
976✔
429

430
vlog_node_t vlog_target(vlog_node_t v)
802✔
431
{
432
   item_t *item = lookup_item(&vlog_object, v, I_TARGET);
802✔
433
   assert(item->object != NULL);
802✔
434
   return container_of(item->object, struct _vlog_node, object);
802✔
435
}
436

437
void vlog_set_target(vlog_node_t v, vlog_node_t e)
370✔
438
{
439
   lookup_item(&vlog_object, v, I_TARGET)->object = &(e->object);
370✔
440
   object_write_barrier(&(v->object), &(e->object));
370✔
441
}
370✔
442

443
vlog_node_t vlog_delay(vlog_node_t v)
74✔
444
{
445
   item_t *item = lookup_item(&vlog_object, v, I_DELAY);
74✔
446
   assert(item->object != NULL);
74✔
447
   return container_of(item->object, struct _vlog_node, object);
74✔
448
}
449

450
bool vlog_has_delay(vlog_node_t v)
551✔
451
{
452
   return lookup_item(&vlog_object, v, I_DELAY)->object != NULL;
551✔
453
}
454

455
void vlog_set_delay(vlog_node_t v, vlog_node_t d)
38✔
456
{
457
   lookup_item(&vlog_object, v, I_DELAY)->object = &(d->object);
38✔
458
   object_write_barrier(&(v->object), &(d->object));
38✔
459
}
38✔
460

461
vlog_node_t vlog_type(vlog_node_t v)
1,948✔
462
{
463
   item_t *item = lookup_item(&vlog_object, v, I_TYPE);
1,948✔
464
   assert(item->object != NULL);
1,948✔
465
   return container_of(item->object, struct _vlog_node, object);
1,948✔
466
}
467

468
bool vlog_has_type(vlog_node_t v)
×
469
{
470
   return lookup_item(&vlog_object, v, I_TYPE)->object != NULL;
×
471
}
472

473
void vlog_set_type(vlog_node_t v, vlog_node_t t)
510✔
474
{
475
   lookup_item(&vlog_object, v, I_TYPE)->object = &(t->object);
510✔
476
   object_write_barrier(&(v->object), &(t->object));
510✔
477
}
510✔
478

479
const char *vlog_text(vlog_node_t v)
483✔
480
{
481
   item_t *item = lookup_item(&vlog_object, v, I_TEXT);
483✔
482
   assert(item->text != NULL);
483✔
483
   return item->text;
483✔
484
}
485

486
void vlog_set_text(vlog_node_t v, const char *text)
343✔
487
{
488
   lookup_item(&vlog_object, v, I_TEXT)->text = xstrdup(text);
343✔
489
}
343✔
490

491
number_t vlog_number(vlog_node_t v)
1,008✔
492
{
493
   return lookup_item(&vlog_object, v, I_NUMBER)->number;
1,008✔
494
}
495

496
void vlog_set_number(vlog_node_t v, number_t n)
663✔
497
{
498
   lookup_item(&vlog_object, v, I_NUMBER)->number = n;
663✔
499
}
663✔
500

501
vlog_node_t vlog_left(vlog_node_t v)
593✔
502
{
503
   item_t *item = lookup_item(&vlog_object, v, I_LEFT);
593✔
504
   assert(item->object != NULL);
593✔
505
   return container_of(item->object, struct _vlog_node, object);
593✔
506
}
507

508
void vlog_set_left(vlog_node_t v, vlog_node_t e)
221✔
509
{
510
   lookup_item(&vlog_object, v, I_LEFT)->object = &(e->object);
221✔
511
   object_write_barrier(&(v->object), &(e->object));
221✔
512
}
221✔
513

514
vlog_node_t vlog_right(vlog_node_t v)
593✔
515
{
516
   item_t *item = lookup_item(&vlog_object, v, I_RIGHT);
593✔
517
   assert(item->object != NULL);
593✔
518
   return container_of(item->object, struct _vlog_node, object);
593✔
519
}
520

521
void vlog_set_right(vlog_node_t v, vlog_node_t e)
221✔
522
{
523
   lookup_item(&vlog_object, v, I_RIGHT)->object = &(e->object);
221✔
524
   object_write_barrier(&(v->object), &(e->object));
221✔
525
}
221✔
526

527
void vlog_visit(vlog_node_t v, vlog_visit_fn_t fn, void *context)
165✔
528
{
529
   vlog_visit_only(v, fn, context, V_LAST_NODE_KIND);
165✔
530
}
165✔
531

532
void vlog_visit_only(vlog_node_t v, vlog_visit_fn_t fn, void *context,
165✔
533
                     vlog_kind_t kind)
534
{
535
   assert(v != NULL);
165✔
536

537
   object_visit_ctx_t ctx = {
165✔
538
      .count      = 0,
539
      .postorder  = (object_visit_fn_t)fn,
540
      .preorder   = NULL,
541
      .context    = context,
542
      .kind       = kind,
543
      .tag        = OBJECT_TAG_VLOG,
544
      .generation = object_next_generation(),
165✔
545
      .deep       = false
546
   };
547

548
   object_visit(&(v->object), &ctx);
165✔
549
}
165✔
550

551
vlog_node_t vlog_rewrite(vlog_node_t v, vlog_rewrite_fn_t fn, void *context)
83✔
552
{
553
   object_arena_t *arena = object_arena(&(v->object));
83✔
554
   if (arena_frozen(arena))
83✔
555
      return v;
556

557
   object_rewrite_ctx_t ctx = {
83✔
558
      .generation = object_next_generation(),
83✔
559
      .context    = context,
560
      .arena      = arena,
561
   };
562

563
   ctx.post_fn[OBJECT_TAG_VLOG] = (object_rewrite_post_fn_t)fn;
83✔
564

565
   object_t *result = object_rewrite(&(v->object), &ctx);
83✔
566
   free(ctx.cache);
83✔
567
   return container_of(result, struct _vlog_node, object);
83✔
568
}
569

570
object_t *vlog_to_object(vlog_node_t v)
374✔
571
{
572
   return &(v->object);
374✔
573
}
574

575
vlog_node_t vlog_from_object(object_t *obj)
4,245✔
576
{
577
   if (obj != NULL && obj->tag == OBJECT_TAG_VLOG)
4,245✔
578
      return container_of(obj, struct _vlog_node, object);
579
   else
580
      return NULL;
4,073✔
581
}
582

583
void vlog_locus(vlog_node_t v, ident_t *unit, ptrdiff_t *offset)
345✔
584
{
585
   assert(v != NULL);
345✔
586
   object_locus(&(v->object), unit, offset);
345✔
587
}
345✔
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