Mixed Signal Microcontroller Simulator      

   ECE492 Project by Engin Ipek Advisor: Bruce Land

Introduction                          High Level Design                           Results                       Netlist Files               Mask Files                 MCU Models            Listing                       

 Improvements

 Introduction:

 The purpose of this project was to extend the Mixed Signal AVR simulator written in Fall’02 so that any single-issue microprocessor could be included in the simulation environment rather than limiting the simulations to systems based around ATMEL AT90S8515 series microcontrollers. In order to achieve this goal, a general architectural description language (ADL) simulator was written and the user was provided with abtractions that allow the full specification of a microcontroller model and the corresponding memory hierarchy. Furthermore, the capabilities of the pre-existing simulator were extended to handle multiple microcontrollers at the same time. The final version of the mixed-signal MCU simulator was tested by implementing a 32-bit, single-issue MIPS microprocessor and L1-cache system. The correctness of this model was verified by comparing against a Verilog model of the same processor. In order to verify the operation of the ADL – Analog interface of the extended simulator, two instances of the MIPS processor were included in a sinewave-generator and run in parallel. Test results showed that the extended version of the simulator successfully handled two MIPS MCU’s running in parallel in a mixed-signal environment.

High Level Design:

 

The final version of the simulator was written entirely in Java programming language. The code was organized roughly as depicted in the figure below, where each box represents a class and arrows denote the interaction of one class with another.  On each arrow, outputs of one type of object that are passed to another object as inputs are shown (eg, the parser passes an array of logic elements to class Logic). For simplicity, only the major classes and the main inputs/outputs of those classes are shown, while a complete listing of the code can be found under the listing section.

 

 

 

 


                                                                                   

                                                                                                 -Program Organization-

 

 The major difference between the current and the previous versions of the project is that the Hex File Reader has been replaced by the ADLSimulator class.

The ADLSimulator is the superclass of all MCU models and is intended to hide the unnecessary details of cycle-accurate simulation and analog – digital interfacing from the user. The ADLSimulator takes the MCU models, the states of the instruction memories at time t=0, and mask files as inputs. It generates instances of the models referenced in the netlist files and loads these models with the proper instructions. The loaded models are passed to the solver class.

Aside form this difference, the solver and the compiler classes were modified significantly to handle general CPU models rather than the hardcoded 8515 model, and further modifications to these files were made to simulate an arbitrary number of CPUs oncurrently. However, the basic working principles of the simulator, the analog-digital interfaces and the algorithms used for analog simulation have remained unchanged.

 

Results:

 

In order to test the operation of the simulator, two MIPS models were run in parallel in a sinewave – generator application. The first processor was used to generate the sinewave by performing memory mapped I/O. Memory address 0 was declared as a port in the netlist file, and this PORT was connected to the rest of the analog circuitry as shown below.  In order to test correct parallel operation, the second CPU was loaded with instructions that toggle the memory location 0 between 0 and 1. for the second CPU, the least significant bit of memory location 0 was declared as a port and connected to ground through a 1K resistor (not shown). The netlist file that describes the se connections is shown below. The assembly instructions running on the processors is also listed. The corresponding MIPS model is included in the listing section.

 

R 1 9 20000

R 9 0 20000

R 2 10 20000

R 3 11 20000

R 4 12 20000

R 5 13 20000

R 6 14 20000

R 7 15 20000

R 8 16 20000

R 9 10 10000

R 10 11 10000

R 11 12 10000

R 12 13 10000

R 13 14 10000

R 14 15 10000

R 15 16 10000

PORT 1 0 0 cpu1            

PORT 2 0 1 cpu1              

PORT 3 0 2 cpu1                  

PORT 4 0 3 cpu1                

PORT 5 0 4 cpu1             

PORT 6 0 5 cpu1                  

PORT 7 0 6 cpu1                  

PORT 8 0 7 cpu1

PORT 19 0 0 cpu2

R 0 19 1000

OPAMP 17 0 18

R 17 18 2000000          

R 18 0 1000

R 16 17 1000000

AND 1 2 20

OR  3 20 21

DUMPLOGIC logicOUT 21 ENDDUMP

DUMP cpu1 portc 0 R0 0 R1 1 R2 2 R3 3 R4 5 R5 5 R6 6 R7 7 R8 8 R9 9 ENDDUMP

DUMP cpu2 reg2 0 ENDDUMP

DUMPANALOG opAmpOut1 18 bit0 19 dacOut 16 zeroOut 9 opAmpNegTerminal 17 ENDDUMP

end   

 
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


The netlist file describing the hardware in the schematics is provided at the right.

The first lines describe an R-2R ladder DAC, followed by the connections to the first

cpu and the logic gates. This is followed by the port declaration for the second cpu.

The dump statements at the end specify the nodes whose values are to be stored into

excel and vcd files for viewing after the simulation. These nodes are also named in the body of

the dump statements to facilitate the viewing process. A more detailed explanation

of the changes to the netlist file format can be found under the netlist files section.



The MIPS assembly instructions running on the two processors are listed below. The code was assembled using the ECE 475 MIPS cross compiler.

 

