Add downsample and skip parameters to input/vcd.

This commit is contained in:
Petteri Aimonen 2012-11-21 16:28:55 +02:00 committed by Uwe Hermann
parent 61a429c963
commit 0157808d74
1 changed files with 85 additions and 13 deletions

View File

@ -1,7 +1,7 @@
/* /*
* This file is part of the sigrok project. * This file is part of the sigrok project.
* *
* Copyright (C) 2010-2012 Bert Vermeulen <bert@biot.com> * Copyright (C) 2012 Petteri Aimonen <jpa@sr.mail.kapsi.fi>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -17,7 +17,40 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
/* Based on Verilog standard IEEE Std 1364-2001 Version C */ /* The VCD input module has the following options:
*
* numprobes: Maximum number of probes to use. The probes are
* detected in the same order as they are listed
* in the $var sections of the VCD file.
*
* skip: Allows skipping until given timestamp in the file.
* This can speed up analyzing of long captures.
*
* Value < 0: Skip until first timestamp listed in
* the file. (default)
*
* Value = 0: Do not skip, instead generate samples
* beginning from timestamp 0.
*
* Value > 0: Start at the given timestamp.
*
* downsample: Divide the samplerate by the given factor.
* This can speed up analyzing of long captures.
*
* Based on Verilog standard IEEE Std 1364-2001 Version C
*
* Supported features:
* - $var with 'wire' and 'reg' types of scalar variables
* - $timescale definition for samplerate
* - multiple character variable identifiers
*
* Most important unsupported features:
* - vector variables (bit vectors etc.)
* - analog, integer and real number variables
* - $dumpvars initial value declaration
*/
/* */
#include <stdlib.h> #include <stdlib.h>
#include <glib.h> #include <glib.h>
@ -131,6 +164,8 @@ struct context
uint64_t samplerate; uint64_t samplerate;
int maxprobes; int maxprobes;
int probecount; int probecount;
int downsample;
int64_t skip;
struct probe probes[SR_MAX_NUM_PROBES]; struct probe probes[SR_MAX_NUM_PROBES];
}; };
@ -192,7 +227,7 @@ static gboolean parse_header(FILE *file, struct context *ctx)
if (period.q % period.p != 0) if (period.q % period.p != 0)
{ {
/* Does not happen unless time value is non-standard */ /* Does not happen unless time value is non-standard */
sr_warn("Inexact rounding of samplerate, %" PRIu64 " / %" PRIu64 " to %" PRIu64 ".", sr_warn("Inexact rounding of samplerate, %" PRIu64 " / %" PRIu64 " to %" PRIu64 " Hz.",
period.q, period.p, ctx->samplerate); period.q, period.p, ctx->samplerate);
} }
@ -284,6 +319,8 @@ static int init(struct sr_input *in)
num_probes = DEFAULT_NUM_PROBES; num_probes = DEFAULT_NUM_PROBES;
ctx->samplerate = 0; ctx->samplerate = 0;
ctx->downsample = 1;
ctx->skip = -1;
if (in->param) { if (in->param) {
param = g_hash_table_lookup(in->param, "numprobes"); param = g_hash_table_lookup(in->param, "numprobes");
@ -295,6 +332,20 @@ static int init(struct sr_input *in)
return SR_ERR; return SR_ERR;
} }
} }
param = g_hash_table_lookup(in->param, "downsample");
if (param) {
ctx->downsample = strtoul(param, NULL, 10);
if (ctx->downsample < 1)
{
ctx->downsample = 1;
}
}
param = g_hash_table_lookup(in->param, "skip");
if (param) {
ctx->skip = strtoul(param, NULL, 10) / ctx->downsample;
}
} }
/* Maximum number of probes to parse from the VCD */ /* Maximum number of probes to parse from the VCD */
@ -360,8 +411,8 @@ static void parse_contents(FILE *file, const struct sr_dev_inst *sdi, struct con
{ {
GString *token = g_string_sized_new(32); GString *token = g_string_sized_new(32);
gboolean first = TRUE;
uint64_t prev_timestamp = 0; uint64_t prev_timestamp = 0;
uint64_t new_values = 0;
uint64_t prev_values = 0; uint64_t prev_values = 0;
/* Read one space-delimited token at a time. */ /* Read one space-delimited token at a time. */
@ -373,19 +424,40 @@ static void parse_contents(FILE *file, const struct sr_dev_inst *sdi, struct con
uint64_t timestamp; uint64_t timestamp;
timestamp = strtoull(token->str + 1, NULL, 10); timestamp = strtoull(token->str + 1, NULL, 10);
if (first) if (ctx->downsample > 1)
timestamp /= ctx->downsample;
/* Skip < 0 => skip until first timestamp.
* Skip = 0 => don't skip
* Skip > 0 => skip until timestamp >= skip.
*/
if (ctx->skip < 0)
{ {
first = FALSE; ctx->skip = timestamp;
}
else if (ctx->skip > 0 && timestamp < (uint64_t)ctx->skip)
{
prev_timestamp = ctx->skip - 1;
}
else if (timestamp == prev_timestamp)
{
/* This only occurs when ctx->downsample > 1 */
if (prev_values != new_values)
{
sr_warn("VCD downsampling hides a glitch at %" PRIu64, timestamp);
prev_values = new_values;
}
} }
else else
{ {
sr_dbg("New timestamp: %" PRIu64, timestamp); sr_dbg("New timestamp: %" PRIu64, timestamp);
/* Generate samples from prev_timestamp up to timestamp - 1. */ /* Generate samples from prev_timestamp up to timestamp - 1. */
send_samples(sdi, prev_values, timestamp - prev_timestamp); send_samples(sdi, new_values, timestamp - prev_timestamp);
}
prev_timestamp = timestamp; prev_timestamp = timestamp;
prev_values = new_values;
}
} }
else if (token->str[0] == '$') else if (token->str[0] == '$')
{ {
@ -417,9 +489,9 @@ static void parse_contents(FILE *file, const struct sr_dev_inst *sdi, struct con
/* Found our probe */ /* Found our probe */
if (bit) if (bit)
prev_values |= (1 << i); new_values |= (1 << i);
else else
prev_values &= ~(1 << i); new_values &= ~(1 << i);
break; break;
} }
@ -467,7 +539,7 @@ static int loadfile(struct sr_input *in, const char *filename)
/* Send metadata about the SR_DF_LOGIC packets to come. */ /* Send metadata about the SR_DF_LOGIC packets to come. */
packet.type = SR_DF_META_LOGIC; packet.type = SR_DF_META_LOGIC;
packet.payload = &meta; packet.payload = &meta;
meta.samplerate = ctx->samplerate; meta.samplerate = ctx->samplerate / ctx->downsample;
meta.num_probes = ctx->probecount; meta.num_probes = ctx->probecount;
sr_session_send(in->sdi, &packet); sr_session_send(in->sdi, &packet);