McGill University Department of Electrical and Computer Engineering ECSE-221 Introduction to Computer Engineering Assignment 5 Assembly and Datapaths Due Date: Monday, November 30 th 2009 at 11:59PM Question 1 Implement a C language function that computes the factorial of a number, recursively, according to the following prototype: void factorial (long argument, long *result); If you are unsure how to proceed, try Googling on the keywords recursive and factorial; the function is relatively straightforward to write. Demonstrate your function by writing an interactive test program that operates as follows: % factorial 6 6! = 720 Question 2 Translate your C function into MIPS assembly, passing arguments on the stack according to the following call convention (assume, below, that the argument is in $10, and that the data is to be returned to location data_return in the data segment): addi $sp, $sp, -8 sw $10, 0($sp) la $11, data_return sw $11, 4($sp) jal factorial addi $sp, $sp, 8 Using the SPIM console I/O functions, write a simple interactive program to query a value from the user and print the factorial of the value as output, e.g., Enter data > 6 6! = 120
Question 3 4 4 8 The figure shown above shows a datapath for a 4-bit x 4-bit unsigned binary multiplier adapted from the one shown in Patterson and Hennessy. The corresponding algorithm, taken literally from the text, is reproduced below. 0. Init. Place Multiplicand in Multiplicand register. Place Multiplier in lower half of Product register. Clear upper half of Product register 1. Test and Update. If the LSB of Product register is 1, add Multiplicand register to upper half of Product register and place result back in the upper half of Product register. 2. Shift. Product register shifted right one 1 bit. 3. Count. If 4th repetition then done else goto step 1.
Do the following: 1. Implement the datapath shown on the previous page in LogicWorks. The Multiplicand and Multiplier inputs are supplied using Hex keypads (i.e. there is no need for an explicit Multiplicand register). The Product register can be implemented using the Shift Reg-4 component and the ALU with the Adder-4. Since the multiplication is unsigned, you will need to take care of the carry out generated by the ALU. Logic will also have to be provided for initializing the Product register at the start of the sequence as well as latching the final product for display. Clearly identify your control lines. 2. A total of 9 clock pulses are necessary to compute the product from the 4-bit multiplier and multiplicand. You will need to synthesize a controller to supply the correct states for your control lines for each of the 9 clock pulses. Start by drawing the state diagram corresponding to this controller, and then produce the state transition table that will be used to generate the ROM program. Implement your controller and validate it with an appropriate LogicWorks simulation. 3. Combine your controller with the datapath and verify that the system functions correctly. Produce 4 examples tracing the clock and the outputs of the product register. 4. Assume the following parameters: Tsu (reg) = 0.1 ns, Th (reg) = 0 ns, Tpd (reg) = 1 ns, Ta (ROM) = 5 ns, Tpd (ALU) = 10 ns, Tpd (all gates) = 0.1 ns. Determine the maximum frequency of operation of the circuit and produce a simulation, to scale, that validates the maximum clock frequency.
Question 1 /*----------------------------------------------------------------------*/ /* Program Name: factorial */ /* Function: Computes the factorial of a command line */ /* argument. */ /* Usage: % factorial [long] */ /* Author: F.P. Ferrie */ /* Date: March 28, 2008 */ /*----------------------------------------------------------------------*/ #include <stdio.h> void factorial (long argument, long *result); int main (int argc, char *argv[]) { long argument, result; if (argc!= 2) { printf("usage: factorial [long]\n"); return(0); } sscanf(argv[1],"%ld",&argument); factorial(argument,&result); printf("%ld! = %ld\n",argument,result); return(0); } /*----------------------------------------------------------------------*/ /* Recursive factorial function */ /* void factorial (long argument, long *result) */ /*----------------------------------------------------------------------*/ void factorial (long argument, long *result) { long temp; if (argument < 2) *result=1; else { factorial(argument-1,result); *result=argument*(*result); } } C:\Users\ferrie\221\lcc\lcc>factorial 0 0! = 1 C:\Users\ferrie\221\lcc\lcc>factorial 1 1! = 1 C:\Users\ferrie\221\lcc\lcc>factorial 2 2! = 2 C:\Users\ferrie\221\lcc\lcc>factorial 3 3! = 6 C:\Users\ferrie\221\lcc\lcc>factorial 4 4! = 24 C:\Users\ferrie\221\lcc\lcc>factorial 5 5! = 120 C:\Users\ferrie\221\lcc\lcc>factorial 6 6! = 720 C:\Users\ferrie\221\lcc\lcc>factorial 7 7! = 5040
Question 2 # Program Name: factorial # Function: Computes the factorial of a command line # argument. # Usage: % factorial [long] # Author: F.P. Ferrie # Date: March 28, 2008.text # Factorial: computes factorial of a number. Arguments passed # on stack according to the convention below. ##SP+4: return (reference) # SP argument (value) factorial: # Context save addi $sp, $sp, -20 sw $10, 0($sp) # Argument sw $11, 4($sp) # Return pointer sw $12, 8($sp) # Scratch sw $fp, 12($sp) # Frame pointer sw $31, 16($sp) # Linkage register # Argument fetch addi $fp, $sp, 20 # Set frame pointer lw $10, 0($fp) # Get factorial argument lw $11, 4($fp) # Get pointer to return # Termination condition for recursion slti $12, $10, 2 # Argument < 2? beq $12, $0, fl10 # No, do recursion li $12, 1 # Yes, set return value sw $12, 0($11) # Store at pointer location b fl20 # To restore context fl10: addi $sp, $sp, -8 # Set up stack for call addi $10, $10, -1 # Set arg to arg-1 sw $10, 0($sp) # Argument on stack sw $11, 4($sp) # Return on stack jal factorial # Execute call addi $sp, $sp, 8 # Restore sp addi $10, $10, 1 # Restore argument for next step lw $12, 0($11) # Get (n-1)! mul $12, $10, $12 # Compute argument x result sw $12, 0($11) # Return n x (n-1)! fl20: lw $10, 0($sp) # Restore context lw $11, 4($sp) lw $12, 8($sp) lw $fp, 12($sp) lw $31, 16($sp) addi $sp, $sp, 20
jr $31 # Return # Main program.globl main main: la $4, prompt # Do prompt - Enter value > li $2, 4 syscall li $2, 5 # Get number from console syscall addi $sp, $sp, -8 # Set up function call sw $2, 0($sp) la $4, return sw $4, 4($sp) jal factorial # Do it addi $sp, $sp, 8 move $4, $2 # Print result li $2, 1 syscall la $4, excl li $2, 4 syscall la $4, return lw $4, 0($4) li $2, 1 syscall la $4, crlf li $2, 4 syscall b main # Data Segment.data prompt:.asciiz "Enter value > " excl:.asciiz "! = " crlf:.asciiz "\n".align 2 return:.word 0 7/36 Console ========================= Enter value > 0 0! = 1 Enter value > 1 1! = 1 Enter value > 2 2! = 2 Enter value > 3 3! = 6 Enter value > 4 4! = 24 Enter value > 5 5! = 120 Enter value > 6 6! = 720 Enter value > 7
7! = 5040 Enter value > 8 8! = 40320 Enter value > 9 9! = 362880 Enter value > 10 10! = 3628800 Enter value >
Question 3 a) Datapath implementation using parts from the standard LogicWorks library. There are 2 datapath control signals, Init and Ld, both of which are active 0. When Init is asserted (i.e. 0), the upper product register is cleared and the lower product register is loaded with the multiplier (lower hex keypad). Init is asserted on the first clock pulse, and de-asserted (1) for the remainder of the cycle. The Ld signal determines whether the product register shifts or loads. Ld is asserted on the first clock pulse (initialization), and then at each ALU operation (pulses 0, 1, 3, 5, 7). An additional D- FF is needed to save the carry out so that it can be shifted in to the product register on the subsequent clock pulse. By connecting P0 to the select line of the multiplicand register (i.e. the hex keypad), adding 0 or adding the multiplicand is handled automatically. Finally, we observe that the Init signal marks
both the end of the current cycle and the start of a new one. Hence the Init signal is used to load the two display registers which latch the result from the product register. b) Finite State Machine
State Transition Table Implementation:
b) Multiplier Implementation
d) Timing Analysis and Demonstration Tclock = Tsu(max) + Tpd(max) + Tcl = 0.1 ns + 1 ns + Tcl Tcl = Tpd(Add) + Tpd(AND) = 10.1 ns Tclock = 11.2 ns Fmax = 89.29 Mhz Simulation: Scale by 10. Show correct function with Tclock = 112 units, and incorrect with 111. Correct answer F x F = E1 with Tclock = 112 units
Incorrect answer F X F = C5 with Tclock = 111 units