]> sigrok.org Git - libsigrok.git/blame - src/input/vcd.c
output/csv: use intermediate time_t var, silence compiler warning
[libsigrok.git] / src / input / vcd.c
CommitLineData
99eaa206 1/*
50985c20 2 * This file is part of the libsigrok project.
99eaa206 3 *
0157808d 4 * Copyright (C) 2012 Petteri Aimonen <jpa@sr.mail.kapsi.fi>
7db06394 5 * Copyright (C) 2014 Bert Vermeulen <bert@biot.com>
0ab36d2f 6 * Copyright (C) 2017-2020 Gerhard Sittig <gerhard.sittig@gmx.net>
99eaa206
PA
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
0ab36d2f
GS
22/*
23 * The VCD input module has the following options. See the options[]
24 * declaration near the bottom of the input module's source file.
0157808d 25 *
0ab36d2f
GS
26 * numchannels: Maximum number of sigrok channels to create. VCD signals
27 * are detected in their order of declaration in the VCD file header,
28 * and mapped to sigrok channels.
0157808d 29 *
0ab36d2f
GS
30 * skip: Allows to skip data at the start of the input file. This can
31 * speed up operation on long captures.
32 * Value < 0: Skip until first timestamp that is listed in the file.
33 * (This is the default behaviour.)
34 * Value = 0: Do not skip, instead generate samples beginning from
35 * timestamp 0.
36 * Value > 0: Start at the given timestamp.
0157808d 37 *
0ab36d2f
GS
38 * downsample: Divide the samplerate by the given factor. This can
39 * speed up operation on long captures.
0157808d 40 *
0ab36d2f
GS
41 * compress: Trim idle periods which are longer than this value to span
42 * only this many timescale ticks. This can speed up operation on long
43 * captures (default 0, don't compress).
6b7ace48 44 *
0157808d
PA
45 * Based on Verilog standard IEEE Std 1364-2001 Version C
46 *
47 * Supported features:
48 * - $var with 'wire' and 'reg' types of scalar variables
49 * - $timescale definition for samplerate
50 * - multiple character variable identifiers
0ab36d2f
GS
51 * - same identifer used for multiple signals (identical values)
52 * - vector variables (bit vectors)
53 * - integer variables (analog signals with 0 digits, passed as single
54 * precision float number)
55 * - real variables (analog signals, passed on with single precision,
56 * arbitrary digits value, not user adjustable)
57 * - nested $scope, results in prefixed sigrok channel names
0157808d
PA
58 *
59 * Most important unsupported features:
0ab36d2f
GS
60 * - $dumpvars initial value declaration (is not an issue if generators
61 * provide sample data for the #0 timestamp, otherwise session data
62 * starts from zero values, and catches up when the signal changes its
63 * state to a supported value)
64 *
65 * Implementor's note: This input module specifically does _not_ use
66 * glib routines where they would hurt performance. Lots of memory
67 * allocations increase execution time not by percents but by huge
68 * factors. This motivated this module's custom code for splitting
69 * words on text lines, and pooling previously allocated buffers.
70 *
71 * TODO (in arbitrary order)
72 * - Map VCD scopes to sigrok channel groups?
73 * - Does libsigrok support nested channel groups? Or is this feature
74 * exclusive to Pulseview?
75 * - Check VCD input to VCD output behaviour. Verify that export and
76 * re-import results in identical data (well, VCD's constraints on
77 * timescale values is known to result in differences).
ec302917
GS
78 * - Check the minimum timestamp delta in the input data set, suggest
79 * the downsample=N option to users for reduced resource consumption.
80 * Popular VCD file creation utilities love to specify insanely tiny
81 * timescale values in the pico or even femto seconds range. Which
82 * results in huge sample counts after import, and potentially even
83 * terminates the application due to resource exhaustion. This issue
84 * only will vanish when common libsigrok infrastructure no longer
85 * depends on constant rate streams of samples at discrete points
86 * in time. The current input module implementation has code in place
87 * to gather timestamp statistics, but the most appropriate condition
88 * when to notify users is yet to be found.
0ab36d2f
GS
89 * - Cleanup the implementation.
90 * - Consistent use of the glib API (where appropriate).
91 * - More appropriate variable/function identifiers.
92 * - More robust handling of multi-word input phrases and chunked
93 * input buffers? This implementation assumes that e.g. b[01]+
94 * patterns are complete when they start, and the signal identifier
95 * is available as well. Which may be true assuming that input data
96 * comes in complete text lines.
97 * - See if other input modules have learned lessons that we could
98 * benefit from here as well? Pointless BOM (done), line oriented
99 * processing with EOL variants and with optional last EOL, module
100 * state reset and file re-read (stable channels list), buffered
101 * session feed, synchronized feed for mixed signal sources, digits
102 * or formats support for analog input, single vs double precision,
103 * etc.
104 * - Re-consider logging. Verbosity levels should be acceptable,
105 * but volume is an issue. Drop duplicates, and drop messages from
106 * known good code paths.
0157808d
PA
107 */
108
6ec6c43b 109#include <config.h>
0ab36d2f 110
99eaa206 111#include <glib.h>
c1aae900 112#include <libsigrok/libsigrok.h>
99eaa206 113#include "libsigrok-internal.h"
0ab36d2f
GS
114#include <stdio.h>
115#include <stdlib.h>
116#include <string.h>
99eaa206 117
3544f848 118#define LOG_PREFIX "input/vcd"
99eaa206 119
9a4fd01a 120#define CHUNK_SIZE (4 * 1024 * 1024)
0ab36d2f 121#define SCOPE_SEP '.'
e4c8a4d7
BV
122
123struct context {
0ab36d2f
GS
124 struct vcd_user_opt {
125 size_t maxchannels; /* sigrok channels (output) */
126 uint64_t downsample;
127 uint64_t compress;
128 uint64_t skip_starttime;
129 gboolean skip_specified;
130 } options;
131 gboolean use_skip;
c10ef17c 132 gboolean started;
7db06394 133 gboolean got_header;
f9bc17d4 134 uint64_t prev_timestamp;
e4c8a4d7 135 uint64_t samplerate;
0ab36d2f
GS
136 size_t vcdsignals; /* VCD signals (input) */
137 GSList *ignored_signals;
138 gboolean data_after_timestamp;
139 gboolean ignore_end_keyword;
7db06394 140 gboolean skip_until_end;
ba7dd8bb 141 GSList *channels;
0ab36d2f
GS
142 size_t unit_size;
143 size_t logic_count;
144 size_t analog_count;
145 uint8_t *current_logic;
146 float *current_floats;
147 struct {
148 size_t max_bits;
149 size_t unit_size;
150 uint8_t *value;
151 size_t sig_count;
152 } conv_bits;
153 GString *scope_prefix;
154 struct feed_queue_logic *feed_logic;
ec302917
GS
155 struct ts_stats {
156 size_t total_ts_seen;
157 uint64_t last_ts_value;
158 uint64_t last_ts_delta;
159 size_t min_count;
160 struct {
161 uint64_t delta;
162 size_t count;
163 } min_items[2];
164 uint32_t early_check_shift;
165 size_t early_last_emitted;
166 } ts_stats;
0ab36d2f
GS
167 struct vcd_prev {
168 GSList *sr_channels;
169 GSList *sr_groups;
170 } prev;
e4c8a4d7
BV
171};
172
ba7dd8bb 173struct vcd_channel {
0ab36d2f
GS
174 char *name;
175 char *identifier;
176 size_t size;
177 enum sr_channeltype type;
178 size_t array_index;
179 size_t byte_idx;
180 uint8_t bit_mask;
181 char *base_name;
182 size_t range_lower, range_upper;
183 int submit_digits;
184 struct feed_queue_analog *feed_analog;
e4c8a4d7
BV
185};
186
0ab36d2f
GS
187static void free_channel(void *data)
188{
189 struct vcd_channel *vcd_ch;
190
191 vcd_ch = data;
192 if (!vcd_ch)
193 return;
194
195 g_free(vcd_ch->name);
196 g_free(vcd_ch->identifier);
197 g_free(vcd_ch->base_name);
198 feed_queue_analog_free(vcd_ch->feed_analog);
199
200 g_free(vcd_ch);
201}
202
ec302917
GS
203/*
204 * Another timestamp delta was observed, update statistics: Update the
205 * sorted list of minimum values, and increment the occurance counter.
206 * Returns the position of the item's statistics slot, or returns a huge
207 * invalid index when the current delta is larger than previously found
208 * values.
209 */
210static size_t ts_stats_update_min(struct ts_stats *stats, uint64_t delta)
211{
212 size_t idx, copy_idx;
213
214 /* Advance over previously recorded values which are smaller. */
215 idx = 0;
216 while (idx < stats->min_count && stats->min_items[idx].delta < delta)
217 idx++;
218 if (idx == ARRAY_SIZE(stats->min_items))
219 return idx;
220
221 /* Found the exact value that previously was registered? */
222 if (stats->min_items[idx].delta == delta) {
223 stats->min_items[idx].count++;
224 return idx;
225 }
226
227 /* Allocate another slot, bubble up larger values as needed. */
228 if (stats->min_count < ARRAY_SIZE(stats->min_items))
229 stats->min_count++;
230 for (copy_idx = stats->min_count - 1; copy_idx > idx; copy_idx--)
231 stats->min_items[copy_idx] = stats->min_items[copy_idx - 1];
232
233 /* Start tracking this value in the found or freed slot. */
234 memset(&stats->min_items[idx], 0, sizeof(stats->min_items[idx]));
235 stats->min_items[idx].delta = delta;
236 stats->min_items[idx].count++;
237
238 return idx;
239}
240
241/*
242 * Intermediate check for extreme oversampling in the input data. Rate
243 * limited emission of warnings to avoid noise, "late" emission of the
244 * first potential message to avoid false positives, yet need to emit
245 * the messages early (*way* before EOF) to raise awareness.
246 *
247 * TODO
248 * Tune the limits, improve perception and usefulness of these checks.
249 * Need to start emitting messages soon enough to be seen by users. Yet
250 * avoid unnecessary messages for valid input's idle/quiet phases. Slow
251 * input transitions are perfectly legal before bursty phases are seen
252 * in the input data. Needs the check become an option, on by default,
253 * but suppressable by users?
254 */
255static void ts_stats_check_early(struct ts_stats *stats)
256{
257 static const struct {
258 uint64_t delta;
259 size_t count;
260 } *cp, check_points[] = {
261 { 100, 1000000, }, /* Still x100 after 1mio transitions. */
262 { 1000, 100000, }, /* Still x1k after 100k transitions. */
263 { 10000, 10000, }, /* Still x10k after 10k transitions. */
264 { 1000000, 2500, }, /* Still x1m after 2.5k transitions. */
265 };
266
267 size_t cp_idx;
268 uint64_t seen_delta, check_delta;
269 size_t seen_count;
270
271 /* Get the current minimum's value and count. */
272 if (!stats->min_count)
273 return;
274 seen_delta = stats->min_items[0].delta;
275 seen_count = stats->min_items[0].count;
276
277 /* Emit at most one weak message per import. */
278 if (stats->early_last_emitted)
279 return;
280
281 /* Check arbitrary marks, emit rate limited warnings. */
282 (void)seen_count;
283 check_delta = seen_delta >> stats->early_check_shift;
284 for (cp_idx = 0; cp_idx < ARRAY_SIZE(check_points); cp_idx++) {
285 cp = &check_points[cp_idx];
286 /* No other match can happen below. Done iterating. */
287 if (stats->total_ts_seen > cp->count)
288 return;
289 /* Advance to the next checkpoint description. */
290 if (stats->total_ts_seen != cp->count)
291 continue;
292 /* First occurance of that timestamp count. Check the value. */
968b1a23 293 sr_dbg("TS early chk: total %zu, min delta %" PRIu64 " / %" PRIu64 ".",
ec302917
GS
294 cp->count, seen_delta, check_delta);
295 if (check_delta < cp->delta)
296 return;
297 sr_warn("Low change rate? (weak estimate, min TS delta %" PRIu64 " after %zu timestamps)",
298 seen_delta, stats->total_ts_seen);
299 sr_warn("Consider using the downsample=N option, or increasing its value.");
300 stats->early_last_emitted = stats->total_ts_seen;
301 return;
302 }
303}
304
305/* Reset the internal state of the timestamp tracker. */
306static int ts_stats_prep(struct context *inc)
307{
308 struct ts_stats *stats;
309 uint64_t down_sample_value;
310 uint32_t down_sample_shift;
311
312 stats = &inc->ts_stats;
313 memset(stats, 0, sizeof(*stats));
314
315 down_sample_value = inc->options.downsample;
316 down_sample_shift = 0;
317 while (down_sample_value >= 2) {
318 down_sample_shift++;
319 down_sample_value /= 2;
320 }
321 stats->early_check_shift = down_sample_shift;
322
323 return SR_OK;
324}
325
326/* Inspect another timestamp that was received. */
327static int ts_stats_check(struct ts_stats *stats, uint64_t curr_ts)
328{
329 uint64_t last_ts, delta;
330
331 last_ts = stats->last_ts_value;
332 stats->last_ts_value = curr_ts;
333 stats->total_ts_seen++;
334 if (stats->total_ts_seen < 2)
335 return SR_OK;
336
337 delta = curr_ts - last_ts;
338 stats->last_ts_delta = delta;
339 (void)ts_stats_update_min(stats, delta);
340
341 ts_stats_check_early(stats);
342
343 return SR_OK;
344}
345
346/* Postprocess internal timestamp tracker state. */
347static int ts_stats_post(struct context *inc, gboolean ignore_terminal)
348{
349 struct ts_stats *stats;
350 size_t min_idx;
351 uint64_t delta, over_sample, over_sample_scaled, suggest_factor;
352 enum sr_loglevel log_level;
353 gboolean is_suspicious, has_downsample;
354
355 stats = &inc->ts_stats;
356
357 /*
358 * Lookup the smallest timestamp delta which was found during
359 * data import. Ignore the last delta if its timestamp was never
360 * followed by data, and this was the only occurance. Absence of
361 * result data is non-fatal here -- this code exclusively serves
362 * to raise users' awareness of potential pitfalls, but does not
363 * change behaviour of data processing.
364 *
365 * TODO Also filter by occurance count? To not emit warnings when
366 * captured signals only change slowly by design. Only warn when
367 * the sample rate and samples count product exceeds a threshold?
368 * See below for the necessity (and potential) to adjust the log
369 * message's severity and content.
370 */
371 min_idx = 0;
372 if (ignore_terminal) do {
373 if (min_idx >= stats->min_count)
374 break;
375 delta = stats->last_ts_delta;
376 if (stats->min_items[min_idx].delta != delta)
377 break;
378 if (stats->min_items[min_idx].count != 1)
379 break;
380 min_idx++;
381 } while (0);
382 if (min_idx >= stats->min_count)
383 return SR_OK;
384
385 /*
386 * TODO Refine the condition whether to notify the user, and
387 * which severity to use after having inspected all input data.
388 * Any detail could get involved which previously was gathered
389 * during data processing: total sample count, channel count
390 * including their data type and bits width, the oversampling
391 * factor (minimum observed "change rate"), or any combination
392 * thereof. The current check is rather simple (unconditional
393 * warning for ratios starting at 100, regardless of sample or
394 * channel count).
395 */
396 over_sample = stats->min_items[min_idx].delta;
397 over_sample_scaled = over_sample / inc->options.downsample;
398 sr_dbg("TS post stats: oversample unscaled %" PRIu64 ", scaled %" PRIu64,
399 over_sample, over_sample_scaled);
400 if (over_sample_scaled < 10) {
401 sr_dbg("TS post stats: Low oversampling ratio, good.");
402 return SR_OK;
403 }
404
405 /*
406 * Avoid constructing the message from several tiny pieces by
407 * design, because this would be hard on translators. Stick with
408 * complete sentences instead, and accept the redundancy in the
409 * user's interest.
410 */
411 log_level = (over_sample_scaled > 20) ? SR_LOG_WARN : SR_LOG_INFO;
412 is_suspicious = over_sample_scaled > 20;
413 if (is_suspicious) {
414 sr_log(log_level, LOG_PREFIX ": "
415 "Suspiciously low overall change rate (total min TS delta %" PRIu64 ").",
416 over_sample_scaled);
417 } else {
418 sr_log(log_level, LOG_PREFIX ": "
419 "Low overall change rate (total min TS delta %" PRIu64 ").",
420 over_sample_scaled);
421 }
422 has_downsample = inc->options.downsample > 1;
423 suggest_factor = inc->options.downsample;
424 while (over_sample_scaled >= 10) {
425 suggest_factor *= 10;
426 over_sample_scaled /= 10;
427 }
428 if (has_downsample) {
429 sr_log(log_level, LOG_PREFIX ": "
430 "Suggest higher downsample value, like %" PRIu64 ".",
431 suggest_factor);
432 } else {
433 sr_log(log_level, LOG_PREFIX ": "
434 "Suggest to downsample, value like %" PRIu64 ".",
435 suggest_factor);
436 }
437
438 return SR_OK;
439}
440
0ab36d2f
GS
441static void check_remove_bom(GString *buf)
442{
443 static const char *bom_text = "\xef\xbb\xbf";
444
445 if (buf->len < strlen(bom_text))
446 return;
447 if (strncmp(buf->str, bom_text, strlen(bom_text)) != 0)
448 return;
449 g_string_erase(buf, 0, strlen(bom_text));
450}
451
e4c8a4d7 452/*
7db06394 453 * Reads a single VCD section from input file and parses it to name/contents.
d9251a2c 454 * e.g. $timescale 1ps $end => "timescale" "1ps"
ec557141
GS
455 *
456 * The section (its content and its opening/closing markers) can span
457 * multiple text lines. This routine must not modify the caller's input
458 * buffer. Executes potentially multiple times on the same input data,
459 * and executes outside of the processing of the file's data section.
99eaa206 460 */
0ab36d2f 461static gboolean parse_section(GString *buf, char **name, char **contents)
99eaa206 462{
0ab36d2f
GS
463 static const char *end_text = "$end";
464
99eaa206 465 gboolean status;
0ab36d2f
GS
466 size_t pos, len;
467 const char *grab_start, *grab_end;
468 GString *sname, *scontent;
7db06394 469
0ab36d2f 470 /* Preset falsy return values. Gets updated below. */
7db06394
BV
471 *name = *contents = NULL;
472 status = FALSE;
1f706c21 473
7db06394 474 /* Skip any initial white-space. */
0ab36d2f 475 pos = 0;
7db06394
BV
476 while (pos < buf->len && g_ascii_isspace(buf->str[pos]))
477 pos++;
cd1b0e8f 478
99eaa206 479 /* Section tag should start with $. */
7db06394 480 if (buf->str[pos++] != '$')
99eaa206 481 return FALSE;
cd1b0e8f 482
7db06394 483 /* Read the section tag. */
0ab36d2f 484 grab_start = &buf->str[pos];
7db06394 485 while (pos < buf->len && !g_ascii_isspace(buf->str[pos]))
0ab36d2f
GS
486 pos++;
487 grab_end = &buf->str[pos];
488 sname = g_string_new_len(grab_start, grab_end - grab_start);
7db06394
BV
489
490 /* Skip whitespace before content. */
491 while (pos < buf->len && g_ascii_isspace(buf->str[pos]))
492 pos++;
493
0ab36d2f
GS
494 /* Read the content up to the '$end' marker. */
495 scontent = g_string_sized_new(128);
496 grab_start = &buf->str[pos];
497 grab_end = g_strstr_len(grab_start, buf->len - pos, end_text);
498 if (grab_end) {
499 /* Advance 'pos' to after '$end' and more whitespace. */
500 pos = grab_end - buf->str;
501 pos += strlen(end_text);
7db06394
BV
502 while (pos < buf->len && g_ascii_isspace(buf->str[pos]))
503 pos++;
0ab36d2f
GS
504
505 /* Grab the (trimmed) content text. */
506 while (grab_end > grab_start && g_ascii_isspace(grab_end[-1]))
507 grab_end--;
508 len = grab_end - grab_start;
509 g_string_append_len(scontent, grab_start, len);
510 if (sname->len)
511 status = TRUE;
512
513 /* Consume the input text which just was taken. */
7db06394
BV
514 g_string_erase(buf, 0, pos);
515 }
99eaa206 516
0ab36d2f 517 /* Return section name and content if a section was seen. */
99eaa206 518 *name = g_string_free(sname, !status);
7db06394 519 *contents = g_string_free(scontent, !status);
7db06394 520
99eaa206
PA
521 return status;
522}
523
0ab36d2f
GS
524static gboolean have_header(GString *buf)
525{
526 static const char *enddef_txt = "$enddefinitions";
527 static const char *end_txt = "$end";
528
529 char *p, *p_stop;
530
531 /* Search for "end of definitions" section keyword. */
532 p = g_strstr_len(buf->str, buf->len, enddef_txt);
533 if (!p)
534 return FALSE;
535 p += strlen(enddef_txt);
536
ec557141
GS
537 /*
538 * Search for end of section (content expected to be empty).
539 * Uses DIY logic to scan for the literals' presence including
540 * empty space between keywords. MUST NOT modify the caller's
541 * input data, potentially executes several times on the same
542 * receive buffer, and executes outside of the processing the
543 * file's data section.
544 */
0ab36d2f
GS
545 p_stop = &buf->str[buf->len];
546 p_stop -= strlen(end_txt);
547 while (p < p_stop && g_ascii_isspace(*p))
548 p++;
549 if (strncmp(p, end_txt, strlen(end_txt)) != 0)
550 return FALSE;
551 p += strlen(end_txt);
552
553 return TRUE;
554}
555
556static int parse_timescale(struct context *inc, char *contents)
db9679af 557{
0ab36d2f
GS
558 uint64_t p, q;
559
560 /*
561 * The standard allows for values 1, 10 or 100
562 * and units s, ms, us, ns, ps and fs.
563 */
564 if (sr_parse_period(contents, &p, &q) != SR_OK) {
565 sr_err("Parsing $timescale failed.");
566 return SR_ERR_DATA;
567 }
568
569 inc->samplerate = q / p;
570 sr_dbg("Samplerate: %" PRIu64, inc->samplerate);
571 if (q % p != 0) {
572 /* Does not happen unless time value is non-standard */
573 sr_warn("Inexact rounding of samplerate, %" PRIu64 " / %" PRIu64 " to %" PRIu64 " Hz.",
574 q, p, inc->samplerate);
575 }
576
577 return SR_OK;
578}
579
580/*
581 * Handle '$scope' and '$upscope' sections in the input file. Assume that
582 * input signals have a "base name", which may be ambiguous within the
583 * file. These names get declared within potentially nested scopes, which
584 * this implementation uses to create longer but hopefully unique and
585 * thus more usable sigrok channel names.
586 *
587 * Track the currently effective scopes in a string variable to simplify
588 * the channel name creation. Start from an empty string, then append the
589 * scope name and a separator when a new scope opens, and remove the last
590 * scope name when a scope closes. This allows to simply prefix basenames
591 * with the current scope to get a full name.
592 *
593 * It's an implementation detail to keep the trailing NUL here in the
594 * GString member, to simplify the g_strconcat() call in the channel name
595 * creation.
596 *
597 * TODO
598 * - Check whether scope types must get supported, this implementation
599 * does not distinguish between 'module' and 'begin' and what else
600 * may be seen. The first word simply gets ignored.
601 * - Check the allowed alphabet for scope names. This implementation
602 * assumes "programming language identifier" style (alphanumeric with
603 * underscores, plus brackets since we've seen them in example files).
604 */
605static int parse_scope(struct context *inc, char *contents, gboolean is_up)
606{
ec557141 607 char *sep_pos, *name_pos, *type_pos;
0ab36d2f
GS
608 size_t length;
609
610 /*
611 * The 'upscope' case, drop one scope level (if available). Accept
612 * excess 'upscope' calls, assume that a previous 'scope' section
613 * was ignored because it referenced our software package's name.
614 */
615 if (is_up) {
616 /*
617 * Check for a second right-most separator (and position
618 * right behind that, which is the start of the last
619 * scope component), or fallback to the start of string.
620 * g_string_erase() from that positon to the end to drop
621 * the last component.
622 */
623 name_pos = inc->scope_prefix->str;
624 do {
625 sep_pos = strrchr(name_pos, SCOPE_SEP);
626 if (!sep_pos)
627 break;
628 *sep_pos = '\0';
629 sep_pos = strrchr(name_pos, SCOPE_SEP);
630 if (!sep_pos)
631 break;
632 name_pos = ++sep_pos;
633 } while (0);
634 length = name_pos - inc->scope_prefix->str;
635 g_string_truncate(inc->scope_prefix, length);
636 g_string_append_c(inc->scope_prefix, '\0');
637 sr_dbg("$upscope, prefix now: \"%s\"", inc->scope_prefix->str);
638 return SR_OK;
639 }
640
641 /*
642 * The 'scope' case, add another scope level. But skip our own
643 * package name, assuming that this is an artificial node which
644 * was emitted by libsigrok's VCD output module.
645 */
646 sr_spew("$scope, got: \"%s\"", contents);
ec557141
GS
647 type_pos = sr_text_next_word(contents, &contents);
648 if (!type_pos) {
649 sr_err("Cannot parse 'scope' directive");
650 return SR_ERR_DATA;
651 }
652 name_pos = sr_text_next_word(contents, &contents);
653 if (!name_pos || contents) {
654 sr_err("Cannot parse 'scope' directive");
0ab36d2f
GS
655 return SR_ERR_DATA;
656 }
ec557141 657
0ab36d2f
GS
658 if (strcmp(name_pos, PACKAGE_NAME) == 0) {
659 sr_info("Skipping scope with application's package name: %s",
660 name_pos);
661 *name_pos = '\0';
662 }
663 if (*name_pos) {
664 /* Drop NUL, append scope name and separator, and re-add NUL. */
665 g_string_truncate(inc->scope_prefix, inc->scope_prefix->len - 1);
666 g_string_append_printf(inc->scope_prefix,
667 "%s%c%c", name_pos, SCOPE_SEP, '\0');
668 }
0ab36d2f
GS
669 sr_dbg("$scope, prefix now: \"%s\"", inc->scope_prefix->str);
670
671 return SR_OK;
672}
673
674/**
675 * Parse a $var section which describes a VCD signal ("variable").
676 *
677 * @param[in] inc Input module context.
678 * @param[in] contents Input text, content of $var section.
679 */
680static int parse_header_var(struct context *inc, char *contents)
681{
0ab36d2f
GS
682 char *type, *size_txt, *id, *ref, *idx;
683 gboolean is_reg, is_wire, is_real, is_int;
c1310f7d 684 gboolean is_str;
0ab36d2f
GS
685 enum sr_channeltype ch_type;
686 size_t size, next_size;
4237ab9e
GS
687 struct vcd_channel *vcd_ch;
688
0ab36d2f
GS
689 /*
690 * Format of $var or $reg header specs:
691 * $var type size identifier reference [opt-index] $end
692 */
ec557141
GS
693 type = sr_text_next_word(contents, &contents);
694 size_txt = sr_text_next_word(contents, &contents);
695 id = sr_text_next_word(contents, &contents);
696 ref = sr_text_next_word(contents, &contents);
697 idx = sr_text_next_word(contents, &contents);
698 if (idx && !*idx)
699 idx = NULL;
700 if (!type || !size_txt || !id || !ref || contents) {
0ab36d2f 701 sr_warn("$var section should have 4 or 5 items");
0ab36d2f
GS
702 return SR_ERR_DATA;
703 }
704
0ab36d2f
GS
705 is_reg = g_strcmp0(type, "reg") == 0;
706 is_wire = g_strcmp0(type, "wire") == 0;
707 is_real = g_strcmp0(type, "real") == 0;
708 is_int = g_strcmp0(type, "integer") == 0;
c1310f7d 709 is_str = g_strcmp0(type, "string") == 0;
0ab36d2f
GS
710
711 if (is_reg || is_wire) {
712 ch_type = SR_CHANNEL_LOGIC;
713 } else if (is_real || is_int) {
714 ch_type = SR_CHANNEL_ANALOG;
c1310f7d
GS
715 } else if (is_str) {
716 sr_warn("Skipping id %s, name '%s%s', unsupported type '%s'.",
717 id, ref, idx ? idx : "", type);
718 inc->ignored_signals = g_slist_append(inc->ignored_signals,
719 g_strdup(id));
c1310f7d 720 return SR_OK;
0ab36d2f 721 } else {
1a35f711 722 sr_err("Unsupported signal type: '%s'", type);
0ab36d2f
GS
723 return SR_ERR_DATA;
724 }
725
726 size = strtol(size_txt, NULL, 10);
727 if (ch_type == SR_CHANNEL_ANALOG) {
728 if (is_real && size != 32 && size != 64) {
729 /*
730 * The VCD input module does not depend on the
731 * specific width of the floating point value.
732 * This is just for information. Upon value
733 * changes, a mere string gets converted to
734 * float, so we may not care at all.
735 *
736 * Strictly speaking we might warn for 64bit
737 * (double precision) declarations, because
738 * sigrok internally uses single precision
739 * (32bit) only.
740 */
741 sr_info("Unexpected real width: '%s'", size_txt);
742 }
743 /* Simplify code paths below, by assuming size 1. */
744 size = 1;
745 }
746 if (!size) {
747 sr_warn("Unsupported signal size: '%s'", size_txt);
0ab36d2f
GS
748 return SR_ERR_DATA;
749 }
750 if (inc->conv_bits.max_bits < size)
751 inc->conv_bits.max_bits = size;
752 next_size = inc->logic_count + inc->analog_count + size;
753 if (inc->options.maxchannels && next_size > inc->options.maxchannels) {
754 sr_warn("Skipping '%s%s', exceeds requested channel count %zu.",
755 ref, idx ? idx : "", inc->options.maxchannels);
756 inc->ignored_signals = g_slist_append(inc->ignored_signals,
757 g_strdup(id));
0ab36d2f
GS
758 return SR_OK;
759 }
760
761 vcd_ch = g_malloc0(sizeof(*vcd_ch));
762 vcd_ch->identifier = g_strdup(id);
763 vcd_ch->name = g_strconcat(inc->scope_prefix->str, ref, idx, NULL);
764 vcd_ch->size = size;
765 vcd_ch->type = ch_type;
766 switch (ch_type) {
767 case SR_CHANNEL_LOGIC:
768 vcd_ch->array_index = inc->logic_count;
769 vcd_ch->byte_idx = vcd_ch->array_index / 8;
770 vcd_ch->bit_mask = 1 << (vcd_ch->array_index % 8);
771 inc->logic_count += size;
772 break;
773 case SR_CHANNEL_ANALOG:
774 vcd_ch->array_index = inc->analog_count++;
775 /* TODO: Use proper 'digits' value for this input module. */
776 vcd_ch->submit_digits = is_real ? 2 : 0;
777 break;
778 }
779 inc->vcdsignals++;
780 sr_spew("VCD signal %zu '%s' ID '%s' (size %zu), sr type %s, idx %zu.",
781 inc->vcdsignals, vcd_ch->name,
782 vcd_ch->identifier, vcd_ch->size,
783 vcd_ch->type == SR_CHANNEL_ANALOG ? "A" : "L",
784 vcd_ch->array_index);
785 inc->channels = g_slist_append(inc->channels, vcd_ch);
0ab36d2f
GS
786
787 return SR_OK;
db9679af
ML
788}
789
0ab36d2f
GS
790/**
791 * Construct the name of the nth sigrok channel for a VCD signal.
792 *
793 * Uses the VCD signal name for scalar types and single-bit signals.
794 * Uses "signal.idx" for multi-bit VCD signals without a range spec in
795 * their declaration. Uses "signal[idx]" when a range is known and was
796 * verified.
797 *
798 * @param[in] vcd_ch The VCD signal's description.
799 * @param[in] idx The sigrok channel's index within the VCD signal's group.
800 *
801 * @return An allocated text buffer which callers need to release, #NULL
802 * upon failure to create a sigrok channel name.
803 */
804static char *get_channel_name(struct vcd_channel *vcd_ch, size_t idx)
99eaa206 805{
0ab36d2f
GS
806 char *open_pos, *close_pos, *check_pos, *endptr;
807 gboolean has_brackets, has_range;
808 size_t upper, lower, tmp;
809 char *ch_name;
810
811 /* Handle simple scalar types, and single-bit logic first. */
812 if (vcd_ch->size <= 1)
813 return g_strdup(vcd_ch->name);
814
815 /*
816 * If not done before: Search for a matching pair of brackets in
817 * the right-most position at the very end of the string. Get the
818 * two colon separated numbers between the brackets, which are
819 * the range limits for array indices into the multi-bit signal.
820 * Grab the "base name" of the VCD signal.
821 *
822 * Notice that arrays can get nested. Earlier path components can
823 * be indexed as well, that's why we need the right-most range.
824 * This implementation does not handle bit vectors of size 1 here
825 * by explicit logic. The check for a [0:0] range would even fail.
826 * But the case of size 1 is handled above, and "happens to" give
827 * the expected result (just the VCD signal name).
828 *
829 * This implementation also deals with range limits in the reverse
830 * order, as well as ranges which are not 0-based (like "[4:7]").
831 */
832 if (!vcd_ch->base_name) {
833 has_range = TRUE;
834 open_pos = strrchr(vcd_ch->name, '[');
835 close_pos = strrchr(vcd_ch->name, ']');
836 if (close_pos && close_pos[1])
837 close_pos = NULL;
838 has_brackets = open_pos && close_pos && close_pos > open_pos;
839 if (!has_brackets)
840 has_range = FALSE;
841 if (has_range) {
842 check_pos = &open_pos[1];
843 endptr = NULL;
844 upper = strtoul(check_pos, &endptr, 10);
845 if (!endptr || *endptr != ':')
846 has_range = FALSE;
847 }
848 if (has_range) {
849 check_pos = &endptr[1];
850 endptr = NULL;
851 lower = strtoul(check_pos, &endptr, 10);
852 if (!endptr || endptr != close_pos)
853 has_range = FALSE;
854 }
855 if (has_range && lower > upper) {
856 tmp = lower;
857 lower = upper;
858 upper = tmp;
859 }
860 if (has_range) {
861 if (lower >= upper)
862 has_range = FALSE;
863 if (upper + 1 - lower != vcd_ch->size)
864 has_range = FALSE;
865 }
866 if (has_range) {
867 /* Temporarily patch the VCD channel's name. */
868 *open_pos = '\0';
869 vcd_ch->base_name = g_strdup(vcd_ch->name);
870 *open_pos = '[';
871 vcd_ch->range_lower = lower;
872 vcd_ch->range_upper = upper;
873 }
99eaa206 874 }
0ab36d2f
GS
875 has_range = vcd_ch->range_lower + vcd_ch->range_upper;
876 if (has_range && idx >= vcd_ch->size)
877 has_range = FALSE;
878 if (!has_range)
879 return g_strdup_printf("%s.%zu", vcd_ch->name, idx);
cd1b0e8f 880
0ab36d2f
GS
881 /*
882 * Create a sigrok channel name with just the bit's index in
883 * brackets. This avoids "name[7:0].3" results, instead results
884 * in "name[3]".
885 */
886 ch_name = g_strdup_printf("%s[%zu]",
887 vcd_ch->base_name, vcd_ch->range_lower + idx);
888 return ch_name;
889}
890
891/*
892 * Create (analog or logic) sigrok channels for the VCD signals. Create
893 * multiple sigrok channels for vector input since sigrok has no concept
894 * of multi-bit signals. Create a channel group for the vector's bits
895 * though to reflect that they form a unit. This is beneficial when UIs
896 * support optional "collapsed" displays of channel groups (like
897 * "parallel bus, hex output").
898 *
899 * Defer channel creation until after completion of parsing the input
900 * file header. Make sure to create all logic channels first before the
901 * analog channels get created. This avoids issues with the mapping of
902 * channel indices to bitmap positions in the sample buffer.
903 */
904static void create_channels(const struct sr_input *in,
905 struct sr_dev_inst *sdi, enum sr_channeltype ch_type)
906{
907 struct context *inc;
908 size_t ch_idx;
909 GSList *l;
910 struct vcd_channel *vcd_ch;
911 size_t size_idx;
912 char *ch_name;
913 struct sr_channel_group *cg;
914 struct sr_channel *ch;
915
916 inc = in->priv;
917
918 ch_idx = 0;
919 if (ch_type > SR_CHANNEL_LOGIC)
920 ch_idx += inc->logic_count;
921 if (ch_type > SR_CHANNEL_ANALOG)
922 ch_idx += inc->analog_count;
923 for (l = inc->channels; l; l = l->next) {
924 vcd_ch = l->data;
925 if (vcd_ch->type != ch_type)
926 continue;
927 cg = NULL;
d810901a
GS
928 if (vcd_ch->size != 1)
929 cg = sr_channel_group_new(sdi, vcd_ch->name, NULL);
0ab36d2f
GS
930 for (size_idx = 0; size_idx < vcd_ch->size; size_idx++) {
931 ch_name = get_channel_name(vcd_ch, size_idx);
932 sr_dbg("sigrok channel idx %zu, name %s, type %s, en %d.",
933 ch_idx, ch_name,
934 ch_type == SR_CHANNEL_ANALOG ? "A" : "L", TRUE);
935 ch = sr_channel_new(sdi, ch_idx, ch_type, TRUE, ch_name);
936 g_free(ch_name);
937 ch_idx++;
938 if (cg)
939 cg->channels = g_slist_append(cg->channels, ch);
940 }
0ab36d2f
GS
941 }
942}
943
944static void create_feeds(const struct sr_input *in)
945{
946 struct context *inc;
947 GSList *l;
948 struct vcd_channel *vcd_ch;
949 size_t ch_idx;
950 struct sr_channel *ch;
951
952 inc = in->priv;
953
954 /* Create one feed for logic data. */
2cb4204c
GS
955 if (inc->logic_count) {
956 inc->unit_size = (inc->logic_count + 7) / 8;
957 inc->feed_logic = feed_queue_logic_alloc(in->sdi,
958 CHUNK_SIZE / inc->unit_size, inc->unit_size);
959 }
0ab36d2f
GS
960
961 /* Create one feed per analog channel. */
962 for (l = inc->channels; l; l = l->next) {
963 vcd_ch = l->data;
964 if (vcd_ch->type != SR_CHANNEL_ANALOG)
965 continue;
966 ch_idx = vcd_ch->array_index;
967 ch_idx += inc->logic_count;
968 ch = g_slist_nth_data(in->sdi->channels, ch_idx);
969 vcd_ch->feed_analog = feed_queue_analog_alloc(in->sdi,
970 CHUNK_SIZE / sizeof(float),
971 vcd_ch->submit_digits, ch);
972 }
99eaa206
PA
973}
974
08f8421a
GS
975/*
976 * Keep track of a previously created channel list, in preparation of
977 * re-reading the input file. Gets called from reset()/cleanup() paths.
978 */
979static void keep_header_for_reread(const struct sr_input *in)
980{
981 struct context *inc;
982
983 inc = in->priv;
0ab36d2f 984
d810901a 985 g_slist_free_full(inc->prev.sr_groups, sr_channel_group_free_cb);
0ab36d2f
GS
986 inc->prev.sr_groups = in->sdi->channel_groups;
987 in->sdi->channel_groups = NULL;
988
989 g_slist_free_full(inc->prev.sr_channels, sr_channel_free_cb);
990 inc->prev.sr_channels = in->sdi->channels;
08f8421a
GS
991 in->sdi->channels = NULL;
992}
993
994/*
995 * Check whether the input file is being re-read, and refuse operation
996 * when essential parameters of the acquisition have changed in ways
997 * that are unexpected to calling applications. Gets called after the
998 * file header got parsed (again).
999 *
1000 * Changing the channel list across re-imports of the same file is not
1001 * supported, by design and for valid reasons, see bug #1215 for details.
1002 * Users are expected to start new sessions when they change these
1003 * essential parameters in the acquisition's setup. When we accept the
1004 * re-read file, then make sure to keep using the previous channel list,
1005 * applications may still reference them.
1006 */
0ab36d2f 1007static gboolean check_header_in_reread(const struct sr_input *in)
08f8421a
GS
1008{
1009 struct context *inc;
1010
1011 if (!in)
1012 return FALSE;
1013 inc = in->priv;
1014 if (!inc)
1015 return FALSE;
0ab36d2f 1016 if (!inc->prev.sr_channels)
08f8421a
GS
1017 return TRUE;
1018
0ab36d2f 1019 if (sr_channel_lists_differ(inc->prev.sr_channels, in->sdi->channels)) {
08f8421a
GS
1020 sr_err("Channel list change not supported for file re-read.");
1021 return FALSE;
1022 }
0ab36d2f 1023
d810901a 1024 g_slist_free_full(in->sdi->channel_groups, sr_channel_group_free_cb);
0ab36d2f
GS
1025 in->sdi->channel_groups = inc->prev.sr_groups;
1026 inc->prev.sr_groups = NULL;
1027
08f8421a 1028 g_slist_free_full(in->sdi->channels, sr_channel_free_cb);
0ab36d2f
GS
1029 in->sdi->channels = inc->prev.sr_channels;
1030 inc->prev.sr_channels = NULL;
08f8421a
GS
1031
1032 return TRUE;
1033}
1034
0ab36d2f
GS
1035/* Parse VCD file header sections (rate and variables declarations). */
1036static int parse_header(const struct sr_input *in, GString *buf)
99eaa206 1037{
7db06394 1038 struct context *inc;
93a28f0b 1039 gboolean enddef_seen, header_valid;
0ab36d2f
GS
1040 char *name, *contents;
1041 size_t size;
ec302917 1042 int ret;
99eaa206 1043
7db06394 1044 inc = in->priv;
0ab36d2f
GS
1045
1046 /* Parse sections until complete header was seen. */
93a28f0b
GS
1047 enddef_seen = FALSE;
1048 header_valid = TRUE;
0ab36d2f
GS
1049 name = contents = NULL;
1050 inc->conv_bits.max_bits = 1;
7db06394 1051 while (parse_section(buf, &name, &contents)) {
99eaa206 1052 sr_dbg("Section '%s', contents '%s'.", name, contents);
cd1b0e8f 1053
e4c8a4d7 1054 if (g_strcmp0(name, "enddefinitions") == 0) {
93a28f0b 1055 enddef_seen = TRUE;
0ab36d2f
GS
1056 goto done_section;
1057 }
1058 if (g_strcmp0(name, "timescale") == 0) {
1059 if (parse_timescale(inc, contents) != SR_OK)
93a28f0b 1060 header_valid = FALSE;
0ab36d2f
GS
1061 goto done_section;
1062 }
1063 if (g_strcmp0(name, "scope") == 0) {
1064 if (parse_scope(inc, contents, FALSE) != SR_OK)
93a28f0b 1065 header_valid = FALSE;
0ab36d2f
GS
1066 goto done_section;
1067 }
1068 if (g_strcmp0(name, "upscope") == 0) {
1069 if (parse_scope(inc, NULL, TRUE) != SR_OK)
93a28f0b 1070 header_valid = FALSE;
0ab36d2f
GS
1071 goto done_section;
1072 }
1073 if (g_strcmp0(name, "var") == 0) {
1074 if (parse_header_var(inc, contents) != SR_OK)
93a28f0b 1075 header_valid = FALSE;
0ab36d2f 1076 goto done_section;
99eaa206 1077 }
cd1b0e8f 1078
0ab36d2f 1079done_section:
db0e5c99
PA
1080 g_free(name);
1081 name = NULL;
1082 g_free(contents);
1083 contents = NULL;
0ab36d2f 1084
93a28f0b 1085 if (enddef_seen)
0ab36d2f 1086 break;
99eaa206 1087 }
99eaa206
PA
1088 g_free(name);
1089 g_free(contents);
cd1b0e8f 1090
93a28f0b
GS
1091 inc->got_header = enddef_seen && header_valid;
1092 if (!inc->got_header)
0ab36d2f 1093 return SR_ERR_DATA;
cd1b0e8f 1094
0ab36d2f
GS
1095 /* Create sigrok channels here, late, logic before analog. */
1096 create_channels(in, in->sdi, SR_CHANNEL_LOGIC);
1097 create_channels(in, in->sdi, SR_CHANNEL_ANALOG);
1098 if (!check_header_in_reread(in))
1099 return SR_ERR_DATA;
1100 create_feeds(in);
99eaa206 1101
e4c8a4d7 1102 /*
0ab36d2f
GS
1103 * Allocate space for text to number conversion, and buffers to
1104 * hold current sample values before submission to the session
1105 * feed. Allocate one buffer for all logic bits, and another for
1106 * all floating point values of all analog channels.
1107 *
1108 * The buffers get updated when the VCD input stream communicates
1109 * value changes. Upon reception of VCD timestamps, the buffer can
1110 * provide the previously received values, to "fill in the gaps"
1111 * in the generation of a continuous stream of samples for the
1112 * sigrok session.
99eaa206 1113 */
0ab36d2f
GS
1114 size = (inc->conv_bits.max_bits + 7) / 8;
1115 inc->conv_bits.unit_size = size;
1116 inc->conv_bits.value = g_malloc0(size);
1117 if (!inc->conv_bits.value)
1118 return SR_ERR_MALLOC;
1119
1120 size = (inc->logic_count + 7) / 8;
1121 inc->unit_size = size;
1122 inc->current_logic = g_malloc0(size);
1123 if (inc->unit_size && !inc->current_logic)
1124 return SR_ERR_MALLOC;
1125 size = sizeof(inc->current_floats[0]) * inc->analog_count;
1126 inc->current_floats = g_malloc0(size);
1127 if (size && !inc->current_floats)
1128 return SR_ERR_MALLOC;
1129 for (size = 0; size < inc->analog_count; size++)
1130 inc->current_floats[size] = 0.;
54ee427d 1131
ec302917
GS
1132 ret = ts_stats_prep(inc);
1133 if (ret != SR_OK)
1134 return ret;
1135
54ee427d 1136 return SR_OK;
99eaa206
PA
1137}
1138
0ab36d2f
GS
1139/*
1140 * Add N copies of previously received values to the session, before
1141 * subsequent value changes will update the data buffer. Locally buffer
1142 * sample data to minimize the number of send() calls.
1143 */
1144static void add_samples(const struct sr_input *in, size_t count, gboolean flush)
61a429c9 1145{
db0e5c99 1146 struct context *inc;
0ab36d2f
GS
1147 GSList *ch_list;
1148 struct vcd_channel *vcd_ch;
1149 struct feed_queue_analog *q;
1150 float value;
cd1b0e8f 1151
db0e5c99 1152 inc = in->priv;
61a429c9 1153
0ab36d2f 1154 if (inc->logic_count) {
f40d8479 1155 feed_queue_logic_submit_one(inc->feed_logic,
0ab36d2f
GS
1156 inc->current_logic, count);
1157 if (flush)
1158 feed_queue_logic_flush(inc->feed_logic);
1159 }
1160 for (ch_list = inc->channels; ch_list; ch_list = ch_list->next) {
1161 vcd_ch = ch_list->data;
1162 if (vcd_ch->type != SR_CHANNEL_ANALOG)
1163 continue;
1164 q = vcd_ch->feed_analog;
1165 if (!q)
1166 continue;
1167 value = inc->current_floats[vcd_ch->array_index];
f40d8479 1168 feed_queue_analog_submit_one(q, value, count);
0ab36d2f
GS
1169 if (flush)
1170 feed_queue_analog_flush(q);
1171 }
1172}
cd1b0e8f 1173
0ab36d2f
GS
1174static gint vcd_compare_id(gconstpointer a, gconstpointer b)
1175{
1176 return strcmp((const char *)a, (const char *)b);
db0e5c99
PA
1177}
1178
0ab36d2f 1179static gboolean is_ignored(struct context *inc, const char *id)
db0e5c99 1180{
0ab36d2f 1181 GSList *ignored;
db0e5c99 1182
0ab36d2f
GS
1183 ignored = g_slist_find_custom(inc->ignored_signals, id, vcd_compare_id);
1184 return ignored != NULL;
1185}
cd1b0e8f 1186
0ab36d2f
GS
1187/*
1188 * Get an analog channel's value from a bit pattern (VCD 'integer' type).
1189 * The implementation assumes a maximum integer width (64bit), the API
1190 * doesn't (beyond the return data type). The use of SR_CHANNEL_ANALOG
1191 * channels may further constraint the number of significant digits
1192 * (current asumption: float -> 23bit).
1193 */
1194static float get_int_val(uint8_t *in_bits_data, size_t in_bits_count)
1195{
1196 uint64_t int_value;
1197 size_t byte_count, byte_idx;
1198 float flt_value; /* typeof(inc->current_floats[0]) */
1199
1200 /* Convert bit pattern to integer number (limited range). */
1201 int_value = 0;
1202 byte_count = (in_bits_count + 7) / 8;
1203 for (byte_idx = 0; byte_idx < byte_count; byte_idx++) {
1204 if (byte_idx >= sizeof(int_value))
1205 break;
1206 int_value |= *in_bits_data++ << (byte_idx * 8);
1207 }
1208 flt_value = int_value;
db0e5c99 1209
0ab36d2f
GS
1210 return flt_value;
1211}
cd1b0e8f 1212
0ab36d2f
GS
1213/*
1214 * Set a logic channel's level depending on the VCD signal's identifier
1215 * and parsed value. Multi-bit VCD values will affect several sigrok
1216 * channels. One VCD signal name can translate to several sigrok channels.
1217 */
1218static void process_bits(struct context *inc, char *identifier,
1219 uint8_t *in_bits_data, size_t in_bits_count)
1220{
1221 size_t size;
1222 gboolean have_int;
1223 GSList *l;
1224 struct vcd_channel *vcd_ch;
1225 float int_val;
1226 size_t bit_idx;
1227 uint8_t *in_bit_ptr, in_bit_mask;
1228 uint8_t *out_bit_ptr, out_bit_mask;
1229 uint8_t bit_val;
1230
1231 size = 0;
1232 have_int = FALSE;
1233 int_val = 0;
1234 for (l = inc->channels; l; l = l->next) {
1235 vcd_ch = l->data;
1236 if (g_strcmp0(identifier, vcd_ch->identifier) != 0)
1237 continue;
1238 if (vcd_ch->type == SR_CHANNEL_ANALOG) {
1239 /* Special case for 'integer' VCD signal types. */
1240 size = vcd_ch->size; /* Flag for "VCD signal found". */
1241 if (!have_int) {
1242 int_val = get_int_val(in_bits_data, in_bits_count);
1243 have_int = TRUE;
1244 }
1245 inc->current_floats[vcd_ch->array_index] = int_val;
1246 continue;
1247 }
1248 if (vcd_ch->type != SR_CHANNEL_LOGIC)
1249 continue;
1250 sr_spew("Processing %s data, id '%s', ch %zu sz %zu",
1251 (size == 1) ? "bit" : "vector",
1252 identifier, vcd_ch->array_index, vcd_ch->size);
1253
1254 /* Found our (logic) channel. Setup in/out bit positions. */
1255 size = vcd_ch->size;
1256 in_bit_ptr = in_bits_data;
1257 in_bit_mask = 1 << 0;
1258 out_bit_ptr = &inc->current_logic[vcd_ch->byte_idx];
1259 out_bit_mask = vcd_ch->bit_mask;
1260
1261 /*
1262 * Pass VCD input bit(s) to sigrok logic bits. Conversion
1263 * must be done repeatedly because one VCD signal name
1264 * can translate to several sigrok channels, and shifting
1265 * a previously computed bit field to another channel's
1266 * position in the buffer would be nearly as expensive,
1267 * and certain would increase complexity of the code.
1268 */
1269 for (bit_idx = 0; bit_idx < size; bit_idx++) {
1270 /* Get the bit value from input data. */
1271 bit_val = 0;
1272 if (bit_idx < in_bits_count) {
1273 bit_val = *in_bit_ptr & in_bit_mask;
1274 in_bit_mask <<= 1;
1275 if (!in_bit_mask) {
1276 in_bit_mask = 1 << 0;
1277 in_bit_ptr++;
1278 }
1279 }
1280 /* Manipulate the sample buffer data image. */
1281 if (bit_val)
1282 *out_bit_ptr |= out_bit_mask;
1283 else
1284 *out_bit_ptr &= ~out_bit_mask;
1285 /* Update output position after bitmap update. */
1286 out_bit_mask <<= 1;
1287 if (!out_bit_mask) {
1288 out_bit_mask = 1 << 0;
1289 out_bit_ptr++;
1290 }
db0e5c99 1291 }
61a429c9 1292 }
0ab36d2f
GS
1293 if (!size && !is_ignored(inc, identifier))
1294 sr_warn("VCD signal not found for ID '%s'.", identifier);
61a429c9
PA
1295}
1296
0ab36d2f
GS
1297/*
1298 * Set an analog channel's value from a floating point number. One
1299 * VCD signal name can translate to several sigrok channels.
1300 */
1301static void process_real(struct context *inc, char *identifier, float real_val)
36dacf17 1302{
0ab36d2f 1303 gboolean found;
36dacf17
WS
1304 GSList *l;
1305 struct vcd_channel *vcd_ch;
36dacf17 1306
0ab36d2f
GS
1307 found = FALSE;
1308 for (l = inc->channels; l; l = l->next) {
36dacf17 1309 vcd_ch = l->data;
0ab36d2f
GS
1310 if (vcd_ch->type != SR_CHANNEL_ANALOG)
1311 continue;
1312 if (g_strcmp0(identifier, vcd_ch->identifier) != 0)
1313 continue;
1314
1315 /* Found our (analog) channel. */
1316 found = TRUE;
1317 sr_spew("Processing real data, id '%s', ch %zu, val %.16g",
1318 identifier, vcd_ch->array_index, real_val);
1319 inc->current_floats[vcd_ch->array_index] = real_val;
36dacf17 1320 }
0ab36d2f
GS
1321 if (!found && !is_ignored(inc, identifier))
1322 sr_warn("VCD signal not found for ID '%s'.", identifier);
1323}
1324
1325/*
1326 * Converts a bit position's text character to a number value.
1327 *
1328 * TODO Check for complete coverage of Verilog's standard logic values
1329 * (IEEE-1364). The set is said to be “01XZHUWL-”, which only a part of
1330 * is handled here. What would be the complete mapping?
1331 * - 0/L -> bit value 0
1332 * - 1/H -> bit value 1
1333 * - X "don't care" -> TODO
1334 * - Z "high impedance" -> TODO
1335 * - W "weak(?)" -> TODO
1336 * - U "undefined" -> TODO
1337 * - '-' "TODO" -> TODO
1338 *
1339 * For simplicity, this input module implementation maps "known low"
1340 * values to 0, and "known high" values to 1. All other values will
1341 * end up assuming "low" (return number 0), while callers might warn.
1342 * It's up to users to provide compatible input data, or accept the
1343 * warnings. Silently accepting unknown input data is not desirable.
1344 */
1345static uint8_t vcd_char_to_value(char bit_char, int *warn)
1346{
1347
1348 bit_char = g_ascii_tolower(bit_char);
1349
1350 /* Convert the "undisputed" variants. */
1351 if (bit_char == '0' || bit_char == 'l')
1352 return 0;
1353 if (bit_char == '1' || bit_char == 'h')
1354 return 1;
1355
1356 /* Convert the "uncertain" variants. */
1357 if (warn)
1358 *warn = 1;
1359 if (bit_char == 'x' || bit_char == 'z')
1360 return 0;
1361 if (bit_char == 'u')
1362 return 0;
35810515
GS
1363 if (bit_char == '-')
1364 return 0;
0ab36d2f
GS
1365
1366 /* Unhandled input text. */
1367 return ~0;
36dacf17
WS
1368}
1369
c1310f7d
GS
1370/*
1371 * Check the validity of a VCD string value. It's essential to reliably
1372 * accept valid data which the community uses in the field, yet robustly
1373 * reject invalid data for users' awareness. Since IEEE 1800-2017 would
1374 * not discuss the representation of this data type, it's assumed to not
1375 * be an official feature of the VCD file format. This implementation is
1376 * an educated guess after inspection of other arbitrary implementations,
1377 * not backed by any specification or public documentation.
1378 *
1379 * A quick summary of the implemented assumptions: Must be a sequence of
1380 * ASCII printables. Must not contain whitespace. Might contain escape
1381 * sequences: A backslash followed by a single character, like '\n' or
1382 * '\\'. Or a backslash and the letter x followed by two hex digits,
1383 * like '\x20'. Or a backslash followed by three octal digits, like
1384 * '\007'. As an exception also accepts a single digit '\0' but only at
1385 * the text end. The string value may be empty, but must not be NULL.
1386 *
1387 * This implementation assumes an ASCII based platform for simplicity
1388 * and readability. Should be a given on sigrok supported platforms.
1389 */
1390static gboolean vcd_string_valid(const char *s)
1391{
1392 char c;
1393
1394 if (!s)
1395 return FALSE;
1396
1397 while (*s) {
1398 c = *s++;
1399 /* Reject non-printable ASCII chars including DEL. */
1400 if (c < ' ')
1401 return FALSE;
1402 if (c > '~')
1403 return FALSE;
1404 /* Deeper inspection of escape sequences. */
1405 if (c == '\\') {
1406 c = *s++;
1407 switch (c) {
1408 case 'a': /* BEL, bell aka "alarm" */
1409 case 'b': /* BS, back space */
1410 case 't': /* TAB, tabulator */
1411 case 'n': /* NL, newline */
1412 case 'v': /* VT, vertical tabulator */
1413 case 'f': /* FF, form feed */
1414 case 'r': /* CR, carriage return */
1415 case '"': /* double quotes */
1416 case '\'': /* tick, single quote */
1417 case '?': /* question mark */
1418 case '\\': /* backslash */
1419 continue;
1420 case 'x': /* \xNN two hex digits */
1421 c = *s++;
1422 if (!g_ascii_isxdigit(c))
1423 return FALSE;
1424 c = *s++;
1425 if (!g_ascii_isxdigit(c))
1426 return FALSE;
1427 continue;
1428 case '0': /* \NNN three octal digits */
1429 case '1':
1430 case '2':
1431 case '3':
1432 case '4':
1433 case '5':
1434 case '6':
1435 case '7':
1436 /* Special case '\0' at end of text. */
1437 if (c == '0' && !*s)
1438 return TRUE;
1439 /*
1440 * First digit was covered by the outer
1441 * switch(). Two more digits to check.
1442 */
1443 c = *s++;
1444 if (!g_ascii_isdigit(c) || c > '7')
1445 return FALSE;
1446 c = *s++;
1447 if (!g_ascii_isdigit(c) || c > '7')
1448 return FALSE;
1449 continue;
1450 default:
1451 return FALSE;
1452 }
1453 }
1454 }
1455
1456 return TRUE;
1457}
1458
0ab36d2f 1459/* Parse one text line of the data section. */
ec557141 1460static int parse_textline(const struct sr_input *in, char *line)
61a429c9 1461{
7db06394 1462 struct context *inc;
0ab36d2f 1463 int ret;
ec557141 1464 char *curr_word, curr_first;
c1310f7d
GS
1465 gboolean is_timestamp, is_section;
1466 gboolean is_real, is_multibit, is_singlebit, is_string;
f9bc17d4 1467 uint64_t timestamp;
dd8bec71 1468 char *identifier, *endptr;
0ab36d2f 1469 size_t count;
cd1b0e8f 1470
7db06394 1471 inc = in->priv;
cd1b0e8f 1472
0ab36d2f 1473 /*
ec557141
GS
1474 * Consume space separated words from a caller's text line. Note
1475 * that many words are self contained, but some require another
1476 * word to follow. This implementation assumes that both words
1477 * (when involved) become available in the same invocation, that
1478 * is that both words reside on the same text line of the file.
0ab36d2f 1479 * The fact that callers always pass complete text lines should
ec557141
GS
1480 * make this assumption acceptable. No generator is known to
1481 * split two corresponding words across text lines.
1482 *
1483 * This constraint applies to bit vector data, multi-bit integer
1484 * and real (float) values, text strings, as well as single-bit
1485 * values with whitespace before their identifiers (if that is
1486 * valid in VCD, we'd accept it here; if generators don't create
1487 * such input, then support for it does not harm).
0ab36d2f
GS
1488 */
1489 ret = SR_OK;
ec557141 1490 while (line) {
0ab36d2f 1491 /*
ec557141
GS
1492 * Lookup one word here which is mandatory. Locations
1493 * below conditionally lookup another word as needed.
0ab36d2f 1494 */
ec557141
GS
1495 curr_word = sr_text_next_word(line, &line);
1496 if (!curr_word)
1497 break;
1498 if (!*curr_word)
0ab36d2f
GS
1499 continue;
1500 curr_first = g_ascii_tolower(curr_word[0]);
0ab36d2f
GS
1501
1502 /*
1503 * Optionally skip some sections that can be interleaved
1504 * with data (and may or may not be supported by this
1505 * input module). If the section is not skipped but the
1506 * $end keyword needs to get tracked, specifically handle
1507 * this case, for improved robustness (still reject files
1508 * which happen to use invalid syntax).
1509 */
7db06394 1510 if (inc->skip_until_end) {
0ab36d2f 1511 if (strcmp(curr_word, "$end") == 0) {
7db06394 1512 /* Done with unhandled/unknown section. */
0ab36d2f 1513 sr_dbg("done skipping until $end");
7db06394 1514 inc->skip_until_end = FALSE;
0ab36d2f
GS
1515 } else {
1516 sr_spew("skipping word: %s", curr_word);
1517 }
1518 continue;
1519 }
1520 if (inc->ignore_end_keyword) {
1521 if (strcmp(curr_word, "$end") == 0) {
1522 sr_dbg("done ignoring $end keyword");
1523 inc->ignore_end_keyword = FALSE;
1524 continue;
7db06394
BV
1525 }
1526 }
cd1b0e8f 1527
0ab36d2f
GS
1528 /*
1529 * There may be $keyword sections inside the data part of
1530 * the input file. Do inspect some of the sections' content
1531 * but ignore their surrounding keywords. Silently skip
1532 * unsupported section types (which transparently covers
1533 * $comment sections).
1534 */
1535 is_section = curr_first == '$' && curr_word[1];
1536 if (is_section) {
1537 gboolean inspect_data;
1538
1539 inspect_data = FALSE;
1540 inspect_data |= g_strcmp0(curr_word, "$dumpvars") == 0;
1541 inspect_data |= g_strcmp0(curr_word, "$dumpon") == 0;
1542 inspect_data |= g_strcmp0(curr_word, "$dumpoff") == 0;
1543 if (inspect_data) {
1544 /* Ignore keywords, yet parse contents. */
1545 sr_dbg("%s section, will parse content", curr_word);
1546 inc->ignore_end_keyword = TRUE;
1547 } else {
1548 /* Ignore section from here up to $end. */
1549 sr_dbg("%s section, will skip until $end", curr_word);
1550 inc->skip_until_end = TRUE;
1551 }
1552 continue;
1553 }
1554
1555 /*
1556 * Numbers prefixed by '#' are timestamps, which translate
1557 * to sigrok sample numbers. Apply optional downsampling,
1558 * and apply the 'skip' logic. Check the recent timestamp
1559 * for plausibility. Submit the corresponding number of
1560 * samples of previously accumulated data values to the
1561 * session feed.
1562 */
1563 is_timestamp = curr_first == '#' && g_ascii_isdigit(curr_word[1]);
1564 if (is_timestamp) {
dd8bec71
GS
1565 endptr = NULL;
1566 timestamp = strtoull(&curr_word[1], &endptr, 10);
1567 if (!endptr || *endptr) {
1568 sr_err("Invalid timestamp: %s.", curr_word);
1569 ret = SR_ERR_DATA;
1570 break;
1571 }
0ab36d2f 1572 sr_spew("Got timestamp: %" PRIu64, timestamp);
ec302917
GS
1573 ret = ts_stats_check(&inc->ts_stats, timestamp);
1574 if (ret != SR_OK)
1575 break;
0ab36d2f
GS
1576 if (inc->options.downsample > 1) {
1577 timestamp /= inc->options.downsample;
1578 sr_spew("Downsampled timestamp: %" PRIu64, timestamp);
1579 }
cd1b0e8f 1580
e4c8a4d7
BV
1581 /*
1582 * Skip < 0 => skip until first timestamp.
0157808d
PA
1583 * Skip = 0 => don't skip
1584 * Skip > 0 => skip until timestamp >= skip.
1585 */
0ab36d2f 1586 if (inc->options.skip_specified && !inc->use_skip) {
dd8bec71
GS
1587 sr_dbg("Seeding skip from user spec %" PRIu64,
1588 inc->options.skip_starttime);
1589 inc->prev_timestamp = inc->options.skip_starttime;
0ab36d2f
GS
1590 inc->use_skip = TRUE;
1591 }
1592 if (!inc->use_skip) {
dd8bec71 1593 sr_dbg("Seeding skip from first timestamp");
0ab36d2f 1594 inc->options.skip_starttime = timestamp;
f9bc17d4 1595 inc->prev_timestamp = timestamp;
0ab36d2f
GS
1596 inc->use_skip = TRUE;
1597 continue;
1598 }
1599 if (inc->options.skip_starttime && timestamp < inc->options.skip_starttime) {
1600 sr_spew("Timestamp skipped, before user spec");
1601 inc->prev_timestamp = inc->options.skip_starttime;
1602 continue;
1603 }
1604 if (timestamp == inc->prev_timestamp) {
1605 /*
1606 * Ignore repeated timestamps (e.g. sigrok
1607 * outputs these). Can also happen when
1608 * downsampling makes distinct input values
1609 * end up at the same scaled down value.
1610 * Also transparently covers the initial
1611 * timestamp.
1612 */
1613 sr_spew("Timestamp is identical to previous timestamp");
1614 continue;
1615 }
1616 if (timestamp < inc->prev_timestamp) {
1617 sr_err("Invalid timestamp: %" PRIu64 " (leap backwards).", timestamp);
1618 ret = SR_ERR_DATA;
ed367d68 1619 break;
0ab36d2f
GS
1620 }
1621 if (inc->options.compress) {
1622 /* Compress long idle periods */
1623 count = timestamp - inc->prev_timestamp;
1624 if (count > inc->options.compress) {
1625 sr_dbg("Long idle period, compressing");
1626 count = timestamp - inc->options.compress;
1627 inc->prev_timestamp = count;
6b7ace48 1628 }
61a429c9 1629 }
0ab36d2f
GS
1630
1631 /* Generate samples from prev_timestamp up to timestamp - 1. */
0ab36d2f 1632 count = timestamp - inc->prev_timestamp;
dd8bec71 1633 sr_spew("Got a new timestamp, feeding %zu samples", count);
0ab36d2f
GS
1634 add_samples(in, count, FALSE);
1635 inc->prev_timestamp = timestamp;
1636 inc->data_after_timestamp = FALSE;
1637 continue;
1638 }
1639 inc->data_after_timestamp = TRUE;
1640
1641 /*
1642 * Data values come in different formats, are associated
1643 * with channel identifiers, and correspond to the period
1644 * of time from the most recent timestamp to the next
1645 * timestamp.
1646 *
1647 * Supported input data formats are:
c1310f7d 1648 * - S<value> <sep> <id> (value not used, VCD type 'string').
0ab36d2f
GS
1649 * - R<value> <sep> <id> (analog channel, VCD type 'real').
1650 * - B<value> <sep> <id> (analog channel, VCD type 'integer').
1651 * - B<value> <sep> <id> (logic channels, VCD bit vectors).
1652 * - <value> <id> (logic channel, VCD single-bit values).
1653 *
1654 * Input values can be:
1655 * - Floating point numbers.
1656 * - Bit strings (which covers multi-bit aka integers
1657 * as well as vectors).
1658 * - Single bits.
1659 *
1660 * Things to note:
1661 * - Individual bits can be 0/1 which is supported by
1662 * libsigrok, or x or z which is treated like 0 here
1663 * (sigrok lacks support for ternary logic, neither is
1664 * there support for the full IEEE set of values).
1665 * - Single-bit values typically won't be separated from
1666 * the signal identifer, multi-bit values and floats
1667 * are separated (will reference the next word). This
1668 * implementation silently accepts separators for
1669 * single-bit values, too.
1670 */
1671 is_real = curr_first == 'r' && curr_word[1];
1672 is_multibit = curr_first == 'b' && curr_word[1];
1673 is_singlebit = curr_first == '0' || curr_first == '1';
35810515 1674 is_singlebit |= curr_first == 'l' || curr_first == 'h';
0ab36d2f 1675 is_singlebit |= curr_first == 'x' || curr_first == 'z';
35810515 1676 is_singlebit |= curr_first == 'u' || curr_first == '-';
c1310f7d 1677 is_string = curr_first == 's';
0ab36d2f
GS
1678 if (is_real) {
1679 char *real_text;
1680 float real_val;
1681
1682 real_text = &curr_word[1];
ec557141 1683 identifier = sr_text_next_word(line, &line);
0ab36d2f
GS
1684 if (!*real_text || !identifier || !*identifier) {
1685 sr_err("Unexpected real format.");
1686 ret = SR_ERR_DATA;
7db06394 1687 break;
8be87469 1688 }
0ab36d2f
GS
1689 sr_spew("Got real data %s for id '%s'.",
1690 real_text, identifier);
1691 if (sr_atof_ascii(real_text, &real_val) != SR_OK) {
1692 sr_err("Cannot convert value: %s.", real_text);
1693 ret = SR_ERR_DATA;
76bc28c3 1694 break;
0ab36d2f
GS
1695 }
1696 process_real(inc, identifier, real_val);
1697 continue;
1698 }
1699 if (is_multibit) {
1700 char *bits_text_start;
1701 size_t bit_count;
1702 char *bits_text, bit_char;
1703 uint8_t bit_value;
1704 uint8_t *value_ptr, value_mask;
1705 GString *bits_val_text;
1706
1707 /* TODO
1708 * Fold in single-bit code path here? To re-use
1709 * the X/Z support. Current redundancy is few so
1710 * there is little pressure to unify code paths.
1711 * Also multi-bit handling is often different
1712 * from single-bit handling, so the "unified"
1713 * path would often check for special cases. So
1714 * we may never unify code paths at all here.
34724ffa 1715 */
0ab36d2f 1716 bits_text = &curr_word[1];
ec557141 1717 identifier = sr_text_next_word(line, &line);
0ab36d2f
GS
1718
1719 if (!*bits_text || !identifier || !*identifier) {
1720 sr_err("Unexpected integer/vector format.");
1721 ret = SR_ERR_DATA;
34724ffa
WS
1722 break;
1723 }
0ab36d2f
GS
1724 sr_spew("Got integer/vector data %s for id '%s'.",
1725 bits_text, identifier);
7db06394
BV
1726
1727 /*
0ab36d2f
GS
1728 * Accept a bit string of arbitrary length (sort
1729 * of, within the limits of the previously setup
1730 * conversion buffer). The input text omits the
1731 * leading zeroes, hence we convert from end to
1732 * the start, to get the significant bits. There
1733 * should only be errors for invalid input, or
1734 * for input that is rather strange (data holds
1735 * more bits than the signal's declaration in
1736 * the header suggested). Silently accept data
1737 * that fits in the conversion buffer, and has
1738 * more significant bits than the signal's type
1739 * (that'd be non-sence yet acceptable input).
7db06394 1740 */
0ab36d2f
GS
1741 bits_text_start = bits_text;
1742 bits_text += strlen(bits_text);
1743 bit_count = bits_text - bits_text_start;
1744 if (bit_count > inc->conv_bits.max_bits) {
1745 sr_err("Value exceeds conversion buffer: %s",
1746 bits_text_start);
1747 ret = SR_ERR_DATA;
1748 break;
1749 }
1750 memset(inc->conv_bits.value, 0, inc->conv_bits.unit_size);
1751 value_ptr = &inc->conv_bits.value[0];
1752 value_mask = 1 << 0;
1753 inc->conv_bits.sig_count = 0;
1754 while (bits_text > bits_text_start) {
1755 inc->conv_bits.sig_count++;
1756 bit_char = *(--bits_text);
1757 bit_value = vcd_char_to_value(bit_char, NULL);
1758 if (bit_value == 0) {
1759 /* EMPTY */
1760 } else if (bit_value == 1) {
1761 *value_ptr |= value_mask;
1762 } else {
1763 inc->conv_bits.sig_count = 0;
73f052d3
WS
1764 break;
1765 }
0ab36d2f
GS
1766 value_mask <<= 1;
1767 if (!value_mask) {
1768 value_ptr++;
1769 value_mask = 1 << 0;
1770 }
61a429c9 1771 }
0ab36d2f
GS
1772 if (!inc->conv_bits.sig_count) {
1773 sr_err("Unexpected vector format: %s",
1774 bits_text_start);
1775 ret = SR_ERR_DATA;
1776 break;
1777 }
1778 if (sr_log_loglevel_get() >= SR_LOG_SPEW) {
1779 bits_val_text = sr_hexdump_new(inc->conv_bits.value,
1780 value_ptr - inc->conv_bits.value + 1);
1781 sr_spew("Vector value: %s.", bits_val_text->str);
1782 sr_hexdump_free(bits_val_text);
1783 }
1784
1785 process_bits(inc, identifier,
1786 inc->conv_bits.value, inc->conv_bits.sig_count);
1787 continue;
8be87469 1788 }
0ab36d2f
GS
1789 if (is_singlebit) {
1790 char *bits_text, bit_char;
1791 uint8_t bit_value;
1792
1793 /* Get the value text, and signal identifier. */
1794 bits_text = &curr_word[0];
1795 bit_char = *bits_text;
1796 if (!bit_char) {
1797 sr_err("Bit value missing.");
1798 ret = SR_ERR_DATA;
1799 break;
1800 }
1801 identifier = ++bits_text;
ec557141
GS
1802 if (!*identifier)
1803 identifier = sr_text_next_word(line, &line);
0ab36d2f
GS
1804 if (!identifier || !*identifier) {
1805 sr_err("Identifier missing.");
1806 ret = SR_ERR_DATA;
1807 break;
1808 }
1809
1810 /* Convert value text to single-bit number. */
1811 bit_value = vcd_char_to_value(bit_char, NULL);
1812 if (bit_value != 0 && bit_value != 1) {
1813 sr_err("Unsupported bit value '%c'.", bit_char);
1814 ret = SR_ERR_DATA;
1815 break;
1816 }
1817 inc->conv_bits.value[0] = bit_value;
1818 process_bits(inc, identifier, inc->conv_bits.value, 1);
1819 continue;
1820 }
c1310f7d
GS
1821 if (is_string) {
1822 const char *str_value;
1823
1824 str_value = &curr_word[1];
ec557141 1825 identifier = sr_text_next_word(line, &line);
c1310f7d
GS
1826 if (!vcd_string_valid(str_value)) {
1827 sr_err("Invalid string data: %s", str_value);
1828 ret = SR_ERR_DATA;
1829 break;
1830 }
1831 if (!identifier || !*identifier) {
1832 sr_err("String value without identifier.");
1833 ret = SR_ERR_DATA;
1834 break;
1835 }
1836 sr_spew("Got string data, id '%s', value \"%s\".",
1837 identifier, str_value);
1838 if (!is_ignored(inc, identifier)) {
1839 sr_err("String value for identifier '%s'.",
1840 identifier);
1841 ret = SR_ERR_DATA;
1842 break;
1843 }
1844 continue;
1845 }
0ab36d2f
GS
1846
1847 /* Design choice: Consider unsupported input fatal. */
1848 sr_err("Unknown token '%s'.", curr_word);
1849 ret = SR_ERR_DATA;
1850 break;
7db06394 1851 }
0ab36d2f
GS
1852
1853 return ret;
7db06394
BV
1854}
1855
0ab36d2f 1856static int process_buffer(struct sr_input *in, gboolean is_eof)
7db06394 1857{
7db06394 1858 struct context *inc;
0ab36d2f
GS
1859 uint64_t samplerate;
1860 GVariant *gvar;
1861 int ret;
ec557141
GS
1862 char *rdptr, *line;
1863 size_t taken, rdlen;
7db06394 1864
0ab36d2f 1865 inc = in->priv;
cd1b0e8f 1866
93a28f0b
GS
1867 if (!inc->got_header)
1868 return SR_ERR_DATA;
1869
0ab36d2f
GS
1870 /* Send feed header and samplerate (once) before sample data. */
1871 if (!inc->started) {
1872 std_session_send_df_header(in->sdi);
7db06394 1873
0ab36d2f
GS
1874 samplerate = inc->samplerate / inc->options.downsample;
1875 if (samplerate) {
1876 gvar = g_variant_new_uint64(samplerate);
1877 sr_session_send_meta(in->sdi, SR_CONF_SAMPLERATE, gvar);
1878 }
7db06394 1879
0ab36d2f
GS
1880 inc->started = TRUE;
1881 }
7db06394 1882
0ab36d2f
GS
1883 /*
1884 * Workaround broken generators which output incomplete text
1885 * lines. Enforce the trailing line feed. Proper input is not
1886 * harmed by another empty line of input data.
1887 */
1888 if (is_eof)
1889 g_string_append_c(in->buf, '\n');
1890
1891 /* Find and process complete text lines in the input data. */
1892 ret = SR_OK;
1893 rdptr = in->buf->str;
ec557141
GS
1894 taken = 0;
1895 while (rdptr) {
0ab36d2f 1896 rdlen = &in->buf->str[in->buf->len] - rdptr;
ec557141
GS
1897 line = sr_text_next_line(rdptr, rdlen, &rdptr, &taken);
1898 if (!line)
0ab36d2f 1899 break;
ec557141 1900 if (!*line)
0ab36d2f 1901 continue;
ec557141 1902 ret = parse_textline(in, line);
0ab36d2f
GS
1903 if (ret != SR_OK)
1904 break;
1905 }
ec557141 1906 g_string_erase(in->buf, 0, taken);
db0e5c99 1907
0ab36d2f 1908 return ret;
61a429c9
PA
1909}
1910
0ab36d2f 1911static int format_match(GHashTable *metadata, unsigned int *confidence)
7db06394 1912{
0ab36d2f
GS
1913 GString *buf, *tmpbuf;
1914 gboolean status;
1915 char *name, *contents;
7db06394 1916
0ab36d2f
GS
1917 buf = g_hash_table_lookup(metadata,
1918 GINT_TO_POINTER(SR_INPUT_META_HEADER));
1919 tmpbuf = g_string_new_len(buf->str, buf->len);
1920
1921 /*
1922 * If we can parse the first section correctly, then it is
1923 * assumed that the input is in VCD format.
1924 */
1925 check_remove_bom(tmpbuf);
1926 status = parse_section(tmpbuf, &name, &contents);
1927 g_string_free(tmpbuf, TRUE);
1928 g_free(name);
1929 g_free(contents);
1930
1931 if (!status)
1932 return SR_ERR;
7db06394 1933
0ab36d2f
GS
1934 *confidence = 1;
1935 return SR_OK;
7db06394
BV
1936}
1937
0ab36d2f 1938static int init(struct sr_input *in, GHashTable *options)
99eaa206 1939{
7db06394 1940 struct context *inc;
0ab36d2f 1941 GVariant *data;
7db06394 1942
0ab36d2f 1943 inc = g_malloc0(sizeof(*inc));
99eaa206 1944
0ab36d2f
GS
1945 data = g_hash_table_lookup(options, "numchannels");
1946 inc->options.maxchannels = g_variant_get_uint32(data);
d0181813 1947
0ab36d2f
GS
1948 data = g_hash_table_lookup(options, "downsample");
1949 inc->options.downsample = g_variant_get_uint64(data);
1950 if (inc->options.downsample < 1)
1951 inc->options.downsample = 1;
99eaa206 1952
0ab36d2f
GS
1953 data = g_hash_table_lookup(options, "compress");
1954 inc->options.compress = g_variant_get_uint64(data);
1955 inc->options.compress /= inc->options.downsample;
1956
1957 data = g_hash_table_lookup(options, "skip");
1958 if (data) {
1959 inc->options.skip_specified = TRUE;
1960 inc->options.skip_starttime = g_variant_get_uint64(data);
dd8bec71
GS
1961 if (inc->options.skip_starttime == ~UINT64_C(0)) {
1962 inc->options.skip_specified = FALSE;
1963 inc->options.skip_starttime = 0;
1964 }
0ab36d2f 1965 inc->options.skip_starttime /= inc->options.downsample;
7db06394 1966 }
99eaa206 1967
0ab36d2f
GS
1968 in->sdi = g_malloc0(sizeof(*in->sdi));
1969 in->priv = inc;
1970
1971 inc->scope_prefix = g_string_new("\0");
1972
7db06394
BV
1973 return SR_OK;
1974}
cd1b0e8f 1975
7066fd46
BV
1976static int receive(struct sr_input *in, GString *buf)
1977{
1978 struct context *inc;
1979 int ret;
1980
0ab36d2f
GS
1981 inc = in->priv;
1982
1983 /* Collect all input chunks, potential deferred processing. */
7066fd46 1984 g_string_append_len(in->buf, buf->str, buf->len);
0ab36d2f
GS
1985 if (!inc->got_header && in->buf->len == buf->len)
1986 check_remove_bom(in->buf);
7066fd46 1987
0ab36d2f 1988 /* Must complete reception of the VCD header first. */
7066fd46
BV
1989 if (!inc->got_header) {
1990 if (!have_header(in->buf))
1991 return SR_OK;
0ab36d2f
GS
1992 ret = parse_header(in, in->buf);
1993 if (ret != SR_OK)
1994 return ret;
7066fd46 1995 /* sdi is ready, notify frontend. */
0ab36d2f 1996 in->sdi_ready = TRUE;
7066fd46
BV
1997 return SR_OK;
1998 }
1999
0ab36d2f
GS
2000 /* Process sample data. */
2001 ret = process_buffer(in, FALSE);
7066fd46
BV
2002
2003 return ret;
2004}
2005
2006static int end(struct sr_input *in)
7db06394
BV
2007{
2008 struct context *inc;
7066fd46 2009 int ret;
0ab36d2f 2010 size_t count;
7066fd46 2011
db0e5c99
PA
2012 inc = in->priv;
2013
0ab36d2f 2014 /* Must complete processing of previously received chunks. */
7066fd46 2015 if (in->sdi_ready)
0ab36d2f 2016 ret = process_buffer(in, TRUE);
7066fd46
BV
2017 else
2018 ret = SR_OK;
99eaa206 2019
0ab36d2f 2020 /* Flush most recently queued sample data when EOF is seen. */
93a28f0b
GS
2021 if (inc->got_header && ret == SR_OK) {
2022 count = inc->data_after_timestamp ? 1 : 0;
2023 add_samples(in, count, TRUE);
2024 }
db0e5c99 2025
ec302917 2026 /* Optionally suggest downsampling after all input data was seen. */
93a28f0b
GS
2027 if (inc->got_header)
2028 (void)ts_stats_post(inc, !inc->data_after_timestamp);
ec302917 2029
0ab36d2f 2030 /* Must send DF_END when DF_HEADER was sent before. */
3be42bc2 2031 if (inc->started)
bee2b016 2032 std_session_send_df_end(in->sdi);
c10ef17c 2033
7066fd46
BV
2034 return ret;
2035}
2036
d5cc282f 2037static void cleanup(struct sr_input *in)
7066fd46
BV
2038{
2039 struct context *inc;
2040
2041 inc = in->priv;
0ab36d2f 2042
08f8421a 2043 keep_header_for_reread(in);
0ab36d2f 2044
7db06394 2045 g_slist_free_full(inc->channels, free_channel);
4237ab9e 2046 inc->channels = NULL;
0ab36d2f
GS
2047 feed_queue_logic_free(inc->feed_logic);
2048 inc->feed_logic = NULL;
2049 g_free(inc->conv_bits.value);
2050 inc->conv_bits.value = NULL;
2051 g_free(inc->current_logic);
2052 inc->current_logic = NULL;
2053 g_free(inc->current_floats);
2054 inc->current_floats = NULL;
2055 g_string_free(inc->scope_prefix, TRUE);
2056 inc->scope_prefix = NULL;
2057 g_slist_free_full(inc->ignored_signals, g_free);
2058 inc->ignored_signals = NULL;
99eaa206
PA
2059}
2060
f4b4725b
SA
2061static int reset(struct sr_input *in)
2062{
0ab36d2f
GS
2063 struct context *inc;
2064 struct vcd_user_opt save;
2065 struct vcd_prev prev;
2066
2067 inc = in->priv;
f4b4725b 2068
0ab36d2f 2069 /* Relase previously allocated resources. */
f4b4725b 2070 cleanup(in);
f4b4725b
SA
2071 g_string_truncate(in->buf, 0);
2072
0ab36d2f
GS
2073 /* Restore part of the context, init() won't run again. */
2074 save = inc->options;
2075 prev = inc->prev;
2076 memset(inc, 0, sizeof(*inc));
2077 inc->options = save;
2078 inc->prev = prev;
2079 inc->scope_prefix = g_string_new("\0");
4237ab9e 2080
f4b4725b
SA
2081 return SR_OK;
2082}
2083
0ab36d2f
GS
2084enum vcd_option_t {
2085 OPT_NUM_CHANS,
2086 OPT_DOWN_SAMPLE,
2087 OPT_SKIP_COUNT,
2088 OPT_COMPRESS,
2089 OPT_MAX,
2090};
2091
7db06394 2092static struct sr_option options[] = {
0ab36d2f
GS
2093 [OPT_NUM_CHANS] = {
2094 "numchannels", "Max number of sigrok channels",
2095 "The maximum number of sigrok channels to create for VCD input signals.",
2096 NULL, NULL,
2097 },
2098 [OPT_DOWN_SAMPLE] = {
2099 "downsample", "Downsampling factor",
2100 "Downsample the input file's samplerate, i.e. divide by the specified factor.",
2101 NULL, NULL,
2102 },
2103 [OPT_SKIP_COUNT] = {
2104 "skip", "Skip this many initial samples",
2105 "Skip samples until the specified timestamp. "
2106 "By default samples start at the first timestamp in the file. "
2107 "Value 0 creates samples starting at timestamp 0. "
2108 "Values above 0 only start processing at the given timestamp.",
2109 NULL, NULL,
2110 },
2111 [OPT_COMPRESS] = {
2112 "compress", "Compress idle periods",
2113 "Compress idle periods which are longer than the specified number of timescale ticks.",
2114 NULL, NULL,
2115 },
2116 [OPT_MAX] = ALL_ZERO,
7db06394
BV
2117};
2118
2c240774 2119static const struct sr_option *get_options(void)
7db06394
BV
2120{
2121 if (!options[0].def) {
0ab36d2f
GS
2122 options[OPT_NUM_CHANS].def = g_variant_ref_sink(g_variant_new_uint32(0));
2123 options[OPT_DOWN_SAMPLE].def = g_variant_ref_sink(g_variant_new_uint64(1));
dd8bec71 2124 options[OPT_SKIP_COUNT].def = g_variant_ref_sink(g_variant_new_uint64(~UINT64_C(0)));
0ab36d2f 2125 options[OPT_COMPRESS].def = g_variant_ref_sink(g_variant_new_uint64(0));
7db06394
BV
2126 }
2127
2128 return options;
2129}
2130
d4c93774 2131SR_PRIV struct sr_input_module input_vcd = {
99eaa206 2132 .id = "vcd",
7db06394 2133 .name = "VCD",
b20eb520 2134 .desc = "Value Change Dump data",
c7bc82ff 2135 .exts = (const char*[]){"vcd", NULL},
7db06394
BV
2136 .metadata = { SR_INPUT_META_HEADER | SR_INPUT_META_REQUIRED },
2137 .options = get_options,
99eaa206
PA
2138 .format_match = format_match,
2139 .init = init,
7db06394 2140 .receive = receive,
7066fd46 2141 .end = end,
7db06394 2142 .cleanup = cleanup,
f4b4725b 2143 .reset = reset,
99eaa206 2144};