Skip to content

Commit e829f2b

Browse files
author
ga
committed
Add a new tracing option, AVR_MMCU_TAG_VCD_IO_IRQ, that allows
any Input/Output IRQ to be logged in a VCD file. Make it available in run_avr. Also add a new macro, AVR_MCU_VCD_REGISTER_BIT(), to simplify the tracing of peripheral register bits. Use these in atmega88_example.c, fixing the broken trace file reported in Bug #486 - "Unable to reproduce tests/atmega88_example.axf results" as an alternative to PR #547 - "bugfix: Fix Test VCD Output".
1 parent ba29825 commit e829f2b

File tree

5 files changed

+87
-17
lines changed

5 files changed

+87
-17
lines changed

simavr/sim/avr/avr_mcu_section.h

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ enum {
6464
AVR_MMCU_TAG_VCD_IRQ,
6565
AVR_MMCU_TAG_VCD_SRAM_8,
6666
AVR_MMCU_TAG_VCD_SRAM_16,
67+
AVR_MMCU_TAG_VCD_IO_IRQ,
6768
AVR_MMCU_TAG_PORT_EXTERNAL_PULL,
6869
};
6970

@@ -109,6 +110,14 @@ struct avr_mmcu_vcd_trace_t {
109110
char name[32];
110111
} __attribute__((__packed__));
111112

