|
Assignment 1 - Emu - a simple AVR Emulator
|
|
Program memory is used only to hold program instructions. It consists of 32768 16-bit words. Their addresses range from 0 to 32767. Each 16-bit word can contain a single Emu instruction. Program memory can not be accessed directly by an executing program. It does not change during program execution.
SRAM is used only to hold program data. It consists of 4096 8-bit bytes. Their addresses range from 256 to 4351. The contents of an SRAM byte can be accessed via the LDD instruction. The contents of an SRAM byte can be changed via the STD instruction. Note both LDD and STD instructions operate only on a single data space byte. It is not possible to access or change only part of a byte.
The LDD and STD instructions provide general-purpose access to SRAM..
The only other instructions which access SRAM, PUSH, POP, ICALL and RET, are more specialized.
The Emu CPU has 3 special purpose registers.
The upper 4 bits of the status register are unused on the Emu CPU and are always 0. The lower 4 bits of the status register have the same meaning as the AVR (CVNZ).
| Assembler | Opcode | Status Bits | Semantics |
|---|---|---|---|
| ADC Rd,Rr | 0001 11rd dddd rrrr | VNZC | Rd = Rd + Rr + C |
| ADD Rd,Rr | 0000 11rd dddd rrrr | VNZC | Rd = Rd + Rr |
| SBC Rd,Rr | 0000 10rd dddd rrrr | VNZC | Rd = Rd - Rr - C |
| SUB Rd,Rr | 0001 10rd dddd rrrr | VNZC | Rd = Rd - Rr |
| AND Rd,Rr | 0010 00rd dddd rrrr | VNZ | Rd = Rd & Rr |
| OR Rd,Rr | 0010 10rd dddd rrrr | VNZ | Rd = Rd | Rr |
| EOR Rd,Rr | 0010 01rd dddd rrrr | VNZ | Rd = Rd ^ Rr |
| MOV Rd,Rr | 0010 11rd dddd rrrr | Rd = Rr | |
| MULS Rd,Rr | 0000 0010 dddd rrrr | ZC | R1:R0 = R(d+16) * R(r+16) |
| LSR Rd | 1001 010d dddd 0110 | VNZC | Rd = Rd >> 1 |
| ASR Rd | 1001 010d dddd 0101 | VNZC | Rd = (Rd & 0x80) | (Rd >> 1) |
| LDI Rd,k | 1110 kkkk dddd kkkk | R(d+16) = k | |
| LDD Rd,Y+q | 10q0 qq0d dddd 1qqq | Rd = SRAM[r29:r28 + q] | |
| STD Y+q,Rd | 10q0 qq1d dddd 1qqq | SRAM[r29:r28 + q] = Rd | |
| BRBC s,k | 1111 01kk kkkk ksss | PC = PC + k + 1 if !STATUS_REGISTER[s] | |
| BRBS s,k | 1111 00kk kkkk ksss | PC = PC + k + 1 if STATUS_REGISTER[s] | |
| IJMP | 1001 0100 0000 1001 | PC = R31:R30 | |
| ICALL | 1001 0101 0000 1001 | SRAM[SP:(SP-1)] = PC+1; SP = SP - 2; PC = R31:R30 | |
| RET | 1001 0101 0000 1000 | SP = SP + 2; PC = SRAM[SP:(SP-1)] | |
| POP Rd | 1001 000d dddd 1111 | SP = SP + 1; Rd = SRAM[SP] | |
| PUSH Rd | 1001 001d dddd 1111 | SRAM[SP] = Rd; SP = SP - 1 | |
| NOP | 0000 0000 0000 0000 |
| System call (R24) C | Meaning
| 0 | exit(0) | terminate program execution
| 1 | printf("%d\n", R26) | print a signed integer (-128..127)
| 2 | printf("%2x\n", R26) | print an unsigned integer in hexadecimal
| 3 | printf("%c", R26) | print a character
| 4 | scanf("%d", R24)) | read an signed integer (-128..127)
| 5 | R24=getchar() | read a character
| |
|---|
Note, system calls do not change memory or any register. The only exception is register 24 is changed by systems call 4 & 5 (only).
| hello_world.asm (hex) | Print "hello\n". |
| iota.asm (hex) | Print the integers 1 to 10. |
| evenodd.asm (hex) | Tets if a number is even/odd |
| store_load.asm (hex) | Simple use of SRAM |
| sram.asm (hex) | Store numbers in SRAM |
| read_array.asm (hex) | Read numbers into SRAM, then print |
| fib.asm (hex) | Simple recursive function using of ICALL, RET, PUSH & POP. |
| call.asm (hex) | Simple use of ICALL & RET. |
| hello10.asm (hex) | Another use of ICALL & RET. |
| fib.asm (hex) | Simple recursive function using of ICALL, RET, PUSH & POP. |
More examples will be added.
You will need to convert Emu assembler to Intel hex (ihex) format. As Emu is a subset of the AVR architecture. Standard AVR tools can be used to Emu assembler to ihex. For example:
% cat iota.asm
; for (i = 0;i != 10; i++) printf("%d\n", i);
; i in r16
;
LDI r16, 0 ; i = 0
LDI r24, 1 ; printf("%d\n", i);
MOV r26, r16
LDI r31, 0x70
LDI r30, 0x00
ICALL
LDI r17, 1
ADD r16, r17 ; i++
LDI r17, 10
SUB r17, r16
BRBC 1, 2
LDI r24, 0 ; exit
LDI r31, 0x70
LDI r30, 0x00
ICALL
% /home/cs1721/bin/avr-as iota.asm -o iota.elf
% /home/cs1721/bin/avr-ld iota.elf -o iota.exe
% /home/cs1721/bin/avr-objcopy -O ihex iota.exe iota.hex
% cat iota.ihex
:1000000000E081E0A02FF0E7E0E0099511E0010FAA
:0E00100014E6101BB1F780E0F0E7E0E0099580
:00000001FF
Read and decoding ihex format file will be covered in week 5 tutes/labs.
The input to the Emu Emulator is an ihex file containing SAVY machine code. The Emu Emulator allows a user to examine and run Emu programs.
The emulator has nine interactive commands.
| registers | Print the contents of registers | ||||||||||
| data | Print the contents of SRAM. | ||||||||||
| data address | Print the contents of the SRAM byte at address. | ||||||||||
| data address1 address2 | Print the contents of th eSRAM bytes at address1 to address2.
| program | Print the contents of program memory
| step | Print and execute the next instruction.
| run | continue program execution from the next instruction. Do not print instructions or addresses.
| restart | Re-initialize all registers and SRAM
| quit | Exit the emulator.
| |
Your emulator should initialize SRAM and unused program memory to zero. All registers including PC and SREG should also be initialized to 0, except the SP which should be initialized to 4351.
A reference implementation program has been provided for you to use for comparison. Your emulator should match its behaviour exactly. Given the same input, it should produce the same output character-for-character.
It is very likely students will find bugs in the reference implementation. These will be fixed as reported. When testing your program, make sure you compare it to the latest version of the reference implementation.
Here is an example of the reference implementation in operation.
% /home/cs1721/bin/emu /home/cs1721/public_html/05s2/emu/examples/iota.hex Emu Reference Implementation v0.? > program 0000: e000 LDI R16,0 0001: e081 LDI R24,1 0002: 2fa0 MOV R26,R16 0003: e7f0 LDI R31,112 0004: e0e0 LDI R30,0 0005: 9509 ICALL 0006: e011 LDI R17,1 0007: 0f01 ADD R16,R17 0008: e614 LDI R17,100 0009: 1b10 SUB R17,R16 000a: f7b1 BRBC 1,-10 000b: e080 LDI R24,0 000c: e7f0 LDI R31,112 000d: e0e0 LDI R30,0 000e: 9509 ICALL > registers PC=0000 SP=1100 SR=[C=0,Z=0,N=0,V=0] r00-r0f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 r10-r1f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 > step 0000: e000 LDI R16,0 PC=0001 SP=1100 SR=[C=0,Z=0,N=0,V=0] r00-r0f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 r10-r1f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 > run 0 1 2 3 4 5 6 7 8 9 > restart > run 0 1 2 3 4 5 6 7 8 9 > registers PC=000f SP=1100 SR=[C=0,Z=1,N=0,V=0] r00-r0f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 r10-r1f 0a 00 00 00 00 00 00 00 00 00 09 00 00 00 00 70 > restart > registers PC=0000 SP=1100 SR=[C=0,Z=0,N=0,V=0] r00-r0f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 r10-r1f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 > step 0000: e000 LDI R16,0 PC=0001 SP=1100 SR=[C=0,Z=0,N=0,V=0] r00-r0f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 r10-r1f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 > quit % /home/cs1721/bin/emu /home/cs1721/public_html/05s2/emu/examples/sram.hex Emu Reference Implementation v0.? > run 0 1 ... 99 > data 280 0x0118: 18 > data 300 400 0x012c: 2c 2d 2e 2f 0x0130: 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 0x0140: 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 0x0150: 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f 0x0160: 60 61 62 63 00 00 00 00 00 00 00 00 00 00 00 00 0x0170: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0190: 00 > data 0x0100: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 0x0110: 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 0x0120: 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 0x0130: 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 0x0140: 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 0x0150: 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f 0x0160: 60 61 62 63 00 00 00 00 00 00 00 00 00 00 00 00 0x0170: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0190: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x01a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x01b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x01c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x01d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x01e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x01f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0200: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ... 0x10f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1a 00
Given the argument -execute your emulator should immediately run the supplied program. Your emulator should exit when the program terminates. For example:
% /home/cs1721/bin/emu -execute /home/cs1721/public_html/05s2/emu/examples/iota.hex 0 1 2 3 4 5 6 7 8 9 %
Make sure you understand the AVR machine and its instructions. These will be explained in lectures and tutes.
You must understand the representation of numbers in the decimal, binary and hexadecimal.
Note,tute/labs covered reading and decoding ihex format.
Tackle some of the simple emulator functions first.
There is some starting point code which you may care to use (or not) in emu.c and emu.h.
You can the spcified ihex files will be in the correct format and contain only valid EMU opcodes.
In general, you should handle errors sensibly. If in doubt imitate the reference implementation. The automatic marking will not test error handling.
The marking scheme for this assignment will recognise the difficulty of the task. 80% of the marks for this assignment will come from testing your program automatically on a number of Emu programs You will receive marks according to how many Emu programs your emulator handles correctly. These programs will be different to the ones you have been supplied.
20% of the marks for this assignment will come from hand marking by your tutor. These marks will be awarded on the basis of clarity, commenting, elegance and style. In other words, your tutor will assess how easy it is for a human to read and understand your program.
Programs which implement little or none of the emulator correctly, but which contain some correct useful C will be entirely hand-marked and will likely receive marks of 30-45%.
Here is an indicative marking scheme (out of 10).
| 100% | A well-documented and very readable program which works perfectly |
| 85+% | All emulator functions work for all programs tested. |
| 75% | Emulator largely working for most programs. |
| 65% | Emulator largely working for some programs. |
| 55% | Emulator partially working for some programs. |
| 45% | Significant progress has been made on the assignment.. |
| -100% | Knowingly supplying work to any other person which is subsequently submitted by another student. |
| 0 FL for COMP1721 | Submitting any another person's work with their consent. This includes joint work. |
| academic misconduct | Submitting another person's work without their consent. |
The lecturer may vary the above marking scheme after seeing the assignment submissions.
The lecturer may vary the above marking scheme after seeing the assignment submissions.
You program will be compiled and tested with dcc -O -Wall. It may be penalized if dcc produces compile-time warnings or un-time errors.
The output from your program must be identical (character-for-character) to the reference implementation you have supplied. You may be penalized if your program produces output in another format or produces any extra output.
Up to 3 bonus marks are available for successfully completing an optional advanced component for the assignment.
The optional advanced component is to implement a graphical user interface (GUI) for your emulator and provide the full AVR instruction set.
As up to 3 bonus marks are available, so you may obtain a mark of up to 13/10 for the assignment. Note, the optional component is a large amount of work for few marks.
You must keep a record of all work on your assignment. The entries should include date, starting time, finishing time, general category, and a brief (one or two line) description of the work carried out. For example:
| Date | Start | Stop | Activity | Comments |
|---|---|---|---|---|
| 10/9 | 16:00 | 17:30 | coding | implemented get_move function |
| 10/9 | 20:00 | 10:30 | debugging | found bug in legal_move method |
Your implementation diary should be placed in a file named diary.txt. The diary will not be marked but there is a 20% penalty if you fail to provide it.
You also should also keep a record of your testing of your programs and a defect history for your work. This should give the general approach to testing you used and the results of your testing.
This description should also contain a bug tracking report. This should describe when major bugs appeared and were removed from your program.
| When Created | When Discovered | When Fixed | Activity | Description |
|---|---|---|---|---|
| 10/9 | 13/9 10:00 | 14/9 19:00 | coding | incorrect array index in legal_move method |
Your testing description should be placed in a file named testing.txt. Again there is a 20% penalty if you fail to provide this section.
The work you submit must be your own work. Submission of work partially or completely derived from any other person or jointly written with any other person is not permitted. The penalties for such an offence may include negative marks, automatic failure of the course and possibly other academic discipline. Assignment submissions will be examined both automatically and manually for such submissions.
Relevant scholarship authorities will be informed if students holding scholarships are involved in an incident of plagiarism or other misconduct.
Do not provide or show your assignment work to any other person - apart from the teaching staff of Higher Computing 1B. If you knowingly provide or show your assignment work to another person for any reason, and work derived from it is submitted you may be penalized, even if the work was submitted without your knowledge or consent. This may apply even if your work is submitted by a third party unknown to you.
Note, you will not be penalized if your work is taken without your consent or knowledge.
You must submit your assignment using the give command, e.g.:
give cs1721 emu a.h b.h a.c b.c c.c d.c
Note, all files must be submitted together.
Your assignment is tentatively due at 23:59pm Monday September 26
Note, submission even one second after this deadline is considered as one day late.
If your assignment is submitted after this date, each day it is late reduces the maximum mark it can achieve by 20%. For example if an assignment worth 76% was submitted one day late, the late submission would have no effect. If the same assignment was submitted 2 days late it would be awarded 60%, the maximum mark it can achieve at that date.