// converts back a number of cycles to usecs (for usleep)
static inline uint32_t avr_cycles_to_usec(avr_t * avr, avr_cycle_count_t cycles)
{
- return 1000000 * cycles / avr->frequency;
+ return 1000000L * cycles / avr->frequency;
+}
+
+// converts back a number of cycles to nsecs
+static inline uint64_t avr_cycles_to_nsec(avr_t * avr, avr_cycle_count_t cycles)
+{
+ return (uint64_t)1E6 * (uint64_t)cycles / (avr->frequency/1000);
}
// converts a number of hz (to megahertz etc) to a number of cycle
static void avr_vcd_flush_log(avr_vcd_t * vcd)
{
- if (!vcd->logindex)
- return;
-// printf("avr_vcd_flush_log %d\n", vcd->logindex);
- uint32_t oldbase = 0; // make sure it's different
- char out[48];
-
#if AVR_VCD_MAX_SIGNALS > 32
uint64_t seen = 0;
#else
uint32_t seen = 0;
#endif
- for (int li = 0; li < vcd->logindex; li++) {
+ uint64_t oldbase = 0; // make sure it's different
+ char out[48];
+
+ if (!vcd->logindex)
+ return;
+// printf("avr_vcd_flush_log %d\n", vcd->logindex);
+
+
+ for (uint32_t li = 0; li < vcd->logindex; li++) {
avr_vcd_log_t *l = &vcd->log[li];
- uint32_t base = avr_cycles_to_usec(vcd->avr, l->when - vcd->start);
+ uint64_t base = avr_cycles_to_nsec(vcd->avr, l->when - vcd->start); // 1ns base
// if that trace was seen in this usec already, we fudge the base time
// to make sure the new value is offset by one usec, to make sure we get
if (base > oldbase || li == 0) {
seen = 0;
- fprintf(vcd->output, "#%uld\n", base);
+ fprintf(vcd->output, "#%llu\n", base);
oldbase = base;
}
seen |= (1 << l->signal->irq.irq); // mark this trace as seen for this timestamp
return -1;
}
- fprintf(vcd->output, "$timescale 1us $end\n");
+ fprintf(vcd->output, "$timescale 1ns $end\n"); // 1ns base
fprintf(vcd->output, "$scope module logic $end\n");
for (int i = 0; i < vcd->signal_count; i++) {
*/
#define AVR_VCD_MAX_SIGNALS 32
-#define AVR_VCD_LOG_SIZE 256
+#define AVR_VCD_LOG_SIZE 5120
typedef struct avr_vcd_signal_t {
avr_irq_t irq; // receiving IRQ
--- /dev/null
+/*
+ atmega88_example.c
+
+ */
+
+#ifndef F_CPU
+#define F_CPU 8000000
+#endif
+#include <avr/io.h>
+#include <stdio.h>
+#include <avr/interrupt.h>
+#include <avr/eeprom.h>
+#include <avr/sleep.h>
+#include <util/delay.h>
+
+/*
+ * This demonstrate how to use the avr_mcu_section.h file
+ * The macro adds a section to the ELF file with useful
+ * information for the simulator
+ */
+#include "avr_mcu_section.h"
+AVR_MCU(F_CPU, "atmega88");
+
+
+int main()
+{
+ DDRB = 1;
+ PORTB = 0;
+
+
+ // test VCD output for 100us
+ for(int i=0; i<10; i++)
+ {
+ PORTB = 1 ^ PORTB;
+ _delay_us(100);
+ }
+
+
+ // this quits the simulator, since interupts are off
+ // this is a "feature" that allows running tests cases and exit
+ sleep_cpu();
+}
--- /dev/null
+#include "sim_avr.h"
+#include "avr_ioport.h"
+#include "sim_vcd_file.h"
+
+#include "tests.h"
+
+int main(int argc, char **argv) {
+ tests_init(argc, argv);
+
+
+ avr_t *avr = tests_init_avr("atmega88_vcd.axf");
+
+ avr_vcd_t vcd_file;
+ avr_vcd_init(avr, "atmega88_vcd.vcd", &vcd_file, 10000);
+ avr_vcd_add_signal(&vcd_file, avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('B'), IOPORT_IRQ_PIN0), 1, "PB0" );
+ avr_vcd_start(&vcd_file);
+
+ tests_run_test(avr, 10000);
+
+ avr_vcd_stop(&vcd_file);
+ tests_success();
+ return 0;
+}