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

nickg / nvc / 18428170938

11 Oct 2025 09:39AM UTC coverage: 92.549% (-0.002%) from 92.551%
18428170938

push

github

nickg
Better handling of System Verilog nulls

40 of 44 new or added lines in 4 files covered. (90.91%)

2 existing lines in 2 files now uncovered.

74468 of 80463 relevant lines covered (92.55%)

446696.77 hits per line

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

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

24
#include <assert.h>
25

26
bool vlog_is_net(vlog_node_t v)
920✔
27
{
28
   switch (vlog_kind(v)) {
965✔
29
   case V_REF:
277✔
30
   case V_HIER_REF:
31
      return vlog_has_ref(v) ? vlog_is_net(vlog_ref(v)) : false;
277✔
32
   case V_PORT_DECL:
98✔
33
      return vlog_has_ref(v) ? vlog_is_net(vlog_ref(v)) : true;
98✔
34
   case V_NET_DECL:
35
      return true;
36
   case V_BIT_SELECT:
45✔
37
   case V_PART_SELECT:
38
      return vlog_is_net(vlog_value(v));
45✔
39
   case V_CONCAT:
3✔
40
      {
41
         const int nparams = vlog_params(v);
3✔
42
         for (int i = 0; i < nparams; i++) {
12✔
43
            if (!vlog_is_net(vlog_param(v, i)))
9✔
44
               return false;
45
         }
46
         return true;
47
      }
48
   default:
132✔
49
      return false;
132✔
50
   }
51
}
52

53
unsigned vlog_dimensions(vlog_node_t v)
×
54
{
55
   return vlog_ranges(vlog_type(v)) + vlog_ranges(v);
×
56
}
57

58
bool vlog_get_const(vlog_node_t v, int64_t *value)
5,358✔
59
{
60
   switch (vlog_kind(v)) {
5,358✔
61
   case V_NUMBER:
5,358✔
62
      {
63
         number_t n = vlog_number(v);
5,358✔
64
         if (number_is_defined(n)) {
5,358✔
65
            *value = number_integer(n);
5,334✔
66
            return true;
5,334✔
67
         }
68
         else
69
            return false;
70
      }
71
   case V_REF:
×
72
      return vlog_get_const(vlog_ref(v), value);
×
73
   case V_LOCALPARAM:
×
74
      return vlog_get_const(vlog_value(v), value);
×
75
   default:
×
76
      fatal_at(vlog_loc(v), "expression is not constant");
×
77
   }
78
}
79

80
bool vlog_is_const(vlog_node_t v)
141✔
81
{
82
   switch (vlog_kind(v)) {
144✔
83
   case V_NUMBER:
84
      return true;
85
   case V_REF:
3✔
86
      return vlog_is_const(vlog_ref(v));
3✔
87
   case V_LOCALPARAM:
×
88
      return vlog_is_const(vlog_value(v));
×
89
   default:
3✔
90
      return false;
3✔
91
   }
92
}
93

94
bool vlog_is_up(vlog_node_t v)
24✔
95
{
96
   assert(vlog_kind(v) == V_DIMENSION);
24✔
97

98
   int64_t left, right;
24✔
99
   vlog_bounds(v, &left, &right);
24✔
100

101
   return left <= right;
24✔
102
}
103

104
bool vlog_bounds(vlog_node_t v, int64_t *left, int64_t *right)
2,649✔
105
{
106
   bool is_defined = true;
2,649✔
107
   is_defined &= vlog_get_const(vlog_left(v), left);
2,649✔
108
   is_defined &= vlog_get_const(vlog_right(v), right);
2,649✔
109
   return is_defined;
2,649✔
110
}
111

112
unsigned vlog_size(vlog_node_t v)
5,295✔
113
{
114
   switch (vlog_kind(v)) {
5,295✔
115
   case V_DATA_TYPE:
4,794✔
116
   case V_VAR_DECL:
117
   case V_NET_DECL:
118
   case V_PORT_DECL:
119
   case V_TF_PORT_DECL:
120
      {
121
         unsigned size = 1;
4,794✔
122

123
         const int nranges = vlog_ranges(v);
4,794✔
124
         for (int i = 0; i < nranges; i++) {
6,471✔
125
            vlog_node_t r = vlog_range(v, i);
1,677✔
126

127
            int64_t left, right;
1,677✔
128
            vlog_bounds(r, &left, &right);
1,677✔
129

130
            if (left < right)
1,677✔
131
               size *= right - left + 1;
153✔
132
            else
133
               size *= left - right + 1;
1,524✔
134
         }
135

136
         return size;
137
      }
138
   case V_PART_SELECT:
135✔
139
      if (vlog_subkind(v) != V_RANGE_CONST) {
135✔
140
         int64_t width;
39✔
141
         if (vlog_get_const(vlog_right(v), &width))
39✔
142
            return width;
39✔
143
         else
144
            return 0;  // Undefined
145
      }
146
      // Fall-through
147
   case V_DIMENSION:
148
      {
149
         int64_t left, right;
462✔
150
         if (!vlog_bounds(v, &left, &right))
462✔
151
            return 0;  // Undefined
152

153
         if (left < right)
444✔
154
            return right - left + 1;
135✔
155
         else
156
            return left - right + 1;
309✔
157
      }
158
   default:
×
159
      CANNOT_HANDLE(v);
×
160
   }
161
}
162

163
bool is_top_level(vlog_node_t v)
1,397✔
164
{
165
   switch (vlog_kind(v)) {
1,397✔
166
   case V_MODULE:
167
   case V_PRIMITIVE:
168
   case V_INST_BODY:
169
   case V_PACKAGE:
170
   case V_PROGRAM:
171
      return true;
172
   default:
6✔
173
      return false;
6✔
174
   }
175
}
176