113+
struct avr_mmcu_vcd_ioirq_t {
114+
uint8_t tag;
115+
uint8_t len;
116+
uint8_t irqno;
117+
char ioctl[5]; // Allow for null in string initialiser.
118+
char name[32];
119+
} __attribute__((__packed__));
120+
112121
#define AVR_MCU_STRING(_tag, _str) \
113122
const struct avr_mmcu_string_t _##_tag _MMCU_ = {\
114123
.tag = _tag,\
@@ -122,6 +131,7 @@ struct avr_mmcu_vcd_trace_t {
122131
*/
123132
#define DO_CONCAT2(_a, _b) _a##_b
124133
#define DO_CONCAT(_a, _b) DO_CONCAT2(_a,_b)
134+
#define STRINGIFY(_a) #_a
125135

126136
#define AVR_MCU_LONG(_tag, _val) \
127137
const struct avr_mmcu_long_t DO_CONCAT(DO_CONCAT(_, _tag), __LINE__) _MMCU_ = {\
@@ -151,6 +161,25 @@ struct avr_mmcu_vcd_trace_t {
151161
.len = sizeof(struct avr_mmcu_vcd_trace_t) - 2,\
152162
.name = _name
153163

164+
/*!
165+
* Independent macro to trace a bit in an I/O register.
166+
*/
167+
168+
#define AVR_MCU_VCD_REGISTER_BIT(_register, _bit) \
169+
const struct avr_mmcu_vcd_trace_t \
170+
DO_CONCAT(_REGBIT_##_register##_##_bit##_, __LINE__) _MMCU_ = { \
171+
.tag = AVR_MMCU_TAG_VCD_TRACE, \
172+
.len = sizeof(struct avr_mmcu_vcd_trace_t) - 2, \
173+
.mask = (1 << _bit), \
174+
.what = (void*)&_register, \
175+
.name = STRINGIFY(_register##_##_bit), \
176+
}
177+
/*DO_CONCAT(DO_CONCAT(DO_CONCAT(_REGBIT, _register), DO_CONCAT(_, _bit)), \ */
178+
179+
/*!
180+
* Set traces on a RAM location, 8 or 15-bit.
181+
*/
182+
154183
#define AVR_MCU_VCD_SRAM_8(_name) \
155184
.tag = AVR_MMCU_TAG_VCD_SRAM_8, \
156185
.len = sizeof(struct avr_mmcu_vcd_trace_t) - 2,\
@@ -213,7 +242,7 @@ struct avr_mmcu_vcd_trace_t {
213242
/*!
214243
* Add this port/pin to the VCD file. The syntax uses the name of the
215244
* port as a character, and not a pointer to a register.
216-
* AVR_MCU_VCD_PORT_PIN('B', 5);
245+
* AVR_MCU_VCD_PORT_PIN('B', 5, "trace_name");
217246
*/
218247
#define AVR_MCU_VCD_PORT_PIN(_port, _pin, _name) \
219248
const struct avr_mmcu_vcd_trace_t DO_CONCAT(DO_CONCAT(_, _tag), __LINE__) _MMCU_ = {\
@@ -247,6 +276,21 @@ struct avr_mmcu_vcd_trace_t {
247276
#define AVR_MCU_VCD_ALL_IRQ_PENDING() \
248277
AVR_MCU_VCD_IRQ_TRACE(0xff, 0, "IRQ_PENDING")
249278

279+
/*!
280+
* Above, "IRQ" refers to the IRQs associated with interrupts,
281+
* but calls to any of Simavr's peripheral IRQs may be logged to a VCD file.
282+
*/
283+
284+
#define AVR_MCU_VCD_IO_IRQ(_ioctl, _select, _trace_name) \
285+
const struct avr_mmcu_vcd_ioirq_t \
286+
DO_CONCAT(_IO_IRQ_##_ioctl##_##_select##_, __LINE__) _MMCU_ = { \
287+
.tag = AVR_MMCU_TAG_VCD_IO_IRQ, \
288+
.len = sizeof(struct avr_mmcu_vcd_ioirq_t) - 2,\
289+
.irqno = _select, \
290+
.ioctl = #_ioctl, \
291+
.name = _trace_name, \
292+
};
293+
250294
/*!
251295
* This tag allows you to specify the voltages used by your board
252296
* It is optional in most cases, but you will need it if you use

simavr/sim/sim_elf.c

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,10 @@ avr_load_firmware(
330330
&bit[firmware->trace[ti].addr],
331331
firmware->trace[ti].mask == 0xff ? 8 : 1,
332332
firmware->trace[ti].name);
333+
} else if (firmware->trace[ti].kind == AVR_MMCU_TAG_VCD_IO_IRQ) {
334+
avr_irq_t * irq = avr_io_getirq(avr, firmware->trace[ti].addr, firmware->trace[ti].mask);
335+
if (irq)
336+
avr_vcd_add_signal(avr->vcd, irq, 8, firmware->trace[ti].name);
333337
} else if ( (firmware->trace[ti].kind == AVR_MMCU_TAG_VCD_SRAM_8) ||
334338
(firmware->trace[ti].kind == AVR_MMCU_TAG_VCD_SRAM_16) ) {
335339
if ((firmware->trace[ti].addr <= 31) || (firmware->trace[ti].addr > avr->ramend)) {
@@ -462,7 +466,6 @@ elf_parse_mmcu_section(
462466
uint8_t mask = src[0];
463467
uint16_t addr = src[1] | (src[2] << 8);
464468
char * name = (char*)src + 3;
465-
466469
#if 0
467470
AVR_LOG(NULL, LOG_DEBUG,
468471
"VCD_TRACE %d %04x:%02x - %s\n", tag,
@@ -475,6 +478,20 @@ elf_parse_mmcu_section(
475478
sizeof(firmware->trace[firmware->tracecount].name));
476479
firmware->tracecount++;
477480
} break;
481+
case AVR_MMCU_TAG_VCD_IO_IRQ: {
482+
uint8_t mask = src[0];
483+
uint32_t ioctl;
484+
char *name;
485+
486+
ioctl = AVR_IOCTL_DEF(src[1], src[2], src[3], src[4]);
487+
name = (char*)src + 6;
488+
firmware->trace[firmware->tracecount].kind = tag;
489+
firmware->trace[firmware->tracecount].mask = mask;
490+
firmware->trace[firmware->tracecount].addr = ioctl;
491+
strncpy(firmware->trace[firmware->tracecount].name, name,
492+
sizeof(firmware->trace[firmware->tracecount].name));
493+
firmware->tracecount++;
494+
} break;
478495
case AVR_MMCU_TAG_VCD_FILENAME: {
479496
strcpy(firmware->tracename, (char*)src);
480497
} break;

simavr/sim/sim_elf.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ typedef struct elf_firmware_t {
6969
struct {
7070
uint8_t kind;
7171
uint8_t mask;
72-
uint16_t addr;
72+
uint32_t addr; // May be an ioctl value.
7373
char name[64];
7474
} trace[32];
7575

tests/atmega88_example.c

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,17 @@
2121
AVR_MCU(F_CPU, "atmega88");
2222

2323
/*
24-
* This small section tells simavr to generate a VCD trace dump with changes to these
25-
* registers.
26-
* Opening it with gtkwave will show you the data being pumped out into the data register
27-
* UDR0, and the UDRE0 bit being set, then cleared
24+
* This small section tells simavr to generate a VCD trace dump.
25+
* Opening it with gtkwave will show you the data being pumped out into
26+
* the data register UDR0, and the UDRE0 ("empty") bit being set, then cleared
27+
*
28+
* The output bytes are logged as the value of an IRQ, because the special
29+
* nature of UDRE0 (separate read and write buffers) means that logging
30+
* the register UDRE0 would return any data received by the UART.
2831
*/
29-
const struct avr_mmcu_vcd_trace_t _mytrace[] _MMCU_ = {
30-
{ AVR_MCU_VCD_SYMBOL("UDR0"), .what = (void*)&UDR0, },
31-
{ AVR_MCU_VCD_SYMBOL("UDRE0"), .mask = (1 << UDRE0), .what = (void*)&UCSR0A, },
32-
};
3332

33+
AVR_MCU_VCD_REGISTER_BIT(UCSR0A, UDRE0);
34+
AVR_MCU_VCD_IO_IRQ(uar0, 1 /* UART_IRQ_OUTPUT */, "UART_output");
3435

3536
/* declare this in a .eeprom ELF section */
3637
uint32_t value EEMEM = 0xdeadbeef;

tests/tests.c

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -139,12 +139,20 @@ int tests_run_test(avr_t *avr, unsigned long run_usec) {
139139
// setjmp() returned directly, run avr
140140
while (1)
141141
my_avr_run(avr);
142-
} else if (reason == 1) {
143-
// returned from longjmp(); cycle timer fired
144-
return reason;
145-
} else if (reason == 2) {
146-
// returned from special deinit, avr stopped
147-
return reason;
142+
} else {
143+
/* Normal cleanup before exit, includes VCD flush. */
144+
145+
avr->custom.deinit = NULL;
146+
avr_terminate(avr);
147+
148+
if (reason == 1) {
149+
// returned from longjmp(); cycle timer fired
150+
151+
return reason;
152+
} else if (reason == 2) {
153+
// returned from special deinit, avr stopped
154+
return reason;
155+
}
148156
}
149157
fail("Error in test case: Should never reach this.");
150158
return 0;

0 commit comments

Comments
 (0)