Advertisement
timothy235

sicp-3-3-4-a-simulator-for-digital-circuits

Mar 2nd, 2017
262
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Racket 6.45 KB | None | 0 0
  1. #lang racket
  2. (require racket/mpair)
  3.  
  4. ;;;;;;;;;;
  5. ;; 3.28 ;;
  6. ;;;;;;;;;;
  7.  
  8. (define (or-gate a1 a2 output)
  9.   (define (or-action-procedure)
  10.     (define new-value (logical-or (get-signal a1) (get-signal a2)))
  11.     (after-delay or-gate-delay
  12.                  (lambda ()
  13.                    (set-signal! output new-value))))
  14.   (add-action! a1 or-action-procedure)
  15.   (add-action! a2 or-action-procedure)
  16.   'ok)
  17.  
  18. ;;;;;;;;;;
  19. ;; 3.29 ;;
  20. ;;;;;;;;;;
  21.  
  22. ;; Defining an or-gate this way, the or-gate-delay would equal one and-gate-delay
  23. ;; plus two inverter-delay's because the first two inverters can run
  24. ;; simultaneously, but then the other gates must run in sequence.
  25.  
  26. (define (alternate-or-gate a1 a2 output)
  27.   (define b1 (make-wire))
  28.   (define b2 (make-wire))
  29.   (define c (make-wire))
  30.   (inverter a1 b1)
  31.   (inverter a2 b2)
  32.   (and-gate b1 b2 c)
  33.   (inverter c output)
  34.   'ok)
  35.  
  36. ;;;;;;;;;;
  37. ;; 3.30 ;;
  38. ;;;;;;;;;;
  39.  
  40. (define (half-adder a b s c)
  41.   (define d (make-wire))
  42.   (define e (make-wire))
  43.   (or-gate a b d)
  44.   (and-gate a b c)
  45.   (inverter c e)
  46.   (and-gate d e s)
  47.   'ok)
  48.  
  49. (define (full-adder a b c-in sum c-out)
  50.   (define s (make-wire))
  51.   (define c1 (make-wire))
  52.   (define c2 (make-wire))
  53.   (half-adder b c-in s c1)
  54.   (half-adder a s sum c2)
  55.   (or-gate c2 c2 c-out)
  56.   'ok)
  57.  
  58. (define (ripple-carry-adder as bs ss c)
  59.   ; The book goes from index n to index 1; we go from n - 1 to 0.
  60.   (unless (= (length as)
  61.              (length bs)
  62.              (length ss))
  63.     (error "Lists must be same length -- RIPPLE-CARRY-ADDER" as bs ss))
  64.   (define zero-wire (make-wire))
  65.   (set-signal! zero-wire 0)
  66.   (define (loop i carry)
  67.     (cond [(< i 0) 'ok]
  68.           [else
  69.             ; use c for the last carry
  70.             (define next-carry (if (zero? i) c (make-wire)))
  71.             (full-adder (list-ref as i)
  72.                         (list-ref bs i)
  73.                         carry
  74.                         (list-ref ss i)
  75.                         next-carry)
  76.             (loop (sub1 i) next-carry)]))
  77.   (loop (sub1 (length as))
  78.         zero-wire))
  79.  
  80. ;; How much is one ripple-carry-delay in terms of inverter-delay, or-gate-delay,
  81. ;; and and-gate-delay?
  82.  
  83. ;; Look at the sicp-3-3-4-test-cases file to see these test runs.
  84.  
  85. ;; For the given delay times:
  86.  
  87. ;; inverter-delay = 2
  88. ;; and-gate-delay = 3
  89. ;; or-gate-delay  = 5
  90.  
  91. ;; we had:
  92.  
  93. ;; 1 half-adder-delay = 8 = 1 and-gate-delay + 1 or-gate-delay
  94.  
  95. ;; Surprisingly, one full-adder-delay was also 8, and the ripple-carry-adder-delay,
  96. ;; for n = 3, was 48 = 2 * n * (or-gate-delay + and-gate-delay).
  97.  
  98. ;; I would not have gotten this right just by looking at the formulas.  The
  99. ;; function boxes trigger whenever an input wire changes state.  They do not
  100. ;; necessarily run in sequence.  For me that makes it hard to see.
  101.  
  102. ;; Also I think the answer depends on the exact delay times for the primitive
  103. ;; gates.  If one primitive gate were a bottleneck, that would change the function
  104. ;; box delay times in terms of the primitive gate delay times.  For example, if
  105. ;; the inverter delay were huge compared to the others, the half-adder-delay would
  106. ;; be one and-gate-delay plus one inverter-delay, instead of one and-gate-delay
  107. ;; plus one or-gate-delay.
  108.  
  109. ;;;;;;;;;;
  110. ;; 3.31 ;;
  111. ;;;;;;;;;;
  112.  
  113. ;; Here is some half-adder test code:
  114.  
  115. ;; TRY A HALF-ADDER
  116.  
  117. (displayln 'HALF-ADDER)
  118. (define in5 (make-wire))
  119. (set-signal! in5 1)
  120. (define in6 (make-wire))
  121. (define sum (make-wire))
  122. (define carry (make-wire))
  123. (displayln 'BEFORE)
  124. (probe 'in5 in5)
  125. (probe 'in6 in6)
  126. (probe 'sum sum)
  127. (probe 'carry carry)
  128. (displayln 'DURING)
  129. (half-adder in5 in6 sum carry)
  130. (propagate)
  131. (displayln 'AFTER)
  132. (probe 'in5 in5)
  133. (probe 'in6 in6)
  134. (probe 'sum sum)
  135. (probe 'carry carry)
  136. (printf "~n")
  137.  
  138. ;; When you run this "with proc", you get:
  139.  
  140. ;; HALF-ADDER
  141. ;; 'done
  142. ;; BEFORE
  143. ;; in5 0  New-value = 1
  144. ;; in6 0  New-value = 0
  145. ;; sum 0  New-value = 0
  146. ;; carry 0  New-value = 0
  147. ;; DURING
  148. ;; 'ok
  149. ;; sum 8  New-value = 1
  150. ;; 'done
  151. ;; AFTER
  152. ;; in5 8  New-value = 1
  153. ;; in6 8  New-value = 0
  154. ;; sum 8  New-value = 1
  155. ;; carry 8  New-value = 0
  156.  
  157. ;; When you run this "without proc", you get:
  158.  
  159. ;; HALF-ADDER
  160. ;; 'done
  161. ;; BEFORE
  162. ;; DURING
  163. ;; 'ok
  164. ;; 'done
  165. ;; AFTER
  166.  
  167. ;; So even though running add-action! without proc will add the proc to the wire's
  168. ;; action-procedures list, it is not getting put on the agenda.  So when we later
  169. ;; call propagate, nothing happens.  This is because after-delay is the function
  170. ;; that adds actions to the agenda, and after-delay is not called until we run the
  171. ;; proc.
  172.  
  173. ;; For example, if you look at inverter, the proc that gets added to the
  174. ;; action-procedures list for the input wire is invert-input.  But invert-input
  175. ;; calls after-delay, and after-delay calls add-to-agenda!.  So you have to call
  176. ;; the proc to put it on the agenda.
  177.  
  178. ;;;;;;;;;;
  179. ;; 3.32 ;;
  180. ;;;;;;;;;;
  181.  
  182. ;; Even though all the actions in a given segment occur at the same time, their
  183. ;; order still matters, some come before others.  If the segment used a LIFO
  184. ;; container like a stack, then the actions would be performed in the wrong order.
  185. ;; We need a FIFO container like a queue to preserve the correct ordering.
  186.  
  187. ;; To get LIFO behavior, I used the deque construction from 3.3.2.  Then you just
  188. ;; had to change insert-queue! to front-insert-deque! etc.  This was easier than
  189. ;; trying to rewrite the book program to use a list.
  190.  
  191. ;; I couldn't get the exact book example to work.  But I did get this example:
  192.  
  193. ;; TRY AN AND-GATE
  194. (define in1 (make-wire))
  195. (set-signal! in1 1)
  196. (define in2 (make-wire))
  197. (set-signal! in2 0)
  198. (define out (make-wire))
  199. (and-gate in1 in2 out)
  200. (set-signal! in2 1)
  201. (probe 'in1 in1)
  202. (probe 'in2 in2)
  203. (probe 'out out)
  204. (propagate)
  205.  
  206. ;; Here we have two wires, in1 = 1 and in2 = 0, then we apply an and, then we
  207. ;; change the 0 to a 1, and then we propagate.  So the out wire should be 1, which
  208. ;; it is with the FIFO queue:
  209.  
  210. ;; 'done
  211. ;; 'done
  212. ;; 'ok
  213. ;; 'done
  214. ;; in1 0  New-value = 1
  215. ;; in2 0  New-value = 1
  216. ;; out 0  New-value = 0
  217. ;; out 3  New-value = 1
  218. ;; 'done
  219.  
  220. ;; However, with the LIFO deque, out first becomes 1 at time 3 but then reverts to
  221. ;; 0 as the original set-signal! of in2 to 0 is hit coming out of the segment:
  222.  
  223. ;; 'done
  224. ;; 'done
  225. ;; 'ok
  226. ;; 'done
  227. ;; in1 0  New-value = 1
  228. ;; in2 0  New-value = 1
  229. ;; out 0  New-value = 0
  230. ;; out 3  New-value = 1
  231. ;; out 3  New-value = 0
  232. ;; 'done
  233.  
  234. ;; So the book is right.  Order within segments matters.  We need a FIFO
  235. ;; container.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement