;;; -*- Mode:LISP; Package:SIM; Readtable:CL; Base:10 -*- (defflavor sim-frame () (tv:bordered-constraint-frame-with-shared-io-buffer) (:default-init-plist :panes '((lisp lam:sensitive-lisp-listener :save-bits t) (display tv:window :blinker-deselected-visibility :off :save-bits t)) :constraints '((sim-frame (display lisp) ((display 6 :lines)) ((lisp :even))))) ) (defmethod (sim-frame :after :init) (&rest ignore) (send self :set-selection-substitute (send self :get-pane 'lisp))) (tv:add-system-key #\1 'sim-frame "Simulator") (defun display () (let ((sup (send terminal-io :superior))) (cond ((typep sup 'sim-frame) (send sup :get-pane 'display)) (t terminal-io)))) (defun update-display () (labels ((register-contents (inst base-code offset) (ecase base-code (0 (send *proc* :read-open offset)) (1 (send *proc* :read-active offset)) (2 (send *proc* :read-return offset)) (3 (send *proc* :read-frames (+ (ash (ldb %%i-immediate inst) 4) offset))) (4 (send *proc* :read-functional offset)) ))) (catch-error-restart ((sys:abort error) "Give up trying to UPDATE-DISPLAY") (let* ((w (display)) (pc (send *proc* :read-next-pc)) (inst (send *proc* :read-main-memory (send *proc* :read-pc)))) (send w :clear-screen) (format w "PC=#o~o " pc) (print-symbolic-adr pc w) (format w "~40t") (format w "~s" (disassemble-inst inst)) (format w "~&DEST=~o~20tSRC1=~o~40tSRC2=~o" (register-contents inst (ldb %%i-dest-base inst) (ldb %%i-dest-offset inst)) (register-contents inst (ldb %%i-src-1-base inst) (ldb %%i-src-1-offset inst)) (register-contents inst (ldb %%i-src-2-base inst) (ldb %%i-src-2-offset inst))) (format w "~&O=~o~20tA=~o~40tR=~o" (send *proc* :read-open-frame) (send *proc* :read-active-frame) (send *proc* :read-return-frame)) (when (not (zerop (send *proc* :read-noop-next-bit))) (format w "~&NOOP")) ) ))) (defvar *get-next-command-unget* nil) (defun unget-command (blip) (setq *get-next-command-unget* (append *get-next-command-unget* (list blip)))) (defconst *activation-list* '(#\/ #\tab #\space #\: #\altmode #\@ #\linefeed #\^ #\= #\page #\: #\. #\_ #\( )) (defun get-next-command () (cond ((null *get-next-command-unget*) (labels ((act-fun (char) (or (ldb-test %%kbd-super char) (member char *activation-list* :test 'char-equal)))) (do (command blip error-p) (()) (multiple-value (command blip) (with-input-editing (terminal-io `((:activation ,#'act-fun) (:preemptable) (:full-rubout :full-rubout) ) ) (do ((out-string (make-string 10. :fill-pointer 0)) (char (send terminal-io :any-tyi) (send terminal-io :any-tyi))) ((or (not (integerp char) (characterp char))) (values out-string char)) (array-push-extend out-string char)))) (cond ((eq blip :full-rubout) (return :full-rubout)) ((consp command) (case (car command) (:typeout-execute (case (cadr command) (lam:force-object-kbd-input (funcall (cadr command) (caddr command) terminal-io)))))) (t (multiple-value (*command-prefix* error-p) (ignore-errors (read-from-string command nil))) (cond (error-p (format t "?? error reading ")) (t (when (not (member (cadr blip) '(#\linefeed #\( ) :test 'char-equal)) (format t "~c" (cadr blip))) (return blip)))))))) (t (pop *get-next-command-unget*)))) (defvar *accumulator*) (defvar *command-prefix*) (defvar *last-command*) (defvar *update-display*) (defvar *current-address*) (defun sim () (let ((*accumulator* nil) (*command-prefix* nil) (*update-display* t) (*read-base* 8) (*print-base* 8) (*last-command* nil) (*current-address* 0) ) (command-loop) )) (defsignal bad-reg-adr error ()) (defsignal sim error ()) (defun command-loop () (format t "~&") (catch 'exit (do-forever (catch-error-restart ((sys:abort error) "Return to top level in SIM") (condition-case (error) (do-forever (when *update-display* (update-display) (setq *update-display* nil)) (let ((blip (get-next-command))) (cond ((eq blip :full-rubout) (format t " ?? ")) (t (let ((val (sim-eval *command-prefix*))) (when (numberp val) (if (null *accumulator*) (setq *accumulator* 0)) (incf *accumulator* val))) (when (consp blip) (case (car blip) (:activation (let* ((fun-name (format nil "SIM-~@:(~:C~)" (cadr blip))) (fun (intern-soft fun-name 'sim))) (cond ((fboundp fun) (funcall fun) (setq *last-command* fun) (when (not (memq fun '(sim-@ sim-space sim-.))) (setq *accumulator* nil))) (t (format t "?? ~s " fun-name))))))))))) ((bad-reg-adr sim) (format t "~&Error: ") (send error :report terminal-io) (format t "~&") (setq *accumulator* nil)))) (format t "~&Back to SIM top level.~&")))) (defun sim-space () ) (defun sim-altmode () (throw 'exit (>convert-to-pointer *last-value*))) (defun sim-page () (setq *update-display* t)) (defun sim-super-n () (send *proc* :single-step) (setq *update-display* t)) (defun sim-@ () (let ((blip (get-next-command))) (unget-command blip) (case *command-prefix* (G (when (null *accumulator*) (ferror 'sim "no value available")) (send *proc* :write-next-pc *accumulator*) (send *proc* :write-noop-next-bit 1) (format t "~&") (setq *update-display* t)) (t (let ((off (ra-command-to-address *command-prefix*))) (cond ((null off) (format t "?? unknown base")) ((null *accumulator*) (ferror 'sim "@ requires a prefix value")) (t (incf *accumulator* off)))))))) (defun sim-/ (&aux val) (format t " ") (when (null *accumulator*) (ferror 'sim "no value accumulated")) (setq *current-address* *accumulator*) (multiple-value-bind (sym-base offset adr-mode value-type) (symbolic-adr *current-address*) sym-base offset adr-mode (cond ((< *current-address* 0) (setq val (ra-read *current-address*))) (t (setq val (send *proc* :read-main-memory *current-address*)))) (incf *current-address* (sim-print-val val value-type *current-address*)))) (defvar *last-value* 0) (defun sim-= () (cond ((null *accumulator*) (format t " ~o " *last-value*)) (t (format t " ~o " *accumulator*) (setq *last-value* *accumulator*)))) (defun sim-print-val (val type &optional adr) (setq *last-value* val) (ecase type (:inst (let ((sym-inst (disassemble-inst val))) (cond ((and (eq (car sym-inst) 'store-immediate) adr (>= adr 0)) (format t "~s " sym-inst) (format t "~o " (send *proc* :read-main-memory (+ adr 1))) 1) (t (format t "~s " sym-inst) 0)))) (:opc (when (ldb-test (byte 1 31.) val) (format t " {N} ")) (print-symbolic-adr (ldb-big (byte 31. 0) val)) (format t " ") 0) (nil (format t " ~o " val) 0))) (defun symbolic-adr (adr &aux info) (declare (values base offset adr-mode value-type)) (setq info (ra-address-info adr)) (cond ((< adr 0) (when (null info) (ferror 'bad-reg-adr "unknown reg-adr ~o" adr)) (values (cadr info) (- adr (car info)) :at-sign (cadddr (cdr info)))) (t (cond ((null info) (values nil adr :number (cadddr (cdr info)))) ((= (car info) adr) (values (cadr info) 0 :symbol (cadddr (cdr info)))) (t (values (cadr info) (- adr (car info)) :list (cadddr (cdr info)))))))) (defun print-symbolic-adr (adr &optional (stream t)) (declare (values sym-base offset adr-mode value-type)) (multiple-value-bind (sym-base offset adr-mode value-type) (symbolic-adr adr) (ecase adr-mode (:at-sign (format stream "~o@~s" offset sym-base)) (:number (format stream "~o" offset)) (:symbol (format stream "~s" sym-base)) (:list (format stream "(~s ~o)" sym-base offset))) (values sym-base offset adr-mode value-type))) (defun print-new-adr-and-contents (&aux val) (format t "~&") (multiple-value-bind (sym-base offset adr-mode value-type) (print-symbolic-adr *current-address*) sym-base offset adr-mode (cond ((< *current-address* 0) (setq val (ra-read *current-address*))) (t (setq val (send *proc* :read-main-memory *current-address*)))) (format t "/ ") (incf *current-address* (sim-print-val val value-type *current-address*)))) (defun sim-tab () (when (< *last-value* 0) (ferror 'sim "current address must be main memory")) (let ((ptr (>convert-to-pointer *last-value*))) (setq *current-address* (>pointer-as-integer ptr))) (print-new-adr-and-contents)) (defun sim-line () (incf *current-address*) (print-new-adr-and-contents)) (defun sim-^ () (decf *current-address*) (print-new-adr-and-contents)) (defun sim-super-p () (format t "--RUN--") (send *proc* :run t) (format t "STOP~&") (setq *update-display* t)) (defun sim-super-t () (let ((start-time (time)) end-time) (format t "--RUN--") (send *proc* :run) (setq end-time (time)) (format t "STOP~&") (format t "~&Real time ~\\time-interval\\" (round (time-difference end-time start-time) 60.)) (let ((n (read-register 'micro:a-sim-inst-counter))) (format t "~&~:d instructions" n) (let ((clock 72.)) (format t "~&Simulated time (~d ns/clk) = ~8f sec" clock (* n clock 1e-9)))) (format t "~&Memory cost = ~d." (read-register 'micro:a-sim-memory-cost)) (format t "~&") (setq *update-display* t))) (defun sim-colon-memory-cost () (let ((cost (read-with-full-rubout terminal-io))) (when (y-or-n-p "~&New memory cost = ~d., OK? " cost) (setq *memory-cost* cost) (write-register 'micro:a-sim-memory-cost cost))) (format t "~&")) (defun sim-. () (when (null *accumulator*) (setq *accumulator* 0)) (incf *accumulator* *current-address*)) (defun read-with-full-rubout (stream) (with-input-editing (terminal-io '((:full-rubout :full-rubout))) (read stream))) (defun sim-colon-try () (let ((form (read-with-full-rubout terminal-io))) (cold-reset) (sim-test (car form) (cdr form)) (setq *update-display* t) (format t "~&") )) (defun |SIM-:| () (let ((command (read-with-full-rubout terminal-io))) (cond ((null command) (format t " ?? ")) (t (when (not (symbolp command)) (ferror nil "colon commands must be symbols")) (let ((func (intern-soft (string-append "SIM-COLON-" command) 'sim))) (cond ((and func (fboundp func)) (funcall func)) (t (format t "~&SIM-COLON-~a is not implemented~&" command)))))))) (defvar *breakpoint-list* nil) (defun adr-to-breakpoint-name (adr) (multiple-value-bind (sym-base offset) (symbolic-adr adr) (cond ((null sym-base) nil) ((zerop offset) sym-base) (t (list sym-base offset))))) (defun breakpoint-name-to-adr (name) (let ((base-name (if (consp name) (car name) name)) (offset (if (consp name) (cadr name) 0))) (let ((base-adr (symbol-lookup base-name))) (cond ((null base-adr) (ferror nil "unknown name ~s" name)) (t (+ base-adr offset)))))) (defun sim-colon-b (&optional (adr *accumulator*)) (when (null adr) (ferror nil "no value accumulated")) (when (< adr 0) (ferror nil "breakpoints only work in main memory")) (let ((breakpoint-name (adr-to-breakpoint-name adr))) (cond ((null breakpoint-name) (ferror nil "~&no symbol at adr ~s~&" adr)) (t (when (not (member breakpoint-name *breakpoint-list* :test 'equal)) (push breakpoint-name *breakpoint-list*)) (let ((inst (send *proc* :read-main-memory adr))) (cond ((ldb-test %%i-halt inst) (format t "~&~s already has the halt bit set~&" breakpoint-name)) (t (send *proc* :write-main-memory adr (dpb 1 %%i-halt inst)) (format t "~&Breakpoint set at ~s~&" breakpoint-name)))))))) (defun sim-colon-ub (&aux x) (when (null *accumulator*) (ferror nil "no value accumulated")) (when (< *accumulator* 0) (ferror nil "breakpoints only work in main memory")) (let ((inst (send *proc* :read-main-memory *accumulator*))) (cond ((ldb-test %%i-halt inst) (send *proc* :write-main-memory *accumulator* (dpb 0 %%i-halt inst))) (t (format t "~&halt bit not set~&")))) (let ((breakpoint-name (adr-to-breakpoint-name *accumulator*))) (cond ((null breakpoint-name) (format t "~&No name for location ~s" *accumulator*)) ((setq x (member breakpoint-name *breakpoint-list*)) (setq *breakpoint-list* (delq (car x) *breakpoint-list*)) (format t "~&Breakpoint at ~s removed.~&" breakpoint-name)) (t (format t "~&~s is not on the breakpoint list~&" breakpoint-name))))) (defun sim-colon-uab (&optional dont-print-newline) (dolist (breakpoint-name *breakpoint-list*) (let ((adr (breakpoint-name-to-adr breakpoint-name))) (cond ((null adr) (format t "~&Can't find address for ~s" breakpoint-name)) (t (send *proc* :write-main-memory adr (dpb 0 %%i-halt (send *proc* :read-main-memory adr))))))) (setq *breakpoint-list* nil) (when (not dont-print-newline) (format t "~&"))) (defun sim-colon-rb () (dolist (breakpoint-name (copylist *breakpoint-list*)) (let ((adr (breakpoint-name-to-adr breakpoint-name))) (cond ((null adr) (format t "~&Can't find address for ~s" breakpoint-name) (setq *breakpoint-list* (delq breakpoint-name *breakpoint-list*))) (t (send *proc* :write-main-memory adr (dpb 1 %%i-halt (send *proc* :read-main-memory adr))) (format t "~&Breakpoint ~s replaced.~&" breakpoint-name)))))) (defun sim-colon-reload () (sim-reload) (sim-colon-rb) (setq *update-display* t)) (defun print-function-and-offset (adr) (let ((info (main-mem-symbol-info adr))) (cond ((null info) (format t "unknown-function-~o" adr)) (t (format t "~S[#o~O]" (cadr info) (- adr (car info))))))) (defun sim-colon-trace () (do ((prev-frame (send *proc* :previous-active (send *proc* :read-active-frame)) (send *proc* :previous-active prev-frame)) (frame (send *proc* :read-active-frame) (send *proc* :previous-active frame)) (pc (send *proc* :read-next-pc) (send *proc* :frame-saved-pc frame))) (()) (format t "~&~4o: " frame) (print-function-and-offset pc) (when (zerop prev-frame) (return nil))) (format t "~&")) (defun sim-colon-return-break () (let ((pc (send *proc* :frame-saved-pc (send *proc* :read-active-frame)))) (sim-colon-b pc))) (defun sim-_ () (let ((underline-command (send standard-input :tyi))) (send standard-output :tyo underline-command) (let* ((fun-name (format nil "SIM-UNDERLINE-~@:(~:C~)" underline-command)) (fun (intern-soft fun-name 'sim))) (cond ((or (null fun) (not (fboundp fun))) (format t "~&~s is not implemented~&" fun-name)) (t (funcall fun)))))) (defun sim-underline-q () (let ((q (>convert-to-pointer *last-value*))) (format t " ") (>print-random-object q) (format t " "))) (defun sim-underline-s () (let ((q (>convert-to-pointer *last-value*))) (format t " ") (>prin1 q) (format t " "))) (defun sim-underline-t () (format t " ") (send standard-output :tyo (ldb (byte 8 0) *last-value*)) (send standard-output :tyo (ldb (byte 8 8) *last-value*)) (send standard-output :tyo (ldb (byte 8 16.) *last-value*)) (send standard-output :tyo (ldb (byte 8 24.) *last-value*)) (format t " ")) (defun |SIM-(| () (format t "~&") (let ((form (with-input-editing (terminal-io `((:full-rubout :full-rubout) (:initial-input "(") (:initial-input-pointer 1) (:prompt "Eval: "))) (read)))) (let ((val (eval form))) (print val) (format t "~&") (typecase val (integer (setq *last-value* val)) (sim-pointer (setq *last-value* (>pointer-as-integer val)))))))