EECE 321 Midterm with Solution, Spring 2014

American University of Beirut · Computer Organization · 7 pages · Prof. Mohammad Mansour · with solution

All EECE 321 files
EECE 321 Midterm with Solution, Spring 2014, page 1

Stuck on a question? A tutor can walk you through it.

EECE 321 Midterm with Solution, Spring 2014, page 2 EECE 321 Midterm with Solution, Spring 2014, page 3 EECE 321 Midterm with Solution, Spring 2014, page 4 EECE 321 Midterm with Solution, Spring 2014, page 5 EECE 321 Midterm with Solution, Spring 2014, page 6 EECE 321 Midterm with Solution, Spring 2014, page 7

More EECE 321 files

Show the text of this exam
Problem #1: CPU Performance [12 points] a) Consider the following C++ code. Assume you generated MIPS assembly code for the C++ code using two different compilers. Compiler 1 generated the code in the first column while compiler 2 generated the code in the second column. Assume that all the instructions used by the compilers are real instructions (as opposed to pseudo-instructions) in the MIPS architecture. Assume arithmetic/logic instructions require 2 cycles to execute, loads 5 cycles, branches 3 cycles, and jumps 1 cycle. void probx(int arr[ ], int n) { for(int i=0 ; i<n ; i=i+1) arr[i] = i+1; } Compiler 1 Compiler 2 add $t0, $zero, $zero add $t1, $zero, $zero loop: bge $t1, $a1, back sll $t2, $t1, 2 add $t2, $t2, $a0 addi $t3, $t1, 1 sw $t3, 0($t2) addi $t1, $t1, 1 j loop back: jal $ra sll $a1, $a1, 2 sll $t3, $zero, 2 sll $t1, $zero, 2 bge $t1, $a1, back loop: add $t2, $t1, $a0 addi $t3, $t3, 1 sw $t3, 0($t2) addi $t1, $t1, 4 blt $t1, $a1 loop back: jal $ra a) Fill the table below with the number of instructions of each type that will be executed by the code generated by compiler 1 and by compiler 2 when the function probx(arr, 100) is invoked. Instruction Type Compiler 1 Code Compiler 2 Code Arithmetic/logic 402 304 Loads 100 100 Branches 101 101 Jumps 101 1 b) Compute the average number of clock cycles per instruction (CPI) for each version of the program. Average CPI (Compiler 1) (402*2 + 100*5 + 101*3 + 101*1)/704 = 1,708/704 Average CPI (Compiler 2) (304*2 + 100*5 + 101*3 + 1*1)/506 = 1,412/506 c) Which version of probx() is faster if you run it on a 1 GHz processor and by how much? Answer: _______1708/1412 = 1.209  21%______________ Problem #2: Single-Cycle MIPS Control [12 Points] Consider the single cycle MIPS datapath shown in the figure below. In the Table below, fill in the corresponding values of the 9 control signals when executing the instructions shown on the left hand-side of the table. The ALU control bits are shown in a table at the bottom. Use X to denote don’t-care entries where necessary. Do not mark entries with 0 or 1 when a don’t-care condition applies. Instruction RegDest Jmp Brnch MemRd MemtoReg ALUOp MemWr ALUSrc RegWr or $2, $5,$7 1 0 0 0 0 10 0 0 1 beq $3, $4, L X 0 1 0 X 01 0 0 0 lw $1, 8($2) 0 0 0 1 1 00 0 1 1 j FINISH X 1 0 0 X XX 0 X 0 Problem #3: MIPS Programs [12 points] Consider the following MIPS assembly code. origami: li $t0, 0 li $v0, 0 pear: mul $t1, $t0, 4 add $t1, $a0, $t1 lw $t1, 0($t1) blt $t1, $0, pizza mul $t2, $v0, 4 add $t2, $a1, $t2 sw $t1, 0($t2) add $v0, $v0, 1 pizza: add $t0, $t0, 1 blt $t0, $a2, pear jr $ra a) Translate the function origami above into C++. You should include a header that lists the types of any arguments and return values. Also, your code should be as concise as possible, without pointers. We will not deduct points for syntax errors unless they are significant enough to alter the meaning of your code. int origami(int A[], int B[], int a2) { // array A[] starts at a0 and array B[] starts at a1 int t0 = 0; int v0 = 0; do { int t1 = A[t0]; if ( t1 >= 0) { B[v0] = A[t0]; v0++; } t0++; }while (t0 < a2); return v0; } b) Describe briefly, in English, what this function does. This function inspects first a2 elements of array A and copies them into array B if they are nonnegative. The return value is the number of copies. Problem #4: Compiling Recursive Functions [12 points] Compile the following function into MIPS instructions and add comments to your code. The function pow takes two arguments (n and m, both 32-bit numbers) and returns nm (i.e., n raised to the mth power). This function assumes that m is greater than or equal to one. int pow(int n, int m) { if (m == 1) return n; return n * pow(n, m-1); } Argument registers $a0 and $a1 will correspond to n and m, and the return value should be placed in $v0 as usual. You will not be graded on the efficiency of your code, but you must follow all MIPS conventions. Comment your code. pow: bne $a1, 1, rec # if m == 1, return a0 move $v0, $a0 # base case: set return value to n j $ra # jump back to the caller rec: addi $sp, $sp, -8 # adjust the stack to store $ra sw $ra, 0($sp) # save $ra sw $a0, 4($sp) # save $a0 addi $a1, $a1, -1 # recursive case: m = m - 1 jal pow # call pow with n and m - 1 lw $a0, 4($sp) # restore $a0 mult $v0, $v0, $a0 # multiply the result by n lw $ra, 0 ($sp) # restore the return address of pow addi $sp, $sp, 8 # readjust the stack pointer $sp j $ra # jump back to the caller Notes: • Since pow does not manipulate $a0, it is OK (but perhaps bad style) not to preserve its value in this program. • Contents of $a1 need not be saved, because $a1 is not used by pow after the recursive call. Problem #5: Short Questions, 4 points each [32 Points] a) Convert to Decimal the following single-precision IEEE 754 floating point number: 1 10000111 11011000000000000000000 -472.0 b) Convert -128.875(10) from decimal to single precision IEEE 754 floating-point representation. Express your result in hexadecimal. 0xC300E000 = 11000011 00000000 11100000 00000000 c) The hexadecimal number 0xC08F400000000000 represents a double precision IEEE floating-point number. What is the corresponding decimal value? -1000(10) d) Perform the following floating-point addition as computed in a single-precision FP hardware adder with a total of 4 precision bits. Show all steps and give the final result in: a. Normalized binary (4 bits of precision) b. Normalized decimal (4 digits of precision) -1.1012 x 2-2 + 1.0112 x 2-3 -1.111(2) x 2-3 = -0.2344(10) = -2.344(10) x 10-1 e) If the instruction beq $s0, $s1, Exit is located at address 0x004000BC, and encoded as 0x10800007, what is the byte address of the label Exit? Show your steps. 0x004000DC Instruction j Label is stored at 0x004400A4, and Label is at instruction address 0x0044008C. Encode this instruction and express your answer in hexadecimal. The opcode for the jump instruction is (000010). 000010 [0000 0100 0100 0000 0000 1000 11] = 0000 1000 0001 0001 0000 0000 0010 0011 = 0x 08110023 f) Write MIPS instructions in the body of the C++ function flip_nb(x,n) below that takes a 16-bit unsigned integer x (b15b14b13… b1b0) and returns the same value with the “n”th bit (bn) inverted (i.e., bn flipped from 1 to 0 or from 0 to 1). For example, calling flip_nb(0x04F2,7) returns 0x0472. unsigned flip_nb(unsigned x, unsigned n) { li $t0, 1 sll $t0, $t0, $a1 xor $v0, $t0, $a0 jr $ra } g) Consider the following sequence of MIPS instructions. Where does the jr $ra instruction jump? jal L1 L1: addi $ra, $ra, 8 L2: jr $ra Second instruction after L2 Problem #6: MIPS Compilation [12 points] Compile the following C++ statements shown on the left column. Assume the following register- to-variable mappings: i:$s0, j:$s1, A:$s2. You can only use the following MIPS instructions: sll, srl, add, addi, andi, sub, lw, sw, slt, beq, bne, j. NO OTHER INSTRUCTIONS ARE ALLOWED. The variables i, j, and the array A are all integers. A[2*i+3*j] = A[7*i+5*j]; sll $t0, $s0, 1 //t0=2*i sll $t1, $s1, 1 //t1=2*j add $t1, $t1, $s1 //t1=3*j add $t1, $t0, $t1 //t1=2*i+3*j sll $t1, $t1, 2 //t1=4*(2*i+3*j) add $t1, $t1, $s2 //t1=t1+base lw $t0, (0)$t1 //t0=A[t1] sll $t0, $s0, 3 //t0=8*i sub $t0, $t0, $s0 //t0=7*i sll $t1, $s1, 2 //t1=4*j add $t1, $s1, $t1 //t1=5*j add $t1, $t0, $t1 //t1=7*i+5*j sll $t1, $t1, 2 //t1=4*(7*i+5*j) add $t1, $t1, $s2 //t1=t1+base sw $t0, (0)$t1 //A[2*i+3*j]=A[7*i+5*j] if (i ≤ j) i = (i % 16) + 1; //Note: i%16 is i modulo 16 slt $t0, $s1, $s0 //t0=(j<i) bne $t0, $0, EXIT //branch if t0=1 andi $s0, $s0, 0xF addi $s0, $0, 1 EXIT: for(i=5; i<100 || j>0; i++) A[j] = i; addi $s0, $0, 5 addi $t0, $0, 100 START: slt $t1, $s0, $t0 beq $t1, $0, EXIT slt $t2, $0, $s1 beq $t2, $0, EXIT sll $t3, $s1, 2 Problem #7: Pseudo-Instructions [8 points] Consider the SWAP pseudo-instruction that swaps the contents of two registers $s0 and $s1: SWAP $s0, $s1 // swaps contents $s0 and $s1 a) You are told that you can implement the SWAP instruction without using any registers other than $s0 and $s1 in your MIPS code. Can you come up with such a sequence of instructions to implement SWAP? xor $s0,$s0,$s1 // $s0 = $s0 ⊕ $s1 xor $s1,$s0,$s1 // $s1 = ($s0 ⊕ $s1) ⊕ $s1 = $s0 xor $s0,$s0,$s1 // $s0 = ($s0 ⊕ $s1) ⊕ $s1 = ($s0 ⊕ $s1) ⊕ $s0 = $s1 b) Use the above SWAP pseudo-instruction to implement a three-way swapping among three registers $s0, $s1, $s2 as follows: $s0 <- $s1, $s1 <- $s2, $s2 <- $s0 SWAP $s0, $s1 //$s0 = $s1, $s1 = $s0; SWAP $s1, $s2 //$s2 = $s1 = $s0 (old), $s1 = $s2