Commit f97d1c890b4aa9b1db6da9af829b87acf6776076
authorMichel Pollet <buserror@gmail.com>
Wed, 15 Feb 2017 19:19:17 +0000 (19:19 +0000)
committerMichel Pollet <buserror@gmail.com>
Wed, 15 Feb 2017 19:19:17 +0000 (19:19 +0000)
Allows specing VCD traces for PORT/PIN directly in the firmware using a
MMCU macro.

Also did a bit of housekeeping in sim_elf since I was there...

Signed-off-by: Michel Pollet <buserror@gmail.com>
3 files changed:
simavr/sim/avr/avr_mcu_section.h
simavr/sim/sim_elf.c
simavr/sim/sim_elf.h

index dc690d8281d14af4bdc57762f2fd47bb091722ac..e5289553d2e14577be4e77404236835d4be07e28 100644 (file)
@@ -60,6 +60,7 @@ enum {
        AVR_MMCU_TAG_VCD_FILENAME,
        AVR_MMCU_TAG_VCD_PERIOD,
        AVR_MMCU_TAG_VCD_TRACE,
+       AVR_MMCU_TAG_VCD_PORTPIN,
        AVR_MMCU_TAG_PORT_EXTERNAL_PULL,
 };
 
@@ -196,6 +197,15 @@ struct avr_mmcu_vcd_trace_t {
                (((unsigned long)((_port)&0xff) << 16) | \
                ((unsigned long)((_mask)&0xff) << 8) | \
                ((_val)&0xff)));