Sinewave Generator:

 

#Repeatedly load the next value of the sine function into memory address 0.

Label:      li $1,0x80

                sw $1, 0($0)

                li $1, 0xb1

                 sw $1, 0($0)

                li $1,0xda

                sw $1,  0($0)

                li $1,0xf6

                 sw $1, 0($0)   

                li $1, 0xff

                sw $1, 0($0)

                li $1, 0xf6

                 sw $1, 0($0)

                li $1, 0xda

                 sw $1, 0($0)

                li $1, 0xb1

                 sw $1, 0($0)

                li $1, 0x80

                 sw $1, 0($0)

                li $1, 0x4f

                 sw $1, 0($0)

                li $1, 0x26

                 sw $1, 0($0)

                li $1, 0x0a

                 sw $1, 0($0)

                li $1, 0x00

                 sw $1, 0($0)

                li $1, 0x0a

                 sw $1, 0($0)

                li $1, 0x26

                 sw $1, 0($0)

                li $1, 0x4f

                sw $1, 0($0)

                j Label 

 

Toggle Mem[0]:

 

#Toggle memory location 0 between 0 and 1

 

Label:             li $2, 0

                        sw $2, 0($0)

                        li $2, 1

                        sw $2, 0($0)

                        j Label

 

 

The results of the simulation are shown below. The plots are taken directly form the excel file generated by the simulator, where the node names agree with the definitions in the dump statements. The plot on the left shows the output of the DAC and the output of the Op Amp vs. time. The plot on the right shows the voltage on the second cpu’s port as a function of time. The microcontrollers spend the initial 40 cycles warming up the L1 cache.  After this point, the sine values are stable. The second cpu is also affected by the cache miss in the same way.

 

 

Figure 1

 

Figure 2

The results of the digital simulation are shown below. The bottom 3 rows show the output of the logic gates, the values of the emory location for CPU1 and CPU2, respectively.

Figure 3

 

 

As expected CPU1 sets MEM[0] to the sine values while the second CPU toggles its MEM[0].

           

Netlist Files:

The only update to the netlist files in this version of the simulator is the syntax of the PORT declarations. PORT declarations must now have the name of the corresponding CPU as their first argument since there can be more than one processor running simulataneously. Hence, a typical PORT declaration would look like:

 

PORT cpu_name node_number IO_address bit_number.

 

Other than this difference, the format of the Netlist file remained unchanged.

 

Mask Files:

In order for the ADL simulator to correctly distinguish between instructions, a mask file that describes the opcodes of the instructions is necessary. As different ISA’s encode instructions differently, the mask file consists of a list of entries that gives the name of the instruction, a bitmask, a key and an instruction format. These fields are separated by semicolons:

 

Instruction_name : bit_mask : key : instruction_format

 

At runtime, the ADL simulator performs a logical AND between the current instruction and a the bit mask. If the result is equal to the key, the getArgs() function is called with the given instruction format and the corresponding instruction is executed with the resulting arguments. Hence, the bitmask/key pair can be used to distinguish between instructions in any ISA.

 

 

MCU Models:

In order to specify a processor model, the user must write a java file that extends ADLSimulator. The key features of these models are listed below while an example is provided in the listing section:

 

Instructions:

All instructions are represented by methods that have the following signature:

 

public void instruction_name( Integer[] args){}

 

The args[] array is an array of arguments that will be extracted from the instruction based on the corresponding instruction format. Within the body of the method, the uiser is free to use any features of the simulator as well as any general java constructs.

 

Arguments:

In order for the arguments of the instructions to be extracted properly, the user must provide the following function:

 

public Integer[] getArgs(String format, long Instruction){}

 

Once the current instruction is compared against the entries in the mask file, the corresponding format string will be passed to getArgs with the instruction.

GetArgs must extract the arguments from the instruction and return them in an array.

 

PC:

PC is a reserved key word and represents the program counter. The user can specify how the instruction changes the PC by peforming operations on this

Identifier (eg. PC++; will increment the PC for the next iteration of the simulation).

 

LATENCY:

The latency of every instruction is 1 cycle by default. However, the user can change this by using the LATENCY keyword. For instance, using

“LATENCY = 32;” within the body of an instruction will cause the instruction to have a 32 cycle latency. Instructions that access the memory hierarcy

will have a variable latency based on the cache hits and misses and the latencies will be calculated by simulator at runtime.

 

Register File:

The keyword “R” is used to represent the register file. The register file is an array of integers whose length must be specified by the used.

 

Data Memory:

The data memory can be specified either as a single main memory or as a memory hierarchy. If there are no caches, then the keyword DMEM must be used to access data memory. DMEM is an array of integers whose length must be specified by the used.

If a memory hierarchy with caches is present, the DMEMH keyword will represent the hierarchy. DMEMH.putWord(int address, long data) can be used for stores, and DMEMH.getWord(int address) can be used for loads.

Caches:

The constructor for instantiating a new cache has the following signature. The user can call this constructor to instantiate a cache in the constructor for the MCU model.

 

