ruby_rtl 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/examples/adder.rb +39 -0
- data/examples/and.rb +19 -0
- data/examples/counter.rb +27 -0
- data/examples/fsm.rb +37 -0
- data/examples/full_adder.rb +27 -0
- data/examples/gcd.rb +57 -0
- data/examples/half_adder.rb +19 -0
- data/lib/ruby_rtl/ast.rb +353 -0
- data/lib/ruby_rtl/ast_builder.rb +183 -0
- data/lib/ruby_rtl/ast_printer.rb +85 -0
- data/lib/ruby_rtl/code.rb +50 -0
- data/lib/ruby_rtl/compiler.rb +61 -0
- data/lib/ruby_rtl/contextual_analyzer.rb +88 -0
- data/lib/ruby_rtl/dsl.rb +198 -0
- data/lib/ruby_rtl/dsl_printer.rb +267 -0
- data/lib/ruby_rtl/ruby_rtl_package.vhd +77 -0
- data/lib/ruby_rtl/sexp_generator.rb +132 -0
- data/lib/ruby_rtl/type_checker.rb +209 -0
- data/lib/ruby_rtl/version.rb +3 -0
- data/lib/ruby_rtl/vhdl_generator.rb +564 -0
- data/lib/ruby_rtl/visitor.rb +163 -0
- data/lib/ruby_rtl.rb +5 -0
- metadata +92 -0
@@ -0,0 +1,564 @@
|
|
1
|
+
require_relative 'code'
|
2
|
+
|
3
|
+
module RubyRTL
|
4
|
+
|
5
|
+
class VhdlGenerator < Visitor
|
6
|
+
|
7
|
+
attr_accessor :entity
|
8
|
+
attr_accessor :ios
|
9
|
+
attr_accessor :archi_elements
|
10
|
+
|
11
|
+
def generate circuit
|
12
|
+
puts "[+] VHDL code generation"
|
13
|
+
|
14
|
+
code=Code.new
|
15
|
+
@circuit=circuit
|
16
|
+
@ios,@archi_elements=[],[]
|
17
|
+
@sigs={}
|
18
|
+
@fsm_defs=[]
|
19
|
+
@sequentials=[]
|
20
|
+
@states={}
|
21
|
+
gen_ruby_rtl_type_package
|
22
|
+
root=circuit.ast
|
23
|
+
return unless root
|
24
|
+
|
25
|
+
gen_type_package()
|
26
|
+
#root.ios.each{|io| io.accept(self)}
|
27
|
+
@typedecls=root.decls.select{|decl| decl.is_a? TypeDecl}
|
28
|
+
non_typedecls=root.decls.reject{|decl| decl.is_a? TypeDecl}
|
29
|
+
non_typedecls.each{|decl| decl.accept(self)}
|
30
|
+
|
31
|
+
code << gen_ieee_header()
|
32
|
+
code << gen_ruby_rtl_package_call()
|
33
|
+
code << gen_package_call(circuit)
|
34
|
+
code << gen_entity(circuit)
|
35
|
+
code.newline
|
36
|
+
code << gen_archi(circuit)
|
37
|
+
code=clean_vhdl(code)
|
38
|
+
puts code.finalize
|
39
|
+
code.save_as "#{name=circuit.name.downcase}.vhd"
|
40
|
+
end
|
41
|
+
|
42
|
+
def clean_vhdl(code)
|
43
|
+
txt=code.finalize
|
44
|
+
txt.gsub! /;(\s*)\)/,")"
|
45
|
+
txt.gsub! /,(\s*)\)/,")"
|
46
|
+
(code=Code.new) << txt
|
47
|
+
return code
|
48
|
+
end
|
49
|
+
|
50
|
+
def gen_ruby_rtl_package_call
|
51
|
+
code=Code.new
|
52
|
+
code << "library ruby_rtl;"
|
53
|
+
code << "use ruby_rtl.ruby_rtl_package.all;"
|
54
|
+
code.newline
|
55
|
+
code
|
56
|
+
end
|
57
|
+
|
58
|
+
def gen_ruby_rtl_type_package
|
59
|
+
code=Code.new
|
60
|
+
code << gen_ieee_header
|
61
|
+
code << "package ruby_rtl_type_package is "
|
62
|
+
code.newline
|
63
|
+
code.indent=2
|
64
|
+
$typedefs.each do |name,definition|
|
65
|
+
case definition
|
66
|
+
when RecordType
|
67
|
+
code << definition_s=definition.accept(self,name)
|
68
|
+
else
|
69
|
+
definition_s=definition.accept(self)
|
70
|
+
case definition
|
71
|
+
when IntType,UIntType,BitType
|
72
|
+
header="sub"
|
73
|
+
else
|
74
|
+
header=""
|
75
|
+
end
|
76
|
+
code << "#{header}type #{name} is #{definition_s};"
|
77
|
+
end
|
78
|
+
code.newline
|
79
|
+
end
|
80
|
+
code.indent=0
|
81
|
+
code << "end package;"
|
82
|
+
code.save_as "ruby_rtl_type_package.vhd"
|
83
|
+
end
|
84
|
+
|
85
|
+
def gen_type_package
|
86
|
+
name=@circuit.name.downcase
|
87
|
+
return unless ast=@circuit.ast
|
88
|
+
typdecls=ast.decls.select{|decl| decl.is_a?(TypeDecl)}
|
89
|
+
package=Code.new
|
90
|
+
package << gen_ieee_header
|
91
|
+
package << "package #{name}_package is"
|
92
|
+
package.indent=2
|
93
|
+
package.newline
|
94
|
+
typdecls.each do |decl|
|
95
|
+
definition=decl.definition.accept(self,decl.name)
|
96
|
+
package << definition
|
97
|
+
package.newline
|
98
|
+
end
|
99
|
+
package.indent=0
|
100
|
+
package << "end package;"
|
101
|
+
puts package.finalize
|
102
|
+
package.save_as "#{name}_package.vhd"
|
103
|
+
end
|
104
|
+
|
105
|
+
def gen_ieee_header
|
106
|
+
header=Code.new
|
107
|
+
header << "-- automatically generated by RubyRTL"
|
108
|
+
header << "library ieee;"
|
109
|
+
header << "use ieee.std_logic_1164.all;"
|
110
|
+
header << "use ieee.numeric_std.all;"
|
111
|
+
header.newline
|
112
|
+
header
|
113
|
+
end
|
114
|
+
|
115
|
+
def gen_package_call circuit
|
116
|
+
name=circuit.name.downcase
|
117
|
+
code=Code.new
|
118
|
+
code << "library #{name}_lib;"
|
119
|
+
code << "use #{name}_lib.#{name}_package.all;"
|
120
|
+
code.newline
|
121
|
+
code
|
122
|
+
end
|
123
|
+
|
124
|
+
def gen_entity circuit
|
125
|
+
entity=Code.new
|
126
|
+
entity << "entity #{name=circuit.name.downcase}_c is"
|
127
|
+
entity.indent=2
|
128
|
+
entity << "port ("
|
129
|
+
entity.indent=4
|
130
|
+
if circuit.has_sequential_statements
|
131
|
+
entity << "reset_n : in std_logic;"
|
132
|
+
entity << "clk : in std_logic;"
|
133
|
+
end
|
134
|
+
ios.each{|io| entity << io}
|
135
|
+
entity.indent=2
|
136
|
+
entity << ");"
|
137
|
+
entity.indent=0
|
138
|
+
entity << "end #{name}_c;"
|
139
|
+
end
|
140
|
+
|
141
|
+
def gen_archi circuit
|
142
|
+
body=circuit.ast.body
|
143
|
+
archi_elements=body.stmts.collect{|stmt| stmt.accept(self)}
|
144
|
+
archi=Code.new
|
145
|
+
archi << "architecture rtl of #{circuit.name.downcase}_c is"
|
146
|
+
archi.indent=2
|
147
|
+
@fsm_defs.each do |decl|
|
148
|
+
archi << decl
|
149
|
+
end
|
150
|
+
@typedecls.each do |typedecl|
|
151
|
+
archi << typedecl.accept(self)
|
152
|
+
end
|
153
|
+
@sigs.each do |sig,name|
|
154
|
+
archi << "signal #{name} : #{sig.type.accept(self)};"
|
155
|
+
end
|
156
|
+
archi.indent=0
|
157
|
+
archi << "begin"
|
158
|
+
archi.indent=2
|
159
|
+
archi.newline
|
160
|
+
archi_elements.each do |element|
|
161
|
+
archi << element
|
162
|
+
archi.newline
|
163
|
+
end
|
164
|
+
archi.indent=0
|
165
|
+
archi.newline
|
166
|
+
archi << "end rtl;"
|
167
|
+
archi
|
168
|
+
end
|
169
|
+
|
170
|
+
def visitComment comment,args=nil
|
171
|
+
"-- #{comment.str}"
|
172
|
+
end
|
173
|
+
|
174
|
+
def visitInput input,args=nil
|
175
|
+
name=@sigs[input] || input.name
|
176
|
+
adapt_name(name,args)
|
177
|
+
end
|
178
|
+
|
179
|
+
def visitOutput output,args=nil
|
180
|
+
name=@sigs[output] || output.name
|
181
|
+
adapt_name(name,args)
|
182
|
+
end
|
183
|
+
|
184
|
+
def visitSigDecl decl,args=nil
|
185
|
+
name=decl.name
|
186
|
+
name.sub!(/@/,'')
|
187
|
+
type=decl.sig.type.accept(self)
|
188
|
+
case decl.sig
|
189
|
+
when Input
|
190
|
+
ios << "#{name} : in #{type};"
|
191
|
+
when Output
|
192
|
+
ios << "#{name} : out #{type};"
|
193
|
+
when Sig
|
194
|
+
@sigs.merge!(decl.sig => name)
|
195
|
+
else
|
196
|
+
raise "ERROR : visitSigDecl : neither input ou output"
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
def visitSig sig,args=nil
|
201
|
+
name=sig.name
|
202
|
+
adapt_name(name,args)
|
203
|
+
end
|
204
|
+
|
205
|
+
def adapt_name name,kind
|
206
|
+
name=name.to_s
|
207
|
+
case kind
|
208
|
+
when :comb
|
209
|
+
name+="_c"
|
210
|
+
when :reg
|
211
|
+
name+="_r"
|
212
|
+
when :var
|
213
|
+
name+="_v"
|
214
|
+
end
|
215
|
+
name
|
216
|
+
end
|
217
|
+
|
218
|
+
def visitTypeDecl decl,args=nil
|
219
|
+
definition=decl.definition.accept(self,decl.name)
|
220
|
+
"type #{decl.name} is #{definition};"
|
221
|
+
end
|
222
|
+
|
223
|
+
def visitEnumType enum_type,name
|
224
|
+
if name
|
225
|
+
"type #{name} is (#{enum_type.items.join(',')});"
|
226
|
+
else
|
227
|
+
idx=$typedefs.values.index(enum_type)
|
228
|
+
$typedefs.keys[idx]
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
def visitRecordType rectype,name
|
233
|
+
if name
|
234
|
+
code=Code.new
|
235
|
+
code << "record"
|
236
|
+
code.indent=2
|
237
|
+
rectype.hash.each do |name,type|
|
238
|
+
type_s=type.accept(self)
|
239
|
+
code << "#{name} : #{type_s};"
|
240
|
+
end
|
241
|
+
code.indent=0
|
242
|
+
code << "end record;"
|
243
|
+
code
|
244
|
+
else
|
245
|
+
idx=$typedefs.values.index(rectype)
|
246
|
+
$typedefs.keys[idx]
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
def visitMemoryType memtype,name
|
251
|
+
if name
|
252
|
+
range="0 to #{memtype.size-1}"
|
253
|
+
type=memtype.type.accept(self)
|
254
|
+
"array(#{range}) of #{type}"
|
255
|
+
else
|
256
|
+
idx=$typedefs.values.index(memtype)
|
257
|
+
$typedefs.keys[idx]
|
258
|
+
end
|
259
|
+
end
|
260
|
+
# ====== body stuff ========
|
261
|
+
# === statements ===
|
262
|
+
def visitAssign assign,args=nil
|
263
|
+
lhs=assign.lhs.accept(self)
|
264
|
+
rhs=assign.rhs.accept(self)
|
265
|
+
"#{lhs} <= #{rhs};"
|
266
|
+
end
|
267
|
+
|
268
|
+
def visitCompDecl comp_decl,args=nil
|
269
|
+
comp=comp_decl.comp
|
270
|
+
instance_name=comp_decl.name
|
271
|
+
sig_decls=comp.ast.decls.select{|node| node.is_a? SigDecl}
|
272
|
+
inputs =sig_decls.select{|decl| decl.sig.is_a? Input}.map(&:sig)
|
273
|
+
outputs=sig_decls.select{|decl| decl.sig.is_a? Output}.map(&:sig)
|
274
|
+
|
275
|
+
instanciation=Code.new
|
276
|
+
instanciation << "#{instance_name} : entity work.#{comp.name}_c"
|
277
|
+
instanciation.indent=2
|
278
|
+
instanciation << "port map("
|
279
|
+
instanciation.indent=4
|
280
|
+
inputs.each do |input|
|
281
|
+
actual_sig_name="#{instance_name}_#{input.name}"
|
282
|
+
@sigs.merge!({input => actual_sig_name})
|
283
|
+
instanciation << "#{input.name} => #{actual_sig_name},"
|
284
|
+
end
|
285
|
+
outputs.each do |output|
|
286
|
+
actual_sig_name="#{instance_name}_#{output.name}"
|
287
|
+
@sigs.merge!(output => actual_sig_name)
|
288
|
+
instanciation << "#{output.name} => #{actual_sig_name},"
|
289
|
+
end
|
290
|
+
instanciation.indent=2
|
291
|
+
instanciation << ");"
|
292
|
+
instanciation.indent=0
|
293
|
+
instanciation.newline
|
294
|
+
instanciation
|
295
|
+
end
|
296
|
+
|
297
|
+
def visitCombinatorial comb,args=nil
|
298
|
+
code=Code.new
|
299
|
+
label=comb.label
|
300
|
+
code << "#{label} : process(all) --VHDL'08"
|
301
|
+
code << "begin"
|
302
|
+
code.indent=2
|
303
|
+
code << comb.body.accept(self)
|
304
|
+
code.indent=0
|
305
|
+
code << "end process;"
|
306
|
+
code
|
307
|
+
end
|
308
|
+
|
309
|
+
def visitSequential sequential,args=nil
|
310
|
+
code=Code.new
|
311
|
+
label=sequential.label
|
312
|
+
code << "#{label} : process(clk)"
|
313
|
+
code << "begin"
|
314
|
+
code.indent=2
|
315
|
+
code << "if rising_edge(clk) then"
|
316
|
+
code.indent=4
|
317
|
+
code << sequential.body.accept(self)
|
318
|
+
code.indent=2
|
319
|
+
code << "end if;"
|
320
|
+
code.indent=0
|
321
|
+
code << "end process;"
|
322
|
+
code
|
323
|
+
end
|
324
|
+
|
325
|
+
# statement
|
326
|
+
def visitBody body,args=nil
|
327
|
+
code=Code.new
|
328
|
+
body.stmts.each{|stmt| code << stmt.accept(self)}
|
329
|
+
code
|
330
|
+
end
|
331
|
+
|
332
|
+
def visitIf if_,args=nil
|
333
|
+
cond=if_.cond.accept(self)
|
334
|
+
if_body=if_.body.accept(self)
|
335
|
+
code=Code.new
|
336
|
+
code << "if #{cond} then"
|
337
|
+
code.indent=2
|
338
|
+
code << if_body
|
339
|
+
code.indent=0
|
340
|
+
if_.elsifs.each{|elsif_|
|
341
|
+
code << elsif_.accept(self)
|
342
|
+
}
|
343
|
+
code << if_.else.accept(self) if if_.else
|
344
|
+
code << "end if;"
|
345
|
+
code
|
346
|
+
end
|
347
|
+
|
348
|
+
def visitElsif elsif_,args=nil
|
349
|
+
cond=elsif_.cond.accept(self)
|
350
|
+
body=elsif_.body.accept(self)
|
351
|
+
code=Code.new
|
352
|
+
code << "elsif #{cond} then"
|
353
|
+
code.indent=2
|
354
|
+
code << body
|
355
|
+
code.indent=0
|
356
|
+
code
|
357
|
+
end
|
358
|
+
|
359
|
+
def visitElse else_,args=nil
|
360
|
+
body=else_.body.accept(self)
|
361
|
+
code=Code.new
|
362
|
+
code << "else "
|
363
|
+
code.indent=2
|
364
|
+
code << body
|
365
|
+
code.indent=0
|
366
|
+
code
|
367
|
+
end
|
368
|
+
# case / switch
|
369
|
+
def visitCase case_,args=nil
|
370
|
+
cond=case_.cond.accept(self)
|
371
|
+
code=Code.new
|
372
|
+
code << "case #{cond} is"
|
373
|
+
code.indent=2
|
374
|
+
code << case_.body.accept(self)
|
375
|
+
code.indent=0
|
376
|
+
code << "end case;"
|
377
|
+
code
|
378
|
+
end
|
379
|
+
|
380
|
+
def visitWhen when_,args=nil
|
381
|
+
unless (value=when_.value).is_a? Symbol
|
382
|
+
value=when_.value.accept(self)
|
383
|
+
end
|
384
|
+
code=Code.new
|
385
|
+
code << "when #{value} =>"
|
386
|
+
code.indent=2
|
387
|
+
code << when_.body.accept(self)
|
388
|
+
code.indent=0
|
389
|
+
code
|
390
|
+
end
|
391
|
+
|
392
|
+
# === FSM ===
|
393
|
+
def visitFsm fsm,args=nil
|
394
|
+
@fsm=fsm
|
395
|
+
state_names=fsm.states.map{|state| state.name}.join(",")
|
396
|
+
@fsm_defs << "type #{fsm.name}_state_t is (#{state_names});"
|
397
|
+
@fsm_defs << "signal #{fsm.name}_state : #{fsm.name}_state_t;"
|
398
|
+
body=Code.new
|
399
|
+
body << "#{fsm.name}_update : process(reset_n,clk)"
|
400
|
+
body << "begin"
|
401
|
+
body.indent=2
|
402
|
+
body << "if reset_n='0' then"
|
403
|
+
body.indent=4
|
404
|
+
body << "#{fsm.name}_state <= #{fsm.states.first.name};"
|
405
|
+
fsm.assignments.each do |assign|
|
406
|
+
lhs=assign.lhs.accept(self)
|
407
|
+
rhs=default_init(assign.lhs.type)
|
408
|
+
body << "#{lhs} <= #{rhs};"
|
409
|
+
end
|
410
|
+
body.indent=2
|
411
|
+
body << "elsif rising_edge(clk) then"
|
412
|
+
body.indent=4
|
413
|
+
body << "if sreset='1' then"
|
414
|
+
body.indent=6
|
415
|
+
body << "#{fsm.name}_state <= #{fsm.states.first.name};"
|
416
|
+
fsm.assignments.each do |assign|
|
417
|
+
lhs=assign.lhs.accept(self)
|
418
|
+
rhs=default_init(assign.lhs.type)
|
419
|
+
body << "#{lhs} <= #{rhs};"
|
420
|
+
end
|
421
|
+
body.indent=4
|
422
|
+
body << "else "
|
423
|
+
body.indent=6
|
424
|
+
body << state_cases(fsm)
|
425
|
+
body.indent=4
|
426
|
+
body << "end if;"
|
427
|
+
body.indent=2
|
428
|
+
body << "end if;"
|
429
|
+
body.indent=0
|
430
|
+
body << "end process;"
|
431
|
+
body
|
432
|
+
end
|
433
|
+
|
434
|
+
def state_cases fsm
|
435
|
+
code=Code.new
|
436
|
+
code << "case #{fsm.name}_state is"
|
437
|
+
code.indent=2
|
438
|
+
fsm.states.each do |state|
|
439
|
+
code << "when #{state.name} =>"
|
440
|
+
code.indent=4
|
441
|
+
code << state_body(state)
|
442
|
+
code.indent=2
|
443
|
+
end
|
444
|
+
code << "when others =>"
|
445
|
+
code << " null;"
|
446
|
+
code.indent=0
|
447
|
+
code << "end case;"
|
448
|
+
code
|
449
|
+
end
|
450
|
+
|
451
|
+
def state_body state
|
452
|
+
code=Code.new
|
453
|
+
state.body.each{|stmt| code << stmt.accept(self)}
|
454
|
+
code
|
455
|
+
end
|
456
|
+
|
457
|
+
def visitState state,args=nil
|
458
|
+
code << "when #{state.name}"
|
459
|
+
code
|
460
|
+
end
|
461
|
+
|
462
|
+
def visitNext next_state,args=nil
|
463
|
+
"#{@fsm.name}_state <= #{next_state.name};"
|
464
|
+
end
|
465
|
+
|
466
|
+
# === expressions ===
|
467
|
+
VHDL_OP={
|
468
|
+
"&" => "and",
|
469
|
+
"|" => "or",
|
470
|
+
"^" => "xor",
|
471
|
+
"=="=> "=",
|
472
|
+
"%" => "mod",
|
473
|
+
"!=" => "/="
|
474
|
+
}
|
475
|
+
def visitBinary bin,args=nil
|
476
|
+
lhs=bin.lhs.accept(self)
|
477
|
+
op=VHDL_OP[bin.op] || bin.op
|
478
|
+
rhs=bin.rhs.accept(self)
|
479
|
+
"(#{lhs} #{op} #{rhs})"
|
480
|
+
end
|
481
|
+
|
482
|
+
def visitFuncCall func,args=nil
|
483
|
+
name=func.name
|
484
|
+
argus=func.args.map{|arg| arg.accept(self)}.join(',')
|
485
|
+
"#{name}(#{argus})"
|
486
|
+
end
|
487
|
+
|
488
|
+
def visitIndexed indexed,args=nil
|
489
|
+
lhs=indexed.lhs.accept(self)
|
490
|
+
rhs=indexed.rhs.accept(self)
|
491
|
+
case indexed.rhs
|
492
|
+
when RUIntLit
|
493
|
+
else
|
494
|
+
conv_int_start="to_integer("
|
495
|
+
conv_int_end =")"
|
496
|
+
end
|
497
|
+
puts indexed.rhs
|
498
|
+
"#{lhs}(#{conv_int_start}#{rhs}#{conv_int_end})"
|
499
|
+
end
|
500
|
+
|
501
|
+
# === types
|
502
|
+
def visitBitType bit,args=nil
|
503
|
+
"std_logic"
|
504
|
+
end
|
505
|
+
|
506
|
+
def visitBitVectorType bv,args=nil
|
507
|
+
range="#{bv.bitwidth-1} downto 0"
|
508
|
+
"std_logic_vector(#{range})"
|
509
|
+
end
|
510
|
+
|
511
|
+
def visitUIntType uint,args=nil
|
512
|
+
range="#{uint.bitwidth-1} downto 0"
|
513
|
+
"unsigned(#{range})"
|
514
|
+
end
|
515
|
+
|
516
|
+
def visitIntType int,args=nil
|
517
|
+
range="#{int.bitwidth-1} downto 0"
|
518
|
+
"signed(#{range})"
|
519
|
+
end
|
520
|
+
|
521
|
+
|
522
|
+
|
523
|
+
def default_init type
|
524
|
+
case type
|
525
|
+
when BitType
|
526
|
+
return "'0'"
|
527
|
+
when BitVectorType
|
528
|
+
return "(others=>'0')"
|
529
|
+
when UintType
|
530
|
+
return "to_unsigned(0,#{type.bitwidth})"
|
531
|
+
when IntType
|
532
|
+
return "to_signed(0,#{type.bitwidth})"
|
533
|
+
else
|
534
|
+
raise "Cannot provide default init value for type #{type}"
|
535
|
+
end
|
536
|
+
ret
|
537
|
+
end
|
538
|
+
|
539
|
+
# === literals
|
540
|
+
def visitIntLit int,args=nil
|
541
|
+
"to_signed(#{int.val},#{int.type.bitwidth})"
|
542
|
+
end
|
543
|
+
|
544
|
+
def visitUIntLit uint,args=nil
|
545
|
+
"to_unsigned(#{uint.val},#{uint.type.bitwidth})"
|
546
|
+
end
|
547
|
+
|
548
|
+
def visitBitLit bit_lit,args=nil
|
549
|
+
"'#{bit_lit.val}'"
|
550
|
+
end
|
551
|
+
|
552
|
+
def visitBitVectorLit bit_lit,args=nil
|
553
|
+
"\"#{bit_lit.val}\""
|
554
|
+
end
|
555
|
+
|
556
|
+
def visitRIntLit lit,args=nil
|
557
|
+
lit.val
|
558
|
+
end
|
559
|
+
|
560
|
+
def visitRUIntLit lit,args=nil
|
561
|
+
lit.val
|
562
|
+
end
|
563
|
+
end
|
564
|
+
end
|
@@ -0,0 +1,163 @@
|
|
1
|
+
|
2
|
+
module RubyRTL
|
3
|
+
class Visitor
|
4
|
+
|
5
|
+
def visit circuit
|
6
|
+
circuit.ast.each{|node| node.accept(self)}
|
7
|
+
end
|
8
|
+
|
9
|
+
def visitComment node,args=nil
|
10
|
+
end
|
11
|
+
|
12
|
+
def visitSig node,args=nil
|
13
|
+
end
|
14
|
+
|
15
|
+
def visitPort node,args=nil
|
16
|
+
end
|
17
|
+
|
18
|
+
def visitInput node,args=nil
|
19
|
+
end
|
20
|
+
|
21
|
+
def visitOutput node,args=nil
|
22
|
+
end
|
23
|
+
|
24
|
+
def visitTypeDecl node,args=nil
|
25
|
+
end
|
26
|
+
|
27
|
+
def visitSigDecl node,args=nil
|
28
|
+
end
|
29
|
+
|
30
|
+
def visitCompDecl node,args=nil
|
31
|
+
end
|
32
|
+
|
33
|
+
def visitCircuitPart node,args=nil
|
34
|
+
end
|
35
|
+
|
36
|
+
def visitCombinatorial comb,args=nil
|
37
|
+
puts comb.body.class
|
38
|
+
comb.body.accept(self)
|
39
|
+
end
|
40
|
+
|
41
|
+
def visitSequential seq,args=nil
|
42
|
+
puts seq.body.class
|
43
|
+
seq.body.accept(self)
|
44
|
+
end
|
45
|
+
|
46
|
+
# === statements
|
47
|
+
def visitBody body,args=nil
|
48
|
+
body.each{|stmt| stmt.accept(self,args)}
|
49
|
+
end
|
50
|
+
|
51
|
+
def visitAssign node,args=nil
|
52
|
+
node.lhs.accept(self)
|
53
|
+
node.rhs.accept(self)
|
54
|
+
end
|
55
|
+
|
56
|
+
def visitIf node,args=nil
|
57
|
+
node.cond.accept(self)
|
58
|
+
node.body.accept(self)
|
59
|
+
node.elsifs.each{|elsif_| elsif_.accept(self)}
|
60
|
+
node.else.accept(self) if node.else
|
61
|
+
end
|
62
|
+
|
63
|
+
def visitElse else_,args=nil
|
64
|
+
else_.body.accept(self)
|
65
|
+
end
|
66
|
+
|
67
|
+
def visitElsif elsif_,args=nil
|
68
|
+
elsif_.cond.accept(self)
|
69
|
+
elsif_.body.accept(self)
|
70
|
+
end
|
71
|
+
|
72
|
+
def visitCase case_,args=nil
|
73
|
+
case_.cond.accept(self)
|
74
|
+
case_.body.accept(self)
|
75
|
+
end
|
76
|
+
|
77
|
+
def visitWhen when_,args=nil
|
78
|
+
when_.value.accept(self) unless when_.value.is_a?(Symbol)
|
79
|
+
when_.body.accept(self)
|
80
|
+
end
|
81
|
+
|
82
|
+
# === fsm
|
83
|
+
def visitFsm fsm,args=nil
|
84
|
+
fsm.body.accept(self)
|
85
|
+
end
|
86
|
+
|
87
|
+
def visitState state,args=nil
|
88
|
+
state.body.accept(self)
|
89
|
+
end
|
90
|
+
|
91
|
+
def visitNext node,args=nil
|
92
|
+
end
|
93
|
+
|
94
|
+
# === expr ===
|
95
|
+
def visitBinary node,args=nil
|
96
|
+
node.lhs.accept(self)
|
97
|
+
node.rhs.accept(self)
|
98
|
+
end
|
99
|
+
|
100
|
+
def visitUnary node,args=nil
|
101
|
+
node.expr.accept(self)
|
102
|
+
end
|
103
|
+
|
104
|
+
def visitIndexed indexed,args=nil
|
105
|
+
lhs=indexed.lhs.accept(self)
|
106
|
+
rhs=indexed.rhs.accept(self)
|
107
|
+
end
|
108
|
+
# === literals ===
|
109
|
+
def visitLiteral node,args=nil
|
110
|
+
node
|
111
|
+
end
|
112
|
+
|
113
|
+
def visitBitLit node,args=nil
|
114
|
+
node
|
115
|
+
end
|
116
|
+
|
117
|
+
def visitIntLit lit,args=nil
|
118
|
+
lit
|
119
|
+
end
|
120
|
+
|
121
|
+
def visitUIntLit lit,args=nil
|
122
|
+
lit
|
123
|
+
end
|
124
|
+
|
125
|
+
def visitRIntLit lit,args=nil
|
126
|
+
lit
|
127
|
+
end
|
128
|
+
|
129
|
+
def visitRUIntLit lit,args=nil
|
130
|
+
lit
|
131
|
+
end
|
132
|
+
# === types ===
|
133
|
+
def visitInteger int,args=nil
|
134
|
+
int
|
135
|
+
end
|
136
|
+
|
137
|
+
def visitType node,args=nil
|
138
|
+
end
|
139
|
+
|
140
|
+
def visitBitType node,args=nil
|
141
|
+
end
|
142
|
+
|
143
|
+
def visitBitVectorType node,args=nil
|
144
|
+
end
|
145
|
+
|
146
|
+
def visitIntType node,args=nil
|
147
|
+
end
|
148
|
+
|
149
|
+
|
150
|
+
def visitUIntType node,args=nil
|
151
|
+
end
|
152
|
+
|
153
|
+
def visitRIntType node,args=nil
|
154
|
+
end
|
155
|
+
|
156
|
+
def visitRUintType node,args=nil
|
157
|
+
end
|
158
|
+
|
159
|
+
def visitRecordType node,args=nil
|
160
|
+
end
|
161
|
+
|
162
|
+
end
|
163
|
+
end
|