177
bool is_data_type(vlog_node_t v)
17✔
178
{
179
   switch (vlog_kind(v)) {
17✔
180
   case V_DATA_TYPE:
181
   case V_ENUM_DECL:
182
   case V_STRUCT_DECL:
183
   case V_UNION_DECL:
184
   case V_TYPE_DECL:
185
   case V_CLASS_DECL:
186
      return true;
187
   default:
1✔
188
      return false;
1✔
189
   }
190
}
191

192
bool is_implicit_data_type(vlog_node_t v)
112✔
193
{
194
   return vlog_kind(v) == V_DATA_TYPE && vlog_subkind(v) == DT_IMPLICIT;
112✔
195
}
196

197
vlog_node_t vlog_longest_static_prefix(vlog_node_t v)
660✔
198
{
199
   switch (vlog_kind(v)) {
660✔
200
   case V_REF:
201
   case V_HIER_REF:
202
      return v;
203
   case V_BIT_SELECT:
99✔
204
      {
205
         vlog_node_t value = vlog_value(v);
99✔
206
         vlog_node_t prefix = vlog_longest_static_prefix(value);
99✔
207

208
         if (prefix != value)
99✔
209
            return prefix;
210

211
         const int nparams = vlog_params(v);
99✔
212
         for (int i = 0; i < nparams; i++) {
201✔
213
            if (!vlog_is_const(vlog_param(v, i)))
105✔
214
               return prefix;
215
         }
216

217
         return v;
218
      }
219
   case V_PART_SELECT:
36✔
220
      {
221
         vlog_node_t value = vlog_value(v);
36✔
222
         vlog_node_t prefix = vlog_longest_static_prefix(value);
36✔
223

224
         if (prefix != value)
36✔
225
            return prefix;
226

227
         if (!vlog_is_const(vlog_left(v)))
36✔
228
            return prefix;
×
229

230
         return v;
231
      }
232
   default:
×
233
      fatal_at(vlog_loc(v), "cannot calculate longest static prefix");
×
234
   }
235
}
236

237
bool vlog_equal_node(vlog_node_t a, vlog_node_t b)
53✔
238
{
239
   if (a == b)
53✔
240
      return true;
241

242
   const vlog_kind_t kind = vlog_kind(a);
53✔
243
   if (kind != vlog_kind(b))
53✔
244
      return false;
245

246
   switch (kind) {
53✔
247
   case V_NUMBER:
31✔
248
      {
249
         number_t an = vlog_number(a);
31✔
250
         number_t bn = vlog_number(b);
31✔
251

252
         return number_equal(an, bn);
31✔
253
      }
254
   case V_BINARY:
3✔
255
      return vlog_subkind(a) == vlog_subkind(b)
3✔
256
         && vlog_equal_node(vlog_left(a), vlog_left(b))
3✔
257
         && vlog_equal_node(vlog_right(a), vlog_right(b));
6✔
258
   case V_REF:
3✔
259
      if (!vlog_has_ref(a) || !vlog_has_ref(b))
3✔
260
         return true;   // Suppress cascading errors
×
261
      else
262
         return vlog_ref(a) == vlog_ref(b);
3✔
263
   case V_PARAM_ASSIGN:
16✔
264
      {
265
         ident_t ia = vlog_has_ident(a) ? vlog_ident(a) : NULL;
16✔
266
         ident_t ib = vlog_has_ident(b) ? vlog_ident(b) : NULL;
16✔
267
         return ia == ib && vlog_equal_node(vlog_value(a), vlog_value(b));
16✔
268
      }
269
   default:
270
      return false;
271
   }
272
}
273

274
uint32_t vlog_hash_node(vlog_node_t v)
300✔
275
{
276
   switch (vlog_kind(v)) {
300✔
277
   case V_NUMBER:
150✔
278
      return number_hash(vlog_number(v));
150✔
279
   case V_REF:
×
280
      return vlog_hash_node(vlog_ref(v));
×
281
   case V_PARAM_ASSIGN:
150✔
282
      {
283
         uint32_t h = vlog_hash_node(vlog_value(v));
150✔
284
         if (vlog_has_ident(v))
150✔
285
            h ^= ident_hash(vlog_ident(v));
6✔
286
         return h;
287
      }
288
   default:
×
289
      return mix_bits_64((uintptr_t)v);
×
290
   }
291
}
292

293
vlog_node_t vlog_get_type(vlog_node_t v)
109✔
294
{
295
   switch (vlog_kind(v)) {
213✔
296
   case V_STRUCT_DECL:
297
   case V_ENUM_DECL:
298
   case V_DATA_TYPE:
299
      return v;
300
   case V_VAR_DECL:
109✔
301
   case V_NET_DECL:
302
   case V_TYPE_DECL:
303
   case V_CLASS_NEW:
304
      return vlog_type(v);
109✔
305
   case V_REF:
104✔
306
   case V_MEMBER_REF:
307
      if (vlog_has_ref(v))
104✔
308
         return vlog_get_type(vlog_ref(v));
104✔
309
      else
310
         return NULL;
311
   case V_HIER_REF:
×
312
   case V_MOD_INST:
313
      return NULL;
×
NEW
314
   case V_NULL:
×
NEW
315
      if (vlog_has_type(v))
×
NEW
316
         return vlog_type(v);
×
317
      else
318
         return NULL;
319
   default:
×
320
      CANNOT_HANDLE(v);
×
321
   }
322
}
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