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

nickg / nvc / 24634463149

19 Apr 2026 05:04PM UTC coverage: 92.356% (+0.04%) from 92.319%
24634463149

push

github

nickg
Store offset with aliased signal

Fixes #1505

29 of 29 new or added lines in 5 files covered. (100.0%)

233 existing lines in 4 files now uncovered.

76771 of 83125 relevant lines covered (92.36%)

610597.24 hits per line

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

88.36
/src/rt/printer.c
1
//
2
//  Copyright (C) 2023  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 "hash.h"
20
#include "rt/printer.h"
21
#include "rt/structs.h"
22
#include "type.h"
23

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

29
typedef void (*type_fn_t)(print_func_t *, const void *, size_t, print_flags_t);
30

31
typedef struct _print_func {
32
   printer_t    *printer;
33
   type_fn_t     typefn;
34
   char         *map;
35
   size_t        stride;
36
   print_func_t *elem;
37
} print_func_t;
38

39
typedef struct _printer {
40
   hash_t     *typemap;
41
   text_buf_t *buf;
42
} printer_t;
43

44
static const char std_logic_map[] = "UX01ZWLH-";
45

46
static void begin_quote(print_func_t *f, print_flags_t flags, char enc)
4✔
47
{
48
   if (flags & PRINT_F_ENCODE)
4✔
49
      tb_append(f->printer->buf, enc);
×
50
   else
51
      tb_append(f->printer->buf, '"');
4✔
52
}
4✔
53

54
static void end_quote(print_func_t *f, print_flags_t flags)
4✔
55
{
56
   if (!(flags & PRINT_F_ENCODE))
4✔
57
      tb_append(f->printer->buf, '"');
4✔
58
}
4✔
59

60
static void int_printer(print_func_t *f, const void *data, size_t size,
16✔
61
                        print_flags_t flags)
62
{
63
   assert(size <= 8);
16✔
64
   assert(is_power_of_2(size));
16✔
65

66
   if (flags & PRINT_F_ENCODE)
16✔
67
      tb_append(f->printer->buf, 'i');
×
68

69
   const int radix = flags & PRINT_F_RADIX;
16✔
70

71
   if (radix == PRINT_F_HEX || radix == PRINT_F_BIN) {
16✔
72
      uint64_t wide = 0;
3✔
73
      switch (size) {
3✔
74
      case 1: wide = *(uint8_t *)data; break;
×
75
      case 2: wide = *(uint16_t *)data; break;
×
76
      case 4: wide = *(uint32_t *)data; break;
3✔
77
      case 8: wide = *(uint64_t *)data; break;
×
78
      }
79

80
      if (radix == PRINT_F_BIN) {
3✔
81
         for (int i = (size * 8) - 1; i >= 0; i--)
33✔
82
            tb_append(f->printer->buf, (wide & (UINT64_C(1) << i)) ? '1' : '0');
62✔
83
      }
84
      else
85
         tb_printf(f->printer->buf, "0x%"PRIx64, wide);
2✔
86
   }
87
   else {
88
      int64_t wide = 0;
13✔
89
      switch (size) {
13✔
90
      case 1: wide = *(int8_t *)data; break;
×
91
      case 2: wide = *(int16_t *)data; break;
×
92
      case 4: wide = *(int32_t *)data; break;
12✔
93
      case 8: wide = *(int64_t *)data; break;
1✔
94
      }
95

96
      tb_printf(f->printer->buf, "%"PRIi64, wide);
13✔
97
   }
98
}
16✔
99

100
static void std_logic_printer(print_func_t *f, const void *data, size_t size,
1✔
101
                              print_flags_t flags)
102
{
103
   assert(size == 1);
1✔
104
   if (flags & PRINT_F_ENCODE) {
1✔
105
      tb_append(f->printer->buf, 'l');
×
106
      tb_append(f->printer->buf, std_logic_map[*(uint8_t *)data]);
×
107
   }
108
   else {
109
      const char str[] = { '\'', std_logic_map[*(uint8_t *)data], '\'' };
1✔
110
      tb_catn(f->printer->buf, str, ARRAY_LEN(str));
1✔
111
   }
112
}
1✔
113

114
static void std_logic_vector_printer(print_func_t *f, const void *data,
2✔
115
                                     size_t size, print_flags_t flags)
