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

nickg / nvc / 6474253934

10 Oct 2023 07:38PM UTC coverage: 91.136% (-0.02%) from 91.159%
6474253934

push

github

nickg
Verilog continuous assignment and binary "&"

41 of 41 new or added lines in 2 files covered. (100.0%)

48876 of 53630 relevant lines covered (91.14%)

590714.14 hits per line

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

97.84
/src/vlog/vlog-node.c
1
//
2
//  Copyright (C) 2022  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 "common.h"
22
#include "object.h"
23

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

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

32
   // V_PORT_DECL
33
   (I_IDENT | I_SUBKIND | I_IDENT2 | I_RANGES),
34

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

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

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

44
   // V_NBASSIGN
45
   (I_TARGET | I_VALUE),
46

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

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

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

56
   // V_SYSTASK
57
   (I_IDENT | I_SUBKIND | I_PARAMS),
58

59
   // V_STRING
60
   (I_TEXT),
61

62
   // V_NUMBER
63
   (I_NUMBER),
64

65
   // V_NET_DECL
66
   (I_IDENT | I_SUBKIND | I_RANGES | I_DATATYPE),
67

68
   // V_ASSIGN
69
   (I_TARGET | I_VALUE | I_IDENT),
70

71
   // V_ROOT
72
   (I_IDENT | I_STMTS | I_DECLS),
73

74
   // V_DIMENSION
75
   (I_SUBKIND | I_LEFT | I_RIGHT),
76

77
   // V_IF
78
   (I_CONDS),
79

80
   // V_COND
81
   (I_VALUE | I_STMTS),
82

83
   // V_VAR_DECL
84
   (I_IDENT | I_RANGES),
85

86
   // V_DELAY_CONTROL
87
   (I_VALUE),
88

89
   // V_BINARY
90
   (I_LEFT | I_RIGHT | I_SUBKIND),
91

92
   // V_BASSIGN
93
   (I_TARGET | I_VALUE | I_SUBKIND),
94
};
95

96
static const char *kind_text_map[V_LAST_NODE_KIND] = {
97
   "V_MODULE",    "V_PORT_DECL",   "V_REF",      "V_ALWAYS",
98
   "V_TIMING",    "V_NBASSIGN",    "V_EVENT",    "V_INITIAL",
99
   "V_SEQ_BLOCK", "V_SYSTASK",     "V_STRING",   "V_NUMBER",
100
   "V_NET_DECL",  "V_ASSIGN",      "V_ROOT",     "V_DIMENSION",
101
   "V_IF",        "V_COND",        "V_VAR_DECL", "V_DELAY_CONTROL",
102
   "V_BINARY",    "V_BASSIGN",
103
};
104

105
static const change_allowed_t change_allowed[] = {
106
   { -1, -1 }
107
};
108

109
object_class_t vlog_object = {
110
   .name           = "vlog",
111
   .change_allowed = change_allowed,
112
   .has_map        = has_map,
113
   .kind_text_map  = kind_text_map,
114
   .tag            = OBJECT_TAG_VLOG,
115
   .last_kind      = V_LAST_NODE_KIND,
116
   .has_loc        = true,
117
   .gc_roots       = { V_MODULE },
118
   .gc_num_roots   = 1
119
};
120

121
struct _vlog_node {
122
   object_t object;
123
};
124

125
static inline vlog_node_t vlog_array_nth(item_t *item, unsigned n)
126
{
127
   object_t *o = obj_array_nth(item->obj_array, n);
128
   return container_of(o, struct _vlog_node, object);
129
}
130

131
static inline void vlog_array_add(item_t *item, vlog_node_t v)
461✔
132
{
133
   obj_array_add(&(item->obj_array), &(v->object));
461✔
134
}
461✔
135

136
vlog_node_t vlog_new(vlog_kind_t kind)
626✔
137
{
138
   object_t *o = object_new(NULL, &vlog_object, kind);
626✔
139
   return container_of(o, struct _vlog_node, object);
626✔
140
}
141

142
vlog_kind_t vlog_kind(vlog_node_t v)
1,631✔
143
{
144
   return v->object.kind;
1,631✔
145
}
146

147
const char *vlog_kind_str(vlog_kind_t kind)
×
148
{
149
   return kind_text_map[kind];
×
150
}
151

