灯下 登录
计算机科学 / SICP / subsection 中英对照

3.3.4 A Simulator for Digital Circuits

Designing complex digital systems, such as computers, is an important

engineering activity. Digital systems are constructed by interconnecting

simple elements. Although the behavior of these individual elements is simple,

networks of them can have very complex behavior. Computer simulation of

proposed circuit designs is an important tool used by digital systems

engineers. In this section we design a system for performing digital logic

simulations. This system typifies a kind of program called an

设计计算机等复杂数字系统是一项重要的工程活动。数字系统通过互联简单元件来构成。虽然这些单个元件的行为很简单,但由它们组成的网络却可以具有非常复杂的行为。对拟建电路设计进行计算机仿真,是数字系统工程师使用的一种重要工具。本节我们设计一个用于执行数字逻辑仿真(digital logic simulations)的系统。这个系统是一类称为

event-driven simulation, in which actions (“events”) trigger

further events that happen at a later time, which in turn trigger more events,

and so on.

事件驱动仿真(event-driven simulation)的程序的典型代表——其中的动作(“事件”)会触发稍后发生的后续事件,这些事件又进一步触发更多事件,如此循环往复。

Our computational model of a circuit will be composed of objects that

correspond to the elementary components from which the circuit is constructed.

There are

wires, which carry

digital signals. A digital

signal may at any moment have only one of two possible values, 0 and 1. There

are also various types of digital

function boxes, which connect wires

carrying input signals to other output wires. Such boxes produce output

signals computed from their input signals. The output signal is delayed by a

time that depends on the type of the function box. For example, an

我们对电路的计算模型将由与电路基本元件相对应的对象组成。其中有导线(wire),用于传载数字信号(digital signal)。数字信号在任意时刻只能取两个可能的值之一:0 或 1。此外还有各种类型的数字功能盒(function box),将传载输入信号的导线连接到其他输出导线。这些功能盒根据输入信号计算并产生输出信号,输出信号的延迟时间取决于功能盒的类型。例如,

inverter is a primitive function box that inverts its input. If the

input signal to an inverter changes to 0, then one inverter-delay later the

inverter will change its output signal to 1. If the input signal to an

inverter changes to 1, then one inverter-delay later the inverter will change

its output signal to 0. We draw an inverter symbolically as in Figure 3.24.

An

and-gate, also shown in figure 3.24, is a primitive

function box with two inputs and one output. It drives its output signal to a

value that is the

logical and of the inputs. That is, if both of its

input signals become 1, then one and-gate-delay time later the and-gate will

force its output signal to be 1; otherwise the output will be 0. An

反相器(inverter)是一种对输入取反的基本功能盒。若反相器的输入信号变为 0,则经过一个 inverter-delay 之后,反相器将其输出信号变为 1;若输入信号变为 1,则经过一个 inverter-delay 之后,输出信号变为 0。反相器的符号表示如图 3.24 所示。与门(and-gate)也在图 3.24 中给出,是一种有两个输入和一个输出的基本功能盒。它将输出信号驱动为两路输入的逻辑与(logical and)值。也就是说,若两路输入信号均变为 1,则经过一个 and-gate-delay 之后与门将其输出信号强制为 1;否则输出为 0。

or-gate is a similar two-input primitive function box that drives its

output signal to a value that is the

logical or of the inputs. That

is, the output will become 1 if at least one of the input signals is 1;

otherwise the output will become 0.

Figure 3.24: Primitive functions in the digital logic simulator.

或门(or-gate)是一种类似的双输入基本功能盒,它将输出信号驱动为两路输入的逻辑或(logical or)值。也就是说,若至少有一路输入信号为 1,输出将变为 1;否则输出将变为 0。图 3.24:数字逻辑仿真器中的基本功能。

We can connect primitive functions together to construct more complex

functions. To accomplish this we wire the outputs of some function boxes to

the inputs of other function boxes. For example, the

half-adder

