Introduction
这个作业属于硬件作业了,要求阅读芯片手册,然后写一个时钟驱动。难度的话其实比不过同期的软件作业难度,已经提供了大部分的代码,不过硬件调试需要一定的功底。
I. OBJECTIVES
The purpose of this assignment is to build a package of timing routines for
the SAPC and use it to time code on the SAPC to determine memory access time
on the SAPC with and without caching. This code does not run on UNIX. Read the
Intel 8254 Programmable Interval Timer (PIT) Data Sheet. Look at $pcex/timer.c
for an example of C code for accessing the timer. Copy all the files needed
for this project.
II. The timing package
A package is a set of utilities that can be called by a program that wants to
use them. When designing a package we carefully consider the things in it that
must be visible to the caller, specify those, and require that everything else
be internal and invisible. The visible parts of the timing package you will
build are in “timepack.h”. A customer for the package’s services includes that
header file (using #include) in the program for compilation and links his or
her object code with “timepack_sapc.opc” to build the executable. You are
asked to modify “timepack_sapc.c” to provide a high resolution timer service
for programs running on the SAPC.
Existing Code
Every package should have a test program showing that it works by calling it
in all important ways. This test program is called a “driver” because it sits
on top of the package and drives it like we test-drive a car – start up, do
this, do that, stop, shut down. It is also called a “unit test” program
because it tests just this one package separate from any other package in a
bigger program. If you suspect something is wrong in a certain package, you’ll
try to make its unit test fail, and then you debug the problem in the
relatively simple environment of the unit test, rather than in the bigger
program. The test program for timepack is testpack.c. You can build testpack
and testpack.lnx right away and run them. Note what is printed out by
testpack.lnx. Capture this in a typescript1 file. It shows that the timing
package (as provided) can time things on the SAPC to 55-ms accuracy, but not
to the microsecond accuracy we want. The next step is to get your
timepack_sapc.c fixed up for the higher resolution and the unit test
executable testpack.lnx will show it.
Modifed Code
You’re working directly with the hardware device, the Programmable Interval
Timer (PIT) with its interrupt handler. This code has been provided to you in
a). The timepack_sapc.c as provided can measure time in timer “ticks” at an
18.2-Hz (55 ms/tick) standard PC tick rate.To use the PIT to measure higher
precision, you make use of “downcounts” within the timer chip. What you need
to do is determine how many counts have downcounted in the timer since the
last tick and compute a higher accuracy time. By doing this at both the start
and the end of the time interval being measured, you can compute the elapsed
time accurate to a few microseconds, a very respectable timer service. You’ll
need to modify the timepack_sapc.c to achieve this.
Since timer downcounts count down from 64K at the tick, you need to subtract
the register value from 65536 to get the number of downcounts since last tick:
number of downcounts since tick = 65536 - observed_count (in register)
Thus the accurate time between A and B is
= 202 clock ticks + (65536 – 43000) downcounts - (200 clock ticks + (65536 – 35000) downcounts)
= 2 clock ticks – 8000 downcounts
where 1 tick = 64 * 1024 downcounts, so this whole thing can be expressed in
downcounts, and then converted to usecs.
Note that you need to convert downcounts (an int) to usecs (another int). To
do this, cast the downcount value to double, multiply by the correct double
conversion factor, and then cast back to int usecs. The idea here is that the
conversion factor is itself non-integral, so the needed multiplication by it
needs to be in floating point, resulting in a floating point number accurate
to about 1 usec, so we might as well cast it back to an int value since ints
are easier to work with.
See the timer.c in the course directory for a C program that reads the timer
downcounts – you can take code from this as needed.
Don’t leave any printf’s in your final code that output during timing runs!!
They take a really long time and ruin the data. Save the timing figures in
memory and print them out after the stoptimer call.
Any private functions or variables you need should be declared static in
“timepack_sapc.c”, so that the calling program can never accidentally use a
variable or function with the same name, or interfere with yours. Capture your
improved result in a typescript2 file.
III. Timing i486 instructions and a C loop
In this part of the assignment you will use the timing package to time x86
instructions. Instruction execution time is measured in system clock cycles,
here 2.5 nsecs for our 400Mhz Pentium systems. The PC timer 0 is accurate only
in the usec (microsecond) range so you will need to loop many times and divide
by the loop count to get the accuracy needed.
The actual instructions to be timed appear in loops in “itests.s”, which is an
x86 assembler source. These are called from itimes.c.
- Finish “itests.s”, so that the third instruction to be timed (immediate move of IDATA to register) is properly implemented. Add a fourth instruction of your choice “itests.s” and “itimes.c”
- You can use the provided makefile to build an optimized version of the SAPC executable file. The provided makefile has the following definitions:
development build: -g provides debugging support, slows down execution
Use -O2 optimization, no -g on final timing runs!
PC_CFLAGS_DEV = -g -Wall -Wno-implicit -Wshadow -I$(PC_INC) -I$(TIMING)
PC_CFLAGS_OPT = -O2 -Wall -Wno-implicit -Wshadow -I$(PC_INC) -I$(TIMING)make default PC_CFLAGS be PC_CFLAGS_DEV
O = DEVallow user to override DEV via O=OPT on the command line
PC_CFLAGS = $(PC_CFLAGS_$(O))
—|—
You can use O=OPT on the make command line to build an optimized version of
the sapc executables. Note that you need to “make clean” between a development
build and an optimized build to get rid of object files. Note that we are
turning off debugging when we turn on optimizations. Although gcc allows both
at once, debugging with optimizations on can be confusing, and debugging
support slows down execution.
Do your final timing runs with the optimized version, except for the “C test”
– this should be done both ways to see the effect of development vs.
production compiling.
- Look at the itests code in memory using the i386-gdb “x/i” command. Use “disas itests.opc” (at the UNIX prompt, using the disas alias from the ulab module) to see addresses of individual instructions. From this information figure out how many bytes there are per tested instruction. Then convert bytes to quadwords(64 bits) to see how many 64-bit reads are involved in instruction fetches. Allow fractional reads, for example .25 or .625 because the CPU does 64-bit reads and then saves unused instruction parts, even with caching off, for use as the next instruction. Add on memory reads or writes needed for the operands to find the total number of reads and writes for each tested instruction. For these operand accesses, the CPU does not save the extra bytes, so even a byte operand access counts as a full 64-bit read or write. Fill in the blanks on the form itimes.txt.
- Use your modified “itimes.c” and “itests.s” to time “movl %eax,%edx”, “movl , %eax”, “movl $MEMADDR, %eax” and one other instruction of your choice on a SAPC. Use several values of loopcount and the same value several times to see if the time per instruction is consistent. When you get decent repeatability, fill in the form itimes.txt memory access time estimation. Add your discussion to your copy of the form.
NOTE: Even on the fairly well-defined environment of the SAPC, there are
sneaky mechanisms that disturb picture-perfect timing results, so don’t
despair if your data doesn’t follow theory exactly – report what you found and
discuss it.
Files in this directory:
mp3.txt the assignment, link this or just print it
makefile copy this, read for build instructions
itests.s assembler code for loops to be timed – you copy, edit
itimes.c source code for instruction timer driver – you copy, edit
timepack_sapc.c SAPC timing package – copy, edit
testpack.c source code for testpack, timing pkg driver – copy, use as needed (build with make C=testpack)
You shouldn’t need to copy or link these: the makefile knows where they are
$SAPC_TOOLS/timing/timepack.h header file for timing package
timepack_unix.c unix implementation of timing package primitives
timepack_unix_dbg.o unix object code, debug version, for timepack_unix
timepack_unix_opt.o unix object code, opt. version, for timepack_unix
You should have the following files in your directory:
Sources for the master directory for the group:
timepack_sapc.c: make sure you comment the code properly
itests.s: indicating the new tests
itimes.c: clearly indicate any changes you have made
FINAL NOTE
In the event that you are unable to correctly complete this assignment by the
due date, do not remove the work you were able to accomplish – partial credit
is always better than none.