code: /**
   * Copyright (c) 2005, Regents of the University of California
   * All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * Redistributions of source code must retain the above copyright notice,
   * this list of conditions and the following disclaimer.
   *
   * Redistributions in binary form must reproduce the above copyright
   * notice, this list of conditions and the following disclaimer in the
   * documentation and/or other materials provided with the distribution.
   *
   * Neither the name of the University of California, Los Angeles nor the
   * names of its contributors may be used to endorse or promote products
   * derived from this software without specific prior written permission.
   *
   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
   * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   *
   * Creation date: Nov 29, 2005
   */
  
  package avrora.test.sim;
  
  import avrora.core.Program;
  import avrora.sim.Simulator;
  import cck.util.Arithmetic;
  import cck.util.Util;
  import java.util.*;
  
  /**
   * The <code>StateAccessor</code> class separates the simulation test engine from the details of
   * the state implementations for each architecture. The basic model is that this class provides
   * methods that allow getting and setting single variables, which may correspond to registers,
   * the program counter, stack pointer, etc, as well as getting and setting elements of arrays
   * indexed by an integer, such as memory and flash.
   *
   * Each architecture that would like to have automated tests needs to provide an implementation
   * of this class that maps variables and arrays to the internal state of the simulation.
   *
   * @author Ben L. Titzer
   */
  public abstract class StateAccessor {
  
      protected final Program program;
      protected final Simulator simulator;
      protected final HashMap<String, Accessor> accessors;
  
      /**
       * The <code>Accessor</code> class is exposed for subclasses of the <code>StateAccess</code> class
       * in order to provide the access for a single variable or array. This allows instances of this class
       * to be added to an internal hashmap that is used by the default implementation of the <code>StateAccessor</code>
       * <code>.get()</code>, <code>.set()</code>, etc. methods.
       */
      protected abstract class Accessor {
          protected abstract int get();
          protected abstract void set(int val);
          protected int getIndex(int ind) {
              return Arithmetic.getBit(get(), ind) ? 1 : 0;
          }
          protected void setIndex(int ind, int val) {
              int value = Arithmetic.setBit(get(), ind, (val & 1) != 0);
              set(value);
          }
      }
  
      /**
       * The default constructor of the <code>StateAccessor</code> class stores a reference to the
       * program instance and the simulator. The simulator, in turn, allows access to the <code>State</code>
       * object, interpreter, event queue, etc.
       * @param p the program
       * @param sim the simulator
       */
      protected StateAccessor(Program p, Simulator sim) {
          program = p;
          simulator = sim;
          accessors = new HashMap<String, Accessor>();
      }
  
      /**
       * The <code>get()</code> method provides access to single variables that are distinguished
       * by their names as a string. The string need not have any particular format--it need only
       * be unique. For example, the string may include special characters such as '$', '.', etc.
       * @param name the name of the variable represented as a string
       * @return the value of the variable represented as an integer
       */
      public int get(String name) {
          Accessor a = accessors.get(name);
          if ( a == null ) throw Util.failure("unknown variable "+name);
          return a.get();
      }
  
      /**
       * The <code>getIndex()</code> method provides access to arrays that are distinguished by
       * their name and indexed by an integer. Arrays might represent the memory, IO register space,
       * flash memory, EEPROM, etc.
       * @param name the name of the array
       * @param ind the index into the array which to read
       * @return the value of the array at the specified position represented as an integer
       */
      public int getIndex(String name, int ind) {
          Accessor a = (Accessor)accessors.get(name);
          if ( a == null ) throw Util.failure("unknown variable "+name);
          return a.getIndex(ind);
      }
  
      /**
       * The <code>set()</code> method sets the value of the specified variable. This method is provided
       * so that the simulation framework can parse the values of an initial state from the test file
       * and use the accessor to initialize the state accordingly.
       * @param name the name of the variable to set
       * @param val the value to assign to the variable
       */
      public void set(String name, int val) {
          Accessor a = (Accessor)accessors.get(name);
          if ( a == null ) throw Util.failure("unknown variable "+name);
          a.set(val);
      }
  
      /**
       * The <code>setIndex()</code> methods sets the value of the specified array at the specified index.
       * This method is provided so that the simulation framework can parse the values of the initial state
       * from the test file and use the accessor to initialize the state accordingly.
       * @param name the name of the array as a string
       * @param ind the index into the array where to assign
       * @param val the value to assign to the element of the array
       */
      public void setIndex(String name, int ind, int val) {
          Accessor a = (Accessor)accessors.get(name);
          if ( a == null ) throw Util.failure("unknown variable "+name);
          a.setIndex(ind, val);
      }
  
      public Program getProgram() {
          return program;
      }
  
      public Simulator getSimulator() {
          return simulator;
      }
  
      public void init(List<Predicate> inits) {
          for (Predicate p : inits) {
              p.init(this);
          }
      }
  }
  