circuit shown in Figure 3.25 consists of an or-gate, two and-gates, and

an inverter. It takes two input signals, A and B, and has two output signals,

S and C. S will become 1 whenever precisely one of A and B is 1, and C will

become 1 whenever A and B are both 1. We can see from the figure that, because

of the delays involved, the outputs may be generated at different times. Many

of the difficulties in the design of digital circuits arise from this fact.

Figure 3.25: A half-adder circuit.

我们可以将基本功能连接在一起,构建更复杂的功能。为此,我们将某些功能盒的输出接到其他功能盒的输入上。例如,图 3.25 所示的半加器(half-adder)电路由一个或门、两个与门和一个反相器组成。它有两路输入信号 A 和 B,以及两路输出信号 S 和 C。当 A 和 B 中恰好有一个为 1 时,S 变为 1;当 A 和 B 同时为 1 时,C 变为 1。从图中可以看出,由于存在延迟,各路输出可能在不同时刻产生。数字电路设计中的许多难点正源于此。图 3.25:一个半加器电路。

We will now build a program for modeling the digital logic circuits we wish to

study. The program will construct computational objects modeling the wires,

which will “hold” the signals. Function boxes will be modeled by procedures

that enforce the correct relationships among the signals.

现在我们来构建一个对所研究的数字逻辑电路进行建模的程序。该程序将构建对导线建模的计算对象,这些对象将“保存”信号。功能盒将由过程来建模,这些过程强制维护信号之间的正确关系。

One basic element of our simulation will be a procedure make-wire, which

constructs wires. For example, we can construct six wires as follows:

我们仿真的基本元素之一是过程 make-wire,用于构造导线。例如,我们可以如下构造六条导线:

We attach a function box to a set of wires by calling a procedure that

constructs that kind of box. The arguments to the constructor procedure are

the wires to be attached to the box. For example, given that we can construct

and-gates, or-gates, and inverters, we can wire together the half-adder shown

in Figure 3.25:

我们通过调用构造相应类型功能盒的过程,将功能盒连接到一组导线上。构造函数的参数就是要连接到功能盒的导线。例如,假设我们可以构造与门、或门和反相器,就可以如下连接图 3.25 所示的半加器:

Better yet, we can explicitly name this operation by defining a procedure

half-adder that constructs this circuit, given the four external wires

to be attached to the half-adder:

更好的做法是,通过定义过程 half-adder 来为这一操作命名,给定连接到半加器的四条外部导线,该过程便可构造出相应的电路:

The advantage of making this definition is that we can use half-adder

itself as a building block in creating more complex circuits. Figure 3.26,

for example, shows a

full-adder composed of two half-adders

and an or-gate. We can construct a full-adder as follows:

这样定义的好处在于,我们可以将 half-adder 本身作为构建更复杂电路的积木。例如,图 3.26 展示了一个由两个半加器和一个或门组成的全加器(full-adder)。我们可以如下构造一个全加器:

Figure 3.26: A full-adder circuit.

图 3.26:一个全加器电路。

Having defined full-adder as a procedure, we can now use it as a

building block for creating still more complex circuits. (For example, see

Exercise 3.30.)

将 full-adder 定义为一个过程之后,我们就可以将其作为积木,用来创建更为复杂的电路。(例如,参见练习 3.30。)

In essence, our simulator provides us with the tools to construct a language of

circuits. If we adopt the general perspective on languages with which we

approached the study of Lisp in 1.1, we can say that the

primitive function boxes form the primitive elements of the language, that

wiring boxes together provides a means of combination, and that specifying

wiring patterns as procedures serves as a means of abstraction.

Subheading: Primitive function boxes

从本质上说,我们的仿真器为我们提供了构建一种电路语言所需的工具。如果采用我们在 1.1 节研究 Lisp 时所持的对语言的一般性视角,可以说:基本功能盒构成了这种语言的基本元素,将功能盒连接在一起提供了组合的方法,而将连接方式规范为过程则充当了抽象的方法。子标题:基本功能盒

