#include <stdint.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
typedef uint64_t avr_cycle_count_t;
typedef uint16_t avr_io_addr_t;
// real SREG
R_SREG = 32+0x3f,
- // maximum number of IO regisrer, on normal AVRs
+ // maximum number of IO registers, on normal AVRs
MAX_IOs = 256 - 32, // minus 32 GP registers
};
#define AVR_IO_TO_DATA(v) ((v) + 32)
/*
- * Core states. This will need populating with debug states for gdb
+ * Core states.
*/
enum {
cpu_Limbo = 0, // before initialization is finished
- cpu_Stopped,
- cpu_Running,
- cpu_Sleeping,
+ cpu_Stopped, // all is stopped, timers included
+
+ cpu_Running, // we're free running
- cpu_Step,
- cpu_StepDone,
+ cpu_Sleeping, // we're now sleeping until an interrupt
+
+ cpu_Step, // run ONE instruction, then...
+ cpu_StepDone, // tell gdb it's all OK, and give it registers
};
/*
uint8_t vector_size;
uint8_t signature[3];
uint8_t fuse[4];
+ avr_io_addr_t rampz; // optional, only for ELPM/SPM on >64Kb cores
+ avr_io_addr_t eind; // optional, only for EIJMP/EICALL on >64Kb cores
// filled by the ELF data, this allow tracking of invalid jumps
uint32_t codeend;
int state; // stopped, running, sleeping
uint32_t frequency; // frequency we are running at
+ // mostly used by the ADC for now
+ uint32_t vcc,avcc,aref; // (optional) voltages in millivolts
+
+ // cycles gets incremented when sleeping and when running; it corresponds
+ // not only to "cycles that runs" but also "cycles that might have run"
+ // like, sleeping.
avr_cycle_count_t cycle; // current cycle
// called at init time
// in the opcode decoder.
// This array is re-synthetized back/forth when SREG changes
uint8_t sreg[8];
+ uint8_t i_shadow; // used to detect edges on I flag
/*
* ** current PC **
- * Note that the PC is reoresenting /bytes/ while the AVR value is
+ * Note that the PC is representing /bytes/ while the AVR value is
* assumed to be "words". This is in line with what GDB does...
- * this is why you will see >>1 ane <<1 in the decoder to handle jumps
+ * this is why you will see >>1 and <<1 in the decoder to handle jumps.
+ * It CAN be a little confusing, so concentrate, young grasshopper.
*/
uint32_t pc;
/*
- * callback when specific IO registers are read/written
- * these should probably be allocated dynamically in init()..
+ * callback when specific IO registers are read/written.
+ * There is one drawback here, there is in way of knowing what is the
+ * "beginning of useful sram" on a core, so there is no way to deduce
+ * what is the maximum IO register for a core, and thus, we can't
+ * allocate this table dynamically.
+ * If you wanted to emulate the BIG AVRs, and XMegas, this would need
+ * work.
*/
struct {
- void * param;
- avr_io_read_t r;
- } ior[MAX_IOs];
- struct {
- void * param;
- avr_io_write_t w;
- } iow[MAX_IOs];
+ struct avr_irq_t * irq; // optional, used only if asked for with avr_iomem_getirq()
+ struct {
+ void * param;
+ avr_io_read_t c;
+ } r;
+ struct {
+ void * param;
+ avr_io_write_t c;
+ } w;
+ } io[MAX_IOs];
// flash memory (initialized to 0xff, and code loaded into it)
uint8_t * flash;
uint8_t pending_wait; // number of cycles to wait for pending
uint32_t pending[2]; // pending interrupts
- // DEBUG ONLY
+ // DEBUG ONLY -- value ignored if CONFIG_SIMAVR_TRACE = 0
int trace;
#if CONFIG_SIMAVR_TRACE
uint32_t touched[256 / 32]; // debug
#endif
+ // VALUE CHANGE DUMP file (waveforms)
+ // this is the VCD file that gets allocated if the
+ // firmware that is loaded explicitly asks for a trace
+ // to be generated, and allocates it's own symbols
+ // using AVR_MMCU_TAG_VCD_TRACE (see avr_mcu_section.h)
+ struct avr_vcd_t * vcd;
+
// gdb hooking structure. Only present when gdb server is active
struct avr_gdb_t * gdb;
+
// if non-zero, the gdb server will be started when the core
// crashed even if not activated at startup
// if zero, the simulator will just exit() in case of a crash
void avr_reset(avr_t * avr);
// run one cycle of the AVR, sleep if necessary
int avr_run(avr_t * avr);
+// finish any pending operations
+void avr_terminate(avr_t * avr);
+
+// set an IO register to receive commands from the AVR firmware
+// it's optional, and uses the ELF tags
+void avr_set_command_register(avr_t * avr, avr_io_addr_t addr);
+
+// specify the "console register" -- output sent to this register
+// is printed on the simulator console, without using a UART
+void avr_set_console_register(avr_t * avr, avr_io_addr_t addr);
// load code in the "flash"
void avr_loadcode(avr_t * avr, uint8_t * code, uint32_t size, uint32_t address);
-// converts a nunber of usec to a nunber of machine cycles, at current speed
-avr_cycle_count_t avr_usec_to_cycles(avr_t * avr, uint32_t usec);
-// converts a number of hz (to megahertz etc) to a number of cycle
-avr_cycle_count_t avr_hz_to_cycles(avr_t * avr, uint32_t hz);
-// converts back a number of cycles to usecs (for usleep)
-uint32_t avr_cycles_to_usec(avr_t * avr, avr_cycle_count_t cycles);
-
-// register for calling 'timer' in 'when' cycles
-void avr_cycle_timer_register(avr_t * avr, avr_cycle_count_t when, avr_cycle_timer_t timer, void * param);
-// register a timer to call in 'when' usec
-void avr_cycle_timer_register_usec(avr_t * avr, uint32_t when, avr_cycle_timer_t timer, void * param);
-// cancel a previously set timer
-void avr_cycle_timer_cancel(avr_t * avr, avr_cycle_timer_t timer, void * param);
/*
* these are accessors for avr->data but allows watchpoints to be set for gdb
// this might activate gdb server
void avr_sadly_crashed(avr_t *avr, uint8_t signal);
+#ifdef __cplusplus
+};
+#endif
+
#include "sim_io.h"
#include "sim_regbit.h"
#include "sim_interrupts.h"
#include "sim_irq.h"
+#include "sim_cycle_timers.h"
#endif /*__SIM_AVR_H__*/