public Cache(int blockSize, int Associativity, int Replacement, int NumLines, Mem Parent,int Latency){}

 

The first 4 arguments are regular cache parameters. Parent is either another cache or MainMem that is immediatelyabove this cache in the hierarchy.

Latency is the access time of the cache.

 

Main Memory:

The constructor for the main memory is shown below

 

public MainMem(int accessTime){}

 

The main memory must be the topmost node of every memory hierarchy for correct operation.

 

Other Methods:

Aside from these features, the following methods are provided as abstractions to the user:

 

public void beforeInst(){} : will be called before every instruction

public void afterInst(){}    : will be called after every instruction

public void always(){}      : will be called every cycle

public void init(){}            : will be called before the simulation starts, after the CPU model is loaded with instructions

public void finish(){}        : will be called after the simulation ends

Improvements:

Given enough time, the simulator could be optimized by performing sparse matrix techniques in analog simulation. This would significantly reduce the simulation time of mixed signal systems with a high number of analog components.

Listing:

Below is a listing of the code that can be compiled with any standard Java compiler.

ADLSimulator

package adlsim;

 

/**

 * <p>Title: </p>

 * <p>Description: </p>

 * <p>Copyright: Copyright (c) 2003</p>

 * <p>Company: </p>

 * @author not attributable

 * @version 1.0

 */

 

public class ADLSimulator {

  //name of the processor

  public String name;

  //Number of cycles passed so far

  public long cycleNum;

  //Pipeline structure

  public String PIPELINE;

  //DMEM size

  public int dmemSize;

  //RF size

  public int regfileSize;

  //Register File

  public int[] R;

  //PC

  public int PC;

  //Latency of the instruction

  public int LATENCY;

  //Data memory

  public long DMEM[];

  //Fetcher

   public fetcher f;

   //Memory Hierarchy

   public Mem DMEMH;

  //Constructor

  public ADLSimulator(String instFile, String maskFile,int dmemSize,int regfileSize,String PIPELINE){

    DMEMH = new Mem();

    cycleNum = 0;

    PC = 0;

    LATENCY = 1;

    f = new fetcher(instFile, maskFile);

    DMEM = new long[dmemSize];

   // DMEM = Mem.vals;

    R = new int[regfileSize];

  }

  //Constructor

  public ADLSimulator(){

  }

  //Template for getArgs

   public Integer[] getArgs(String format, long instruction){

     return null;

   }

  //Step the CPU

  public void run() {

    LATENCY = 1;

    beforeInst();

    f.run(PC,this);

    cycleNum = cycleNum + LATENCY;

    afterInst();

  }

  //Initialization

  public void init(){}

  //Last call

  public void finish(){}

  //Called once before every instruction

  public void beforeInst(){}

  //Called once after every instruction

  public void afterInst(){}

  public boolean getBit(byte b, int bitNum) {

    byte temp = 1;

    return ( (b & (temp << bitNum)) != 0);

  }

 

  public boolean getBit(int i, int bitNum) {

    int temp = 1;

    return ( (i & (temp << bitNum)) != 0);

  }

 

  public boolean getBit(long i, int bitNum) {

   int temp = 1;

   return ( (i & (temp << bitNum)) != 0);

 }

 

 

 

}

 

Cache

package adlsim;

 

/**

 * <p>Title: </p>

 * <p>Description: </p>

 * <p>Copyright: Copyright (c) 2003</p>

 * <p>Company: </p>

 * @author unascribed

 * @version 1.0

 */

 

 //Memory Hierarchy simulation class

public class Cache extends Mem{

 

   //Statistics

   public long numMisses;

   public long numHits;

   //Cache parameters

   int byteOffsetLength;

   int associativity;

   int replacement;

   int numLines;

   int numLinesLog2;

   //Upper level of Mem hierarchy

   Mem parent;

   //Tags and data

   long[][] tags;

   int fifo[][];

   public int log2(int powerOf2){

     int i = 0;

     for(int j=1; j != 0; j = j <<1){

       if((powerOf2 & j) != 0)

         break;

       i++;

     }

     return i;

   }

   public Cache(int blockSize, int Associativity, int Replacement, int NumLines, Mem Parent,int Latency){

     numMisses = 0;

     numHits = 0;

     tags = new long[NumLines][Associativity];

     fifo = new int[NumLines][Associativity];

     for(int i = 0; i < tags.length; i++){

       for(int j = 0; j < tags[0].length; j++){

         tags[i][j] = -1;

         fifo[i][j] = j;

       }

     }

     byteOffsetLength = log2(blockSize);

     associativity = Associativity;

     replacement = Replacement;

     numLines = NumLines;

     parent = Parent;

     latency = Latency;

     numLinesLog2 = log2(NumLines);

 

   }

   public long getWord(int address){

     totalLatency = totalLatency + latency;

     long result = vals[address];

     int index = (int)((address >>> byteOffsetLength) & (numLines - 1));

     long tag = address >>> (byteOffsetLength + numLinesLog2);

     for(int i = 0; i < tags[0].length; i++){

       if(tags[index][i] == tag){

         numHits++;

         return vals[address];

       }

     }

     numMisses++;

     tags[index][getSet(index)] = tag;

     long temp = parent.getWord(address);

     return result;

   }

