- Main Page
- Related Pages
- Files

# avrcore.c

Go to the documentation of this file.

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

Automatically generated by Doxygen 1.5.5 on 5 Mar 2009.