The primitive function boxes implement the “forces” by which a change in the

signal on one wire influences the signals on other wires. To build function

boxes, we use the following operations on wires:

基本功能盒实现了一条导线上的信号变化影响其他导线上信号的“作用力”。为了构建功能盒,我们对导线使用以下操作:

(get-signal ⟨wire⟩)

returns the current value of the signal on the wire.

返回导线上信号的当前值。

(set-signal! ⟨wire⟩ ⟨new value⟩)

changes the value of the signal on the wire to the new value.

将导线上信号的值更改为新值。

(add-action! ⟨wire⟩ ⟨procedure of no arguments⟩)

asserts that the designated procedure should be run whenever the signal on the

wire changes value. Such procedures are the vehicles by which changes in the

signal value on the wire are communicated to other wires.

断言:每当导线上的信号值发生变化时,指定的过程都应被运行。这些过程是导线上信号值的变化传递给其他导线的媒介。

In addition, we will make use of a procedure after-delay that takes a

time delay and a procedure to be run and executes the given procedure after the

given delay.

此外,我们还将使用过程 after-delay,它接受一个时间延迟量和一个待运行的过程,并在给定延迟之后执行该过程。

Using these procedures, we can define the primitive digital logic functions.

To connect an input to an output through an inverter, we use add-action!

to associate with the input wire a procedure that will be run whenever the

signal on the input wire changes value. The procedure computes the

logical-not of the input signal, and then, after one

inverter-delay, sets the output signal to be this new value:

利用这些过程,我们可以定义基本的数字逻辑功能。要通过反相器将输入连接到输出,我们使用 add-action! 为输入导线关联一个过程,该过程在输入导线上的信号值发生变化时被运行。该过程计算输入信号的 logical-not,然后在经过一个 inverter-delay 之后,将输出信号设置为这个新值:

An and-gate is a little more complex. The action procedure must be run if

either of the inputs to the gate changes. It computes the logical-and

(using a procedure analogous to logical-not) of the values of the

signals on the input wires and sets up a change to the new value to occur on

the output wire after one and-gate-delay.

与门稍微复杂一些。无论哪路输入发生变化,动作过程都必须被运行。该过程计算两路输入导线上信号的 logical-and(使用类似于 logical-not 的过程),并安排在经过一个 and-gate-delay 之后在输出导线上产生相应的新值变化。

Racket #lang sicp
(define a (make-wire))
(define b (make-wire))
(define c (make-wire))
(define d (make-wire))
(define e (make-wire))
(define s (make-wire))
Racket #lang sicp
(or-gate a b d)
ok

(and-gate a b c)
ok

(inverter c e)
ok

(and-gate d e s)
ok
Racket #lang sicp
(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))
Racket #lang sicp
(define (full-adder a b c-in sum c-out)
 (let ((c1 (make-wire))
 (c2 (make-wire))
 (s (make-wire)))
 (half-adder b c-in s c1)
 (half-adder a s sum c2)
 (or-gate c1 c2 c-out)
 'ok))
Racket #lang sicp
(define (inverter input output)
 (define (invert-input)
 (let ((new-value
 (logical-not (get-signal input))))
 (after-delay
 inverter-delay
 (lambda ()
 (set-signal! output new-value)))))
 (add-action! input invert-input)
 'ok)

(define (logical-not s)
 (cond ((= s 0) 1)
 ((= s 1) 0)
 (else (error "Invalid signal" s))))
Racket #lang sicp
(define (and-gate a1 a2 output)
 (define (and-action-procedure)
 (let ((new-value
 (logical-and (get-signal a1)
 (get-signal a2))))
 (after-delay
 and-gate-delay
 (lambda ()
 (set-signal! output new-value)))))
 (add-action! a1 and-action-procedure)
 (add-action! a2 and-action-procedure)
 'ok)