   public void putWord(int address, long data){

     vals[address] = data;

     totalLatency = totalLatency + latency;

     int index = (int)((address >>> byteOffsetLength) & (numLines - 1));

     long tag = address >>> (byteOffsetLength + numLinesLog2);

     for(int i = 0; i < tags[0].length; i++){

       if(tags[index][i] == tag){

         numHits++;

         return;

       }

     }

     numMisses++;

     tags[index][getSet(index)] = tag;

     parent.putWord(address,data);

   }

   public int getSet(int index){

     if(replacement == RANDOM){

       return (int)Math.random()*associativity;

     }

     else if(replacement == FIFO){

       fifo[index][fifo[index].length-1] = fifo[index][0];

       for(int i = 0; i < fifo[index].length - 1; i++){

         fifo[index][i] = fifo[index][i+1];

       }

       return fifo[index][0];

     }

     else return 0;

   }

   public long getNumHits(){

     return numHits;

   }

   public long getNumMisses(){

     return numMisses;

   }

 

}

 

Compiler

package adlsim;

 

/**

 * <p>Title: </p>

 * <p>Description: </p>

 * <p>Copyright: Copyright (c) 2002</p>

 * <p>Company: </p>

 * @author unascribed

 * @version 1.0

 */

 

public class Compiler {

  final int G = 0;

  final int VSRC = 1;

  final int CSRC = 2;

  final int CCVS = 3;

  final int CCCS = 4;

  final int VCVS = 5;

  final int VCCS = 6;

  final int OpAmp = 7;

  final int GI = 8;

  final int D = 9;

  final int CAC = 10;

  final int CDC = 11;

  final int VAC = 12;

  double x[];

  double z[];

  //Compile the circuit & formulate the matrixsys