116
{
117
   begin_quote(f, flags, 'L');
2✔
118

119
   for (int i = 0; i < size; i++) {
10✔
120
      const uint8_t bit = *((uint8_t *)data + i);
8✔
121
      assert(bit < ARRAY_LEN(std_logic_map));
8✔
122
      tb_append(f->printer->buf, std_logic_map[bit]);
8✔
123
   }
124

125
   end_quote(f, flags);
2✔
126
}
2✔
127

128
static void bit_printer(print_func_t *f, const void *data, size_t size,
1✔
129
                        print_flags_t flags)
130
{
131
   assert(size == 1);
1✔
132
   if (flags & PRINT_F_ENCODE) {
1✔
UNCOV
133
      tb_append(f->printer->buf, 'b');
×
UNCOV
134
      tb_append(f->printer->buf, *(uint8_t *)data ? '1' : '0');
×
135
   }
136
   else
137
      tb_cat(f->printer->buf, *(uint8_t *)data ? "'1'" : "'0'");
1✔
138
}
1✔
139

140
static void bit_vector_printer(print_func_t *f, const void *data,
1✔
141
                               size_t size, print_flags_t flags)
142
{
143
   begin_quote(f, flags, 'B');
1✔
144

145
   for (int i = 0; i < size; i++)
4✔
146
      tb_append(f->printer->buf, *((uint8_t *)data + i) ? '1' : '0');
4✔
147

148
   end_quote(f, flags);
1✔
149
}
1✔
150

151
static void physical_printer(print_func_t *f, const void *data, size_t size,
1✔
152
                             print_flags_t flags)
153
{
154
   if (flags & PRINT_F_ENCODE)
1✔
155
      tb_append(f->printer->buf, 'p');
×
156

157
   int_printer(f, data, size, 0);
1✔
158

159
   tb_append(f->printer->buf, ' ');
1✔
160
   tb_cat(f->printer->buf, f->map);
1✔
161
}
1✔
162

163
static void enum_printer(print_func_t *f, const void *data, size_t size,
5✔
164
                         print_flags_t flags)
165
{
166
   if (flags & PRINT_F_ENCODE)
5✔
UNCOV
167
      tb_append(f->printer->buf, 'e');
×
168

169
   assert(size == 1);
5✔
170
   const int lit = *(uint8_t *)data;
5✔
171
   tb_cat(f->printer->buf, f->map + lit * f->stride);
5✔
172
}
5✔
173

174
static void make_enum_map(print_func_t *f, type_t type)
2✔
175
{
176
   int stride = 0;
2✔
177

178
   const unsigned nlits = type_enum_literals(type);
2✔
179
   for (int i = 0; i < nlits; i++)
261✔
180
      stride = MAX(stride, ident_len(tree_ident(type_enum_literal(type, i))));
259✔
181

182
   f->stride = stride + 1;
2✔
183
   f->map = xcalloc_array(nlits, f->stride);
2✔
184

185
   for (int i = 0; i < nlits; i++) {
261✔
186
      ident_t id = tree_ident(type_enum_literal(type, i));
259✔
187
      memcpy(f->map + i*f->stride, istr(id), ident_len(id));
259✔
188
   }
189
}
2✔
190

191
static void enum_vector_printer(print_func_t *f, const void *data,
2✔
192
                                size_t size, print_flags_t flags)
193
{
194
   if (flags & PRINT_F_ENCODE)
2✔
195
      tb_append(f->printer->buf, 'E');
×
196

197
   flags &= ~PRINT_F_ENCODE;
2✔
198

199
   tb_append(f->printer->buf, '(');
2✔
200

201
   for (int i = 0; i < size; i++) {
7✔
202
      if (i > 0) tb_cat(f->printer->buf, ", ");
5✔
203
      (*f->elem->typefn)(f->elem, data + i, 1, flags);
5✔
204
   }
205

206
   tb_append(f->printer->buf, ')');
2✔
207
}
2✔
208

209
static void string_printer(print_func_t *f, const void *data,
2✔
210
                           size_t size, print_flags_t flags)
211
{
212
   bool allprint = true;
2✔
213
   for (int i = 0; i < size; i++)
9✔
214
      allprint &= isprint_iso88591(*((uint8_t *)data + i));
7✔
215

216
   if (allprint) {
2✔
217
      begin_quote(f, flags, 'S');
1✔
218

219
      for (int i = 0; i < size; i++)
6✔
220
         tb_append(f->printer->buf, *((uint8_t *)data + i));
5✔
221

222
      end_quote(f, flags);
1✔
223
   }
224
   else
225
      enum_vector_printer(f, data, size, flags);
1✔
226
}
2✔
227

