How to build a simulator using AINT
AINT acts as a front-end to program-driven simulation of computer systems.
To build a simulator using AINT, the programmer writes interface functions
and links them with the aint libraries to generate the simulator. The simulator
is a binary executable which opens target program binaries and simulates
their execution.
Here is an introduction to AINT variables,
objects and functions.
The following describes the actions of the simulator built using AINT:
- AINT processes some command-line options (including the name of the
executables), and passes the remaining options (if any) to the back-end.
- Next, AINT opens the target executable, and translates the instructions
into an internal decoded format (the "icode").
- For each target binary specified, AINT creates one process, with one
(main) thread, and informs the back-end using the sim_thread_begin()
function.
- Next, AINT passes control to the back-end using the sim_execute()
function
- Before a thread can be executed, a main execution path ("path")
has to be associated with it. The back-end uses the AINT_create_path()
function to do this.
- Instructions in the program go through fetch - execute - commit
phases. An instruction is in the pipeline once it is fetched, until it
is committed. Any instruction in the pipeline can be "killed."
- The back-end calls the AINT_fetch() function to fetch into
a specified path from a specified address. This function returns a pointer
to a structure representing the in-flight instance of the fetched instruction.
This pointer is used to access information about the in-flight instruction.
It is also the handle used with other functions that process in-flight
instructions.
- The AINT_issue() function simulates the execution of the in-flight
instruction, and its effects on the simulated register file. Memory load/store
instructions go through an additional phase, specified by the AINT_do_read()
and AINT_do_write() functions, which simulate the effect of the
instruction on the simulated address space (memory).
- The AINT_commit() function makes the effects of an instruction
architecturally visible, and removes the instruction from the pipeline.
For correct execution, instructions must be committed in program order
(ie, in the order they were fetched).
- The AINT_kill() function rolls back the state of the register
file to that prior to the fetching of an instruction, and removes the instruction
from the pipeline.
- Similarly, the AINT_kill_path() function kills a specified
path, and the path sub-tree rooted at that path.
- The AINT_create_path() function can be used to create a new
execution path and associates it with an existing in-flight instruction
and a new starting address (PC). The new path becomes the child of the
path containing the specified in-flight-instruction. Each path may have
at most two child paths.
The following example illustrates a simple back-end simulator that executes
the binary in a non-pipelined fashion, in program order:
simple.C: source file for the simple
simulator
cache.C: the simple simulator with a simple
cache
Makefile for the above programs
How to get AINT
The pipeline-level, multi-path AINT (MSAINT.MP) is available
on cs department alpha's with access to /srl/dirkcvs. To obtain
a copy of MSAINT.MP, set the CVSROOT environment variable
to /srl/dirkcvs, and execute the command:
The makefile listed above shows how to link the back-end simulator with
the aint object (aint.o) and the simulation library (libsim.a).
CVS can be found under /tools/cs/cvs.