  public double[][] Compile(Element[] e, int noOfNodes) {

    Element[] element = new Element[e.length];

    for(int i = 0; i< element.length; i++){

     //System.out.println(e[i].TYPE+" "+e[i].nj+" "+e[i].nk+" "+e[i].np+" "+e[i].nq+" "+e[i].p+" "+e[i].pnl0

       //                       +" "+e[i].pnl1+" "+e[i].pnl2);

      element[i] = new Element(e[i].TYPE,e[i].nj,e[i].nk,e[i].np,e[i].nq,e[i].p,e[i].pnl0,e[i].pnl1,e[i].pnl2);

      element[i].MCU = e[i].MCU;

    }

   // System.out.println("*******************************************************************");

    //Find the number of additional current variables needed

    // & generate additional current variables for dependent sources

    int m = 0;

    int iTemp = 1;

    for(int i = 0; i < element.length ; i++){

      if((element[i].TYPE == VSRC) |

         (element[i].TYPE == VAC) |

         (element[i].TYPE == VCVS) |

         (element[i].TYPE == GI)   |

         (element[i].TYPE == CCCS) |

         (element[i].TYPE == OpAmp)){

         m++;

         element[i].iVar0 = iTemp;

         iTemp++;

         }

      if(element[i].TYPE == CCVS){

        m = m+2;

        element[i].iVar0 = iTemp;

        element[i].iVar1 = iTemp + 1;

        iTemp = iTemp + 2;

      }

 

    }

    //Initialize the matrix & vectors

    double A[][] = new double[noOfNodes+m][noOfNodes+m];

    x = new double[noOfNodes+m];

    z = new double[noOfNodes+m];

    //Process the element list

    for(int i = 0; i < element.length ; i++){

      element[i].nj--;

      element[i].nk--;

      element[i].np--;

      element[i].nq--;

      switch(element[i].TYPE){

        //Conductance

        case G:

        if(element[i].nj>-1)

          A[element[i].nj][element[i].nj] = A[element[i].nj][element[i].nj] + element[i].p;

        if(element[i].nk>-1)

          A[element[i].nk][element[i].nk] = A[element[i].nk][element[i].nk] + element[i].p;

        if((element[i].nj>-1)&&(element[i].nk>-1)){

          A[element[i].nj][element[i].nk] = A[element[i].nj][element[i].nk] - element[i].p;

          A[element[i].nk][element[i].nj] = A[element[i].nk][element[i].nj] - element[i].p;

        }

        break;

        //Current Source

        case CSRC:

        if(element[i].nj>-1)

          z[element[i].nj] = z[element[i].nj] + element[i].p;

        if(element[i].nk>-1)

          z[element[i].nk] = z[element[i].nk] - element[i].p;

        break;

        //Voltage Source

        case VSRC:

        if(element[i].nk>-1)

          A[element[i].nk][element[i].iVar0 + noOfNodes - 1]++;

        if(element[i].nj>-1)

          A[element[i].nj][element[i].iVar0 + noOfNodes - 1]--;

        if(element[i].nk>-1)

          A[element[i].iVar0 + noOfNodes -1][element[i].nk]++;

        if(element[i].nj>-1)

          A[element[i].iVar0 + noOfNodes -1][element[i].nj]--;

          z[element[i].iVar0 + noOfNodes -1] = element[i].p;

        break;

        //Current Controlled Voltage Source

        case CCVS:

        if(element[i].nk>-1)

          A[element[i].nk][element[i].iVar0 +noOfNodes -1]++;

        if(element[i].nj>-1)

          A[element[i].nj][element[i].iVar0+noOfNodes -1]--;

        if(element[i].nk>-1)

          A[element[i].iVar1 +noOfNodes-1][element[i].nk]++;

        if(element[i].nj>-1)

          A[element[i].iVar1 +noOfNodes-1][element[i].nj]--;

          A[element[i].iVar1 +noOfNodes-1][element[i].iVar1 +noOfNodes-1] =

          A[element[i].iVar1 +noOfNodes-1][element[i].iVar1 +noOfNodes-1] + element[i].p;

        break;

        //Voltage Controlled Voltage Source

        case VCVS:

        if(element[i].nk>-1)

          A[element[i].nk][element[i].iVar0 +noOfNodes -1]++;

        if(element[i].nj>-1)

          A[element[i].nj][element[i].iVar0+noOfNodes -1]--;

        if(element[i].nk>-1)

          A[element[i].iVar0 +noOfNodes-1][element[i].nk]++;

        if(element[i].nj>-1)

          A[element[i].iVar0 +noOfNodes-1][element[i].nj]--;

        if(element[i].np>-1)

          A[element[i].iVar0 +noOfNodes-1][element[i].np]= A[element[i].iVar0 +noOfNodes-1][element[i].np]-element[i].p;

        if(element[i].nq>-1)

          A[element[i].iVar0 +noOfNodes-1][element[i].nq]= A[element[i].iVar0 +noOfNodes-1][element[i].nq]+element[i].p;

        break;

        //Current Controlled Current Source

        case CCCS:

        if(element[i].nk>-1)

          A[element[i].nk][element[i].iVar0+noOfNodes -1] = A[element[i].nk][element[i].iVar0+noOfNodes -1] +element[i].p;

        if(element[i].nj>-1)

          A[element[i].nj][element[i].iVar0+noOfNodes -1] = A[element[i].nj][element[i].iVar0+noOfNodes -1] -element[i].p;

        break;

        //Voltage Controlled Current Source

        case VCCS:

        if((element[i].nk>-1)&&(element[i].np>-1))

          A[element[i].nk][element[i].np]=A[element[i].nk][element[i].np]+element[i].p;

         if((element[i].nk>-1)&&(element[i].nq>-1))

          A[element[i].nk][element[i].nq]=A[element[i].nk][element[i].nq]-element[i].p;

         if((element[i].nj>-1)&&(element[i].np>-1))

          A[element[i].nj][element[i].np]=A[element[i].nj][element[i].np]-element[i].p;

         if((element[i].nj>-1)&&(element[i].nq>-1))

          A[element[i].nj][element[i].nq]=A[element[i].nj][element[i].nq]+element[i].p;

        break;

        //Ideal Op Amp

        case OpAmp:

         if(element[i].np>-1)

          A[element[i].np][element[i].iVar0+noOfNodes-1]++;

         if(element[i].nk>-1)

          A[element[i].iVar0+noOfNodes-1][element[i].nk]++;

         if(element[i].nj>-1)

          A[element[i].iVar0+noOfNodes-1][element[i].nj]--;

        break;

        //Conductance with current as an output variable

        case GI:

         if(element[i].nk>-1)

          A[element[i].nk][element[i].iVar0+noOfNodes-1]++;

        if(element[i].nj>-1)

          A[element[i].nj][element[i].iVar0+noOfNodes-1]--;

        if(element[i].nk>-1)

          A[element[i].iVar0+noOfNodes-1][element[i].nk]=A[element[i].iVar0+noOfNodes-1][element[i].nk]+element[i].p;

        if(element[i].nj>-1)

          A[element[i].iVar0+noOfNodes-1][element[i].nj]=A[element[i].iVar0+noOfNodes-1][element[i].nj]-element[i].p;

          A[element[i].iVar0+noOfNodes-1][element[i].iVar0+noOfNodes-1]--;

        break;

        //Diode

        case D:

        if(element[i].nj>-1){

          A[element[i].nj][element[i].nj] = A[element[i].nj][element[i].nj] + element[i].p;

          z[element[i].nj]=z[element[i].nj]+element[i].pnl0;

        }

        if(element[i].nk>-1){

          A[element[i].nk][element[i].nk] = A[element[i].nk][element[i].nk] + element[i].p;

          z[element[i].nk]=z[element[i].nk]-element[i].pnl0;

        }

        if((element[i].nj>-1)&&(element[i].nk>-1)){

          A[element[i].nj][element[i].nk] = A[element[i].nj][element[i].nk] - element[i].p;

          A[element[i].nk][element[i].nj] = A[element[i].nk][element[i].nj] - element[i].p;

        }

        break;

      //Capacitor

      case CAC:

      if(element[i].nj>-1){

          A[element[i].nj][element[i].nj] = A[element[i].nj][element[i].nj] + element[i].p;

          z[element[i].nj]=z[element[i].nj]-element[i].pnl0;

        }

        if(element[i].nk>-1){

          A[element[i].nk][element[i].nk] = A[element[i].nk][element[i].nk] + element[i].p;

          z[element[i].nk]=z[element[i].nk]+element[i].pnl0;

        }

        if((element[i].nj>-1)&&(element[i].nk>-1)){

          A[element[i].nj][element[i].nk] = A[element[i].nj][element[i].nk] - element[i].p;

          A[element[i].nk][element[i].nj] = A[element[i].nk][element[i].nj] - element[i].p;

        }

      break;

 

    //VAC

    case VAC:

        if(element[i].nk>-1)

          A[element[i].nk][element[i].iVar0 + noOfNodes - 1]++;

        if(element[i].nj>-1)

          A[element[i].nj][element[i].iVar0 + noOfNodes - 1]--;

        if(element[i].nk>-1)

          A[element[i].iVar0 + noOfNodes -1][element[i].nk]++;

        if(element[i].nj>-1)

          A[element[i].iVar0 + noOfNodes -1][element[i].nj]--;

          z[element[i].iVar0 + noOfNodes -1] = element[i].p;

        break;

      }

    }

 

    return A;

  }

 

 

}

 

