Main Page | Directories | File List | Globals | Related Pages

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 
00398     core->breakpoints = NULL;
00399 
00400     core->irq_pending = NULL;
00401     core->irq_vtable = (IntVect *)(global_vtable_list[vtab_idx]);
00402     core->irq_offset = 0;
00403 
00404     core->CK = 0;
00405     core->inst_CKS = 0;
00406 
00407     core->clk_cb = NULL;
00408     core->async_cb = NULL;
00409 
00410     /* FIXME: hack to get it to compile. */
00411     if (dev_supp_has_ext_io_reg (dev))
00412         core->mem = mem_new (0x1f, 0xff, 0xff + sram_sz, 0xffff);
00413     else
00414         core->mem = mem_new (0x1f, 0x5f, 0x5f + sram_sz, 0xffff);
00415 
00416     /* Attach the gpwr's to the memory bus. */
00417 
00418     core->gpwr = gpwr_new ();
00419     for (addr = 0; addr < 0x20; addr++)
00420     {
00421         static char *reg_name[] = { "r00", "r01", "r02", "r03", "r04", "r05",
00422                                     "r06", "r07", "r08", "r09", "r10", "r11",
00423                                     "r12", "r13", "r14", "r15", "r16", "r17",
00424                                     "r18", "r19", "r20", "r21", "r22", "r23",
00425                                     "r24", "r25", "r26", "r27", "r28", "r29",
00426                                     "r30", "r31" };
00427 
00428         avr_core_attach_vdev (core, addr, reg_name[addr],
00429                               (VDevice *)core->gpwr, 0, 0, 0xff, 0xff);
00430     }
00431 
00432     dev_supp_attach_io_regs (core, dev);
00433 
00434     /* Set up the stack. */
00435 
00436     if (stack_sz)
00437     {
00438         core->stack = (Stack *)hwstack_new (stack_sz);
00439     }
00440     else
00441     {
00442         /* Assuming that SPL is always at 0x5d. */
00443 
00444         core->stack = (Stack *)memstack_new (core->mem, 0x5d);
00445     }
00446 
00447     /* Assuming the SREG is always at 0x5f. */
00448 
00449     core->sreg = (SREG *)avr_core_get_vdev_by_addr (core, 0x5f);
00450     class_ref ((AvrClass *)core->sreg);
00451 
00452     /* Assuming that RAMPZ is always at 0x5b. If the device doesn't support
00453        RAMPZ, install a NULL pointer. */
00454 
00455     core->rampz = (RAMPZ *)avr_core_get_vdev_by_addr (core, 0x5b);
00456     if (core->rampz)
00457         class_ref ((AvrClass *)core->rampz);
00458 
00459     /* Attach the internal sram to the memory bus if needed. */
00460 
00461     if (sram_sz)
00462     {
00463         int base;
00464         VDevice *sram;
00465 
00466         if (dev_supp_has_ext_io_reg (dev))
00467             base = SRAM_EXTENDED_IO_BASE;
00468         else
00469             base = SRAM_BASE;
00470 
00471         core->sram = sram_new (base, sram_sz);
00472         sram = (VDevice *)core->sram;
00473 
00474         avr_message ("attach: Internal SRAM from 0x%04x to 0x%04x\n", base,
00475                      (base + sram_sz - 1));
00476 
00477         for (addr = base; addr < (base + sram_sz); addr++)
00478         {
00479             avr_core_attach_vdev (core, addr, "Internal SRAM", sram, 0, 0,
00480                                   0xff, 0xff);
00481         }
00482     }
00483     else
00484     {
00485         core->sram = NULL;
00486     }
00487 
00488     /* Initialize the decoder lookup table */
00489 
00490     decode_init_lookup_table ();
00491 }
00492 
00493 /**
00494  * \brief Destructor for the AvrCore class.
00495  * 
00496  * Not to be called directly, except by a derived class.
00497  * Called via class_unref.
00498  */
00499 void
00500 avr_core_destroy (void *core)
00501 {
00502     AvrCore *_core = (AvrCore *)core;
00503 
00504     if (_core == NULL)
00505         return;
00506 
00507     class_unref ((AvrClass *)_core->sreg);
00508     class_unref ((AvrClass *)_core->flash);
00509     class_unref ((AvrClass *)_core->gpwr);
00510     class_unref ((AvrClass *)_core->mem);
00511     class_unref ((AvrClass *)_core->stack);
00512 
00513     dlist_delete_all (_core->breakpoints);
00514     dlist_delete_all (_core->clk_cb);
00515     dlist_delete_all (_core->async_cb);
00516     dlist_delete_all (_core->irq_pending);
00517 
00518     class_destroy (core);
00519 }
00520 
00521 /** \brief Query the sizes of the 3 memory spaces: flash, sram, and eeprom. */
00522 void
00523 avr_core_get_sizes (AvrCore *core, int *flash, int *sram, int *sram_start,
00524                     int *eeprom)
00525 {
00526     *flash = flash_get_size (core->flash);
00527 
00528     if (core->sram)
00529     {
00530         *sram = sram_get_size (core->sram);
00531         *sram_start = sram_get_base (core->sram);
00532     }
00533     else
00534     {
00535         *sram = 0;
00536         *sram_start = 0;
00537     }
00538 
00539     if (core->eeprom)
00540         *eeprom = eeprom_get_size (core->eeprom);
00541     else
00542         *eeprom = 0;
00543 }
00544 
00545 /** \brief Attach a virtual device into the Memory. */
00546 extern inline void avr_core_attach_vdev (AvrCore *core, uint16_t addr,
00547                                          char *name, VDevice *vdev,
00548                                          int flags, uint8_t reset_value,
00549                                          uint8_t rd_mask, uint8_t wr_mask);
00550 
00551 /** \brief Returns the \c VDevice with the name \a name. */
00552 extern inline VDevice *avr_core_get_vdev_by_name (AvrCore *core, char *name);
00553 
00554 /** \brief Returns the \c VDevice which handles the address \a addr. */
00555 extern inline VDevice *avr_core_get_vdev_by_addr (AvrCore *core, int addr);
00556 
00557 /** \brief Sets the device's state (running, stopped, breakpoint, sleep). */
00558 extern inline void avr_core_set_state (AvrCore *core, StateType state);
00559 
00560 /** \brief Returns the device's state (running, stopped, breakpoint, sleep). */
00561 extern inline int avr_core_get_state (AvrCore *core);
00562 
00563 /** \brief Sets the device to a sleep state.
00564   * \param core Pointer to the core.
00565   * \param sleep_mode The BITNUMBER of the sleepstate.
00566   */
00567 extern inline void avr_core_set_sleep_mode (AvrCore *core, int sleep_mode);
00568 
00569 /** \brief Return the device's sleepmode. */
00570 extern inline int avr_core_get_sleep_mode (AvrCore *core);
00571 
00572 /*@}*/
00573 
00574 /** \name Program Memory Space Access Methods */
00575 
00576 /*@{*/
00577 
00578 /** \brief Reads a word from flash memory. */
00579 static inline uint16_t avr_core_flash_read (AvrCore *core, int addr);
00580 
00581 /** \brief Writes a word to flash memory. */
00582 static inline void avr_core_flash_write (AvrCore *core, int addr,
00583                                          uint16_t val);
00584 
00585 /** \brief Writes a byte to flash memory.
00586   *
00587   * This function writes the lower 8 bit of a flash word.
00588   * Use avr_core_flash_write() write to write a full word,
00589   * or avr_core_flash_write_hi8() to write the upper 8 bits.
00590   */
00591 static inline void avr_core_flash_write_lo8 (AvrCore *core, int addr,
00592                                              uint8_t val);
00593 
00594 /** \brief Writes a byte to flash memory.
00595   *
00596   * This function writes the upper 8 bit of a flash word.
00597   * Use avr_core_flash_write() write to write a full word,
00598   * or avr_core_flash_write_lo8() to write the lower 8 bits.
00599   */
00600 static inline void avr_core_flash_write_hi8 (AvrCore *core, int addr,
00601                                              uint8_t val);
00602 
00603 /*@}*/
00604 
00605 /** \name Data Memory Space Access Methods */
00606 
00607 /*@{*/
00608 
00609 /** \brief Reads a byte from memory.
00610   *
00611   * This accesses the \a register \a file and the \a SRAM.
00612   */
00613 static inline uint8_t avr_core_mem_read (AvrCore *core, int addr);
00614 
00615 /** \brief Writes a byte to memory.
00616   *
00617   * This accesses the \a register \a file and the \a SRAM.
00618   */
00619 static inline void avr_core_mem_write (AvrCore *core, int addr, uint8_t val);
00620 
00621 /*@}*/
00622 
00623 /** \name Status Register Access Methods */
00624 
00625 /*@{*/
00626 
00627 /** \brief Get the value of the status register. */
00628 
00629 static inline uint8_t avr_core_sreg_get (AvrCore *core);
00630 
00631 /** \brief Set the value of the status register. */
00632 
00633 static inline void avr_core_sreg_set (AvrCore *core, uint8_t v);
00634 
00635 /** \brief Get the value of bit \c b of the status register. */
00636 
00637 extern inline int avr_core_sreg_get_bit (AvrCore *core, int b);
00638 
00639 /** \brief Set the value of bit \c b of the status register. */
00640 
00641 extern inline void avr_core_sreg_set_bit (AvrCore *core, int b, int v);
00642 
00643 /*@}*/
00644 
00645 /** \name RAMPZ access methods */
00646 
00647 /*@{*/
00648 
00649 /** \brief Get the value of the rampz register. */
00650 
00651 extern inline uint8_t avr_core_rampz_get (AvrCore *core);
00652 
00653 /** \brief Set the value of the rampz register. */
00654 
00655 extern inline void avr_core_rampz_set (AvrCore *core, uint8_t v);
00656 
00657 /*@}*/
00658 
00659 /**
00660  * \Name General Purpose Working Register Access Methods
00661  */
00662 
00663 /*@{*/
00664 
00665 /** \brief Returns a GPWR's(\a r0-r31) value. */
00666 static inline uint8_t avr_core_gpwr_get (AvrCore *core, int reg);
00667 
00668 /** \brief Writes a GPWR's (\a r0-r31) value. */
00669 static inline void avr_core_gpwr_set (AvrCore *core, int reg, uint8_t val);
00670 
00671 /*@}*/
00672 
00673 /**
00674  * \name Direct I/O Register Access Methods
00675  *
00676  * IO Registers are mapped in memory directly after the 32 (0x20)
00677  * general registers.
00678  */
00679 
00680 /*@{*/
00681 
00682 /** \brief Displays all registers. */
00683 void
00684 avr_core_io_display_names (AvrCore *core)
00685 {
00686     int i;
00687     uint8_t val;
00688     char name[80];
00689 
00690     for (i = IO_REG_ADDR_BEGIN; i < IO_REG_ADDR_END; i++)
00691     {
00692         mem_io_fetch (core->mem, i, &val, name, sizeof (name) - 1);
00693         display_io_reg_name (i - IO_REG_ADDR_BEGIN, name);
00694     }
00695 }
00696 
00697 /** \brief Reads the value of a register.
00698   * \param core Pointer to the core.
00699   * \param reg The registers address. This address is counted above the
00700   *  beginning of the registers memory block (0x20).
00701   */
00702 extern inline uint8_t avr_core_io_read (AvrCore *core, int reg);
00703 
00704 /** \brief Writes the value of a register.
00705   * See avr_core_io_read() for a discussion of \a reg. */
00706 extern inline void avr_core_io_write (AvrCore *core, int reg, uint8_t val);
00707 
00708 /** \brief Read an io register into val and put the name of the register into
00709   * buf. */
00710 static inline void avr_core_io_fetch (AvrCore *core, int reg, uint8_t * val,
00711                                       char *buf, int bufsiz);
00712 
00713 /*@}*/
00714 
00715 /** \name Stack Methods */
00716 
00717 /*@{*/
00718 
00719 /** \brief Pop 1-4 bytes off of the stack.
00720  *
00721  * See stack_pop() for more details.
00722  */
00723 extern inline uint32_t avr_core_stack_pop (AvrCore *core, int bytes);
00724 
00725 /** \brief Push 1-4 bytes onto the stack.
00726  *
00727  * See stack_push() for more details.
00728  */
00729 extern inline void avr_core_stack_push (AvrCore *core, int bytes,
00730                                         uint32_t val);
00731 
00732 /*@}*/
00733 
00734 /** \name Program Counter Methods */
00735 
00736 /*@{*/
00737 
00738 /** \brief Returns the size of the Program Counter in bytes.
00739  *
00740  * Most devices have a 16-bit PC (2 bytes), but some larger ones
00741  * (e.g. mega256), have a 22-bit PC (3 bytes).
00742  */
00743 extern inline int32_t avr_core_PC_size (AvrCore *core);
00744 
00745 /** \brief Returns the maximum value of the Program Counter.
00746  *
00747  * This is flash_size / 2.
00748  */
00749 static inline int32_t avr_core_PC_max (AvrCore *core);
00750 
00751 /** \brief Return the current of the Program Counter. */
00752 static inline int32_t avr_core_PC_get (AvrCore *core);
00753 
00754 /** \brief Set the Program Counter to val.
00755  *
00756  * If val is not in the valid range of PC values, it is adjusted to fall in
00757  * the valid range.
00758  */
00759 static inline void avr_core_PC_set (AvrCore *core, int32_t val);
00760 
00761 /** \brief Increment the Program Counter by val.
00762  *
00763  * val can be either positive or negative.
00764  *
00765  * If the result of the incrememt is outside the valid range for PC, it is
00766  * adjusted to fall in the valid range. This allows addresses to wrap around
00767  * the end of the insn space.
00768  */
00769 extern inline void avr_core_PC_incr (AvrCore *core, int val);
00770 
00771 /*@}*/
00772 
00773 /** \name Methods for accessing CK and instruction Clocks */
00774 
00775 /*@{*/
00776 
00777 /** \brief Get the current clock counter. */
00778 extern inline uint64_t avr_core_CK_get (AvrCore *core);
00779 
00780 /** \brief Increment the clock counter. */
00781 extern inline void avr_core_CK_incr (AvrCore *core);
00782 
00783 /** \brief Get the number of clock cycles remaining for the currently
00784  *  executing instruction. */
00785 extern inline int avr_core_inst_CKS_get (AvrCore *core);
00786 
00787 /** \brief Set the number of clock cycles for the instruction being
00788  *  executed. */
00789 extern inline void avr_core_inst_CKS_set (AvrCore *core, int val);
00790 
00791 /** \name Interrupt Access Methods. */
00792 
00793 /*@{*/
00794 
00795 /** \brief Gets the first pending irq. */
00796 IntVect *
00797 avr_core_irq_get_pending (AvrCore *core)
00798 {
00799     return irq_get_pending_vector (core->irq_pending, core->state,
00800                                    core->sleep_mode);
00801 }
00802 
00803 /** \brief Raises an irq by adding it's data to the irq_pending list. */
00804 void
00805 avr_core_irq_raise (AvrCore *core, int irq)
00806 {
00807     IntVect *irq_ptr = &core->irq_vtable[irq];
00808 
00809 #if !defined(DISABLE_IRQ_MESSAGES)
00810     avr_message ("Raising irq # %d [%s at 0x%x]\n", irq, irq_ptr->name,
00811                  irq_ptr->addr * 2);
00812 #endif
00813     core->irq_pending = irq_list_add (core->irq_pending, irq_ptr);
00814 }
00815 
00816 /** \brief Calls the interrupt's callback to clear the flag. */
00817 void
00818 avr_core_irq_clear (AvrCore *core, IntVect *irq)
00819 {
00820     core->irq_pending = irq_list_delete (core->irq_pending, irq);
00821 }
00822 
00823 /** \brief Removes all irqs from the irq_pending list. */
00824 extern inline void avr_core_irq_clear_all (AvrCore *core);
00825 
00826 /*@}*/
00827 
00828 /** \name Break point access methods. */
00829 
00830 /*@{*/
00831 
00832 /** \brief Inserts a break point. */
00833 
00834 void
00835 avr_core_insert_breakpoint (AvrCore *core, int pc)
00836 {
00837 #define BREAK_OPCODE 0x9598
00838 
00839     uint16_t insn = flash_read (core->flash, pc);
00840 
00841     core->breakpoints = brk_pt_list_add (core->breakpoints, pc, insn);
00842 
00843     flash_write (core->flash, pc, BREAK_OPCODE);
00844 }
00845 
00846 /** \brief Removes a break point. */
00847 
00848 void
00849 avr_core_remove_breakpoint (AvrCore *core, int pc)
00850 {
00851     BreakPt *bp;
00852 
00853     bp = brk_pt_list_lookup (core->breakpoints, pc);
00854     if (bp)
00855     {
00856         uint16_t insn = bp->opcode;
00857 
00858         core->breakpoints = brk_pt_list_delete (core->breakpoints, pc);
00859 
00860         flash_write (core->flash, pc, insn);
00861     }
00862 }
00863 
00864 #ifndef DOXYGEN                 /* don't expose to doxygen */
00865 
00866 struct bp_enable_data
00867 {
00868     AvrCore *core;
00869     int enable;
00870 };
00871 
00872 #endif /* DOXYGEN */
00873 
00874 static int
00875 iter_enable_breakpoint (AvrClass *data, void *user_data)
00876 {
00877     BreakPt *bp = (BreakPt *)data;
00878     struct bp_enable_data *bed = (struct bp_enable_data *)user_data;
00879 
00880     if (bed->enable)
00881     {
00882         uint16_t insn = flash_read (bed->core->flash, bp->pc);
00883 
00884         if (insn != BREAK_OPCODE)
00885         {
00886             /* Enable the breakpoint */
00887             bp->opcode = insn;
00888             flash_write (bed->core->flash, bp->pc, BREAK_OPCODE);
00889         }
00890     }
00891     else
00892     {
00893         /* Disable the breakpoint */
00894         flash_write (bed->core->flash, bp->pc, bp->opcode);
00895     }
00896 
00897     return 0;                   /* Don't delete any item from the list. */
00898 }
00899 
00900 /** \brief Disable breakpoints.
00901 
00902     Disables all breakpoints that where set using avr_core_insert_breakpoint().
00903     The breakpoints are not removed from the breakpoint list.  */
00904 
00905 void
00906 avr_core_disable_breakpoints (AvrCore *core)
00907 {
00908     struct bp_enable_data bed = { core, 0 };
00909 
00910     core->breakpoints =
00911         brk_pt_iterator (core->breakpoints, iter_enable_breakpoint, &bed);
00912 }
00913 
00914 /** \brief Enable breakpoints. 
00915 
00916     Enables all breakpoints that where previous disabled. */
00917 
00918 void
00919 avr_core_enable_breakpoints (AvrCore *core)
00920 {
00921     struct bp_enable_data bed = { core, 1 };
00922 
00923     core->breakpoints =
00924         brk_pt_iterator (core->breakpoints, iter_enable_breakpoint, &bed);
00925 }
00926 
00927 /*@}*/
00928 
00929 /* Private
00930   
00931    Execute an instruction.
00932    Presets the number of instruction clocks to zero so that break points and
00933    invalid opcodes don't add extraneous clock counts.
00934    
00935    Also checks for software breakpoints. 
00936    Any opcode except 0xffff can be a breakpoint.
00937    
00938    Returns BREAK_POINT, or >= 0. */
00939 
00940 static int
00941 exec_next_instruction (AvrCore *core)
00942 {
00943     int result, pc;
00944     uint16_t opcode;
00945     struct opcode_info *opi;
00946 
00947     pc = avr_core_PC_get (core);
00948     opcode = flash_read (core->flash, pc);
00949 
00950     /* Preset the number of instruction clocks to zero so that break points
00951        and invalid opcodes don't add extraneous clock counts. */
00952     avr_core_inst_CKS_set (core, 0);
00953 
00954     opi = decode_opcode (opcode);
00955 
00956     result = opi->func (core, opcode, opi->arg1, opi->arg2);
00957 
00958     if (global_debug_inst_output)
00959         fprintf (stderr, "0x%06x (0x%06x) : 0x%04x : %s\n", pc, pc * 2,
00960                  opcode, global_opcode_name[result]);
00961 
00962     return result;
00963 }
00964 
00965 /** \name Program control methods */
00966 
00967 /*@{*/
00968 
00969 /*
00970  * Private
00971  *
00972  * Checks to see if an interrupt is pending. If any are pending, and
00973  * if SREG(I) is set, the following will occur:
00974  *   - push current PC onto stack
00975  *   - PC <- interrupt vector
00976  *   - I flag of SREG is cleared
00977  *
00978  * Reset vector is not controlled by the SREG(I) flag, thus if reset
00979  * interrupt has occurred, the device will be reset irregardless of state
00980  * of SREG(I).
00981  *
00982  * \note There are different ways of doing this:
00983  * - In register.c  wdtcr_intr_cb() we can directly reset the MCU without
00984  *   the use of irqs. This would require to make the callback an async
00985  *   callback and it would allow the speed improvments commented out below
00986  *   to be activated.
00987  * - Keep it as an interrupt an waste CPU time.
00988  *
00989  * Ted, what do you think we should do?
00990  */
00991 
00992 static void
00993 avr_core_check_interrupts (AvrCore *core)
00994 {
00995     IntVect *irq;
00996 
00997     if (core->irq_pending)
00998     {
00999         irq = avr_core_irq_get_pending (core);
01000 
01001         if (irq)
01002         {
01003             if (irq->name == NULL)
01004             {
01005                 avr_error ("Raised an invalid irq for device");
01006             }
01007 
01008             if (irq->addr == IRQ_RESET_ADDR)
01009             {
01010                 /* The global interrupt (SREG.I) never blocks a reset. We
01011                    don't need to clear the irq since a reset clears all
01012                    pending irq's. */
01013                 avr_core_reset (core);
01014             }
01015 
01016             if (avr_core_sreg_get_bit (core, SREG_I))
01017             {
01018                 int pc = avr_core_PC_get (core);
01019                 int pc_bytes = avr_core_PC_size (core);
01020 
01021                 avr_core_stack_push (core, pc_bytes, pc);
01022                 avr_core_sreg_set_bit (core, SREG_I, 0);
01023 
01024 #if !defined(DISABLE_IRQ_MESSAGES)
01025                 avr_message ("Vectoring to irq at addr:0x%x offset:0x%x\n",
01026                              irq->addr * 2, core->irq_offset * 2);
01027 #endif
01028 
01029                 avr_core_PC_set (core, irq->addr + core->irq_offset);
01030 
01031                 avr_core_irq_clear (core, irq);
01032             }
01033         }
01034     }
01035 }
01036 
01037 /**
01038  * \brief Process a single program instruction, all side effects and
01039  * peripheral stimulii.
01040  *
01041  * Executes instructions, calls callbacks, and checks for interrupts.  */
01042 
01043 int
01044 avr_core_step (AvrCore *core)
01045 {
01046     int res = 0;
01047     int state;
01048 
01049     /* The MCU is stopped when in one of the many sleep modes */
01050     state = avr_core_get_state (core);
01051     if (state != STATE_SLEEP)
01052     {
01053         /* execute an instruction; may change state */
01054         res = exec_next_instruction (core);
01055     }
01056 
01057     /* Execute the clock callbacks */
01058     while (core->inst_CKS > 0)
01059     {
01060         /* propagate clocks here */
01061         avr_core_clk_cb_exec (core);
01062 
01063         avr_core_CK_incr (core);
01064 
01065         core->inst_CKS--;
01066     }
01067 
01068     /* FIXME: async cb's and interrupt checking might need to be put 
01069        somewhere else. */
01070 
01071     /* Execute the asynchronous callbacks */
01072     avr_core_async_cb_exec (core);
01073 
01074     /* Check interrupts here. If the previous instruction was a reti, then we
01075        need to delay handling of any pending IRQs until after the next
01076        instruction is executed. */
01077     if (res != opcode_RETI)
01078         avr_core_check_interrupts (core);
01079 
01080     return res;
01081 }
01082 
01083 /** \brief Start the processing of instructions by the simulator.
01084  *
01085  * The simulated device will run until one of the following occurs:
01086  *   - The state of the core is no longer STATE_RUNNING.
01087  *   - The simulator receives a SIGINT signal.
01088  *   - A breakpoint is reached (currently causes core to stop running).
01089  *   - A fatal internal error occurs.
01090  *
01091  * \note When running simulavr in gdb server mode, this function is not
01092  * used. The avr_core_step() function is called repeatedly in a loop when the
01093  * continue command is issued from gdb. As such, the functionality in this
01094  * loop should be kept to a minimum.
01095  *
01096  * \todo Should add some basic breakpoint handling here. Maybe allow
01097  * continuing, and simple breakpoint management (disable, delete, set)
01098  */
01099 
01100 void
01101 avr_core_run (AvrCore *core)
01102 {
01103     uint64_t cnt = 0;
01104     int res;
01105     uint64_t start_time, run_time;
01106 
01107     avr_core_reset (core);      /* make sure the device is in a sane state. */
01108 
01109     core->state = STATE_RUNNING;
01110 
01111     signal_watch_start (SIGINT);
01112 
01113     /* FIXME: [TRoth 2002/03/19] This loop isn't going to handle sleep or idle
01114        modes properly. */
01115 
01116     start_time = get_program_time ();
01117     while (core->state == STATE_RUNNING)
01118     {
01119         if (signal_has_occurred (SIGINT))
01120             break;
01121 
01122         res = avr_core_step (core);
01123 
01124         if (res == BREAK_POINT)
01125             break;
01126 
01127         cnt++;
01128     }
01129     run_time = get_program_time () - start_time;
01130 
01131     signal_watch_stop (SIGINT);
01132     
01133     /* avoid division by zero below */
01134     if (run_time == 0) run_time = 1;
01135     
01136     avr_message ("Run time was %lld.%03lld seconds.\n", run_time / 1000,
01137                  run_time % 1000);
01138 
01139     if (run_time == 0)
01140          run_time = 1;          /* Avoid division by zero. */
01141 
01142     avr_message ("Executed %lld instructions.\n", cnt);
01143     avr_message ("   %lld insns/sec\n", (cnt * 1000) / run_time);
01144     avr_message ("Executed %lld clock cycles.\n", avr_core_CK_get (core));
01145     avr_message ("   %lld clks/sec\n",
01146                  (avr_core_CK_get (core) * 1000) / run_time);
01147 }
01148 
01149 /** \brief Sets the simulated CPU back to its initial state.
01150  *
01151  *  Zeroes out PC, IRQ's, clock, and memory.
01152  */
01153 
01154 void
01155 avr_core_reset (AvrCore *core)
01156 {
01157     avr_core_PC_set (core, 0);
01158     avr_core_irq_clear_all (core);
01159 
01160     avr_core_inst_CKS_set (core, 0);
01161 
01162     /* Send clock cycles to display.
01163        Normaly the clockcycles must not be reset here!
01164        This leads to an error in the vcd file. */
01165 
01166     display_clock (core->CK);
01167 
01168     mem_reset (core->mem);
01169 }
01170 
01171 /*@}*/
01172 
01173 /** \name Callback Handling Methods */
01174 
01175 /*@{*/
01176 
01177 /**
01178  * \brief For adding external read and write callback functions.
01179  *
01180  * rd and wr should come in pairs, but it is safe to add
01181  * empty function via passing a NULL pointer for either function.
01182  *
01183  * \param core A pointer to an AvrCore object.
01184  *
01185  * \param port_id The ID for handling the simulavr inheritance model.
01186  *
01187  * \param ext_rd Function for the device core to call when it needs to
01188  * communicate with the external world via I/O Ports.
01189  *
01190  * \param ext_wr Function for the device core to call when it needs to
01191  * communicate with the external world via I/O Ports.
01192  *
01193  */
01194 void
01195 avr_core_add_ext_rd_wr (AvrCore *core, int addr, PortFP_ExtRd ext_rd,
01196                         PortFP_ExtWr ext_wr)
01197 {
01198     Port *p = (Port *)mem_get_vdevice_by_addr (core->mem, addr);
01199 
01200     if (p == NULL)
01201     {
01202         avr_warning ("Device does not have vdevice at 0x%04x.\n", addr);
01203         return;
01204     }
01205 
01206     port_add_ext_rd_wr (p, ext_rd, ext_wr);
01207 }
01208 
01209 /**
01210  * \brief Add a new clock callback to list.
01211  */
01212 extern inline void avr_core_clk_cb_add (AvrCore *core, CallBack *cb);
01213 
01214 /**
01215  * \brief Add a new asynchronous callback to list.
01216  */
01217 extern inline void avr_core_async_cb_add (AvrCore *core, CallBack *cb);
01218 
01219 /** \brief Run all the callbacks in the list.
01220  
01221     If a callback returns non-zero (true), then it is done with it's job and
01222     wishes to be removed from the list.
01223  
01224     The time argument has dual meaning. If the callback list is for the clock
01225     callbacks, time is the value of the CK clock counter. If the callback list
01226     is for the asynchronous callback, time is the number of milliseconds from
01227     some unknown, arbitrary time on the host system. */
01228 
01229 extern inline void avr_core_clk_cb_exec (AvrCore *core);
01230 
01231 /**
01232  * \brief Run all the asynchronous callbacks.
01233  */
01234 extern inline void avr_core_async_cb_exec (AvrCore *core);
01235 
01236 /*@}*/
01237 
01238 /**
01239  * \brief Dump the contents of the entire CPU core.
01240  *
01241  * \param core A pointer to an AvrCore object.
01242  * \param f_core An open file descriptor.
01243  */
01244 void
01245 avr_core_dump_core (AvrCore *core, FILE * f_core)
01246 {
01247     unsigned int pc = avr_core_PC_get (core);
01248 
01249     fprintf (f_core, "PC = 0x%06x (PC*2 = 0x%06x)\n\n", pc, pc * 2);
01250     mem_dump_core (core->mem, f_core);
01251     flash_dump_core (core->flash, f_core);
01252 }
01253 
01254 /**
01255  * \brief Load a program from an input file.
01256  */
01257 int
01258 avr_core_load_program (AvrCore *core, char *file, int format)
01259 {
01260     return flash_load_from_file (core->flash, file, format);
01261 }
01262 
01263 /** \brief Load a program from an input file. */
01264 int
01265 avr_core_load_eeprom (AvrCore *core, char *file, int format)
01266 {
01267     EEProm *ee = (EEProm *)mem_get_vdevice_by_name (core->mem, "EEProm");
01268 
01269     return eeprom_load_from_file (ee, file, format);
01270 }

Automatically generated by Doxygen 1.4.1 on 13 Oct 2005.