理系学生日記

おまえはいつまで学生気分なのか

問題3-30 (3.3.4 A Simulator for Digital Circuits)

全加算器を組合せて,ripple carry adder を作る.加算器とか懐しさ満点ですね.
これで,何桁の足し算にも対応できて,カンペキです!

;; 電子回路シミュレータに必要な関数定義を読み込み
(add-load-path "/Users/ykiri/programming/SICP")
(load "section3/simulator")

;;; 半加算器
(define (half-adder a b s c)
  (let ((d (make-wire)) (e (make-wire)))
    (or-gate a b d)
    (and-gate a b c)
    (inverter c e)
    (and-gate d e s)
    'ok))

;;; 全加算器
(define (full-adder a b c-in sum c-out)
  (let ((s (make-wire))
        (c1 (make-wire))
        (c2 (make-wire)))
    (half-adder b c-in s c1)
    (half-adder a s sum c2)
    (or-gate c1 c2 c-out)
    'ok))

;;; ripple carry adder
(define (ripple-carry-adder A_k B_k S_k C)
    (if (null? A_k)
      'ok  ; リストの内容がなくなったとき終了
      (let ((a-wire (car A_k)) 
	    (b-wire (car B_k))
	    (s-wire (car S_k)) 
	    (c-wire (make-wire)))
	(full-adder a-wire b-wire c-wire s-wire C)
	(ripple-carry-adder (cdr A_k) (cdr B_k) (cdr S_k) c-wire))))

今回は実は初めて gauche.test 使ってみた.

(use gauche.test)
(test-start "for problem 3-30")
(add-load-path "/Users/ykiri/programming/SICP")
(load "section3/3-30.scm")

(test-section "make-wires")

; inputs で指定した 2 進数の入力信号を作成
(define (make-wires . inputs)
  (map (lambda (value)
	 (let ((wire (make-wire)))
	   (set-signal! wire value)
	   wire))
       inputs))

;;; まずは 11(2) + 01(2) = 100(2) のてすと
(define A2 (make-wires 1 1))
(define B2 (make-wires 0 1))
(define S2 (make-wires 0 0))
(define carry
  (let ((c (make-wire)))
    (set-signal! c 0)
    c))

(test "length" 2 (lambda () (length A2)))
(test "wire-value A1" 1 (lambda () (get-signal (car A2))))
(test "wire-value A2" 1 (lambda () (get-signal (cadr A2))))
(test "wire-value B1" 0 (lambda () (get-signal (car B2))))
(test "wire-value B2" 1 (lambda () (get-signal (cadr B2))))
(test "wire-value S1" 0 (lambda () (get-signal (car S2))))
(test "wire-value S2" 0 (lambda () (get-signal (cadr S2))))

(test-section "simulation 1")

(define the-agenda (make-agenda))
(define inverter-delay 2)
(define and-gate-delay 3)
(define or-gate-delay 5)

(ripple-carry-adder A2 B2 S2 carry)
(propagate)

(test "wire-value S2" 0 (lambda () (get-signal (cadr S2))))
(test "wire-value S1" 0 (lambda () (get-signal (car S2))))
(test "carry-value"   1 (lambda () (get-signal carry)))

(current-time the-agenda)

;;; 次は 111(2) + 101(2) = 1100(2) のテスト
(test-section "simulation 2")

(define A3 (make-wires 1 1 1))
(define B3 (make-wires 1 0 1))
(define S3 (make-wires 0 0 0))
(define carry
  (let ((c (make-wire)))
    (set-signal! c 1)
    c))

(define the-agenda (make-agenda))

(ripple-carry-adder A3 B3 S3 carry)
(propagate)

(test "wire-value S3" 0 (lambda () (get-signal (caddr S3))))
(test "wire-value S2" 0 (lambda () (get-signal (cadr S3))))
(test "wire-value S1" 1 (lambda () (get-signal (car S3))))
(test "carry-value"   1 (lambda () (get-signal carry)))