From: Michel Pollet <buserror@gmail.com>
Date: Wed, 15 Feb 2017 19:19:17 +0000 (+0000)
Subject: mmcu: Added VCD_PORT_PIN support
X-Git-Tag: v1.5~8
X-Git-Url: https://git.htl-mechatronik.at/public/?a=commitdiff_plain;h=f97d1c890b4aa9b1db6da9af829b87acf6776076;p=sx%2Fsimavr.git

mmcu: Added VCD_PORT_PIN support

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>
---

diff --git a/simavr/sim/avr/avr_mcu_section.h b/simavr/sim/avr/avr_mcu_section.h
index dc690d8..e528955 100644
--- a/simavr/sim/avr/avr_mcu_section.h
+++ b/simavr/sim/avr/avr_mcu_section.h
@@ -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
diff --git a/simavr/sim/sim_elf.c b/simavr/sim/sim_elf.c
index a45fe0a..583011b 100644
--- a/simavr/sim/sim_elf.c
+++ b/simavr/sim/sim_elf.c
@@ -41,7 +41,10 @@
 #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;
diff --git a/simavr/sim/sim_elf.h b/simavr/sim/sim_elf.h
index 9d6bc71..997b8d7 100644
--- a/simavr/sim/sim_elf.h
+++ b/simavr/sim/sim_elf.h
@@ -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;