avrcore.c

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

Automatically generated by Doxygen 1.5.2 on 3 Dec 2007.