+/*!
+ * Add this port/pin to the VCD file. The syntax uses the name of the
+ * port as a character, and not a pointer to a register.
+ * AVR_MCU_VCD_PORT_PIN('B', 5);
+ */
+#define AVR_MCU_VCD_PORT_PIN(_port, _pin) \
+       AVR_MCU_LONG(AVR_MMCU_TAG_VCD_PORTPIN, \
+               (((unsigned long)((_port)&0xff) << 8) | \
+               ((_pin)&0xff)));
 
 /*!
  * This tag allows you to specify the voltages used by your board
index a45fe0a490f9731b9a9c81d427de19fa8b86634d..583011be48fc3ef188ec182da19422f9aab74124 100644 (file)
 #define O_BINARY 0
 #endif
 
-void avr_load_firmware(avr_t * avr, elf_firmware_t * firmware)
+void
+avr_load_firmware(
+               avr_t * avr,
+               elf_firmware_t * firmware)
 {
        if (firmware->frequency)
                avr->frequency = firmware->frequency;
@@ -70,10 +73,17 @@ void avr_load_firmware(avr_t * avr, elf_firmware_t * firmware)
        }
 #endif
 
-       avr_loadcode(avr, firmware->flash, firmware->flashsize, firmware->flashbase);
-       avr->codeend = firmware->flashsize + firmware->flashbase - firmware->datasize;
+       avr_loadcode(avr, firmware->flash,
+                       firmware->flashsize, firmware->flashbase);
+       avr->codeend = firmware->flashsize +
+                       firmware->flashbase - firmware->datasize;
+
        if (firmware->eeprom && firmware->eesize) {
-               avr_eeprom_desc_t d = { .ee = firmware->eeprom, .offset = 0, .size = firmware->eesize };
+               avr_eeprom_desc_t d = {
+                               .ee = firmware->eeprom,
+                               .offset = 0,
+                               .size = firmware->eesize
+               };
                avr_ioctl(avr, AVR_IOCTL_EEPROM_SET, &d);
        }
        if (firmware->fuse)
@@ -81,23 +91,19 @@ void avr_load_firmware(avr_t * avr, elf_firmware_t * firmware)
        if (firmware->lockbits)
                avr->lockbits = firmware->lockbits[0];
        // load the default pull up/down values for ports
-       for (int i = 0; i < 8; i++)
-               if (firmware->external_state[i].port == 0)
-                       break;
-               else {
-                       avr_ioport_external_t e = {
-                               .name = firmware->external_state[i].port,
-                               .mask = firmware->external_state[i].mask,
-                               .value = firmware->external_state[i].value,
-                       };
-                       avr_ioctl(avr, AVR_IOCTL_IOPORT_SET_EXTERNAL(e.name), &e);
-               }
+       for (int i = 0; i < 8 && firmware->external_state[i].port; i++) {
+               avr_ioport_external_t e = {
+                       .name = firmware->external_state[i].port,
+                       .mask = firmware->external_state[i].mask,
+                       .value = firmware->external_state[i].value,
+               };
+               avr_ioctl(avr, AVR_IOCTL_IOPORT_SET_EXTERNAL(e.name), &e);
+       }
        avr_set_command_register(avr, firmware->command_register_addr);
        avr_set_console_register(avr, firmware->console_register_addr);
 
        // rest is initialization of the VCD file
-
-       if (firmware->tracecount == 0)
+       if (firmware->tracecount == 0 && firmware->traceportcount == 0)
                return;
        avr->vcd = malloc(sizeof(*avr->vcd));
        memset(avr->vcd, 0, sizeof(*avr->vcd));
@@ -106,25 +112,42 @@ void avr_load_firmware(avr_t * avr, elf_firmware_t * firmware)
                avr->vcd,
                firmware->traceperiod >= 1000 ? firmware->traceperiod : 1000);
 
-       AVR_LOG(avr, LOG_TRACE, "Creating VCD trace file '%s'\n", avr->vcd->filename);
+       AVR_LOG(avr, LOG_TRACE, "Creating VCD trace file '%s'\n",
+                       avr->vcd->filename);
+
+       for (int ti = 0; ti < firmware->traceportcount; ti++) {
+               avr_irq_t * irq = avr_io_getirq(avr,
+                               AVR_IOCTL_IOPORT_GETIRQ(firmware->traceport[ti].port),
+                               firmware->traceport[ti].pin);
+               if (irq) {
+                       char name[16];
+                       sprintf(name, "%c%d", firmware->traceport[ti].port,
+                                       firmware->traceport[ti].pin);
+                       avr_vcd_add_signal(avr->vcd, irq, 1, name);
+               }
+       }
+
        for (int ti = 0; ti < firmware->tracecount; ti++) {
-               if (firmware->trace[ti].mask == 0xff || firmware->trace[ti].mask == 0) {
+               if (firmware->trace[ti].mask == 0xff ||
+                               firmware->trace[ti].mask == 0) {
                        // easy one
                        avr_irq_t * all = avr_iomem_getirq(avr,
                                        firmware->trace[ti].addr,
                                        firmware->trace[ti].name,
                                        AVR_IOMEM_IRQ_ALL);
                        if (!all) {
-                               AVR_LOG(avr, LOG_ERROR, "ELF: %s: unable to attach trace to address %04x\n",
+                               AVR_LOG(avr, LOG_ERROR,
+                                       "ELF: %s: unable to attach trace to address %04x\n",
                                        __FUNCTION__, firmware->trace[ti].addr);
                        } else {
-                               avr_vcd_add_signal(avr->vcd, all, 8, firmware->trace[ti].name);
+                               avr_vcd_add_signal(avr->vcd, all, 8,
+                                               firmware->trace[ti].name);
                        }
                } else {
-                       int count = 0;
-                       for (int bi = 0; bi < 8; bi++)
-                               if (firmware->trace[ti].mask & (1 << bi))
-                                       count++;
+                       int count = __builtin_popcount(firmware->trace[ti].mask);
+               //      for (int bi = 0; bi < 8; bi++)
+               //              if (firmware->trace[ti].mask & (1 << bi))
+               //                      count++;
                        for (int bi = 0; bi < 8; bi++)
                                if (firmware->trace[ti].mask & (1 << bi)) {
                                        avr_irq_t * bit = avr_iomem_getirq(avr,
@@ -132,18 +155,21 @@ void avr_load_firmware(avr_t * avr, elf_firmware_t * firmware)
                                                        firmware->trace[ti].name,
                                                        bi);
                                        if (!bit) {
-                                               AVR_LOG(avr, LOG_ERROR, "ELF: %s: unable to attach trace to address %04x\n",
+                                               AVR_LOG(avr, LOG_ERROR,
+                                                       "ELF: %s: unable to attach trace to address %04x\n",
                                                        __FUNCTION__, firmware->trace[ti].addr);
                                                break;
                                        }
 
                                        if (count == 1) {
-                                               avr_vcd_add_signal(avr->vcd, bit, 1, firmware->trace[ti].name);
+                                               avr_vcd_add_signal(avr->vcd,
+                                                               bit, 1, firmware->trace[ti].name);
                                                break;
                                        }
                                        char comp[128];
                                        sprintf(comp, "%s.%d", firmware->trace[ti].name, bi);
-                                       avr_vcd_add_signal(avr->vcd, bit, 1, firmware->trace[ti].name);
+                                       avr_vcd_add_signal(avr->vcd,
+                                                       bit, 1, firmware->trace[ti].name);
                                }
                }
        }
@@ -153,13 +179,19 @@ void avr_load_firmware(avr_t * avr, elf_firmware_t * firmware)
                avr_vcd_start(avr->vcd);
 }
 
-static void elf_parse_mmcu_section(elf_firmware_t * firmware, uint8_t * src, uint32_t size)
+static void
+elf_parse_mmcu_section(
+               elf_firmware_t * firmware,
+               uint8_t * src,
+               uint32_t size)
 {
+//     hdump(".mmcu", src, size);
        while (size) {
                uint8_t tag = *src++;
                uint8_t ts = *src++;
                int next = size > 2 + ts ? 2 + ts : size;
-       //      printf("elf_parse_mmcu_section %d, %d / %d\n", tag, ts, size);
+       //      printf("elf_parse_mmcu_section %2d, size %2d / remains %3d\n",
+       //                      tag, ts, size);
                switch (tag) {
                        case AVR_MMCU_TAG_FREQUENCY:
                                firmware->frequency =
@@ -186,7 +218,8 @@ static void elf_parse_mmcu_section(elf_firmware_t * firmware, uint8_t * src, uin
                                                firmware->external_state[i].port = src[2];
                                                firmware->external_state[i].mask = src[1];
                                                firmware->external_state[i].value = src[0];
-                                               AVR_LOG(NULL, LOG_TRACE, "AVR_MMCU_TAG_PORT_EXTERNAL_PULL[%d] %c:%02x:%02x\n",
+                                               AVR_LOG(NULL, LOG_TRACE,
+                                                       "AVR_MMCU_TAG_PORT_EXTERNAL_PULL[%d] %c:%02x:%02x\n",
                                                        i, firmware->external_state[i].port,
                                                        firmware->external_state[i].mask,
                                                        firmware->external_state[i].value);
@@ -197,13 +230,23 @@ static void elf_parse_mmcu_section(elf_firmware_t * firmware, uint8_t * src, uin
                                uint8_t mask = src[0];
                                uint16_t addr = src[1] | (src[2] << 8);
                                char * name = (char*)src + 3;
-                               AVR_LOG(NULL, LOG_TRACE, "AVR_MMCU_TAG_VCD_TRACE %04x:%02x - %s\n", addr, mask, name);
+                               AVR_LOG(NULL, LOG_TRACE,
+                                               "AVR_MMCU_TAG_VCD_TRACE %04x:%02x - %s\n",
+                                               addr, mask, name);
                                firmware->trace[firmware->tracecount].mask = mask;
                                firmware->trace[firmware->tracecount].addr = addr;
                                strncpy(firmware->trace[firmware->tracecount].name, name,
                                        sizeof(firmware->trace[firmware->tracecount].name));
                                firmware->tracecount++;
                        }       break;
+                       case AVR_MMCU_TAG_VCD_PORTPIN: {
+                               firmware->traceport[firmware->traceportcount].pin = src[0];
+                               firmware->traceport[firmware->traceportcount].port = src[1];
+                               printf("trace PORT %c pin %d\n",
+                                               firmware->traceport[firmware->traceportcount].port,
+                                               firmware->traceport[firmware->traceportcount].pin);
+                               firmware->traceportcount++;
+                       }       break;
                        case AVR_MMCU_TAG_VCD_FILENAME: {
                                strcpy(firmware->tracename, (char*)src);
                        }       break;
index 9d6bc71397e3b4ad6906a328942e8b5fa6cdf33d..997b8d7e5eef75906284e604208b2cdbd6f2c4d2 100644 (file)
@@ -53,6 +53,11 @@ typedef struct elf_firmware_t {
                uint16_t addr;
                char    name[64];
        } trace[32];
+       int traceportcount;
+       struct {
+               char port;
+               int8_t pin;
+       } traceport[16];
 
        struct {
                char port;