152
ident_t vlog_ident(vlog_node_t v)
420✔
153
{
154
   item_t *item = lookup_item(&vlog_object, v, I_IDENT);
420✔
155
   assert(item->ident != NULL);
420✔
156
   return item->ident;
420✔
157
}
158

159
void vlog_set_ident(vlog_node_t v, ident_t i)
349✔
160
{
161
   lookup_item(&vlog_object, v, I_IDENT)->ident = i;
349✔
162
}
349✔
163

164
ident_t vlog_ident2(vlog_node_t v)
53✔
165
{
166
   item_t *item = lookup_item(&vlog_object, v, I_IDENT2);
53✔
167
   assert(item->ident != NULL);
53✔
168
   return item->ident;
53✔
169
}
170

171
void vlog_set_ident2(vlog_node_t v, ident_t i)
67✔
172
{
173
   lookup_item(&vlog_object, v, I_IDENT2)->ident = i;
67✔
174
}
67✔
175

176
const loc_t *vlog_loc(vlog_node_t v)
230✔
177
{
178
   assert(v != NULL);
230✔
179
   return &(v->object.loc);
230✔
180
}
181

182
void vlog_set_loc(vlog_node_t v, const loc_t *loc)
626✔
183
{
184
   assert(v != NULL);
626✔
185
   assert(loc != NULL);
626✔
186
   v->object.loc = *loc;
626✔
187
}
626✔
188

189
vlog_node_t vlog_ref(vlog_node_t v)
133✔
190
{
191
   item_t *item = lookup_item(&vlog_object, v, I_REF);
133✔
192
   assert(item->object != NULL);
133✔
193
   return container_of(item->object, struct _vlog_node, object);
133✔
194
}
195

196
bool vlog_has_ref(vlog_node_t v)
29✔
197
{
198
   return lookup_item(&vlog_object, v, I_REF)->object != NULL;
29✔
199
}
200

201
void vlog_set_ref(vlog_node_t v, vlog_node_t d)
150✔
202
{
203
   lookup_item(&vlog_object, v, I_REF)->object = &(d->object);
150✔
204
   object_write_barrier(&(v->object), &(d->object));
150✔
205
}
150✔
206

207
unsigned vlog_stmts(vlog_node_t v)
209✔
208
{
209
   item_t *item = lookup_item(&vlog_object, v, I_STMTS);
209✔
210
   return obj_array_count(item->obj_array);
209✔
211
}
212

213
vlog_node_t vlog_stmt(vlog_node_t v, unsigned n)
341✔
214
{
215
   item_t *item = lookup_item(&vlog_object, v, I_STMTS);
341✔
216
   return vlog_array_nth(item, n);
341✔
217
}
218

219
void vlog_add_stmt(vlog_node_t v, vlog_node_t s)
193✔
220
{
221
   assert(s != NULL);
193✔
222
   vlog_array_add(lookup_item(&vlog_object, v, I_STMTS), s);
193✔
223
   object_write_barrier(&(v->object), &(s->object));
193✔
224
}
193✔
225

226
unsigned vlog_ports(vlog_node_t v)
26✔
227
{
228
   item_t *item = lookup_item(&vlog_object, v, I_PORTS);
26✔
229
   return obj_array_count(item->obj_array);
26✔
230
}
231

232
vlog_node_t vlog_port(vlog_node_t v, unsigned n)
41✔
233
{
234
   item_t *item = lookup_item(&vlog_object, v, I_PORTS);
41✔
235
   return vlog_array_nth(item, n);
41✔
236
}
237

238
void vlog_add_port(vlog_node_t v, vlog_node_t p)
42✔
239
{
240
   assert(p != NULL);
42✔
241
   assert(p->object.kind == V_REF);
42✔
242
   vlog_array_add(lookup_item(&vlog_object, v, I_PORTS), p);
42✔
243
   object_write_barrier(&(v->object), &(p->object));
42✔
244
}
42✔
245

246
unsigned vlog_params(vlog_node_t v)
105✔
247
{
248
   item_t *item = lookup_item(&vlog_object, v, I_PARAMS);
105✔
249
   return obj_array_count(item->obj_array);
105✔
250
}
251

252
vlog_node_t vlog_param(vlog_node_t v, unsigned n)
200✔
253
{
254
   item_t *item = lookup_item(&vlog_object, v, I_PARAMS);
200✔
255
   return vlog_array_nth(item, n);
200✔
256
}
257

