From 051807bbee1640db76b5493a2fea94eeca81d859 Mon Sep 17 00:00:00 2001 From: Michel Pollet Date: Fri, 17 Feb 2017 09:20:55 +0000 Subject: [PATCH] Added new VCD tags for IRQ vector tracing Now allow cool stuff, like tracking pending IRQs, their exact execution time, and also a global one that shows which ones are running and when Signed-off-by: Michel Pollet --- simavr/sim/avr/avr_mcu_section.h | 22 ++++++++++++++++++++++ simavr/sim/sim_elf.c | 11 ++++++++++- simavr/sim/sim_elf.h | 1 + 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/simavr/sim/avr/avr_mcu_section.h b/simavr/sim/avr/avr_mcu_section.h index e528955..cb52dd7 100644 --- a/simavr/sim/avr/avr_mcu_section.h +++ b/simavr/sim/avr/avr_mcu_section.h @@ -61,6 +61,7 @@ enum { AVR_MMCU_TAG_VCD_PERIOD, AVR_MMCU_TAG_VCD_TRACE, AVR_MMCU_TAG_VCD_PORTPIN, + AVR_MMCU_TAG_VCD_IRQ, AVR_MMCU_TAG_PORT_EXTERNAL_PULL, }; @@ -207,6 +208,27 @@ struct avr_mmcu_vcd_trace_t { (((unsigned long)((_port)&0xff) << 8) | \ ((_pin)&0xff))); +/*! + * These allows you to add a trace showing how long an IRQ vector is pending, + * and also how long it is running. You can specify the IRQ as a vector name + * straight from the firmware file, and it will be named properly in the trace + */ + +#define AVR_MCU_VCD_IRQ_TRACE(_vect_number, __what, _trace_name) \ + const struct avr_mmcu_vcd_trace_t DO_CONCAT(DO_CONCAT(_, _tag), __LINE__) _MMCU_ = {\ + .tag = AVR_MMCU_TAG_VCD_IRQ, \ + .len = sizeof(struct avr_mmcu_vcd_trace_t) - 2,\ + .mask = _vect_number, \ + .what = (void*)__what, \ + .name = _trace_name, \ + }; +#define AVR_MCU_VCD_IRQ(_irq_name) \ + AVR_MCU_VCD_IRQ_TRACE(_irq_name##_vect_num, 1, #_irq_name) +#define AVR_MCU_VCD_IRQ_PENDING(_irq_name) \ + AVR_MCU_VCD_IRQ_TRACE(_irq_name##_vect_num, 0, #_irq_name " pend") +#define AVR_MCU_VCD_ALL_IRQ() \ + AVR_MCU_VCD_IRQ_TRACE(0xff, 1, "IRQ") + /*! * This tag allows you to specify the voltages used by your board * It is optional in most cases, but you will need it if you use diff --git a/simavr/sim/sim_elf.c b/simavr/sim/sim_elf.c index 583011b..595652c 100644 --- a/simavr/sim/sim_elf.c +++ b/simavr/sim/sim_elf.c @@ -128,7 +128,14 @@ avr_load_firmware( } for (int ti = 0; ti < firmware->tracecount; ti++) { - if (firmware->trace[ti].mask == 0xff || + if (firmware->trace[ti].kind == AVR_MMCU_TAG_VCD_IRQ) { + avr_irq_t * bit = avr_get_interrupt_irq(avr, firmware->trace[ti].mask); + if (bit && firmware->trace[ti].addr < AVR_INT_IRQ_COUNT) + avr_vcd_add_signal(avr->vcd, + &bit[firmware->trace[ti].addr], + firmware->trace[ti].mask == 0xff ? 8 : 1, + firmware->trace[ti].name); + } else if (firmware->trace[ti].mask == 0xff || firmware->trace[ti].mask == 0) { // easy one avr_irq_t * all = avr_iomem_getirq(avr, @@ -226,6 +233,7 @@ elf_parse_mmcu_section( break; } } break; + case AVR_MMCU_TAG_VCD_IRQ: case AVR_MMCU_TAG_VCD_TRACE: { uint8_t mask = src[0]; uint16_t addr = src[1] | (src[2] << 8); @@ -233,6 +241,7 @@ elf_parse_mmcu_section( AVR_LOG(NULL, LOG_TRACE, "AVR_MMCU_TAG_VCD_TRACE %04x:%02x - %s\n", addr, mask, name); + firmware->trace[firmware->tracecount].kind = tag; firmware->trace[firmware->tracecount].mask = mask; firmware->trace[firmware->tracecount].addr = addr; strncpy(firmware->trace[firmware->tracecount].name, name, diff --git a/simavr/sim/sim_elf.h b/simavr/sim/sim_elf.h index 997b8d7..6a6b490 100644 --- a/simavr/sim/sim_elf.h +++ b/simavr/sim/sim_elf.h @@ -49,6 +49,7 @@ typedef struct elf_firmware_t { uint32_t traceperiod; int tracecount; struct { + uint8_t kind; uint8_t mask; uint16_t addr; char name[64]; -- 2.39.5