;; Die ersten drei Zeilen dieser Datei wurden von DrRacket eingefügt. Sie enthalten Metadaten ;; über die Sprachebene dieser Datei in einer Form, die DrRacket verarbeiten kann. #reader(lib "DMdA-assignments-reader.ss" "deinprogramm")((modname circuit1) (read-case-sensitive #f) (teachpacks ()) (deinprogramm-settings #(#f write repeating-decimal #t #t none explicit #f ()))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Der Schaltkreissimulator: ; Benutze zur Implementierung Warteschlangen und veränderbare Listen: (require "queue.rkt") (require "mlist.rkt") ; Ein Signal ist entweder 0 oder 1 (define signal (signature (one-of 0 1))) ; Um von dem konkreten Format der Aktionen zu abstrahieren (Aktionen sind ; Prozeduren ohne Argumente), führen wir eine Signatur hierfür ein, ; die wir in den folgenden Prozeduresignaturen benutzen: (define action (signature ( -> unspecific))) ; Globale Werte: Gatterverzögerungen (define inverter-delay 2) (define and-gate-delay 3) (define or-gate-delay 5) ; Implementierung der Basisgatter: (: inverter (wire wire -> unspecific)) (define inverter (lambda (input output) (add-action! input (lambda () (letrec ((new-value (logical-not (get-signal input)))) (after-delay inverter-delay (lambda () (set-signal! output new-value)))))))) (: logical-not (signal -> signal)) (define logical-not (lambda (s) (cond ((= s 0) 1) ((= s 1) 0)))) (: and-gate (wire wire wire -> unspecific)) (define and-gate (lambda (a1 a2 output) (letrec ((and-action-procedure (lambda () (letrec ((new-value (logical-and (get-signal a1) (get-signal a2)))) (after-delay and-gate-delay (lambda () (set-signal! output new-value))))))) (begin (add-action! a1 and-action-procedure) (add-action! a2 and-action-procedure))))) (: logical-and (signal signal -> signal)) (define logical-and (lambda (s1 s2) (if (and (= s1 1) (= s2 1)) 1 0))) (: or-gate (wire wire wire -> unspecific)) (define or-gate (lambda (a1 a2 output) (letrec ((or-action-procedure (lambda () (letrec ((new-value (logical-or (get-signal a1) (get-signal a2)))) (after-delay or-gate-delay (lambda () (set-signal! output new-value))))))) (begin (add-action! a1 or-action-procedure) (add-action! a2 or-action-procedure))))) (: logical-or (signal signal -> signal)) (define logical-or (lambda (s1 s2) (if (or (= s1 1) (= s2 1)) 1 0))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Ein Draht ist ein Objekt mit einem Signalwert und Aktionen (Prozeduren), ; die bei einer Wertänderung ausgeführt werden. ; Drahtobjekte reagieren auf die folgenden Nachrichten: (define wire-message (signature (one-of "get-signal" "set-signal!" "add-action!"))) ; Um von der konkreten Drahtimplementierung durch Nachrichtenweitergabe ; zu abstrahieren, führen wir eine Signatur für Drahtobjekte ein: (define wire (signature (wire-message -> any))) ; Der Konstruktor für Drahtobjekte: (: make-wire ( -> wire)) (define make-wire (lambda () (letrec ((signal-value 0) (action-procedures empty) (set-my-signal! (lambda (new-value) (if (not (= signal-value new-value)) (begin (set! signal-value new-value) (call-each action-procedures)) "ok"))) (add-action-procedure (lambda (proc) (begin (set! action-procedures (cons proc action-procedures)) (proc)))) (dispatch (lambda (m) (cond ((equal? m "get-signal") signal-value) ((equal? m "set-signal!") set-my-signal!) ((equal? m "add-action!") add-action-procedure))))) dispatch))) (: call-each ((list-of action) -> unspecific)) (define call-each (lambda (procedures) (if (empty? procedures) "ok" (begin ((first procedures)) (call-each (rest procedures)))))) (: get-signal (wire -> signal)) (define get-signal (lambda (wire) (wire "get-signal"))) (: set-signal! (wire signal -> unspecific)) (define set-signal! (lambda (wire new-value) ((wire "set-signal!") new-value))) (: add-action! (wire action -> unspecific)) (define add-action! (lambda (wire action-procedure) ((wire "add-action!") action-procedure))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;