2007-05-24

Installing LC-2 simulator on Ubuntu Linux 7.04

Forrest Sheng Bao http://forrest.bao.googlepages.com

LC-2 is the CPU instruction set and architecture purposed in Yale Patt and Sanjay Patel's book "Introduction to Computing Systems: From Bits and Gates to C and Beyond!". This text book is widely used in many universities around the world, including School of Software, Nanjing University, China. I like this text book for it provides us a real model to learn how a CPU works. And CPU is the key component of a computer.


Since this kind of CPU actually doesn't exist, we need to use a simulator to study its behavior. The LC-2 simulator is originally designed to run on Microsoft DOS/Windows environment. Prof. Matt Postiff in U. Michigan(but it seems he is not there now) programmed an LC-2 simulator on UNIX. It seems his OS is Solaris. And I also found the OS used in "Guide to Using the UNIX version of the LC-2 Simulator" is also Solaris. The desktop is CDE rather than Java desktop environment based on GNOME.

So I found many problems when i follow the installation instruction enclosed in lc2.tar.gz ball. And when I run it, I got some error like this:
forrest@flavia:/forrest/Applications/lc2/forrest$ ../bin/assemble addnums.asm addnums
Running the assembler on Linux...
/afs/engin.umich.edu/class/perm/eecs100/bin/lc2asm_linux: Command not found.
and this:
forrest@flavia:/forrest/Applications/lc2/bin$ ./simulate &
[1] 15844
forrest@flavia:/forrest/Applications/lc2/bin$ Your current system (Linux 2.6.20-15-generic) is unknown or
support has been discontinued. Please run the
LC-2 simulator on a Sun running Solaris 2.6 (aka SunOS 5.6).

[1]+ Done ./simulate

It cost me about half an hour to make the LC-2 simulator(including "assemble", "convert" program) run smoothly without any error. I plan to write down the whole procedure to help those who wanna run LC-2 simulator on Linux, especially students using their own computer rather than computers deployed ready in the lab. I also plan to contact the author of the book or the simulator programmer to write an guide to Linux.

Ok. let's talk about how to do. At the beginning, you will need to download the LC-2 simulator for UNIX source code from the link on this webpage: http://www.mhhe.com/engcs/compsci/patt/lc2unix.mhtml The source code is archived in a tar.gz ball called lc2.tar.gz

After downloading the lc2.tar.gz, create a directory to extract the lc2.tar.gz. You need to create a new directory since the files in lc2.tar.gz don't have a top level folder. You won't like its contents mixed with other files in your present working directory. For example, do it like this:
$ mkdir LC2
$ cp lc2.tar.gz LC2/
$ cd LC2
$ ls
lc2.tar.gz
$ tar zxfv lc2.tar.gz

Before you start the compile procedure, you need create a symbolic link for Perl 5, otherwise, some Perl scripts can't be executed because the first line of them is : #!/usr/bin/perl5. On Ubuntu Linux 7.04, do like this:
$ sudo ln -s /usr/bin/perl5.8.8 /usr/bin/perl5
or
$ sudo ln -s /usr/bin/perl /usrbin/perl5
(Please enter the administrator password when prompted. No asterisk will be displayed when you enter a password)

And please confirm that you have installed build-essentials package which contains make, gcc and other required programs. Use
$ sudo apt-get install build-essentials
to install.

You should have following things in the LC2 folder:
$ ls
ANNOUNCE doc lc2.h NOTICE README winlc2sim
assembler examples lc2.tar.gz os simulator
bin lc2.def Makefile perllc2sim TODO

Now type and run
$ make

DO NOT follow the instruction in README to run "make distclean" and "make configure". The "make regress" is also unnecessary.

When you are done, we need to manually edit some program and fix file structure errors. Go to the bin subdirectory.
$ ls
assemble halt.obj lc2bintoverilog makeoslinks putc.obj simulate winconvert.exe
convert hexdump lc2help.txt opcstats puts.obj startup.obj winlc2asm.exe
CVS ivtable.obj lc2install project.info putspacked.obj submit100 winlc2sim.exe
getc.obj lc2asm lc2.log promptgetc.obj reply.pl undeftrap.obj xlc2sim
DO NOT add this directory to your $PATH environmental variable unless you plan to make aliases to them since some executable names are same as other popular Linux applications. For example, "convert" is one command of the famous image processing software ImageMagick. It is worth to type few more letters in order to keep your computer safe.

Now run
$ cp lc2asm lc2asm_linux

Now open the "assemble" file, for example using VIM or gedit. Go to line 3. Set lc2home as current directory rather than "/afs/engin.umich.edu/class/perm/eecs100/bin". On my computer, I set it as "/forrest/Applications/LC2/bin". Save and exit

