Carnegie Mellon
Computer Science Department |
|
|
|
|
|
|
|
|
|
|
15-410 Simics Environment Guide
Getting to know your debugger is a deeply useful skill. This documentation
intends to expose some of the internal knobs, bells, and whistles of the
Simics environment for 15-410 for "advanced" use cases of varying kinds.
Invoking Simics
The usual simics command, simics60 has many variants and
silent features. In particular, there is something of a tradition that
some TAs will create a simics60-$TA which may contain
debugging, testing, or experimental code. If you encounter a problem, one or
more TAs may try writing code to help out and may ask you to run their version
of the simics environment for a while.
Most features of the Simics environment are controlled by knobs in the
environment at time of invocation:
- SIMICS_CPU_COUNT
- If the value of this environment variable can be converted to an
integer, simics will attempt to run with that many CPUs. Results
are not necessarily well behaved for values outside of 1 to 15.
- SIMICS_REALTIME
- If this environment variable is nonempty, Simics will watch the wall
clock and attempt to keep the system elapsed time equal to the wall
clock elapsed time, rather than allowing events to happen as fast as
possible. This is generally only useful for simulations which are
mostly idle, notably during Project 1.
- SIMICS_DISK_IMAGE
- Names a file to use as the backing store of the primary IDE bus's
master disk.
- SIMICS_DISK_SIZE
- The size of the primary disk image
Essentially any other knob of the simics environment can (though may not be,
obviously... no, we won't give you a PPC core) be added on reasonable request.
Adding Code To The Simics Environment
Disclaimer
You MUST NOT (let's say that again: MUST
NOT) depend on code you add to the simics environment for the
correctness of your kernel (except under very, very rare exception which must
be confirmed by the professor(s)), as the graders will disable your
modifications before invoking simics to grade your code. However, we will read
this code, as with the rest of your handin. Landing malicious code in a handin
via this mechanism, as any other, is a breach of academic conduct and will be
handled as such.
On an only slightly less dire note, you should make an effort not to
get lost in this. Simics is really, really big, and contains tons and tons of
features, nooks, crannies, and traps. Remember that your objective is to write
a 410 assignment, which is probably not a Simics module. This is intended as
debugging tool, and like any tool, it should not be used when inappropriate.
Moreover, as the power of this tool comes from its flexibility and therefore
bestowes upon this tool a very steep learning curve, it should only be used
when lesser tools are in some way inadequate for the job at hand.
Where do I do this
The 410 Simics environment will slurp in all python (*.py) files in
the root of your project directory (alongside your README.dox, that
is) that begin with "410mods-dynamic-". These files are loaded in
alphabetical order and after the core 410 environment is up and
running. If it all goes well, you'll see a message like
"--> Working directory dynamic modifications loaded from
$PATH/410mods-dynamic-my_awesome_debugging_tools.py"
This is a natural extension of the same mechanism applied to 410mods-dynamic-*.py
files in the simics environment directory and is new this semester for student usage.
What do I do?
Step one, as always, is to familiarize yourself with the contents of the
manual. However, as the reference manual is nearly 3000 pages long, it may
help to use these examples as a starting off point and see where this takes
you. Your TAs will, in general, assist you when they can, but it is remarkably
easy to fall beyond the local-knowledge horizon and end up forging on alone.
Adding a custom breakpoint
Breakpoint handler functions take four parameters:
arg | Per-HAP callback data, unused in the current 410 environment |
obj | The configuration object which caused this breakpoint |
brknum | The breakpoint number |
m | The memory transaction associated with this breakpoint. See the Simics reference manual for more information. |
Here's a way to add a breakpoint that stops only when the address it is
watching takes on any of a set of values and traces all values except a
specified set. It demos how to add breakpoints to the simulation environment
within the breakpoint routing feature provided by the 410 environment.
single_address = 0x01234567 # Breakpoint address
watch_size = 4 # Breakpoint size
trace_silence_values = [ 0x00c0ffee ] # Don't show these values
break_on_values = [ 0xfeedface ] # Stop the simulation on these values
def handle_my_breakpoint(arg, obj, brknum, m):
# Filter out control messages
if SIM_mem_op_is_control(m) :
print "Custom breakpoint got a control transaction, ignoring!"
return
# Extract the CPU
if not SIM_mem_op_is_from_cpu(m) :
print "Custom breakpoint got a non-CPU initiator!"
return
cpu = m.ini_ptr
### This depends on 410 segmentation! The correct way is, much like x86,
### a lot more putrid.
pa = SIM_logical_to_physical(cpu, Sim_DI_Data, m.logical_address)
# Get size of transaction or fall back
size = m.size
if size == 0 :
print "WARNING: Zero size memory transaction is not a control transaction!"
size = watch_size
# Read out the current value at that physical address
# which we assume to be a 32 bit value (thus the 4)
cur_dat = SIM_read_phys_memory(cpu, pa, size)
# Construct informative message
str = "Custom breakpoint %d hit at l:0x%x with size %d, saw there %x" \
% (brknum, m.logical_address, m.size, cur_dat)
# If the value read matches our break-on value, then stop the world.
if cur_dat in break_on_values :
SIM_break_simulation(str)
elif not cur_dat in trace_silence_values :
print str
nbp = SIM_breakpoint(conf.primary_context, # Watch the primary context
Sim_Break_Virtual, # We're interested in Virtual addr
Sim_Access_Read, # Read access
single_address, # The address in question, above
watch_size, # How big of an area are we watching?
Sim_Breakpoint_Simulation # This breakpoint is part of
# the simulation environment.
)
# Register this with the 410mods-core.py breakpoint dispatch system
breakpoint_handlers[ nbp ] = handle_my_breakpoint
# Inform the user of our decision
print("Custom breakpoint registered on p:%x with break values %s as %d"
% (single_address, break_on_values, nbp) )
Adding a custom HAP handler
HAP handler functions take tree parameters:
arg | Per-HAP callback data, unused in the current 410 environment |
cpu | The current CPU of the environment |
param | On X86 this is always zero |
|