Element

package adlsim;

 

/**

 * <p>Title: </p>

 * <p>Description: </p>

 * <p>Copyright: Copyright (c) 2002</p>

 * <p>Company: </p>

 * @author unascribed

 * @version 1.0

 */

 

public class Element {

  //Corresponding MCU for PORTS

  String MCU ;

  //Type of the circuit element

  public int TYPE = 0;

  //Nodes connected to the element

  public int nj, nk, np, nq;

  //Parameter related to the element

  public double p, pnl0, pnl1,pnl2;

  //Additional current variables

  public int iVar0, iVar1;

  //Initizalize an element from given nodes and a parameter

  public Element(int type, int Nj, int Nk, int Np, int Nq, double p0, double pn0,double pn1, double pn2) {

    TYPE = type;

    nj = Nj;

    nk = Nk;

    np = Np;

    nq = Nq;

    p = p0;

    pnl0 = pn0;

    pnl1 = pn1;

    pnl2 = pn2;

  }

}

 

Fetcher

 

package adlsim;

import java.util.*;

import java.io.*;

 

/**

 * <p>Title: </p>

 * <p>Description: </p>

 * <p>Copyright: Copyright (c) 2003</p>

 * <p>Company: </p>

 * @author not attributable

 * @version 1.0

 */

 

public class fetcher {

  long[] Mem;

  long[] masks;

 // Integer[] array;

 // Integer single;

 // Object[] args = {single,array};

  Hashtable functions;

  Hashtable formats;

  FileReader f;

  BufferedReader br;

 

  public fetcher(String instFile, String maskFile) {

     functions = new Hashtable();

     formats = new Hashtable();

     try{

 

        // Create a new file reader

        // connected to maskFile

        FileReader f = new FileReader(maskFile);

        BufferedReader br = new BufferedReader(f);

 

        // Create a new file reader

        // connected to instFile

        FileReader fi = new FileReader(instFile);

        BufferedReader bri = new BufferedReader(fi);

 

        //Vector for decoding the instruction file

        Vector instrs = new Vector();

 

        //Load the instructions

        String str = bri.readLine();

        String[] strArray = str.split(" ");

        String str0 = strArray[1].substring(0,10);

        String str1 = "0x"+strArray[1].substring(10,18);

        //System.out.println(str0+ " " + str1);

        while(str!=null){

          strArray = str.split(" ");

          str0 = strArray[1].substring(0,10);

          str1 = "0x"+strArray[1].substring(10,18);

          instrs.add(str0);

          instrs.add(str1);

          str = bri.readLine();

 

 

        }

 

        Mem = new long[instrs.size()];

 

        for(int i = 0; i<Mem.length; i++){

          Mem[i] = Long.decode((String)instrs.get(i)).longValue();

        }

 

 

        //Vectors for decoding the mask file

        Vector fun = new Vector();

        Vector msk = new Vector();

        Vector key = new Vector();

        Vector format = new Vector();

 

        //Walk through the msk file and set parameters

        String s = br.readLine();

        while(s != null){

          String line[] = s.split(":");

          fun.add(line[0]);

          msk.add(line[1]);

          key.add(line[2]);

          format.add(line[3]);

          s = br.readLine();

        }

        //Insert the masks

        masks = new long[msk.size()];

        for(int i = 0 ; i < masks.length; i++){

          masks[i] = Long.decode((String)msk.get(i)).longValue();

        }

        //Insert the functions

        for(int i = 0; i < key.size(); i++){

          functions.put(Long.decode((String)key.get(i)),fun.get(i));

        }

        //Bind the formats

        for(int i = 0; i < format.size(); i++){

          formats.put(Long.decode((String)key.get(i)),format.get(i));

        }

      }

      catch(Exception exc){System.out.println("Error in mask file or hex file.");}

  }

  public void runAlways(){

 

  }

 

  public void runInit(){

 

  }

 

  public void runFini(){

 

  }

 

 

  //Run the instruction at the given index with the given CPU state

  public void run(int index, ADLSimulator mcu){

    Integer[] temp = new Integer[1];

    Integer[] args;

    Class[] types = {temp.getClass()};

    String funName = null;

    String formatName = null;

    long instruction = Mem[index];

 

    //Get the correct format name

 

    for(int i = 0; i < masks.length; i++){

      formatName = (String)formats.get((new Long((int)masks[i] & instruction)));

      if(formatName != null)

        break;

    }

    //Get the arguments

    args = mcu.getArgs(formatName,instruction);

    //Get the correct function name

    for(int i = 0; i < masks.length; i++){

      funName = (String)functions.get((new Long((int)masks[i] & instruction)));

      if(funName != null)

        break;

    }

 

 

    try{

      Object[] wrapper = {args};

      mcu.getClass().getMethod(funName,types).invoke(mcu,wrapper);

    }

    catch(Exception e){

      System.out.println("Instruction description for \"" +funName+ "\" not found in MCU.java");

 

 

    }

  }

}

 

HexReader

package adlsim;

 

 

 

/**

 * <p>Title: AVRSim</p>

 * <p>Description: Mixed Signal AVR Simulator</p>

 * <p>Copyright: Copyright (c) 2002</p>

 * <p>Company: Cornell University</p>

 * @author unascribed

 * @version 1.0

 */

 

import java.io.*;

 

public class HexReader {

 

  FileReader f; // declare a file reader object

  private int recordLength = 0;

  private String recordLengthS;

  private int address = 0;

  private String addressS;

  private char[] buffer = new char[100];

  private int index;

  private int dataIndex;

 

 

 

  public void loadMEM(String S, short[] Mem){

 

 

 

  try{

 

    // Create a new file reader

    // connected to S

    f = new FileReader(S);

    BufferedReader br = new BufferedReader(f);

    index = 0;

    dataIndex = 9;

    char[] temp0 = (br.readLine()).toCharArray();

    int countMod4 = 0;

    while(index<9){

      buffer[index] = temp0[index];

      index++;

    }

    while(index<temp0.length-2){

      if(countMod4 < 2)

        buffer[index+2] = temp0[index];

      else

        buffer[index-2] = temp0[index];

      index++;

      countMod4 = (countMod4 + 1)%4;

    }

 

 

 

 

    while((buffer[7] != '0') | (buffer[8] != '1')){

    //System.out.println("temp0:"+String.valueOf(temp0));

    //System.out.println("temp0.length=" +temp0.length);

     /// System.out.println("Buffer:"+String.valueOf(buffer));

      index = 0;

      dataIndex = 9;

 

 

      recordLengthS = "0x" +String.copyValueOf(buffer,1,2);

      addressS = "0x"+String.copyValueOf(buffer,3,4);

      recordLength = 2*Integer.decode(recordLengthS).intValue();

      address = Integer.decode(addressS).intValue()/2;

 

 

      while(recordLength > 0){

 

 

 

        Mem[address] = (short)(Integer.decode("0x"+String.copyValueOf(buffer,dataIndex,4)).intValue());

        //System.out.println("MEM["+address+"]="+String.copyValueOf(buffer,dataIndex,4));

        dataIndex = dataIndex +4;

        address++;

 

        recordLength = recordLength - 4;

      }

 

      char[] temp = (br.readLine()).toCharArray();

 

      index = 0;

      countMod4 = 0;

 

      while(index<9){

        buffer[index] = temp[index];

        index++;

      }

      while(index<temp.length-2){

        if(countMod4 < 2)

          buffer[index+2] = temp[index];

        else

          buffer[index-2] = temp[index];

        index++;

        countMod4 = (countMod4 + 1)%4;

      }

  }

}

  catch (Exception e){

 

    System.err.println ("Error reading file");

 

 

  }

  }

  public static void main(String[] args){

    String h = "hello";

    char[] hello = h.toCharArray();

    for(int i = 0; i < hello.length; i++){

      System.out.println((int)hello[i]);

    }

    ADLSimulator MCU = new MCU("INST.txt","MASK.txt","cpu1");

    ADLSimulator MCU2 = new MCU("INST2.txt", "MASK.txt","cpu2");

    ADLSimulator MCUs[] = {MCU,MCU2};

    Parser p = new Parser();

    Element[] e = p.Parse("itestsinewave.net");

    Compiler C = new Compiler();

    Solver S = new Solver();

    double[][]A = C.Compile(e,19);

   // System.out.println("TIME IS:" + System.currentTimeMillis());

    Logic logic = new Logic(22,p.el);

    double[] x = S.SolveAC(A,C.z,1,1,10000,e,MCUs,

                            p.ID,p.dataAddr,p.IDIndex,p.mcuName,

                            p.IDAnalog,p.nodeNum,p.IDIndexAnalog,

                            p.IDLogic,p.nodeNumLogic,p.IDIndexLogic,logic);

   // System.out.println("TIME IS:" + System.currentTimeMillis());

 

}

}

 

