CSCI 162 practice final [90 marks total]

The final is closed book, closed notes, no calculators or other electronics permitted. A reference sheet is included with the exam, covering key Marie opcodes, boolean logic identities, powers of 2, lisp syntax, and prolog syntax.


Question 1: [15 marks]

The prolog fact/rule set below supports a simplified fetch/decode/execute cycle for Marie programs, along with a sample test case. Study the code, and answer the following two questions:

  1. Currently the "execute" rules are only set up to handle instructions halt, input, output, and add, and only positive integers.

    Write a rule to handle the store instruction.

    You may use any of the "helper" functions listed (you do not need to write them).

  2. Write a rule for testCase(2): setting up a marie program that uses/tests your store instruction.

    Be sure to describe the expected output/behaviour of your test case.

% run(M,R)
% --------
% run a Marie program where M is a list representing the
%        contents of memory at the start of the program,
%     and R is a list representing some of the register contents
%        in order [ ACC, PC, IR ]
%
% the contents of each register and each memory cell is
%     represented using a string of 4 hex digits
%        e.g. M = [ "5000", "2005", "3005", "6000", "7000", "0003" ]

run(M,R) :-
        fetch(M,R,R1),       % R1 contains the register values after the fetch/decode
        execute(M,R1,R2,M2), % R2 and M2 are the register/memory contents after execution
        !, (testforhalt(R2)  % quit if the instruction was halt,
        ; run(M2,R2)).       %    otherwise continue execution with new M and R

% fetch(M,R,Rnew)
% ---------------
% fetch the next instruction from memory,
%    using the PC (second element of R) to identify the correct element of M
% the contents of Rnew will be the same as R except as follows:
%    the IR element should contain the newly fetched instruction
%    the PC element should be greater by 1
fetch(M,[Acc, PC, _] , [Acc, NewPC, NewIR] ) :-
   int2hexstr(Addr, PC),       % convert the PC string to an integer address
   nth0(Addr, M, NewIR),       % look up the instruction
   NewAddr is Addr + 1,        % calculate the next instruction address
   int2hexstr(NewAddr, NewPC). % convert the integer address back to a string

% execute(M,R,Rnew,Mnew)
% ----------------------
% M,R represent the current memory and register lists,
%    identify the instruction (the IR element of R), then
%    compute/set the updated register and memory lists

% execute the halt instruction: nothing changes, just succeed
execute(_, [_, _, "7000"], _, _).

% execute the output instruction: no content changes,
%    but the contents of Acc are displayed
execute(M, [Acc, PC, "6000"] , [Acc, PC, "6000"], M) :-
   format("~w~n", [Acc]).

% execute the input instruction: the contents of Acc are updated by a read
execute(M, [_, PC, "5000"] , [NewAcc, PC, "5000"], M) :-
   format("Enter a value followed by a period, e.g. 32.~n"),
   read(NewAcc).

% execute the add instruction: the contents of the Acc are updated\
execute(M, [Acc, PC, IR], [NewAcc, PC, IR], M) :-
   instrMatch("2000", IR),           % make sure the first char of instruction is "2"
   extractArg(IR, "2000", MemAddr),  % get the memory address from the instruction
   lookupMemVal(MemAddr, M, MemVal), % get the int val from memory address
   int2hexstr(AccVal, Acc),          % get the value from Acc as an integer
   NewAccVal is AccVal + MemVal,     % compute int value for new Acc
   int2hexstr(NewAccVal, NewAcc).    % convert to string for register

% ---------- Descriptions of available helper functions ------------------

% testforhalt(R)
% succeeds iff the IR element of R is the halt instruction
testforhalt( [_, "7000" | _] ).

% lookupMemVal(Addr, Mem, Val)
% given an address in memory, lookup the value stored there as an integer

% extractArg(InstrStr, BaseStr, IntArg)
% given a hex string, InstrStr, representing an instruction, (e.g. "2005")
%    and a base string, BaseStr, representing the instruction type (e.g. "2000")
%    extract the argument portion as an integer (e.g. 5)

% int2hexstr(I,HS)
% converts between an integer value I and a hex string HS

% instrMatch(Base,HS)
% succeeds if first char of Base matches first char of string HS

% testCase(N)
% run the simulator on a numbered test case

% test case 1: read a number, output, add 3 (from mem addr 5), output, halt
testCase(1) :- M = [ "5000", "6000", "2005", "6000", "7000", "0003" ],
               R = [ "0000", "0000", "0000" ],
               run(M,R).


Question 2: [15 marks]

Suppose we are given the following regular expression that accepts certain 4-bit strings:
      (1 [01]{2} 0) | ( [01] 10 [01] )

  1. Assuming wxyz represent the four bits in a string, fill in the truth table below, where f is 1 if the string is accepted by the regular expression, 0 otherwise. For example, 1010 is accepted so f is 1 there, 0010 is not accepted, so f is 0 there. (Those two entries have been filled in below.)
    wxyz   f  
    0000  
    0001  
    0010   0
    0011  
    0100  
    0101  
    0110  
    0111  
    1000  
    1001  
    1010   1
    1011  
    1100  
    1101  
    1110  
    1111  

  2. Draw a karnaugh map to represent function f, and produce a minimal sum of products expression for f. (Be sure to clearly circle the groups of terms on your k-map.)


Question 3: [15 marks]

Suppose we decide to represent 6-bit two's complement integers but using base 4, rather than binary/octal/hex. For this representation:

  1. Draw a finite state machine that accepts positive even numbers.

  2. Draw a finite state machine that accepts numbers that are less than 1.


Question 4: [15 marks]

  1. Write a lisp function whose behaviour matches that of the marie program below:
    Top,   input
           store    X
           skipcond 000
           jump     Done
    
           add      Y
           store    Y
           jump     Top
    
    Done,  load     Y
           output
           halt
    
    X,     dec      0
    Y,     dec      0
    

  2. Provide a brief, intuitive documentation string for your lisp function.


Question 5: [15 marks]

Suppose we are given the following lisp function:
(defun f (L)
   (cond
      ((not (listp L)) nil)
      ((null L) nil)
      ((not (numberp (car L))) (f (cdr L)))
      (t (cons (car L) (f (cdr L))))))

  1. Show the return value that would result from the call below, and briefly explain f's apparent purpose.
    (f '(2 "foo" 4 6 nil)

  2. If we regard N as the length of the list passed to f, which of the following best represents the complexity of f?
    O(log(N)) O(N) O(N log(N) O(N2)
    Justify your answer.


Question 6: [15 marks]

Write a set of prolog facts/rules to handle queries of the form
      allbigger(L1,L2).
where the queries succeed if and only if L1 and L2 are non-empty lists of numbers for which every number in L1 is bigger than every number in L2.