Main Page | File List | Globals | Related Pages

avrcore.c

Go to the documentation of this file.
00001 /* 00002 * $Id: avrcore.c,v 1.77 2003/12/03 18:37:59 troth Exp $ 00003 * 00004 **************************************************************************** 00005 * 00006 * simulavr - A simulator for the Atmel AVR family of microcontrollers. 00007 * Copyright (C) 2001, 2002, 2003 Theodore A. Roth 00008 * 00009 * This program is free software; you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation; either version 2 of the License, or 00012 * (at your option) any later version. 00013 * 00014 * This program is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 * GNU General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU General Public License 00020 * along with this program; if not, write to the Free Software 00021 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00022 * 00023 **************************************************************************** 00024 */ 00025 00026 /** 00027 * \file avrcore.c 00028 * \brief Module for the core AvrCore object, which is the AVR CPU to be 00029 * simulated. 00030 */ 00031 00032 #include <config.h> 00033 00034 #include <stdio.h> 00035 #include <stdlib.h> 00036 #include <signal.h> 00037 00038 #include "avrerror.h" 00039 #include "avrmalloc.h" 00040 #include "avrclass.h" 00041 #include "utils.h" 00042 #include "callback.h" 00043 #include "op_names.h" 00044 00045 #include "storage.h" 00046 #include "flash.h" 00047 00048 #include "vdevs.h" 00049 #include "memory.h" 00050 #include "stack.h" 00051 #include "register.h" 00052 #include "sram.h" 00053 #include "eeprom.h" 00054 #include "ports.h" 00055 00056 #include "avrcore.h" 00057 00058 #include "display.h" 00059 #include "decoder.h" 00060 #include "sig.h" 00061 00062 /** \brief Flag for enabling output of instruction debug messages. */ 00063 int global_debug_inst_output = 0; 00064 00065 /***************************************************************************\ 00066 * 00067 * BreakPt(AvrClass) Methods 00068 * 00069 \***************************************************************************/ 00070 00071 #ifndef DOXYGEN /* don't expose to doxygen */ 00072 00073 typedef struct _BreakPt BreakPt; 00074 struct _BreakPt 00075 { 00076 AvrClass parent; 00077 int pc; 00078 uint16_t opcode; 00079 }; 00080 00081 #endif 00082 00083 static inline BreakPt *brk_pt_new (int pc, uint16_t opcode); 00084 static inline void brk_pt_construct (BreakPt *bp, int pc, uint16_t opcode); 00085 static inline void brk_pt_destroy (void *bp); 00086 00087 static inline BreakPt * 00088 brk_pt_new (int pc, uint16_t opcode) 00089 { 00090 BreakPt *bp; 00091 00092 bp = avr_new (BreakPt, 1); 00093 brk_pt_construct (bp, pc, opcode); 00094 class_overload_destroy ((AvrClass *)bp, brk_pt_destroy); 00095 00096 return bp; 00097 } 00098 00099 static inline void 00100 brk_pt_construct (BreakPt *bp, int pc, uint16_t opcode) 00101 { 00102 if (bp == NULL) 00103 avr_error ("passed null ptr"); 00104 00105 class_construct ((AvrClass *)bp); 00106 00107 bp->pc = pc; 00108 bp->opcode = opcode; 00109 } 00110 00111 static inline void 00112 brk_pt_destroy (void *bp) 00113 { 00114 BreakPt *_bp = (BreakPt *)bp; 00115 00116 if (_bp == NULL) 00117 return; 00118 00119 class_destroy (bp); 00120 } 00121 00122 static inline DList *brk_pt_list_add (DList *head, int pc, uint16_t opcode); 00123 static inline DList *brk_pt_list_delete (DList *head, int pc); 00124 static inline BreakPt *brk_pt_list_lookup (DList *head, int pc); 00125 static int brk_pt_cmp (AvrClass *d1, AvrClass *d2); 00126 00127 /* Compare function for break points. */ 00128 00129 static int 00130 brk_pt_cmp (AvrClass *d1, AvrClass *d2) 00131 { 00132 return ((BreakPt *)d1)->pc - ((BreakPt *)d2)->pc; 00133 } 00134 00135 static inline DList * 00136 brk_pt_list_add (DList *head, int pc, uint16_t opcode) 00137 { 00138 BreakPt *bp = brk_pt_new (pc, opcode); 00139 00140 return dlist_add (head, (AvrClass *)bp, brk_pt_cmp); 00141 } 00142 00143 static inline DList * 00144 brk_pt_list_delete (DList *head, int pc) 00145 { 00146 BreakPt *bp = brk_pt_new (pc, 0); 00147 00148 head = dlist_delete (head, (AvrClass *)bp, brk_pt_cmp); 00149 class_unref ((AvrClass *)bp); 00150 00151 return head; 00152 } 00153 00154 static inline BreakPt * 00155 brk_pt_list_lookup (DList *head, int pc) 00156 { 00157 BreakPt *found; 00158 BreakPt *bp = brk_pt_new (pc, 0); 00159 00160 found = (BreakPt *)dlist_lookup (head, (AvrClass *)bp, brk_pt_cmp); 00161 class_unref ((AvrClass *)bp); 00162 00163 return found; 00164 } 00165 00166 static inline DList * 00167 brk_pt_iterator (DList *head, DListFP_Iter func, void *user_data) 00168 { 00169 return dlist_iterator (head, func, user_data); 00170 } 00171 00172 /***************************************************************************\ 00173 * 00174 * Irq(AvrClass) Methods: For managing the irq_pending list. 00175 * 00176 \***************************************************************************/ 00177 00178 #ifndef DOXYGEN /* don't expose to doxygen */ 00179 00180 typedef struct _Irq Irq; 00181 struct _Irq 00182 { 00183 AvrClass parent; 00184 IntVect *vector; 00185 00186 /* These are only used for storing lookup information. Copies of 00187 core->{state,sleep_mode}. */ 00188 int state; 00189 unsigned int sleep_mode; 00190 }; 00191 00192 #endif 00193 00194 static inline Irq *irq_new (IntVect *vector, int state, 00195 unsigned int sleep_mode); 00196 static inline void irq_construct (Irq *irq, IntVect *vector, int state, 00197 unsigned int sleep_mode); 00198 static inline void irq_destroy (void *irq); 00199 00200 static inline Irq * 00201 irq_new (IntVect *vector, int state, unsigned int sleep_mode) 00202 { 00203 Irq *irq; 00204 00205 irq = avr_new (Irq, 1); 00206 irq_construct (irq, vector, state, sleep_mode); 00207 class_overload_destroy ((AvrClass *)irq, irq_destroy); 00208 00209 return irq; 00210 } 00211 00212 static inline void 00213 irq_construct (Irq *irq, IntVect *vector, int state, unsigned int sleep_mode) 00214 { 00215 if (irq == NULL) 00216 avr_error ("passed null ptr"); 00217 00218 class_construct ((AvrClass *)irq); 00219 00220 irq->vector = vector; 00221 irq->state = state; 00222 irq->sleep_mode = sleep_mode; 00223 } 00224 00225 static inline void 00226 irq_destroy (void *irq) 00227 { 00228 Irq *_irq = (Irq *)irq; 00229 00230 if (_irq == NULL) 00231 return; 00232 00233 class_destroy (irq); 00234 } 00235 00236 static inline DList *irq_list_add (DList *head, IntVect *vector); 00237 static inline DList *irq_list_delete (DList *head, IntVect *vector); 00238 #if 0 /* TRoth/2002-09-15: This isn't used. ??? */ 00239 static inline Irq *irq_list_lookup_addr (DList *head, IntVect *vector); 00240 #endif 00241 static int irq_cmp_addr (AvrClass *d1, AvrClass *d2); 00242 static int irq_cmp_pending (AvrClass *d1, AvrClass *d2); 00243 00244 /* Compare function for break points. */ 00245 00246 static int 00247 irq_cmp_addr (AvrClass *d1, AvrClass *d2) 00248 { 00249 return ((Irq *)d1)->vector->addr - ((Irq *)d2)->vector->addr; 00250 } 00251 00252 static inline DList * 00253 irq_list_add (DList *head, IntVect *vector) 00254 { 00255 Irq *irq = irq_new (vector, 0, 0); 00256 00257 return dlist_add (head, (AvrClass *)irq, irq_cmp_addr); 00258 } 00259 00260 static inline DList * 00261 irq_list_delete (DList *head, IntVect *vector) 00262 { 00263 Irq *irq = irq_new (vector, 0, 0); 00264 00265 head = dlist_delete (head, (AvrClass *)irq, irq_cmp_addr); 00266 class_unref ((AvrClass *)irq); 00267 00268 return head; 00269 } 00270 00271 #if 0 /* TRoth/2002-09-15: This isn't used. ??? */ 00272 static inline Irq * 00273 irq_list_lookup_addr (DList *head, IntVect *vector) 00274 { 00275 Irq *found; 00276 Irq *irq = irq_new (vector, 0, 0); 00277 00278 found = (Irq *)dlist_lookup (head, (AvrClass *)irq, irq_cmp_addr); 00279 class_unref ((AvrClass *)irq); 00280 00281 return found; 00282 } 00283 #endif 00284 00285 static int 00286 irq_cmp_pending (AvrClass *d1, AvrClass *d2) 00287 { 00288 Irq *i1 = (Irq *)d1; /* This is the irq which might be ready to be 00289 vectored into. */ 00290 int state = ((Irq *)d2)->state; /* The state the device is currently 00291 in. */ 00292 unsigned int sleep_mode = ((Irq *)d2)->sleep_mode; /* This is the sleep 00293 mode the device in 00294 currently in. Only 00295 one bit should be 00296 set. */ 00297 00298 if (state == STATE_SLEEP) 00299 { 00300 /* If device is in the sleep state, the irq will only pending if it 00301 can wake up the device. */ 00302 00303 if (sleep_mode & i1->vector->can_wake) 00304 return 0; /* vector into the irq */ 00305 else 00306 return -1; /* try the next irq */ 00307 } 00308 00309 /* If the state is not STATE_SLEEP, any irq we see is automatically 00310 pending, so vector it. */ 00311 00312 return 0; 00313 } 00314 00315 /* Walk the list looking for a pending irq which can be handled. If the device 00316 is in a sleep state, the can_wake mask could force the head of the list to 00317 not be the irq which gets vectored. */ 00318 00319 static inline IntVect * 00320 irq_get_pending_vector (DList *head, int state, unsigned int sleep_mode) 00321 { 00322 Irq *found; 00323 Irq *irq = irq_new (NULL, state, sleep_mode); 00324 00325 found = (Irq *)dlist_lookup (head, (AvrClass *)irq, irq_cmp_pending); 00326 class_unref ((AvrClass *)irq); 00327 00328 return found->vector; 00329 } 00330 00331 #if 0 /* TRoth/2002-09-15: This isn't used. ??? */ 00332 static inline IntVect * 00333 irq_get_head_vector (DList *head) 00334 { 00335 return ((Irq *)dlist_get_head_data (head))->vector; 00336 } 00337 #endif 00338 00339 /***************************************************************************\ 00340 * 00341 * AvrCore(AvrClass) Methods 00342 * 00343 \***************************************************************************/ 00344 00345 /** \name AvrCore handling methods */ 00346 00347 /*@{*/ 00348 00349 /** \brief Allocate a new AvrCore object. */ 00350 00351 AvrCore * 00352 avr_core_new (int flash_sz, int PC_sz, StackType stack_type, int stack_sz, 00353 int vtab_idx) 00354 { 00355 AvrCore *core; 00356 00357 core = avr_new (AvrCore, 1); 00358 avr_core_construct (core, flash_sz, PC_sz, stack_type, stack_sz, 00359 vtab_idx); 00360 class_overload_destroy ((AvrClass *)core, avr_core_destroy); 00361 00362 return core; 00363 } 00364 00365 /** \brief Constructor for the AvrCore class. */ 00366 00367 void 00368 avr_core_construct (AvrCore *core, int flash_sz, int PC_sz, 00369 StackType stack_type, int stack_sz, int vtab_idx) 00370 { 00371 if (core == NULL) 00372 avr_error ("passed null ptr"); 00373 00374 class_construct ((AvrClass *)core); 00375 00376 core->state = STATE_STOPPED; 00377 core->sleep_mode = 0; /* each bit represents a sleep mode */ 00378 core->PC = 0; 00379 core->PC_size = PC_sz; 00380 core->PC_max = flash_sz / 2; /* flash_sz is in bytes, need number of 00381 words here */ 00382 core->sreg = sreg_new (); 00383 core->flash = flash_new (flash_sz); 00384 core->gpwr = gpwr_new (); 00385 core->rampz = rampz_new (); 00386 core->mem = mem_new (); 00387 00388 core->breakpoints = NULL; 00389 00390 core->irq_pending = NULL; 00391 core->irq_vtable = (IntVect *)(global_vtable_list[vtab_idx]); 00392 core->irq_offset = 0; 00393 00394 core->CK = 0; 00395 core->inst_CKS = 0; 00396 00397 core->clk_cb = NULL; 00398 core->async_cb = NULL; 00399 00400 switch (stack_type) 00401 { 00402 case STACK_HARDWARE: 00403 core->stack = (Stack *)hwstack_new (stack_sz); 00404 break; 00405 case STACK_MEMORY: 00406 core->stack = (Stack *)memstack_new (core->mem); 00407 break; 00408 default: 00409 avr_error ("Bad stack type.\n"); 00410 } 00411 00412 /* Since these are being stored in two places, we need to ref em */ 00413 00414 avr_core_attach_vdev (core, (VDevice *)core->sreg); 00415 class_ref ((AvrClass *)core->sreg); 00416 00417 avr_core_attach_vdev (core, (VDevice *)core->rampz); 00418 class_ref ((AvrClass *)core->rampz); 00419 00420 avr_core_attach_vdev (core, (VDevice *)core->gpwr); 00421 class_ref ((AvrClass *)core->gpwr); 00422 00423 /* Initialize the decoder lookup table */ 00424 decode_init_lookup_table (); 00425 00426 /* Send initial clock cycles to display */ 00427 display_clock (0); 00428 } 00429 00430 /** 00431 * \brief Destructor for the AvrCore class. 00432 * 00433 * Not to be called directly, except by a derived class. 00434 * Called via class_unref. 00435 */ 00436 void 00437 avr_core_destroy (void *core) 00438 { 00439 AvrCore *_core = (AvrCore *)core; 00440 00441 if (_core == NULL) 00442 return; 00443 00444 class_unref ((AvrClass *)_core->sreg); 00445 class_unref ((AvrClass *)_core->flash); 00446 class_unref ((AvrClass *)_core->gpwr); 00447 class_unref ((AvrClass *)_core->mem); 00448 class_unref ((AvrClass *)_core->stack); 00449 00450 dlist_delete_all (_core->breakpoints); 00451 dlist_delete_all (_core->clk_cb); 00452 dlist_delete_all (_core->async_cb); 00453 dlist_delete_all (_core->irq_pending); 00454 00455 class_destroy (core); 00456 } 00457 00458 /** \brief Query the sizes of the 3 memory spaces: flash, sram, and eeprom. */ 00459 void 00460 avr_core_get_sizes (AvrCore *core, int *flash, int *sram, int *sram_start, 00461 int *eeprom) 00462 { 00463 VDevice *dev; 00464 *flash = flash_get_size (core->flash); 00465 00466 dev = mem_get_vdevice_by_name (core->mem, "SRAM"); 00467 if (dev) 00468 { 00469 *sram = sram_get_size ((SRAM *)dev); 00470 *sram_start = sram_get_base ((SRAM *)dev); 00471 } 00472 else 00473 { 00474 *sram = 0; 00475 *sram_start = 0; 00476 } 00477 00478 dev = mem_get_vdevice_by_name (core->mem, "EEProm"); 00479 if (dev) 00480 *eeprom = eeprom_get_size ((EEProm *)dev); 00481 else 00482 *eeprom = 0; 00483 } 00484 00485 /** \brief Attach a virtual device into the Memory. */ 00486 extern inline void avr_core_attach_vdev (AvrCore *core, VDevice *dev); 00487 00488 /** \brief Returns the \c VDevice with the name \a name. */ 00489 extern inline VDevice *avr_core_get_vdev_by_name (AvrCore *core, char *name); 00490 00491 /** \brief Returns the \c VDevice which handles the address \a addr. */ 00492 extern inline VDevice *avr_core_get_vdev_by_addr (AvrCore *core, int addr); 00493 00494 /** \brief Sets the device's state (running, stopped, breakpoint, sleep). */ 00495 extern inline void avr_core_set_state (AvrCore *core, StateType state); 00496 00497 /** \brief Returns the device's state (running, stopped, breakpoint, sleep). */ 00498 extern inline int avr_core_get_state (AvrCore *core); 00499 00500 /** \brief Sets the device to a sleep state. 00501 * \param core Pointer to the core. 00502 * \param sleep_mode The BITNUMBER of the sleepstate. 00503 */ 00504 extern inline void avr_core_set_sleep_mode (AvrCore *core, int sleep_mode); 00505 00506 /** \brief Return the device's sleepmode. */ 00507 extern inline int avr_core_get_sleep_mode (AvrCore *core); 00508 00509 /*@}*/ 00510 00511 /** \name Program Memory Space Access Methods */ 00512 00513 /*@{*/ 00514 00515 /** \brief Reads a word from flash memory. */ 00516 static inline uint16_t avr_core_flash_read (AvrCore *core, int addr); 00517 00518 /** \brief Writes a word to flash memory. */ 00519 static inline void avr_core_flash_write (AvrCore *core, int addr, 00520 uint16_t val); 00521 00522 /** \brief Writes a byte to flash memory. 00523 * 00524 * This function writes the lower 8 bit of a flash word. 00525 * Use avr_core_flash_write() write to write a full word, 00526 * or avr_core_flash_write_hi8() to write the upper 8 bits. 00527 */ 00528 static inline void avr_core_flash_write_lo8 (AvrCore *core, int addr, 00529 uint8_t val); 00530 00531 /** \brief Writes a byte to flash memory. 00532 * 00533 * This function writes the upper 8 bit of a flash word. 00534 * Use avr_core_flash_write() write to write a full word, 00535 * or avr_core_flash_write_lo8() to write the lower 8 bits. 00536 */ 00537 static inline void avr_core_flash_write_hi8 (AvrCore *core, int addr, 00538 uint8_t val); 00539 00540 /*@}*/ 00541 00542 /** \name Data Memory Space Access Methods */ 00543 00544 /*@{*/ 00545 00546 /** \brief Reads a byte from memory. 00547 * 00548 * This accesses the \a register \a file and the \a SRAM. 00549 */ 00550 static inline uint8_t avr_core_mem_read (AvrCore *core, int addr); 00551 00552 /** \brief Writes a byte to memory. 00553 * 00554 * This accesses the \a register \a file and the \a SRAM. 00555 */ 00556 static inline void avr_core_mem_write (AvrCore *core, int addr, uint8_t val); 00557 00558 /*@}*/ 00559 00560 /** \name Status Register Access Methods */ 00561 00562 /*@{*/ 00563 00564 /** \brief Get the value of the status register. */ 00565 00566 static inline uint8_t avr_core_sreg_get (AvrCore *core); 00567 00568 /** \brief Set the value of the status register. */ 00569 00570 static inline void avr_core_sreg_set (AvrCore *core, uint8_t v); 00571 00572 /** \brief Get the value of bit \c b of the status register. */ 00573 00574 extern inline int avr_core_sreg_get_bit (AvrCore *core, int b); 00575 00576 /** \brief Set the value of bit \c b of the status register. */ 00577 00578 extern inline void avr_core_sreg_set_bit (AvrCore *core, int b, int v); 00579 00580 /*@}*/ 00581 00582 /** \name RAMPZ access methods */ 00583 00584 /*@{*/ 00585 00586 /** \brief Get the value of the rampz register. */ 00587 00588 extern inline uint8_t avr_core_rampz_get (AvrCore *core); 00589 00590 /** \brief Set the value of the rampz register. */ 00591 00592 extern inline void avr_core_rampz_set (AvrCore *core, uint8_t v); 00593 00594 /*@}*/ 00595 00596 /** 00597 * \Name General Purpose Working Register Access Methods 00598 */ 00599 00600 /*@{*/ 00601 00602 /** \brief Returns a GPWR's(\a r0-r31) value. */ 00603 static inline uint8_t avr_core_gpwr_get (AvrCore *core, int reg); 00604 00605 /** \brief Writes a GPWR's (\a r0-r31) value. */ 00606 static inline void avr_core_gpwr_set (AvrCore *core, int reg, uint8_t val); 00607 00608 /*@}*/ 00609 00610 /** 00611 * \name Direct I/O Register Access Methods 00612 * 00613 * IO Registers are mapped in memory directly after the 32 (0x20) 00614 * general registers. 00615 */ 00616 00617 /*@{*/ 00618 00619 /** \brief Displays all registers. */ 00620 void 00621 avr_core_io_display_names (AvrCore *core) 00622 { 00623 int i; 00624 uint8_t val; 00625 char name[80]; 00626 00627 for (i = IO_REG_ADDR_BEGIN; i < IO_REG_ADDR_END; i++) 00628 { 00629 mem_io_fetch (core->mem, i, &val, name, sizeof (name) - 1); 00630 display_io_reg_name (i - IO_REG_ADDR_BEGIN, name); 00631 } 00632 } 00633 00634 /** \brief Reads the value of a register. 00635 * \param core Pointer to the core. 00636 * \param reg The registers address. This address is counted above the 00637 * beginning of the registers memory block (0x20). 00638 */ 00639 extern inline uint8_t avr_core_io_read (AvrCore *core, int reg); 00640 00641 /** \brief Writes the value of a register. 00642 * See avr_core_io_read() for a discussion of \a reg. */ 00643 extern inline void avr_core_io_write (AvrCore *core, int reg, uint8_t val); 00644 00645 /** \brief Read an io register into val and put the name of the register into 00646 * buf. */ 00647 static inline void avr_core_io_fetch (AvrCore *core, int reg, uint8_t * val, 00648 char *buf, int bufsiz); 00649 00650 /*@}*/ 00651 00652 /** \name Stack Methods */ 00653 00654 /*@{*/ 00655 00656 /** \brief Pop 1-4 bytes off of the stack. 00657 * 00658 * See stack_pop() for more details. 00659 */ 00660 extern inline uint32_t avr_core_stack_pop (AvrCore *core, int bytes); 00661 00662 /** \brief Push 1-4 bytes onto the stack. 00663 * 00664 * See stack_push() for more details. 00665 */ 00666 extern inline void avr_core_stack_push (AvrCore *core, int bytes, 00667 uint32_t val); 00668 00669 /*@}*/ 00670 00671 /** \name Program Counter Methods */ 00672 00673 /*@{*/ 00674 00675 /** \brief Returns the size of the Program Counter in bytes. 00676 * 00677 * Most devices have a 16-bit PC (2 bytes), but some larger ones 00678 * (e.g. mega256), have a 22-bit PC (3 bytes). 00679 */ 00680 extern inline int32_t avr_core_PC_size (AvrCore *core); 00681 00682 /** \brief Returns the maximum value of the Program Counter. 00683 * 00684 * This is flash_size / 2. 00685 */ 00686 static inline int32_t avr_core_PC_max (AvrCore *core); 00687 00688 /** \brief Return the current of the Program Counter. */ 00689 static inline int32_t avr_core_PC_get (AvrCore *core); 00690 00691 /** \brief Set the Program Counter to val. 00692 * 00693 * If val is not in the valid range of PC values, it is adjusted to fall in 00694 * the valid range. 00695 */ 00696 static inline void avr_core_PC_set (AvrCore *core, int32_t val); 00697 00698 /** \brief Increment the Program Counter by val. 00699 * 00700 * val can be either positive or negative. 00701 * 00702 * If the result of the incrememt is outside the valid range for PC, it is 00703 * adjusted to fall in the valid range. This allows addresses to wrap around 00704 * the end of the insn space. 00705 */ 00706 extern inline void avr_core_PC_incr (AvrCore *core, int val); 00707 00708 /*@}*/ 00709 00710 /** \name Methods for accessing CK and instruction Clocks */ 00711 00712 /*@{*/ 00713 00714 /** \brief Get the current clock counter. */ 00715 extern inline uint64_t avr_core_CK_get (AvrCore *core); 00716 00717 /** \brief Increment the clock counter. */ 00718 extern inline void avr_core_CK_incr (AvrCore *core); 00719 00720 /** \brief Get the number of clock cycles remaining for the currently 00721 * executing instruction. */ 00722 extern inline int avr_core_inst_CKS_get (AvrCore *core); 00723 00724 /** \brief Set the number of clock cycles for the instruction being 00725 * executed. */ 00726 extern inline void avr_core_inst_CKS_set (AvrCore *core, int val); 00727 00728 /** \name Interrupt Access Methods. */ 00729 00730 /*@{*/ 00731 00732 /** \brief Gets the first pending irq. */ 00733 IntVect * 00734 avr_core_irq_get_pending (AvrCore *core) 00735 { 00736 return irq_get_pending_vector (core->irq_pending, core->state, 00737 core->sleep_mode); 00738 } 00739 00740 /** \brief Raises an irq by adding it's data to the irq_pending list. */ 00741 void 00742 avr_core_irq_raise (AvrCore *core, int irq) 00743 { 00744 IntVect *irq_ptr = &core->irq_vtable[irq]; 00745 00746 #if !defined(DISABLE_IRQ_MESSAGES) 00747 avr_message ("Raising irq # %d [%s at 0x%x]\n", irq, irq_ptr->name, 00748 irq_ptr->addr * 2); 00749 #endif 00750 core->irq_pending = irq_list_add (core->irq_pending, irq_ptr); 00751 } 00752 00753 /** \brief Calls the interrupt's callback to clear the flag. */ 00754 void 00755 avr_core_irq_clear (AvrCore *core, IntVect *irq) 00756 { 00757 core->irq_pending = irq_list_delete (core->irq_pending, irq); 00758 } 00759 00760 /** \brief Removes all irqs from the irq_pending list. */ 00761 extern inline void avr_core_irq_clear_all (AvrCore *core); 00762 00763 /*@}*/ 00764 00765 /** \name Break point access methods. */ 00766 00767 /*@{*/ 00768 00769 /** \brief Inserts a break point. */ 00770 00771 void 00772 avr_core_insert_breakpoint (AvrCore *core, int pc) 00773 { 00774 #define BREAK_OPCODE 0x9598 00775 00776 uint16_t insn = flash_read (core->flash, pc); 00777 00778 core->breakpoints = brk_pt_list_add (core->breakpoints, pc, insn); 00779 00780 flash_write (core->flash, pc, BREAK_OPCODE); 00781 } 00782 00783 /** \brief Removes a break point. */ 00784 00785 void 00786 avr_core_remove_breakpoint (AvrCore *core, int pc) 00787 { 00788 BreakPt *bp; 00789 00790 bp = brk_pt_list_lookup (core->breakpoints, pc); 00791 if (bp) 00792 { 00793 uint16_t insn = bp->opcode; 00794 00795 core->breakpoints = brk_pt_list_delete (core->breakpoints, pc); 00796 00797 flash_write (core->flash, pc, insn); 00798 } 00799 } 00800 00801 #ifndef DOXYGEN /* don't expose to doxygen */ 00802 00803 struct bp_enable_data 00804 { 00805 AvrCore *core; 00806 int enable; 00807 }; 00808 00809 #endif /* DOXYGEN */ 00810 00811 static int 00812 iter_enable_breakpoint (AvrClass *data, void *user_data) 00813 { 00814 BreakPt *bp = (BreakPt *)data; 00815 struct bp_enable_data *bed = (struct bp_enable_data *)user_data; 00816 00817 if (bed->enable) 00818 { 00819 uint16_t insn = flash_read (bed->core->flash, bp->pc); 00820 00821 if (insn != BREAK_OPCODE) 00822 { 00823 /* Enable the breakpoint */ 00824 bp->opcode = insn; 00825 flash_write (bed->core->flash, bp->pc, BREAK_OPCODE); 00826 } 00827 } 00828 else 00829 { 00830 /* Disable the breakpoint */ 00831 flash_write (bed->core->flash, bp->pc, bp->opcode); 00832 } 00833 00834 return 0; /* Don't delete any item from the list. */ 00835 } 00836 00837 /** \brief Disable breakpoints. 00838 00839 Disables all breakpoints that where set using avr_core_insert_breakpoint(). 00840 The breakpoints are not removed from the breakpoint list. */ 00841 00842 void 00843 avr_core_disable_breakpoints (AvrCore *core) 00844 { 00845 struct bp_enable_data bed = { core, 0 }; 00846 00847 core->breakpoints = 00848 brk_pt_iterator (core->breakpoints, iter_enable_breakpoint, &bed); 00849 } 00850 00851 /** \brief Enable breakpoints. 00852 00853 Enables all breakpoints that where previous disabled. */ 00854 00855 void 00856 avr_core_enable_breakpoints (AvrCore *core) 00857 { 00858 struct bp_enable_data bed = { core, 1 }; 00859 00860 core->breakpoints = 00861 brk_pt_iterator (core->breakpoints, iter_enable_breakpoint, &bed); 00862 } 00863 00864 /*@}*/ 00865 00866 /* Private 00867 00868 Execute an instruction. 00869 Presets the number of instruction clocks to zero so that break points and 00870 invalid opcodes don't add extraneous clock counts. 00871 00872 Also checks for software breakpoints. 00873 Any opcode except 0xffff can be a breakpoint. 00874 00875 Returns BREAK_POINT, or >= 0. */ 00876 00877 static int 00878 exec_next_instruction (AvrCore *core) 00879 { 00880 int result, pc; 00881 uint16_t opcode; 00882 struct opcode_info *opi; 00883 00884 pc = avr_core_PC_get (core); 00885 opcode = flash_read (core->flash, pc); 00886 00887 /* Preset the number of instruction clocks to zero so that break points 00888 and invalid opcodes don't add extraneous clock counts. */ 00889 avr_core_inst_CKS_set (core, 0); 00890 00891 opi = decode_opcode (opcode); 00892 00893 result = opi->func (core, opcode, opi->arg1, opi->arg2); 00894 00895 if (global_debug_inst_output) 00896 fprintf (stderr, "0x%06x (0x%06x) : 0x%04x : %s\n", pc, pc * 2, 00897 opcode, global_opcode_name[result]); 00898 00899 return result; 00900 } 00901 00902 /** \name Program control methods */ 00903 00904 /*@{*/ 00905 00906 /* 00907 * Private 00908 * 00909 * Checks to see if an interrupt is pending. If any are pending, and 00910 * if SREG(I) is set, the following will occur: 00911 * - push current PC onto stack 00912 * - PC <- interrupt vector 00913 * - I flag of SREG is cleared 00914 * 00915 * Reset vector is not controlled by the SREG(I) flag, thus if reset 00916 * interrupt has occurred, the device will be reset irregardless of state 00917 * of SREG(I). 00918 * 00919 * \note There are different ways of doing this: 00920 * - In register.c wdtcr_intr_cb() we can directly reset the MCU without 00921 * the use of irqs. This would require to make the callback an async 00922 * callback and it would allow the speed improvments commented out below 00923 * to be activated. 00924 * - Keep it as an interrupt an waste CPU time. 00925 * 00926 * Ted, what do you think we should do? 00927 */ 00928 00929 static void 00930 avr_core_check_interrupts (AvrCore *core) 00931 { 00932 IntVect *irq; 00933 00934 if (core->irq_pending) 00935 { 00936 irq = avr_core_irq_get_pending (core); 00937 00938 if (irq) 00939 { 00940 if (irq->name == NULL) 00941 { 00942 avr_error ("Raised an invalid irq for device"); 00943 } 00944 00945 if (irq->addr == IRQ_RESET_ADDR) 00946 { 00947 /* The global interrupt (SREG.I) never blocks a reset. We 00948 don't need to clear the irq since a reset clears all 00949 pending irq's. */ 00950 avr_core_reset (core); 00951 } 00952 00953 if (avr_core_sreg_get_bit (core, SREG_I)) 00954 { 00955 int pc = avr_core_PC_get (core); 00956 int pc_bytes = avr_core_PC_size (core); 00957 00958 avr_core_stack_push (core, pc_bytes, pc); 00959 avr_core_sreg_set_bit (core, SREG_I, 0); 00960 00961 #if !defined(DISABLE_IRQ_MESSAGES) 00962 avr_message ("Vectoring to irq at addr:0x%x offset:0x%x\n", 00963 irq->addr * 2, core->irq_offset * 2); 00964 #endif 00965 00966 avr_core_PC_set (core, irq->addr + core->irq_offset); 00967 00968 avr_core_irq_clear (core, irq); 00969 } 00970 } 00971 } 00972 } 00973 00974 /** 00975 * \brief Process a single program instruction, all side effects and 00976 * peripheral stimulii. 00977 * 00978 * Executes instructions, calls callbacks, and checks for interrupts. */ 00979 00980 int 00981 avr_core_step (AvrCore *core) 00982 { 00983 int res = 0; 00984 int state; 00985 00986 /* The MCU is stopped when in one of the many sleep modes */ 00987 state = avr_core_get_state (core); 00988 if (state != STATE_SLEEP) 00989 { 00990 /* execute an instruction; may change state */ 00991 res = exec_next_instruction (core); 00992 } 00993 00994 /* Execute the clock callbacks */ 00995 while (core->inst_CKS > 0) 00996 { 00997 /* propagate clocks here */ 00998 avr_core_clk_cb_exec (core); 00999 01000 avr_core_CK_incr (core); 01001 01002 core->inst_CKS--; 01003 } 01004 01005 /* FIXME: async cb's and interrupt checking might need to be put 01006 somewhere else. */ 01007 01008 /* Execute the asynchronous callbacks */ 01009 avr_core_async_cb_exec (core); 01010 01011 /* Check interrupts here. If the previous instruction was a reti, then we 01012 need to delay handling of any pending IRQs until after the next 01013 instruction is executed. */ 01014 if (res != opcode_RETI) 01015 avr_core_check_interrupts (core); 01016 01017 return res; 01018 } 01019 01020 /** \brief Start the processing of instructions by the simulator. 01021 * 01022 * The simulated device will run until one of the following occurs: 01023 * - The state of the core is no longer STATE_RUNNING. 01024 * - The simulator receives a SIGINT signal. 01025 * - A breakpoint is reached (currently causes core to stop running). 01026 * - A fatal internal error occurs. 01027 * 01028 * \note When running simulavr in gdb server mode, this function is not 01029 * used. The avr_core_step() function is called repeatedly in a loop when the 01030 * continue command is issued from gdb. As such, the functionality in this 01031 * loop should be kept to a minimum. 01032 * 01033 * \todo Should add some basic breakpoint handling here. Maybe allow 01034 * continuing, and simple breakpoint management (disable, delete, set) 01035 */ 01036 01037 void 01038 avr_core_run (AvrCore *core) 01039 { 01040 uint64_t cnt = 0; 01041 int res; 01042 uint64_t start_time, run_time; 01043 01044 avr_core_reset (core); /* make sure the device is in a sane state. */ 01045 01046 core->state = STATE_RUNNING; 01047 01048 signal_watch_start (SIGINT); 01049 01050 /* FIXME: [TRoth 2002/03/19] This loop isn't going to handle sleep or idle 01051 modes properly. */ 01052 01053 start_time = get_program_time (); 01054 while (core->state == STATE_RUNNING) 01055 { 01056 if (signal_has_occurred (SIGINT)) 01057 break; 01058 01059 res = avr_core_step (core); 01060 01061 if (res == BREAK_POINT) 01062 break; 01063 01064 cnt++; 01065 } 01066 run_time = get_program_time () - start_time; 01067 01068 signal_watch_stop (SIGINT); 01069 01070 avr_message ("Run time was %lld.%03lld seconds.\n", run_time / 1000, 01071 run_time % 1000); 01072 avr_message ("Executed %lld instructions.\n", cnt); 01073 avr_message (" %lld insns/sec\n", (cnt * 1000) / run_time); 01074 avr_message ("Executed %lld clock cycles.\n", avr_core_CK_get (core)); 01075 avr_message (" %lld clks/sec\n", 01076 (avr_core_CK_get (core) * 1000) / run_time); 01077 } 01078 01079 /** \brief Sets the simulated CPU back to its initial state. 01080 * 01081 * Zeroes out PC, IRQ's, clock, and memory. 01082 */ 01083 01084 void 01085 avr_core_reset (AvrCore *core) 01086 { 01087 avr_core_PC_set (core, 0); 01088 avr_core_irq_clear_all (core); 01089 01090 avr_core_inst_CKS_set (core, 0); 01091 01092 /* Send clock cycles to display. 01093 Normaly the clockcycles must not be reset here! 01094 This leads to an error in the vcd file. */ 01095 01096 display_clock (core->CK); 01097 01098 mem_reset (core->mem); 01099 } 01100 01101 /*@}*/ 01102 01103 /** \name Callback Handling Methods */ 01104 01105 /*@{*/ 01106 01107 /** 01108 * \brief For adding external read and write callback functions. 01109 * 01110 * rd and wr should come in pairs, but it is safe to add 01111 * empty function via passing a NULL pointer for either function. 01112 * 01113 * \param core A pointer to an AvrCore object. 01114 * 01115 * \param port_id The ID for handling the simulavr inheritance model. 01116 * 01117 * \param ext_rd Function for the device core to call when it needs to 01118 * communicate with the external world via I/O Ports. 01119 * 01120 * \param ext_wr Function for the device core to call when it needs to 01121 * communicate with the external world via I/O Ports. 01122 * 01123 */ 01124 void 01125 avr_core_add_ext_rd_wr (AvrCore *core, int port_id, PortFP_ExtRd ext_rd, 01126 PortFP_ExtWr ext_wr) 01127 { 01128 Port *p = (Port *)mem_get_vdevice_by_name (core->mem, name_PORT[port_id]); 01129 01130 if (p == NULL) 01131 { 01132 avr_warning ("Device does not have %s.\n", name_PORT[port_id]); 01133 return; 01134 } 01135 01136 port_add_ext_rd_wr (p, ext_rd, ext_wr); 01137 } 01138 01139 /** 01140 * \brief Add a new clock callback to list. 01141 */ 01142 extern inline void avr_core_clk_cb_add (AvrCore *core, CallBack *cb); 01143 01144 /** 01145 * \brief Add a new asynchronous callback to list. 01146 */ 01147 extern inline void avr_core_async_cb_add (AvrCore *core, CallBack *cb); 01148 01149 /** \brief Run all the callbacks in the list. 01150 01151 If a callback returns non-zero (true), then it is done with it's job and 01152 wishes to be removed from the list. 01153 01154 The time argument has dual meaning. If the callback list is for the clock 01155 callbacks, time is the value of the CK clock counter. If the callback list 01156 is for the asynchronous callback, time is the number of milliseconds from 01157 some unknown, arbitrary time on the host system. */ 01158 01159 extern inline void avr_core_clk_cb_exec (AvrCore *core); 01160 01161 /** 01162 * \brief Run all the asynchronous callbacks. 01163 */ 01164 extern inline void avr_core_async_cb_exec (AvrCore *core); 01165 01166 /*@}*/ 01167 01168 /** 01169 * \brief Dump the contents of the entire CPU core. 01170 * 01171 * \param core A pointer to an AvrCore object. 01172 * \param f_core An open file descriptor. 01173 */ 01174 void 01175 avr_core_dump_core (AvrCore *core, FILE * f_core) 01176 { 01177 unsigned int pc = avr_core_PC_get (core); 01178 01179 fprintf (f_core, "PC = 0x%06x (PC*2 = 0x%06x)\n\n", pc, pc * 2); 01180 mem_dump_core (core->mem, f_core); 01181 flash_dump_core (core->flash, f_core); 01182 } 01183 01184 /** 01185 * \brief Load a program from an input file. 01186 */ 01187 int 01188 avr_core_load_program (AvrCore *core, char *file, int format) 01189 { 01190 return flash_load_from_file (core->flash, file, format); 01191 } 01192 01193 /** \brief Load a program from an input file. */ 01194 int 01195 avr_core_load_eeprom (AvrCore *core, char *file, int format) 01196 { 01197 EEProm *ee = (EEProm *)mem_get_vdevice_by_name (core->mem, "EEProm"); 01198 01199 return eeprom_load_from_file (ee, file, format); 01200 }

Automatically generated by Doxygen 1.3.8 on 11 Aug 2004.