258
void vlog_add_param(vlog_node_t v, vlog_node_t p)
103✔
259
{
260
   assert(p != NULL);
103✔
261
   vlog_array_add(lookup_item(&vlog_object, v, I_PARAMS), p);
103✔
262
   object_write_barrier(&(v->object), &(p->object));
103✔
263
}
103✔
264

265
unsigned vlog_ranges(vlog_node_t v)
39✔
266
{
267
   item_t *item = lookup_item(&vlog_object, v, I_RANGES);
39✔
268
   return obj_array_count(item->obj_array);
39✔
269
}
270

271
vlog_node_t vlog_range(vlog_node_t v, unsigned n)
5✔
272
{
273
   item_t *item = lookup_item(&vlog_object, v, I_RANGES);
5✔
274
   return vlog_array_nth(item, n);
5✔
275
}
276

277
void vlog_add_range(vlog_node_t v, vlog_node_t r)
8✔
278
{
279
   assert(r != NULL);
8✔
280
   assert(r->object.kind == V_DIMENSION);
8✔
281
   vlog_array_add(lookup_item(&vlog_object, v, I_RANGES), r);
8✔
282
   object_write_barrier(&(v->object), &(r->object));
8✔
283
}
8✔
284

285
unsigned vlog_decls(vlog_node_t v)
71✔
286
{
287
   item_t *item = lookup_item(&vlog_object, v, I_DECLS);
71✔
288
   return obj_array_count(item->obj_array);
71✔
289
}
290

291
vlog_node_t vlog_decl(vlog_node_t v, unsigned n)
172✔
292
{
293
   item_t *item = lookup_item(&vlog_object, v, I_DECLS);
172✔
294
   return vlog_array_nth(item, n);
172✔
295
}
296

297
void vlog_add_decl(vlog_node_t v, vlog_node_t d)
96✔
298
{
299
   assert(d != NULL);
96✔
300
   vlog_array_add(lookup_item(&vlog_object, v, I_DECLS), d);
96✔
301
   object_write_barrier(&(v->object), &(d->object));
96✔
302
}
96✔
303

304
unsigned vlog_conds(vlog_node_t v)
16✔
305
{
306
   item_t *item = lookup_item(&vlog_object, v, I_CONDS);
16✔
307
   return obj_array_count(item->obj_array);
16✔
308
}
309

310
vlog_node_t vlog_cond(vlog_node_t v, unsigned n)
25✔
311
{
312
   item_t *item = lookup_item(&vlog_object, v, I_CONDS);
25✔
313
   return vlog_array_nth(item, n);
25✔
314
}
315

316
void vlog_add_cond(vlog_node_t v, vlog_node_t c)
19✔
317
{
318
   assert(c != NULL && c->object.kind == V_COND);
19✔
319
   vlog_array_add(lookup_item(&vlog_object, v, I_CONDS), c);
19✔
320
   object_write_barrier(&(v->object), &(c->object));
19✔
321
}
19✔
322

323
unsigned vlog_subkind(vlog_node_t v)
116✔
324
{
325
   return lookup_item(&vlog_object, v, I_SUBKIND)->ival;
116✔
326
}
327

328
void vlog_set_subkind(vlog_node_t v, unsigned sub)
128✔
329
{
330
   lookup_item(&vlog_object, v, I_SUBKIND)->ival = sub;
128✔
331
}
128✔
332

333
vlog_node_t vlog_value(vlog_node_t v)
180✔
334
{
335
   item_t *item = lookup_item(&vlog_object, v, I_VALUE);
180✔
336
   assert(item->object != NULL);
180✔
337
   return container_of(item->object, struct _vlog_node, object);
180✔
338
}
339

340
bool vlog_has_value(vlog_node_t v)
19✔
341
{
342
   return lookup_item(&vlog_object, v, I_VALUE)->object != NULL;
19✔
343
}
344

345
void vlog_set_value(vlog_node_t v, vlog_node_t e)
101✔
346
{
347
   lookup_item(&vlog_object, v, I_VALUE)->object = &(e->object);
101✔
348
   object_write_barrier(&(v->object), &(e->object));
101✔
349
}
101✔
350

351
vlog_node_t vlog_target(vlog_node_t v)
82✔
352
{
353
   item_t *item = lookup_item(&vlog_object, v, I_TARGET);
82✔
354
   assert(item->object != NULL);
82✔
355
   return container_of(item->object, struct _vlog_node, object);
82✔
356
}
357

