1
1
require 'computer_build/vhdl'
2
2
require 'computer_build/state_machine'
3
3
4
-
5
- class Fixnum
6
- def to_logic ( width )
7
- str = self . to_s ( 2 )
8
- return "0" *( width -str . length ) + str
9
- end
10
- end
11
-
12
4
class Computer
5
+ include VHDL ::Helpers
6
+
13
7
def self . Build ( name )
14
8
instance = Computer . new ( name )
15
9
yield ( instance )
@@ -23,6 +17,7 @@ def initialize(name)
23
17
@instructions = [ ]
24
18
end
25
19
20
+ # DSL method
26
21
def instruction ( name )
27
22
inst = Instruction . new ( name )
28
23
yield ( inst )
@@ -37,11 +32,12 @@ def generate
37
32
38
33
control = state_machine ( "control_unit" ) do |m |
39
34
m . input :reset , VHDL ::STD_LOGIC
35
+ m . input :condition , VHDL ::STD_LOGIC
40
36
m . inout :system_bus , VHDL ::STD_LOGIC_VECTOR ( 7 ..0 )
37
+ m . output :alu_operation , VHDL ::STD_LOGIC_VECTOR ( 2 ..0 )
41
38
control_signals . each do |sig |
42
39
m . output sig , VHDL ::STD_LOGIC
43
40
end
44
- m . output :alu_operation , VHDL ::STD_LOGIC_VECTOR ( 2 ..0 )
45
41
46
42
m . signal :opcode ,
47
43
VHDL ::STD_LOGIC_VECTOR ( ( opcode_length -1 ) ..0 )
@@ -73,13 +69,18 @@ def generate
73
69
end
74
70
75
71
if name == 'store_instruction'
76
- s . if event ( :clock ) , equal ( :clock , "0" ) do |thn |
72
+ s . if event ( :clock ) , VHDL :: Equal . new ( :clock , "0" ) do |thn |
77
73
thn . assign :opcode , "#{ opcode_length -1 } downto 0" , :system_bus , "7 downto #{ 7 -opcode_length +1 } "
78
74
end
79
75
end
80
76
end
81
77
82
- m . transition :from => name , :to => state . next if state . next
78
+ if state . condition
79
+ m . transition :from => name , :to => state . next , :on => VHDL ::Equal . new ( :condition , "0" )
80
+ m . transition :from => name , :to => name +"_0" , :on => VHDL ::Equal . new ( :condition , "1" )
81
+ else
82
+ m . transition :from => name , :to => state . next if state . next
83
+ end
83
84
end
84
85
85
86
# instruction decode
@@ -96,6 +97,7 @@ def generate
96
97
97
98
e . signal :system_bus , VHDL ::STD_LOGIC_VECTOR ( 7 ..0 )
98
99
e . signal :alu_operation , VHDL ::STD_LOGIC_VECTOR ( 2 ..0 )
100
+ e . signal :alu_condition , VHDL ::STD_LOGIC
99
101
100
102
control_signals . each do |sig |
101
103
e . signal sig , VHDL ::STD_LOGIC
@@ -136,25 +138,27 @@ def generate
136
138
c . in :wr_a , VHDL ::STD_LOGIC
137
139
c . in :wr_b , VHDL ::STD_LOGIC
138
140
c . in :rd , VHDL ::STD_LOGIC
141
+ c . out :condition , VHDL ::STD_LOGIC
139
142
end
140
143
141
144
e . component :control_unit do |c |
142
145
c . in :clock , VHDL ::STD_LOGIC
143
146
c . in :reset , VHDL ::STD_LOGIC
144
- c . inout :system_bus , VHDL ::STD_LOGIC_VECTOR ( 7 .. 0 )
147
+ c . in :condition , VHDL ::STD_LOGIC
145
148
c . out :alu_operation , VHDL ::STD_LOGIC_VECTOR ( 2 ..0 )
146
149
control_signals . each do |sig |
147
150
c . out sig , VHDL ::STD_LOGIC
148
151
end
152
+ c . inout :system_bus , VHDL ::STD_LOGIC_VECTOR ( 7 ..0 )
149
153
end
150
154
151
155
e . behavior do |b |
152
156
b . instance :program_counter , "pc" , :clock , :system_bus , :system_bus , :wr_pc , :rd_pc , :inc_pc
153
157
b . instance :reg , "ir" , :clock , :system_bus , :system_bus , :wr_IR , :rd_IR
154
158
b . instance :reg , "A" , :clock , :system_bus , :system_bus , :wr_A , :rd_A
155
159
b . instance :ram , "main_memory" , :clock , :system_bus , :system_bus , subbits ( :system_bus , 4 ..0 ) , :wr_MD , :wr_MA , :rd_MD
156
- b . instance :alu , "alu0" , :clock , :system_bus , :system_bus , :alu_operation , :wr_alu_a , :wr_alu_b , :rd_alu
157
- b . instance :control_unit , "control0" , [ :clock , :reset , :system_bus , :alu_operation ] + control_signals
160
+ b . instance :alu , "alu0" , :clock , :system_bus , :system_bus , :alu_operation , :wr_alu_a , :wr_alu_b , :rd_alu , :alu_condition
161
+ b . instance :control_unit , "control0" , [ :clock , :reset , :alu_condition , :alu_operation ] + control_signals + [ :system_bus ]
158
162
b . assign :bus_inspection , :system_bus
159
163
end
160
164
end
@@ -184,7 +188,11 @@ def move(target, source)
184
188
end
185
189
186
190
def microcode
187
- steps . map &:to_microcode
191
+ steps . map ( &:to_microcode ) . flatten
192
+ end
193
+
194
+ def if ( condition , &body )
195
+ @steps << Conditional . new ( condition , &body )
188
196
end
189
197
end
190
198
@@ -198,15 +206,61 @@ def initialize(op, *operands)
198
206
199
207
def opcode
200
208
return {
209
+ :and => "001" ,
210
+ :or => "010" ,
201
211
:complement => "011" ,
202
- :and => "001" ,
203
- :add => "100" ,
204
- :subtract => "101" } [ @op ]
212
+ :add => "100" ,
213
+ :subtract => "101" ,
214
+ :equal => "110" ,
215
+ :lessthan => "111" } [ @op ]
205
216
end
206
217
end
207
218
208
219
private
209
220
221
+ class Conditional
222
+ def initialize ( condition )
223
+ @condition = condition # instance of ALUOperation
224
+ @steps = [ ]
225
+ @true_body = [ ]
226
+ yield self
227
+ end
228
+
229
+ # DSL method
230
+ def move ( target , source )
231
+ @steps << RTL . new ( target , source )
232
+ end
233
+
234
+ def to_microcode
235
+ steps = [ ]
236
+ steps << MicrocodeState . new do |state |
237
+ state . control_signals = [ "rd_#{ @condition . operands . first } " , "wr_alu_a" ]
238
+ state . alu_op = @condition
239
+ end
240
+ conditional = MicrocodeState . new do |state |
241
+ op = @condition . operands . last
242
+ state . control_signals = [ "wr_alu_b" ]
243
+
244
+ if op . is_a? Fixnum
245
+ state . constant_value = op
246
+ else
247
+ state . control_signals += "rd_#{ op } "
248
+ end
249
+
250
+ state . alu_op = @condition
251
+ state . condition = @condition
252
+ end
253
+ steps << conditional
254
+
255
+ body = @steps . map ( &:to_microcode ) . flatten
256
+ conditional . body_size = body . length
257
+
258
+ body . each { |state | state . conditional = conditional }
259
+
260
+ return steps + body
261
+ end
262
+ end
263
+
210
264
class RTL
211
265
def initialize ( target , source )
212
266
@target = target
@@ -251,7 +305,9 @@ def to_microcode
251
305
end
252
306
253
307
class MicrocodeState
254
- attr_accessor :control_signals , :alu_op , :constant_value , :next
308
+ attr_accessor :control_signals , :alu_op , :constant_value , :next ,
309
+ :condition , :conditional , :body_size , :index
310
+
255
311
def initialize ( &blk )
256
312
yield ( self ) if blk
257
313
end
@@ -260,14 +316,29 @@ def initialize(&blk)
260
316
def make_states ( instructions )
261
317
states = { }
262
318
instructions . each do |instr |
263
- steps = instr . microcode . flatten
264
- steps . each_with_index do |step , index |
265
- if index + 1 < steps . length
266
- step . next = instr . name +"_" +( index +1 ) . to_s
319
+ steps = instr . microcode
320
+ indexes = { nil => 0 }
321
+ steps . each do |step |
322
+ indexes [ step . conditional ] ||= 0
323
+ index = indexes [ step . conditional ]
324
+
325
+ if step . conditional
326
+ if index < step . conditional . body_size - 1
327
+ step . next = instr . name +"_" +( step . conditional . index . to_s ) +"_" +( index +1 ) . to_s
328
+ else
329
+ step . next = step . conditional . next
330
+ end
331
+ states [ instr . name +"_" +( step . conditional . index . to_s ) +"_" +index . to_s ] = step
267
332
else
268
- step . next = :fetch
333
+ if index < steps . reject ( &:conditional ) . length - 1
334
+ step . next = instr . name +"_" +( index +1 ) . to_s
335
+ else
336
+ step . next = :fetch
337
+ end
338
+ states [ instr . name +"_" +index . to_s ] = step
269
339
end
270
- states [ instr . name +"_" +index . to_s ] = step
340
+ step . index = index
341
+ indexes [ step . conditional ] += 1
271
342
end
272
343
end
273
344
@@ -320,3 +391,7 @@ def bitwise_and(operand1, operand2)
320
391
def subtract ( operand1 , operand2 )
321
392
Computer ::ALUOperation . new ( :subtract , operand1 , operand2 )
322
393
end
394
+
395
+ def equal ( operand1 , operand2 )
396
+ Computer ::ALUOperation . new ( :equal , operand1 , operand2 )
397
+ end
0 commit comments