|
1 | 1 | (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)) |
3 | 6 |
|
4 | 7 | (defmacro build [cpuname options & instructions]
|
5 | 8 | `(build* ~cpuname ~options (quote ~instructions)))
|
|
26 | 29 | (defn alu-op-to-opcode [op]
|
27 | 30 | (if op
|
28 | 31 | (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") |
32 | 37 | "000"))
|
33 | 38 |
|
34 | 39 | (defn flatten-1 [things]
|
|
43 | 48 | f with the value"
|
44 | 49 | (zipmap (keys m) (map f (vals m))))
|
45 | 50 |
|
46 |
| -(defn rtl-to-microcode [[target _ source]] |
| 51 | +(defn rtl-to-microcode [[target _ source & conditional-body]] |
47 | 52 | (cond
|
48 | 53 | (number? source) ; constant-to-register
|
49 | 54 | {:control-signals (list (wr target)),
|
|
52 | 57 | (symbol? source) ; register-to-register
|
53 | 58 | {:control-signals (list (rd source) (wr target))}
|
54 | 59 |
|
| 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 | + |
55 | 79 | (and (seq? source) (symbol? (first source))) ; ALU-to-register
|
56 | 80 | (let [[alu_op operand_a operand_b] source]
|
57 | 81 | (list
|
|
66 | 90 | (defn name-for-state [instruction-name index]
|
67 | 91 | (keyword (str instruction-name "_" index)))
|
68 | 92 |
|
| 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 | + |
69 | 111 | (defn make-states-for-instruction [[_ instruction-name & RTLs]]
|
70 | 112 | (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))))) |
85 | 116 |
|
86 | 117 | (defn make-states [instructions]
|
87 | 118 | "Given a set of instructions, create the set of states
|
|
128 | 159 | :system_bus 7 ~(- 8 opcode-width)))]}
|
129 | 160 | :decode {:control-signals '()}}
|
130 | 161 | 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)) |
131 | 164 | control-signals (set (apply concat (map
|
132 | 165 | (fn [[_ body]] (:control-signals body))
|
133 | 166 | states)))
|
134 |
| - inputs {:reset std-logic} |
| 167 | + inputs {:reset std-logic, :condition std-logic} |
135 | 168 | outputs (assoc
|
136 | 169 | (zipmap control-signals (repeat (count control-signals) std-logic))
|
137 | 170 | :alu_operation (std-logic-vector 2 0))]
|
|
155 | 188 | ; transitions
|
156 | 189 | (concat
|
157 | 190 | ; 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 | + |
159 | 197 | ; decode
|
160 | 198 | (map #(list
|
161 | 199 | ; from
|
|
173 | 211 | (let [[control-unit control-in control-out] (control-unit instructions)]
|
174 | 212 | (with-open [main-vhdl (java.io.FileWriter. (str cpuname "/main.vhdl"))
|
175 | 213 | control-vhdl (java.io.FileWriter. (str cpuname "/control.vhdl"))]
|
| 214 | + ;(pprint control-unit) |
176 | 215 | (binding [*out* control-vhdl]
|
177 | 216 | (generate-vhdl control-unit))
|
178 | 217 | (binding [*out* main-vhdl]
|
|
183 | 222 | (:bus_inspection :out ~(std-logic-vector 7 0))]
|
184 | 223 | ; defs
|
185 | 224 | [(signal :system_bus ~(std-logic-vector 7 0))
|
| 225 | + (signal :condition ~std-logic) |
186 | 226 | (signal :alu_operation ~(std-logic-vector 2 0))
|
187 | 227 | (signal :opcode ~(std-logic-vector 7 5))
|
188 | 228 | (signal :wr_pc ~std-logic)
|
|
232 | 272 | (:op :in ~(std-logic-vector 2 0))
|
233 | 273 | (:wr_a :in ~std-logic)
|
234 | 274 | (:wr_b :in ~std-logic)
|
235 |
| - (:rd :in ~std-logic)) |
| 275 | + (:rd :in ~std-logic) |
| 276 | + (:condition :out ~std-logic)) |
236 | 277 |
|
237 | 278 | (component :control_unit
|
238 | 279 | ~@(concat (map input control-in)
|
239 | 280 | (map output control-out)
|
240 |
| - `((:system_bus :inout ~(std-logic-vector 7 0))))) |
241 |
| - ] |
| 281 | + `((:system_bus :inout ~(std-logic-vector 7 0)))))] |
242 | 282 | ; architecture
|
243 | 283 | [
|
244 | 284 | (instance :program_counter "pc" :clock :system_bus :system_bus
|
|
250 | 290 | (instance :ram "main_memory" :clock :system_bus :system_bus
|
251 | 291 | ~(subbits :system_bus 4 0) :wr_MD :wr_MA :rd_MD)
|
252 | 292 | (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) |
254 | 294 | (instance :control_unit "control0"
|
255 | 295 | ; same ports as the control signals we got
|
256 | 296 | ~@(map first (concat control-in control-out)) :system_bus)
|
|
0 commit comments