358
void vlog_set_target(vlog_node_t v, vlog_node_t e)
38✔
359
{
360
   lookup_item(&vlog_object, v, I_TARGET)->object = &(e->object);
38✔
361
   object_write_barrier(&(v->object), &(e->object));
38✔
362
}
38✔
363

364
const char *vlog_text(vlog_node_t v)
56✔
365
{
366
   item_t *item = lookup_item(&vlog_object, v, I_TEXT);
56✔
367
   assert(item->text != NULL);
56✔
368
   return item->text;
56✔
369
}
370

371
void vlog_set_text(vlog_node_t v, const char *text)
58✔
372
{
373
   lookup_item(&vlog_object, v, I_TEXT)->text = xstrdup(text);
58✔
374
}
58✔
375

376
number_t vlog_number(vlog_node_t v)
68✔
377
{
378
   return lookup_item(&vlog_object, v, I_NUMBER)->number;
68✔
379
}
380

381
void vlog_set_number(vlog_node_t v, number_t n)
76✔
382
{
383
   lookup_item(&vlog_object, v, I_NUMBER)->number = n;
76✔
384
}
76✔
385

386
data_type_t vlog_datatype(vlog_node_t v)
×
387
{
388
   return lookup_item(&vlog_object, v, I_DATATYPE)->ival;
×
389
}
390

391
void vlog_set_datatype(vlog_node_t v, data_type_t dt)
5✔
392
{
393
   lookup_item(&vlog_object, v, I_DATATYPE)->ival = dt;
5✔
394
}
5✔
395

396
vlog_node_t vlog_left(vlog_node_t v)
29✔
397
{
398
   item_t *item = lookup_item(&vlog_object, v, I_LEFT);
29✔
399
   assert(item->object != NULL);
29✔
400
   return container_of(item->object, struct _vlog_node, object);
29✔
401
}
402

403
void vlog_set_left(vlog_node_t v, vlog_node_t e)
20✔
404
{
405
   lookup_item(&vlog_object, v, I_LEFT)->object = &(e->object);
20✔
406
   object_write_barrier(&(v->object), &(e->object));
20✔
407
}
20✔
408

409
vlog_node_t vlog_right(vlog_node_t v)
29✔
410
{
411
   item_t *item = lookup_item(&vlog_object, v, I_RIGHT);
29✔
412
   assert(item->object != NULL);
29✔
413
   return container_of(item->object, struct _vlog_node, object);
29✔
414
}
415

416
void vlog_set_right(vlog_node_t v, vlog_node_t e)
20✔
417
{
418
   lookup_item(&vlog_object, v, I_RIGHT)->object = &(e->object);
20✔
419
   object_write_barrier(&(v->object), &(e->object));
20✔
420
}
20✔
421

422
void vlog_visit(vlog_node_t v, vlog_visit_fn_t fn, void *context)
21✔
423
{
424
   vlog_visit_only(v, fn, context, V_LAST_NODE_KIND);
21✔
425
}
21✔
426

427
void vlog_visit_only(vlog_node_t v, vlog_visit_fn_t fn, void *context,
21✔
428
                     vlog_kind_t kind)
429
{
430
   assert(v != NULL);
21✔
431

432
   object_visit_ctx_t ctx = {
21✔
433
      .count      = 0,
434
      .postorder  = (object_visit_fn_t)fn,
435
      .preorder   = NULL,
436
      .context    = context,
437
      .kind       = kind,
438
      .tag        = OBJECT_TAG_VLOG,
439
      .generation = object_next_generation(),
21✔
440
      .deep       = false
441
   };
442

443
   object_visit(&(v->object), &ctx);
21✔
444
}
21✔
445

446
object_t *vlog_to_object(vlog_node_t v)
37✔
447
{
448
   return &(v->object);
37✔
449
}
450

451
vlog_node_t vlog_from_object(object_t *obj)
619✔
452
{
453
   if (obj != NULL && obj->tag == OBJECT_TAG_VLOG)
619✔
454
      return container_of(obj, struct _vlog_node, object);
619✔
455
   else
456
      return NULL;
584✔
457
}
458

459
void vlog_locus(vlog_node_t v, ident_t *unit, ptrdiff_t *offset)
36✔
460
{
461
   assert(v != NULL);
36✔
462
   object_locus(&(v->object), unit, offset);
36✔
463
}
36✔
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