asix-sigma: eliminate magic numbers in sample memory access

Add more symbolic identifiers, and rename some of the existing names for
access to SIGMA sample memory. This eliminates magic numbers and reduces
redundancy and potential for errors during maintenance.

This commit also concentrates DRAM layout related declarations in the
header file in a single location, which previously were scattered, and
separated registers from their respective bit fields.

Extend comments on the difference of events versus sample data.
This commit is contained in:
Gerhard Sittig 2020-05-09 20:23:23 +02:00
parent 7c41c420aa
commit 2c33b09255
2 changed files with 56 additions and 38 deletions

View File

@ -163,6 +163,14 @@ static int sigma_read_pos(uint32_t *stoppos, uint32_t *triggerpos,
* chunks with meta data in the upper 64 bytes. Thus when the * chunks with meta data in the upper 64 bytes. Thus when the
* decrements takes us into this upper part of the chunk, then * decrements takes us into this upper part of the chunk, then
* further move backwards to the end of the chunk's data part. * further move backwards to the end of the chunk's data part.
*
* TODO Re-consider the above comment's validity. It's true
* that a 1024byte row contains 512 u16 entities, of which 64
* are timestamps and 448 are events with sample data. It's not
* true that 64bytes of metadata reside at the top of a 512byte
* block in a row.
*
* TODO Use ROW_MASK and CLUSTERS_PER_ROW here?
*/ */
if ((--*stoppos & 0x1ff) == 0x1ff) if ((--*stoppos & 0x1ff) == 0x1ff)
*stoppos -= 64; *stoppos -= 64;
@ -206,7 +214,7 @@ static int sigma_read_dram(uint16_t startchunk, size_t numchunks,
} }
sigma_write(buf, idx, devc); sigma_write(buf, idx, devc);
return sigma_read(data, numchunks * CHUNK_SIZE, devc); return sigma_read(data, numchunks * ROW_LENGTH_BYTES, devc);
} }
/* Upload trigger look-up tables to Sigma. */ /* Upload trigger look-up tables to Sigma. */
@ -859,11 +867,11 @@ static void sigma_session_send(struct sr_dev_inst *sdi,
} }
/* /*
* This size translates to: event count (1K events per cluster), times * This size translates to: number of events per row (strictly speaking
* the sample width (unitsize, 16bits per event), times the maximum * 448, assuming "up to 512" does not harm here) times the sample data's
* number of samples per event. * unit size (16 bits), times the maximum number of samples per event (4).
*/ */
#define SAMPLES_BUFFER_SIZE (1024 * 2 * 4) #define SAMPLES_BUFFER_SIZE (ROW_LENGTH_U16 * sizeof(uint16_t) * 4)
static void sigma_decode_dram_cluster(struct sigma_dram_cluster *dram_cluster, static void sigma_decode_dram_cluster(struct sigma_dram_cluster *dram_cluster,
unsigned int events_in_cluster, unsigned int events_in_cluster,
@ -894,6 +902,13 @@ static void sigma_decode_dram_cluster(struct sigma_dram_cluster *dram_cluster,
* If this cluster is not adjacent to the previously received * If this cluster is not adjacent to the previously received
* cluster, then send the appropriate number of samples with the * cluster, then send the appropriate number of samples with the
* previous values to the sigrok session. This "decodes RLE". * previous values to the sigrok session. This "decodes RLE".
*
* TODO Improve (mostly: generalize) support for queueing data
* before submission to the session bus. This implementation
* happens to work for "up to 1024 samples" despite the "up to
* 512 entities of 16 bits", due to the "up to 4 sample points
* per event" factor. A better implementation would eliminate
* these magic numbers.
*/ */
for (ts = 0; ts < tsdiff; ts++) { for (ts = 0; ts < tsdiff; ts++) {
i = ts % 1024; i = ts % 1024;
@ -1016,7 +1031,7 @@ static int decode_chunk_ts(struct sigma_dram_line *dram_line,
triggered = 0; triggered = 0;
/* Check if trigger is in this chunk. */ /* Check if trigger is in this chunk. */
if (trigger_event < (64 * 7)) { if (trigger_event < EVENTS_PER_ROW) {
if (devc->cur_samplerate <= SR_MHZ(50)) { if (devc->cur_samplerate <= SR_MHZ(50)) {
trigger_event -= MIN(EVENTS_PER_CLUSTER - 1, trigger_event -= MIN(EVENTS_PER_CLUSTER - 1,
trigger_event); trigger_event);
@ -1062,7 +1077,7 @@ static int download_capture(struct sr_dev_inst *sdi)
uint32_t trg_line, trg_event; uint32_t trg_line, trg_event;
devc = sdi->priv; devc = sdi->priv;
dl_events_in_line = 64 * 7; dl_events_in_line = EVENTS_PER_ROW;
sr_info("Downloading sample data."); sr_info("Downloading sample data.");
devc->state.state = SIGMA_DOWNLOAD; devc->state.state = SIGMA_DOWNLOAD;
@ -1109,15 +1124,13 @@ static int download_capture(struct sr_dev_inst *sdi)
* *
* When RMR_ROUND is set, the circular buffer in DRAM has wrapped * When RMR_ROUND is set, the circular buffer in DRAM has wrapped
* around. Since the status of the very next line is uncertain in * around. Since the status of the very next line is uncertain in
* that case, we skip it and start reading from the next line. The * that case, we skip it and start reading from the next line.
* circular buffer has 32K lines (0x8000).
*/ */
dl_lines_total = (stoppos >> 9) + 1; dl_first_line = 0;
dl_lines_total = (stoppos >> ROW_SHIFT) + 1;
if (modestatus & RMR_ROUND) { if (modestatus & RMR_ROUND) {
dl_first_line = dl_lines_total + 1; dl_first_line = dl_lines_total + 1;
dl_lines_total = 0x8000 - 2; dl_lines_total = ROW_COUNT - 2;
} else {
dl_first_line = 0;
} }
dram_line = g_try_malloc0(chunks_per_read * sizeof(*dram_line)); dram_line = g_try_malloc0(chunks_per_read * sizeof(*dram_line));
if (!dram_line) if (!dram_line)
@ -1128,7 +1141,7 @@ static int download_capture(struct sr_dev_inst *sdi)
dl_lines_curr = MIN(chunks_per_read, dl_lines_total - dl_lines_done); dl_lines_curr = MIN(chunks_per_read, dl_lines_total - dl_lines_done);
dl_line = dl_first_line + dl_lines_done; dl_line = dl_first_line + dl_lines_done;
dl_line %= 0x8000; dl_line %= ROW_COUNT;
bufsz = sigma_read_dram(dl_line, dl_lines_curr, bufsz = sigma_read_dram(dl_line, dl_lines_curr,
(uint8_t *)dram_line, devc); (uint8_t *)dram_line, devc);
/* TODO: Check bufsz. For now, just avoid compiler warnings. */ /* TODO: Check bufsz. For now, just avoid compiler warnings. */

View File

@ -126,11 +126,6 @@ enum sigma_read_register {
#define LEDSEL0 6 #define LEDSEL0 6
#define LEDSEL1 7 #define LEDSEL1 7
#define EVENTS_PER_CLUSTER 7
#define CHUNK_SIZE 1024
/* WRITE_MODE register fields. */ /* WRITE_MODE register fields. */
#define WMR_SDRAMWRITEEN (1 << 0) #define WMR_SDRAMWRITEEN (1 << 0)
#define WMR_SDRAMREADEN (1 << 1) #define WMR_SDRAMREADEN (1 << 1)
@ -155,8 +150,16 @@ enum sigma_read_register {
* Layout of the sample data DRAM, which will be downloaded to the PC: * Layout of the sample data DRAM, which will be downloaded to the PC:
* *
* Sigma memory is organized in 32K rows. Each row contains 64 clusters. * Sigma memory is organized in 32K rows. Each row contains 64 clusters.
* Each cluster contains a timestamp (16bit) and 7 samples (16bits each). * Each cluster contains a timestamp (16bit) and 7 events (16bits each).
* Total memory size is 32K x 64 x 8 x 2 bytes == 32 MB (256 Mbit). * Events contain 16 bits of sample data (potentially taken at multiple
* sample points, see below).
*
* Total memory size is 32K x 64 x 8 x 2 bytes == 32 MiB (256 Mbit). The
* size of a memory row is 1024 bytes. Assuming x16 organization of the
* memory array, address specs (sample count, trigger position) are kept
* in 24bit entities. The upper 15 bit address the "row", the lower 9 bit
* refer to the "event" within the row. Because there is one timestamp for
* seven events each, one memory row can hold up to 64x7 == 448 events.
* *
* Sample data is represented in 16bit quantities. The first sample in * Sample data is represented in 16bit quantities. The first sample in
* the cluster corresponds to the cluster's timestamp. Each next sample * the cluster corresponds to the cluster's timestamp. Each next sample
@ -164,33 +167,35 @@ enum sigma_read_register {
* one sample period, according to the samplerate). In the absence of * one sample period, according to the samplerate). In the absence of
* pin level changes, no data is provided (RLE compression). A cluster * pin level changes, no data is provided (RLE compression). A cluster
* is enforced for each 64K ticks of the timestamp, to reliably handle * is enforced for each 64K ticks of the timestamp, to reliably handle
* rollover and determination of the next timestamp of the next cluster. * rollover and determine the next timestamp of the next cluster.
* *
* For samplerates up to 50MHz, an event directly translates to one set
* of sample data at a single sample point, spanning up to 16 channels.
* For samplerates of 100MHz, there is one 16 bit entity for each 20ns * For samplerates of 100MHz, there is one 16 bit entity for each 20ns
* period (50MHz rate). The 16 bit memory contains 2 samples of up to * period (50MHz rate). The 16 bit memory contains 2 samples of up to
* 8 channels. Bits of multiple samples are interleaved. For samplerates * 8 channels. Bits of multiple samples are interleaved. For samplerates
* of 200MHz one 16bit entity contains 4 samples of up to 4 channels, * of 200MHz one 16bit entity contains 4 samples of up to 4 channels,
* each 5ns apart. * each 5ns apart.
*
* Memory addresses (sample count, trigger position) are kept in 24bit
* entities. The upper 15 bit refer to the "row", the lower 9 bit refer
* to the "event" within the row. Because there is one timestamp for
* seven samples each, one memory row can hold up to 64x7 == 448 samples.
*/ */
/* One "DRAM cluster" contains a timestamp and 7 samples, 16b total. */ #define ROW_COUNT 32768
struct sigma_dram_cluster { #define ROW_LENGTH_BYTES 1024
uint8_t timestamp_lo; #define ROW_LENGTH_U16 (ROW_LENGTH_BYTES / sizeof(uint16_t))
uint8_t timestamp_hi; #define ROW_SHIFT 9 /* log2 of u16 count */
struct { #define ROW_MASK ((1UL << ROW_SHIFT) - 1)
uint8_t sample_hi; #define EVENTS_PER_CLUSTER 7
uint8_t sample_lo; #define CLUSTERS_PER_ROW (ROW_LENGTH_U16 / (1 + EVENTS_PER_CLUSTER))
} samples[7]; #define EVENTS_PER_ROW (CLUSTERS_PER_ROW * EVENTS_PER_CLUSTER)
};
/* One "DRAM line" contains 64 "DRAM clusters", 1024b total. */
struct sigma_dram_line { struct sigma_dram_line {
struct sigma_dram_cluster cluster[64]; struct sigma_dram_cluster {
uint8_t timestamp_lo;
uint8_t timestamp_hi;
struct sigma_dram_event {
uint8_t sample_hi;
uint8_t sample_lo;
} samples[EVENTS_PER_CLUSTER];
} cluster[CLUSTERS_PER_ROW];
}; };
struct clockselect_50 { struct clockselect_50 {