Now open the "simulate" file. Find the same line "set lc2home = /afs/engin.umich.edu/class/perm/eecs100/bin" and replace it as above.
Then comment ALL lines following it(add a # at the beginning of each line) and append one new line:
$lc2home/xlc2sim $*:q &
(Copy this line exactly! DO NOT miss or replace any letter.)

Done!
To start any program in the bin directory, just type the full absolute path or the correct relative path. For example, if I am in LC2, I can type "./bin/simulate" to start the simulator. I can also type "/forrest/Applications/LC2/bin/simulate" to start it. You can also make aliases to them. For example, you can alias the "simulate" as "LC2simulate". Then you don't need to type the long strings. But be sure to avoid using the name that other programs on your computer have or will use.

Now let us prepare a program in binary, hex and LC-2 assembly respectively to test. For example, using the problem in "Guide to Using UNIX version LC-2 simulator": Our goal is to take the ten numbers which are stored in memory locations x3100 through x3109, and add them together, leaving the result in register 1.

The binary is(saved as addnums.bin):
0011 0000 0000 0000 ;start the program at location x3000
0101 0010 0110 0000 ;clear R1, to be used for the running sum
0101 1001 0010 0000 ;clear R4, to be used as a counter
0001 1001 0010 1010 ;load R4 with #10, the number of times to add
1110 0101 0000 0000 ;load the starting address of the data
0110 0110 1000 0000 ;load the next number to be added
0001 0100 1010 0001 ;increment the pointer
0001 0010 0100 0011 ;add the next number to the running sum
0001 1001 0011 1111 ;decrement the counter
0000 0010 0000 0100 ;do it again if the counter is not yet zero
1111 0000 0010 0101 ;halt

The hex is (saved as addnums.hex):
3000 ;start the program at location x3000
5260 ;clear R1, to be used for the running sum
5920 ;clear R4, to be used as a counter
192A ;load R4 with #10, the number of times to add
E500 ;load the starting address of the data
6680 ;load the next number to be added
14A1 ;increment the pointer
1243 ;add the next number to the running sum
193F ;decrement the counter
0204 ;do it again if the counter is not yet zero
F025 ;halt

The assembly is (saved as addnums.asm)
.ORIG x3000
AND R1,R1,x0 ;clear R1, to be used for the running sum
AND R4,R4,x0 ;clear R4, to be used as a counter
ADD R4,R4,xA ;load R4 with #10, the number of times to add
LEA R2,x100 ;load the starting address of the data
LOOP LDR R3,R2,x0 ;load the next number to be added
ADD R2,R2,x1 ;increment the pointer
ADD R1,R1,R3 ;add the next number to the running sum
ADD R4,R4,x-1 ;decrement the counter
BRp LOOP ;do it again if the counter is not yet zero
HALT
.END

All three ASCII files are not able to be run by LC-2. Now we can convert the binary, hex and assembly program into *.obj file which is the program for LC-2 to run.
To convert binary to obj file, use convert command with -b2 option:
$ /forrest/Applications/LC2/bin/convert -b2 addnums.bin addnums.obj
Input format manually set to -b2 (binary)
Input file is addnums.bin
Output file is addnums.obj
You can use the hexdump command to check the content of obj file. You can use hexdump provided by your Linux distribution or the hexdump in LC2 bin directory.
$ hexdump addnums.obj
forrest@flavia:/forrest/Applications/LC2/work$ hexdump addnums.obj
0000000 0030 6052 2059 2a19 00e5 8066 a114 4312
0000010 3f19 0402 25f0
0000016

To convert hex to obj file, use convert command with -b16 option:
$ /forrest/Applications/LC2/bin/convert -b16 addnums.hex addnums.obj
Input format manually set to -b16 (hexadecimal)
Input file is addnums.hex
Output file is addnums.obj
$ hexdump addnums.obj
0000000 0030 6052 2059 2a19 00e5 8066 a114 4312
0000010 3f19 0402 25f0
0000016

To convert assemly to obj file, use assemble command(DO NOT add the obj extension. The program will do it automatically.)
forrest@flavia:/forrest/Applications/LC2/work$ /forrest/Applications/LC2/bin/assemble addnums.asm addnums
Running the assembler on Linux...
forrest@flavia:/forrest/Applications/LC2/work$ hexdump addnums.obj
0000000 0030 6052 2059 2a19 00e5 8066 a114 4312
0000010 3f19 0402 25f0
0000016
The assemble program will generate the binary and hex file. Original binary and hex file has been overwritten.

You can see the content of LST file and SYM file via cat command
$ cat addnums.sym
// Symbol table
// Scope level 0:
// Symbol Name Page Address
// ---------------- ------------
// LOOP 3004

$ cat addnums.lst
(0000) 3000 0011000000000000 ( 1) .orig 0x3000
(3000) 5260 0101001001100000 ( 2) and r1 r1 0x0000
(3001) 5920 0101100100100000 ( 3) and r4 r4 0x0000
(3002) 192A 0001100100101010 ( 4) add r4 r4 0x000A
(3003) E500 1110010100000000 ( 5) lea r2 0x0100
(3004) 6680 0110011010000000 ( 6) LOOP ldr r3 r2 0x0000
(3005) 14A1 0001010010100001 ( 7) add r2 r2 0x0001
(3006) 1243 0001001001000011 ( 8) add r1 r1 r3
(3007) 193F 0001100100111111 ( 9) add r4 r4 0xFFFF
(3008) 0204 0000001000000100 ( 10) brp LOOP
(3009) F025 1111000000100101 ( 11) halt


Now we can move on the start the simulator. For example, I run "/forrest/Applications/LC2/bin/simulate &".
You will see the interface I have shown before. Select "File" -> "Load Program" to load the obj file you have just generated.
Then you can see the memory has content:

You can then select "Run" -> "Run program" or "Run" -> "Step program" to see what's happened inside the CPU. If you wanna step program, you will need to "Run" - > "BreakPoints" first. In this example, you can set the memory value of desired segmentation to see the sum result.

No comments: