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.
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.
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].
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.
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.
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:
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.
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 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).
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.
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.
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.
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.
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.
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
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.
Below is a listing of the code that can be compiled with any standard Java compiler.
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);
}
}
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;
}
}
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;
}
}
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;
}
}
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");
}
}
}
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());
}
}
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;
}
}
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;
}
}
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;
}
}
package adlsim;