Skip to content

Commit a1c88d6

Browse files
committed
Conditionals working in Clojure!
Verified with test program in Quartus
1 parent 23d4ccb commit a1c88d6

File tree

2 files changed

+105
-25
lines changed

2 files changed

+105
-25
lines changed

src/McCalla2.clj

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
(require 'computer-build)
2+
3+
; RTL-level description
4+
(computer-build/build "mccalla2"
5+
; options
6+
{:address-width 4}
7+
(instruction "cla"
8+
(A <- 0))
9+
(instruction "cmp"
10+
(A <- (complement A)))
11+
(instruction "inc"
12+
(A <- (+ A 1)))
13+
(instruction "neg"
14+
(A <- (complement A))
15+
(A <- (+ A 1)))
16+
(instruction "adddir"
17+
(MA <- (and IR 0x0F))
18+
(A <- (+ A MD)))
19+
(instruction "subdir"
20+
(MA <- (and IR 0x0F))
21+
(A <- (- A MD)))
22+
(instruction "addind"
23+
(MA <- (and IR 0x0F))
24+
(MA <- (+ MD 0))
25+
(A <- (+ A MD)))
26+
(instruction "subind"
27+
(MA <- (and IR 0x0F))
28+
(MA <- (+ MD 0))
29+
(A <- (- A MD)))
30+
(instruction "lda"
31+
(MA <- (and IR 0x0F))
32+
(A <- MD))
33+
(instruction "sta"
34+
(MA <- (and IR 0x0F))
35+
(MD <- A))
36+
(instruction "jmp"
37+
(PC <- (and IR 0x0F)))
38+
(instruction "bra0"
39+
(if (= A 0)
40+
(PC <- (and IR 0x0F)))))

src/computer_build.clj

+65-25
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
(ns computer-build
2-
(:use computer-build.vhdl computer-build.state-machine clojure.set))
2+
(:use computer-build.vhdl
3+
computer-build.state-machine
4+
clojure.set
5+
clojure.contrib.pprint))
36