228
printer_t *printer_new(void)
27✔
229
{
230
   printer_t *p = xcalloc(sizeof(printer_t));
27✔
231
   p->typemap = hash_new(128);
27✔
232
   p->buf     = tb_new();
27✔
233

234
   return p;
27✔
235
}
236

237
void printer_free(printer_t *p)
26✔
238
{
239
   hash_iter_t it = HASH_BEGIN;
26✔
240
   const void *key;
26✔
241
   void *value;
26✔
242
   while (hash_iter(p->typemap, &it, &key, &value)) {
42✔
243
      print_func_t *f = value;
16✔
244
      free(f->map);
16✔
245
      free(f);
16✔
246
   }
247

248
   hash_free(p->typemap);
26✔
249
   tb_free(p->buf);
26✔
250
   free(p);
26✔
251
}
26✔
252

253
print_func_t *printer_for(printer_t *p, type_t type)
18✔
254
{
255
   print_func_t *f = hash_get(p->typemap, type);
18✔
256
   if (f != NULL)
18✔
257
      return f;
258

259
   type_t base = type_base_recur(type);
16✔
260
   if ((f = hash_get(p->typemap, base)) != NULL) {
16✔
261
      hash_put(p->typemap, type, f);
×
262
      return f;
×
263
   }
264

265
   f = xcalloc(sizeof(print_func_t));
16✔
266
   f->printer = p;
16✔
267

268
   switch (type_kind(base)) {
16✔
269
   case T_INTEGER:
6✔
270
      f->typefn = int_printer;
6✔
271
      break;
6✔
272
   case T_ENUM:
4✔
273
      switch (is_well_known(type_ident(base))) {
4✔
274
      case W_IEEE_LOGIC:
1✔
275
      case W_IEEE_ULOGIC:
276
         f->typefn = std_logic_printer;
1✔
277
         break;
1✔
278
      case W_STD_BIT:
1✔
279
         f->typefn = bit_printer;
1✔
280
         break;
1✔
281
      default:
2✔
282
         f->typefn = enum_printer;
2✔
283
         make_enum_map(f, type);
2✔
284
         break;
2✔
285
      }
286
      break;
287
   case T_PHYSICAL:
1✔
288
      f->typefn = physical_printer;
1✔
289
      f->map = xstrdup(istr(tree_ident(type_unit(base, 0))));
1✔
290
      break;
1✔
291
   case T_ARRAY:
5✔
292
      switch (is_well_known(type_ident(base))) {
5✔
293
      case W_IEEE_LOGIC_VECTOR:
1✔
294
      case W_IEEE_ULOGIC_VECTOR:
295
      case W_IEEE_UNSIGNED:
296
      case W_IEEE_SIGNED:
297
         f->typefn = std_logic_vector_printer;
1✔
298
         break;
1✔
299
      case W_STD_BIT_VECTOR:
1✔
300
         f->typefn = bit_vector_printer;
1✔
301
         break;
1✔
302
      case W_STD_STRING:
2✔
303
         f->typefn = string_printer;
2✔
304
         f->elem = printer_for(p, type_elem(base));
2✔
305
         break;
2✔
306
      default:
1✔
307
         {
308
            type_t elem = type_elem(type);
1✔
309
            if (type_is_enum(elem)) {
1✔
310
               f->typefn = enum_vector_printer;
1✔
311
               f->elem = printer_for(p, type_elem(base));
1✔
312
               break;
1✔
313
            }
314

315
            goto invalid;
×
316
         }
317
      }
318
      break;
319
   default:
×
320
      goto invalid;
×
321
   }
322

323
   hash_put(p->typemap, type, f);
16✔
324
   return f;
16✔
325

326
 invalid:
×
327
   free(f);
×
328
   return NULL;
×
329
}
330

331
const char *print_signal(print_func_t *fn, rt_signal_t *s, print_flags_t flags)
21✔
332
{
333
   tb_rewind(fn->printer->buf);
21✔
334
   (*fn->typefn)(fn, s->shared.data, s->shared.size, flags);
21✔
335
   return tb_get(fn->printer->buf);
21✔
336
}
337

338
const char *print_raw(print_func_t *fn, const void *data, size_t size,
3✔
339
                      print_flags_t flags)
340
{
341
   tb_rewind(fn->printer->buf);
3✔
342
   (*fn->typefn)(fn, data, size, flags);
3✔
343
   return tb_get(fn->printer->buf);
3✔
344
}
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