3
(include-book "basic-def")
7
; Basic Pipeline Design
8
; Our example machine is very simple. It consists of a program counter,
9
; a register file, the memory, pipeline latches latch1 and latch2.
10
; The programmer visible components are the program counter, the register
11
; file and the memory. It can execute two types of instructions, ADD
12
; and SUB. The format of an instruction is as shown here:
13
; --------------------------------
14
; | op | RC | RA | RB |
15
; --------------------------------
18
; where RC, RA and RB are operand register specifiers. There are only
19
; two valid opcodes 0 (ADD) and 1 (SUB). An instruction without a
20
; valid opcode is considered as a NOP. The ADD instruction reads
21
; registers specified by RA and RB, adds the values and writes the
22
; result back into the register specified by RC. The SUB subtracts RB
23
; from RA. Every machine cycle the program counter is incremented by
24
; 1. No exceptions and no interrupts occur. There is one external
25
; input to the machine. If this input signal is on, the machine may
26
; fetch a new instruction from the memory. Pipeline flushing can be
27
; done by running the machine with 0's as its inputs.
29
; We define this machine at two levels: instruction-set architecture
30
; and micro-architecture.
32
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
34
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
36
; The ISA state consists of only programmer visible states, that is,
37
; the program counter, register file and the memory.
38
; ISA behavior is specified by ISA-step. Depending on the operand,
39
; it executes ADD or SUB operation.
41
; Definition of the ISA state.
43
; Note: For the detail of the definition with defstructure, please
44
; refer to the public ACL2 book data-structures/structures.lisp.
45
; Briefly speaking, an expression (ISA-state PC REGS MEM) returns
46
; an ISA state whose program counter, register file and memory are PC,
47
; REGS and MEM, respectively. The pc value of an ISA state, ISA, can
48
; be obtained by (ISA-pc ISA).
49
(defstructure ISA-state
50
(pc (:assert (addr-p pc) :rewrite))
51
(regs (:assert (regs-p regs) :rewrite))
52
(mem (:assert (mem-p mem) :rewrite))
53
(:options :guards (:conc-name ISA-)))
55
(deflabel begin-ISA-def)
57
; Definition of the effect of an ADD instruction.
58
(defun ISA-add (rc ra rb ISA)
59
(declare (xargs :guard (and (rname-p rc) (rname-p ra) (rname-p rb)
61
(ISA-state (addr (1+ (ISA-pc ISA)))
62
(write-reg (word (+ (read-reg ra (ISA-regs ISA))
63
(read-reg rb (ISA-regs ISA))))
67
; Definition of the effect of an SUB instruction.
68
(defun ISA-sub (rc ra rb ISA)
69
(declare (xargs :guard (and (rname-p rc) (rname-p ra) (rname-p rb)
71
(ISA-state (addr (1+ (ISA-pc ISA)))
72
(write-reg (word (- (read-reg ra (ISA-regs ISA))
73
(read-reg rb (ISA-regs ISA))))
77
; Definition of NOP. It only increments the program counter.
78
(defun ISA-default (ISA)
79
(declare (xargs :guard (ISA-state-p ISA)))
80
(ISA-state (addr (1+ (ISA-pc ISA)))
84
; Next ISA state function. It takes the current ISA state and returns
85
; the ISA state after executing one instruction. This function is a
86
; simple dispatcher of corresponding functions depending on the
89
(declare (xargs :guard (ISA-state-p ISA)))
90
(let ((inst (read-mem (ISA-pc ISA) (ISA-mem ISA))))
91
(let ((op (op-field inst))
96
(0 (ISA-add rc ra rb ISA)) ; add
97
(1 (ISA-sub rc ra rb ISA)) ; sub
98
(otherwise (ISA-default ISA))))))
100
; N step ISA function. It returns the ISA state after executing n
101
; instructions from the initial state, ISA.
102
(defun ISA-stepn (ISA n)
103
(declare (xargs :guard (and (ISA-state-p ISA) (integerp n) (<= 0 n))))
104
(if (zp n) ISA (ISA-stepn (ISA-step ISA) (1- n))))
106
(deflabel end-ISA-def)
108
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
110
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
111
; Definition of MA states
113
; Definition of pipeline latch latch1.
115
(valid? (:assert (bitp valid?) :rewrite))
116
(op (:assert (opcd-p op) :rewrite))
117
(rc (:assert (rname-p rc) :rewrite))
118
(ra (:assert (rname-p ra) :rewrite))
119
(rb (:assert (rname-p rb) :rewrite))
122
; Definition of pipeline latch latch2.
124
(valid? (:assert (bitp valid?) :rewrite))
125
(op (:assert (opcd-p op) :rewrite))
126
(rc (:assert (rname-p rc) :rewrite))
127
(ra-val (:assert (word-p ra-val) :rewrite))
128
(rb-val (:assert (word-p rb-val) :rewrite))
131
; Definition of pipelined micro-architecture.
132
(defstructure MA-state
133
(pc (:assert (addr-p pc) :rewrite (:rewrite (acl2-numberp pc))))
134
(regs (:assert (regs-p regs) :rewrite))
135
(mem (:assert (mem-p mem) :rewrite))
136
(latch1 (:assert (latch1-p latch1) :rewrite))
137
(latch2 (:assert (latch2-p latch2) :rewrite))
138
(:options :guards (:conc-name MA-)))
140
; Defines the signal supplied to the micro-architectural behavioral
141
; function. We assume that the micro-architecture takes one bit
142
; input, which turn on and off instruction fetching.
143
(defun MA-sig-p (sig)
144
(declare (xargs :guard t))
148
(deflist MA-sig-listp (l)
149
(declare (xargs :guard t))
152
(deflabel begin-MA-def)
153
; The definition of ALU. The ALU takes opcode and two operands,
154
; and outputs the result.
155
(defun ALU-output (op val1 val2)
156
(declare (xargs :guard (and (opcd-p op) (word-p val1) (word-p val2))))
157
(cond ((equal op 0) (word (+ val1 val2)))
158
((equal op 1) (word (- val1 val2)))
161
; The behavior of the register file. If the latch2 contains an ADD or
162
; SUB instruction, the register specified by latch2-rc is updated by
163
; the output from the ALU. Otherwise, the register file is unchanged.
164
(defun step-regs (MA)
165
(declare (xargs :guard (MA-state-p MA)))
166
(let ((latch2 (MA-latch2 MA)))
167
(b-if (b-and (latch2-valid? latch2)
168
(b-ior (bv-eqv *opcode-size* (latch2-op latch2) 0)
169
(bv-eqv *opcode-size* (latch2-op latch2) 1)))
170
(write-reg (ALU-output (latch2-op latch2)
171
(latch2-ra-val latch2)
172
(latch2-rb-val latch2))
177
; The dependency check. If there is a true (RAW) dependency
178
; between the instructions at latch1 and latch2, the instruction at
179
; latch1 should stall until the instruction at latch2 completes. We
180
; check whether the destination register of the instruction at latch2
181
; is one of the source registers of the instruction at latch1.
182
(defun dependency? (MA)
183
(declare (xargs :guard (MA-state-p MA)))
184
(let ((latch1 (MA-latch1 MA))
185
(latch2 (MA-latch2 MA)))
186
(b-ior (bv-eqv *rname-size* (latch1-ra latch1) (latch2-rc latch2))
187
(bv-eqv *rname-size* (latch1-rb latch1) (latch2-rc latch2)))))
189
(defthm bitp-dependency
190
(bitp (dependency? MA)))
192
; The stall condition. If both latch1 and latch2 contain valid
193
; instructions, and there are dependencies between the two
194
; instructions, the instruction at latch1 is stalled.
195
(defun stall-cond? (MA)
196
(declare (xargs :guard (MA-state-p MA)))
197
(b-and (latch1-valid? (MA-latch1 MA))
198
(b-and (latch2-valid? (MA-latch2 MA))
201
(defthm bitp-stall-cond
202
(bitp (stall-cond? MA)))
204
; Next state function for pipeline latch latch2. The instruction at
205
; latch1 advances to latch2, only if stall-cond? is off. Note that
206
; the rest of the fields of latch2 are updated anyway. Is it okay?
207
; The answer is yes. The instruction at latch2 always complete, and
208
; the instruction at latch1 may or may not advance to latch2. If
209
; instruction at latch1 stalls, latch2 will hold a bubble in the next
210
; cycle. In this case, we don't care the values the fields of latch2
211
; except for latch2-valid?, which indicates whether the content of
212
; latch2 is a bubble or not.
213
(defun step-latch2 (MA)
214
(declare (xargs :guard (MA-state-p MA)))
215
(let ((latch1 (MA-latch1 MA))
216
(latch2 (MA-latch2 MA)))
217
(latch2 (b-and (latch1-valid? latch1)
218
(b-nand (dependency? MA) (latch2-valid? latch2)))
221
(read-reg (latch1-ra latch1) (MA-regs MA))
222
(read-reg (latch1-rb latch1) (MA-regs MA)))))
225
; This function defines how latch1 is updated. If the stall condition
226
; is true, latch1 is not updated. If latch1 is currently empty or the
227
; stall condition is false, and if the given sig is true, we fetch an
228
; instruction. Sig is an external input that directs the processor to
229
; fetch a new instruction.
230
(defun step-latch1 (MA sig)
231
(declare (xargs :guard (and (MA-state-p MA) (MA-sig-p sig))))
232
(let ((latch1 (MA-latch1 MA))
233
(inst (read-mem (MA-pc MA) (MA-mem MA))))
234
(latch1 (b-ior sig (stall-cond? MA))
235
(b-if (stall-cond? MA) (latch1-op latch1) (op-field inst))
236
(b-if (stall-cond? MA) (latch1-rc latch1) (rc-field inst))
237
(b-if (stall-cond? MA) (latch1-ra latch1) (ra-field inst))
238
(b-if (stall-cond? MA) (latch1-rb latch1) (rb-field inst)))))
241
; The condition whether a new instruction is fetched.
242
(defun fetch-inst? (MA sig)
243
(declare (xargs :guard (and (MA-state-p MA) (MA-sig-p sig))))
245
(b-nand (latch1-valid? (MA-latch1 MA))
246
(b-and (latch2-valid? (MA-latch2 MA))
249
(defthm bitp-fetch-inst?
250
(bitp (fetch-inst? MA sig)))
252
; Function step-pc defines how the program counter is updated.
253
(defun step-pc (MA sig)
254
(declare (xargs :guard (and (MA-state-p MA) (MA-sig-p sig))))
255
(b-if (fetch-inst? MA sig)
256
(addr (1+ (MA-pc MA)))
259
; MA-step defines how the MA state is updated every clock cycle. The
260
; memory does not change in our model. The behavior of other
261
; components is specified by the corresponding step functions.
262
(defun MA-step (MA sig)
263
(declare (xargs :guard (and (MA-state-p MA) (MA-sig-p sig))))
264
(MA-state (step-pc MA sig)
270
; MA-stepn returns the MA state after n clock cycles of MA execution.
271
; The argument MA is the initial state, and sig-list specifies the
273
(defun MA-stepn (MA sig-list n)
274
(declare (xargs :guard (and (MA-state-p MA) (MA-sig-listp sig-list)
275
(integerp n) (<= 0 n)
276
(<= n (len sig-list)))))
279
(MA-stepn (MA-step MA (car sig-list)) (cdr sig-list) (1- n))))
281
(deflabel end-MA-def)
284
(set-difference-theories
285
(set-difference-theories (function-theory 'end-ISA-def)
286
(function-theory 'begin-ISA-def))
290
(set-difference-theories
291
(set-difference-theories (function-theory 'end-MA-def)
292
(function-theory 'begin-MA-def))
295
(in-theory (disable ISA-def MA-def MA-sig-p))
297
;;;;;;;; Type proofs ;;;;;;;;
298
(defthm ISA-state-p-ISA-step
299
(implies (ISA-state-p ISA) (ISA-state-p (ISA-step ISA)))
300
:hints (("Goal" :in-theory (enable ISA-step ISA-add ISA-sub ISA-default))))
302
(defthm ISA-state-p-ISA-stepn
303
(implies (ISA-state-p ISA) (ISA-state-p (ISA-stepn ISA n))))
305
(defthm addr-p-step-pc
306
(implies (MA-state-p MA) (addr-p (step-pc MA sig)))
307
:hints (("Goal" :in-theory (enable step-pc))))
309
(defthm word-p-ALU-output
310
(implies (and (opcd-p op) (word-p val1) (word-p val2))
311
(word-p (ALU-output op val1 val2)))
312
:hints (("Goal" :in-theory (enable ALU-output))))
314
(defthm regs-p-step-regs
315
(implies (MA-state-p MA) (regs-p (step-regs MA)))
316
:hints (("Goal" :in-theory (enable step-regs))))
318
(defthm latch1-p-step-latch1
319
(implies (and (MA-state-p MA) (MA-sig-p sig))
320
(latch1-p (step-latch1 MA sig)))
321
:hints (("Goal" :in-theory (enable step-latch1 MA-sig-p))))
323
(defthm latch1-p-step-latch2
324
(implies (and (MA-state-p MA) (MA-sig-p sig))
325
(latch2-p (step-latch2 MA)))
326
:hints (("Goal" :in-theory (enable step-latch2 MA-sig-p))))
328
(defthm MA-state-p-MA-step
329
(implies (and (MA-state-p MA) (MA-sig-p sig))
330
(MA-state-p (MA-step MA sig)))
331
:hints (("Goal" :in-theory (enable MA-step))))
333
(defthm MA-state-p-MA-stepn
334
(implies (and (MA-state-p MA) (MA-sig-listp sig-list)
335
(<= n (len sig-list)))
336
(MA-state-p (MA-stepn MA sig-list n))))
338
;;; Predicates for correctness
340
; The projection function from an MA state to the corresponding ISA
341
; state. Function proj strips off pipeline latches from the MA state.
343
(declare (xargs :guard (MA-state-p MA)))
344
(ISA-state (MA-pc MA) (MA-regs MA) (MA-mem MA)))
346
; (flushed? MA) is true if the pipeline of MA is flushed.
348
(b-nor (latch1-valid? (MA-latch1 MA))
349
(latch2-valid? (MA-latch2 MA))))
353
We will prove a following lemma for operational correctness:
355
(implies (and (MA-state-p MA)
356
(MA-sig-listp sig-list)
357
(<= n (len sig-list))
359
(b1p (flushed? (MA-stepn MA sig-list n))))
360
(equal (proj (MA-stepn MA sig-list n))
362
(num-insts MA sig-list n)))))
364
where num-insts calculates the nunber of instructions executed in the
365
n cycles of MA execution. We also prove the liveness property with:
368
(implies (MA-state-p MA)
369
(b1p (flushed? (MA-stepn MA
370
(zeros (flush-cycles MA))
371
(flush-cycles MA)))))).
373
Function flush-cycles calculates the number of cycles to flush the pipeline.