Logic:

package adlsim;

 

/**

 * <p>Title: </p>

 * <p>Description: </p>

 * <p>Copyright: Copyright (c) 2002</p>

 * <p>Company: </p>

 * @author unascribed

 * @version 1.0

 */

 

public class Logic {

  final int AND = 1;

  final int OR = 2;

  final int NOT = 3;

  final int DFF = 4;

  public boolean oldNodeVals[];

  public boolean[] externalInputs;

  public LogicElement[] le;

  public Logic(int noOfNodes, LogicElement[] Le){

    oldNodeVals = new boolean[noOfNodes];

    le = new LogicElement[Le.length];

    for(int i =0;i<Le.length; i++){

      le[i] = Le[i];

    }

    externalInputs = new boolean[noOfNodes];

    for(int i=0; i<externalInputs.length; i++){

      externalInputs[i]=true;

    }

    for(int i=0; i<le.length; i++){

      //System.out.println("in1:"+le[i].in1);

        //System.out.println("in2:"+le[i].in2);

      //  System.out.println("out:"+le[i].out);

      for(int j=0;j<le.length; j++){

        if(le[i].in1==le[j].out)

          externalInputs[le[i].in1]=false;

        if(le[i].in2==le[j].out)

          externalInputs[le[i].in2]=false;

        externalInputs[le[j].out]=false;

      }

    }

  }

  public boolean[] SolveLogic(boolean[] nodeVals){

    boolean updatedNodes[] = new boolean[nodeVals.length];

    for(int i = 0; i<nodeVals.length; i++){

      updatedNodes[i] = (oldNodeVals[i]!=nodeVals[i]);

    }

    boolean Done = false;

    while(!Done){

      for(int upIndex = 0 ; upIndex < updatedNodes.length; upIndex++){

        if(updatedNodes[upIndex]){

          updatedNodes[upIndex] = false;

          for(int leIndex = 0; leIndex<le.length; leIndex++){

            if((le[leIndex].in1 == upIndex)|(le[leIndex].in2 == upIndex)){

              if(le[leIndex].TYPE == AND){

                updatedNodes[le[leIndex].out] =

                ((nodeVals[le[leIndex].in1]&nodeVals[le[leIndex].in2])== nodeVals[le[leIndex].out]);

                 nodeVals[le[leIndex].out] = nodeVals[le[leIndex].in1]&nodeVals[le[leIndex].in2];

              }

              else  if(le[leIndex].TYPE == OR){

                updatedNodes[le[leIndex].out] =

                (nodeVals[le[leIndex].in1]|nodeVals[le[leIndex].in2]==nodeVals[le[leIndex].out]);

                 nodeVals[le[leIndex].out] = nodeVals[le[leIndex].in1]|nodeVals[le[leIndex].in2];

              }

               else  if(le[leIndex].TYPE == DFF){

                updatedNodes[le[leIndex].out] =

                (nodeVals[le[leIndex].out]==(nodeVals[le[leIndex].in1]&(le[leIndex].in2==upIndex)&

                nodeVals[le[leIndex].in2]));

                nodeVals[le[leIndex].out] =

                nodeVals[le[leIndex].in1]&(le[leIndex].in2 == upIndex)&nodeVals[le[leIndex].in2];

              }

            }

          }

        }

      }

      Done = true;

      for(int i=0; i < updatedNodes.length; i++){

        if(updatedNodes[i])

          Done = false;

      }

    }

    for(int i = 0; i<nodeVals.length; i++){

      oldNodeVals[i]=nodeVals[i];

    }

    return nodeVals;

  }

 

}

 

LogicElement:

package adlsim;

 

/**

 * <p>Title: </p>

 * <p>Description: </p>

 * <p>Copyright: Copyright (c) 2002</p>

 * <p>Company: </p>

 * @author unascribed

 * @version 1.0

 */

 

public class LogicElement {

  public int TYPE = 0;

  public int in1 = 0;

  public int in2 = 0;

  public int out = 0;

  public LogicElement(int Type, int In1, int In2, int Out) {

    TYPE= Type;

    in1 = In1;

    in2 = In2;

    out = Out;

  }

}

 

MainMem:

package adlsim;

 

/**

 * <p>Title: </p>

 * <p>Description: </p>

 * <p>Copyright: Copyright (c) 2003</p>

 * <p>Company: </p>

 * @author not attributable

 * @version 1.0

 */

 

public class MainMem extends Mem{

  public MainMem(int accessTime) {

    latency = accessTime;

  }

 

  public long getWord(int address){

    //System.out.println("L1 Miss");

    totalLatency = totalLatency + latency;

     return vals[address];

 

  }

  public void putWord(int address, long data){

    vals[address] = data;

    totalLatency = totalLatency + latency;

  }

 

 

}

MCU:

package adlsim;