47
(defmacro build [cpuname options & instructions]
58
`(build* ~cpuname ~options (quote ~instructions)))
@@ -26,9 +29,11 @@
2629
(defn alu-op-to-opcode [op]
2730
(if op
2831
(cond
29-
(= (name op) "complement") "101"
30-
(= (name op) "+") "010"
31-
(= (name op) "-") "110")
32+
(= (name op) "and") "001"
33+
(= (name op) "complement") "011"
34+
(= (name op) "+") "100"
35+
(= (name op) "-") "101"
36+
(= (name op) "=") "110")
3237
"000"))
3338

3439
(defn flatten-1 [things]
@@ -43,7 +48,7 @@
4348
f with the value"
4449
(zipmap (keys m) (map f (vals m))))
4550

46-
(defn rtl-to-microcode [[target _ source]]
51+
(defn rtl-to-microcode [[target _ source & conditional-body]]
4752
(cond
4853
(number? source) ; constant-to-register
4954
{:control-signals (list (wr target)),
@@ -52,6 +57,25 @@
5257
(symbol? source) ; register-to-register
5358
{:control-signals (list (rd source) (wr target))}
5459

60+
(= "if" (name target)) ; conditional
61+
(let [[condition target expectation] _
62+
body (flatten-1 (map rtl-to-microcode (cons source conditional-body)))]
63+
(list
64+
; load target
65+
{:control-signals (list (rd target) (wr :alu_a)) }
66+
; load expectation and compare
67+
(if (number? expectation)
68+
{:control-signals (list (wr :alu_b))
69+
:constant-value expectation
70+
:alu_op condition
71+
:conditional true
72+
:body body}
73+
{:control-signals (list (rd expectation) (wr :alu_b))
74+
:alu_op condition
75+
:conditional true
76+
:body body})
77+
))
78+
5579
(and (seq? source) (symbol? (first source))) ; ALU-to-register
5680
(let [[alu_op operand_a operand_b] source]
5781
(list
@@ -66,22 +90,29 @@
6690
(defn name-for-state [instruction-name index]
6791
(keyword (str instruction-name "_" index)))
6892

93+
(defn link-state [instruction-name last-index body index]
94+
(let [next-state
95+
(if (= index last-index)
96+
:fetch
97+
(name-for-state instruction-name (+ index 1)))
98+
connected-body
99+
{(name-for-state instruction-name index)
100+
(assoc body :next next-state)}]
101+
(if-let [conditional-body (:body body)]
102+
; conditional
103+
(let [instruction-name (str instruction-name "_" index)
104+
last-index (dec (count conditional-body))]
105+
(merge connected-body
106+
(apply merge (map (partial link-state instruction-name last-index)
107+
conditional-body (iterate inc 0)))))
108+
; not conditional
109+
connected-body)))
110+
69111
(defn make-states-for-instruction [[_ instruction-name & RTLs]]
70112
(let [microcode (flatten-1 (map rtl-to-microcode RTLs))
71-
last-index (- (count microcode) 1)
72-
link-state (fn [body index]
73-
{(name-for-state instruction-name index)
74-
; add next state to instruction body
75-
(assoc body
76-
:next
77-
(if (= index last-index)
78-
; then
79-
:fetch
80-
; else
81-
(name-for-state
82-
instruction-name
83-
(+ index 1))))})]
84-
(apply merge (map link-state microcode (iterate inc 0)))))
113+
last-index (- (count microcode) 1)]
114+
(apply merge (map (partial link-state instruction-name last-index)
115+
microcode (iterate inc 0)))))
85116

86117
(defn make-states [instructions]
87118
"Given a set of instructions, create the set of states
@@ -128,10 +159,12 @@
128159
:system_bus 7 ~(- 8 opcode-width)))]}
129160
:decode {:control-signals '()}}
130161
states (merge (make-states instructions) static-states)
162+
conditional-states (select-keys states (for [[k v] states :when (:conditional v)] k))
163+
unconditional-states (select-keys states (for [[k v] states :when (not (:conditional v))] k))
131164
control-signals (set (apply concat (map
132165
(fn [[_ body]] (:control-signals body))
133166
states)))
134-
inputs {:reset std-logic}
167+
inputs {:reset std-logic, :condition std-logic}
135168
outputs (assoc
136169
(zipmap control-signals (repeat (count control-signals) std-logic))
137170
:alu_operation (std-logic-vector 2 0))]
@@ -155,7 +188,12 @@
155188
; transitions
156189
(concat
157190
; states
158-
(map #(list (first %) (:next (second %))) (dissoc states :decode))
191+
(map (fn [[k v]] (list k (:next v))) (dissoc unconditional-states :decode))
192+
; conditional false
193+
(map (fn [[k v]] (list k '(= :condition 0) (:next v))) conditional-states)
194+
; conditional true
195+
(map (fn [[k v]] (list k '(= :condition 1) (name-for-state (name k) 0))) conditional-states)
196+
159197
; decode
160198
(map #(list
161199
; from
@@ -173,6 +211,7 @@
173211
(let [[control-unit control-in control-out] (control-unit instructions)]
174212
(with-open [main-vhdl (java.io.FileWriter. (str cpuname "/main.vhdl"))
175213
control-vhdl (java.io.FileWriter. (str cpuname "/control.vhdl"))]
214+
;(pprint control-unit)
176215
(binding [*out* control-vhdl]
177216
(generate-vhdl control-unit))
178217
(binding [*out* main-vhdl]
@@ -183,6 +222,7 @@
183222
(:bus_inspection :out ~(std-logic-vector 7 0))]
184223
; defs
185224
[(signal :system_bus ~(std-logic-vector 7 0))
225+
(signal :condition ~std-logic)
186226
(signal :alu_operation ~(std-logic-vector 2 0))
187227
(signal :opcode ~(std-logic-vector 7 5))
188228
(signal :wr_pc ~std-logic)
@@ -232,13 +272,13 @@
232272
(:op :in ~(std-logic-vector 2 0))
233273
(:wr_a :in ~std-logic)
234274
(:wr_b :in ~std-logic)
235-
(:rd :in ~std-logic))
275+
(:rd :in ~std-logic)
276+
(:condition :out ~std-logic))
236277

237278
(component :control_unit
238279
~@(concat (map input control-in)
239280
(map output control-out)
240-
`((:system_bus :inout ~(std-logic-vector 7 0)))))
241-
]
281+
`((:system_bus :inout ~(std-logic-vector 7 0)))))]
242282
; architecture
243283
[
244284
(instance :program_counter "pc" :clock :system_bus :system_bus
@@ -250,7 +290,7 @@
250290
(instance :ram "main_memory" :clock :system_bus :system_bus
251291
~(subbits :system_bus 4 0) :wr_MD :wr_MA :rd_MD)
252292
(instance :alu "alu0" :clock :system_bus :system_bus :alu_operation
253-
:wr_alu_a :wr_alu_b :rd_alu)
293+
:wr_alu_a :wr_alu_b :rd_alu, :condition)
254294
(instance :control_unit "control0"
255295
; same ports as the control signals we got
256296
~@(map first (concat control-in control-out)) :system_bus)

0 commit comments

Comments
 (0)