;; a simple simulator for the ILOC virtual machine, described in ;; COMP 210, SPRING 2000 Lecture 35 ;; ;; To run this simulator, you must ;; - initialize the program and data memory for your program ;; - start the simulator by invoking (Run) ;; The example from the program is available in the function (Toggle) ;; given below... ;; ;; Thus, you can perform the example from Lecture 35 by invoking ;; (Toggle) followed by (Run). The parameter n is read from Data location ;; 100. The result is stored back to Data location 101. ;; an operation is a structure ;; (make-op fn arg1 arg2 arg3) ;; where fn is a symbol and arg1, arg2, & arg3 are integers (define-struct op (fn arg1 arg2 arg3)) ;; The processor has a set of registers (define Regs (build-vector 32 (lambda (i) 0))) ;; and a data memory (1k numbers or words) (define Data (build-vector 1024 (lambda (i) 0))) ;; and a program memory (1k operations) (define Prog (build-vector 1024 (lambda (i) (make-op 'STOP 0 0 0)))) ;; the program counter (PC) keeps track of where the next operation ;; is to be found in the program memory (define PC 0) ;; first op is at location zero ;; code for the control unit ;; hard coding 'STOP into this is a minor kludge, but it ;; provides a termination condition and, experience suggests, ;; it simplifies debugging ;; (define (ControlUnit) (local [(define ThisOp (vector-ref Prog PC))] (begin (set! PC (add1 PC)) ;; update next operation's position (cond [(symbol=? (op-fn ThisOp) 'STOP) true] [else (FunctionalUnit ThisOp) (ControlUnit) ]) ))) ;; the functional unit of a stripped-down ILOC VM ;; This code is invoked by the control unit to execute a single ;; operation. ;; Effect: if the operation is a taken 'BRANCH, then it will ;; alter the value of the global variable PC ;; ;; Note: This version includes code for tracing each operation. (define (FunctionalUnit AnOp) (local [(define f (op-fn AnOp)) (define r1 (op-arg1 AnOp)) (define r2 (op-arg2 AnOp)) (define r3 (op-arg3 AnOp)) ] (begin (printf "at ~a: " (sub1 PC)) ;; tracing code (cond ;; heart of the functional unit [(symbol=? f 'ADD) (vector-set! Regs r3 (+ (vector-ref Regs r1) (vector-ref Regs r2)))] [(symbol=? f 'SUB) (vector-set! Regs r3 (- (vector-ref Regs r1)(vector-ref Regs r2)))] [(symbol=? f 'MUL) (vector-set! Regs r3 (* (vector-ref Regs r1)(vector-ref Regs r2)))] [(symbol=? f 'DIV) (vector-set! Regs r3 (/ (vector-ref Regs r1)(vector-ref Regs r2)))] [(symbol=? f 'LOAD) (vector-set! Regs r2 (vector-ref Data (vector-ref Regs r1)))] [(symbol=? f 'STORE) (vector-set! Data (vector-ref Regs r2) (vector-ref Regs r1))] [(symbol=? f 'LOADI) (vector-set! Regs r2 r1)] [(symbol=? f 'COPY) (vector-set! Regs r2 (vector-ref Regs r1))] [(symbol=? f 'EQ?) (vector-set! Regs r3 (= (vector-ref Regs r1)(vector-ref Regs r2)))] [(symbol=? f 'BRANCH) (cond [(vector-ref Regs r1) (set! PC r2)] ;; not Regs[r2], but r2 itself [else true])] ) (cond ;; more tracing code [(symbol=? f 'LOAD) (printf "LOAD r~a => r~a (~a)~n" r1 r2 (vector-ref Regs r2))] [(symbol=? f 'STORE) (printf "STORE r~a => r~a (~a)~n" r1 r2 (vector-ref Regs r2))] [(symbol=? f 'LOADI) (printf "LOADI ~a => r~a (~a)~n" r1 r2 (vector-ref Regs r2))] [(symbol=? f 'COPY) (printf "COPY r~a => r~a (~a)~n" r1 r2 (vector-ref Regs r2))] [(symbol=? f 'BRANCH) (printf "BRANCH r~a -> ~a~n" r1 r2)] [else (printf "~a r~a r~a => r~a (~a)~n" f r1 r2 r3 (vector-ref Regs r3) )]) ))) ;; To execute the simulator, we need to set the PC to zero and start ;; the Control Unit (define (Run) (begin (set! PC 0) (ControlUnit))) ;; Because we lack sophisticated I/O operations, we need to toggle ;; the program into Program memory and some test data into data memory ;; (define (Toggle) (begin (vector-set! Prog 0 (make-op 'LOADI 1 0 0)) (vector-set! Prog 1 (make-op 'LOADI 100 1 0)) (vector-set! Prog 2 (make-op 'EQ? 1 1 11)) (vector-set! Prog 3 (make-op 'LOAD 1 2 0)) (vector-set! Prog 4 (make-op 'COPY 0 3 0)) (vector-set! Prog 5 (make-op 'ADD 3 2 3)) (vector-set! Prog 6 (make-op 'SUB 2 0 2)) (vector-set! Prog 7 (make-op 'EQ? 2 0 10)) (vector-set! Prog 8 (make-op 'BRANCH 10 10 0)) (vector-set! Prog 9 (make-op 'BRANCH 11 5 0)) (vector-set! Prog 10 (make-op 'LOADI 101 11 0)) (vector-set! Prog 11 (make-op 'STORE 3 11 0)) (vector-set! Prog 12 (make-op 'STOP 0 0 0)) (vector-set! Data 100 3) ))