ruby_rtl 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 4913770bc9fffd154e1999f027238f71dc5e9ec56b2a72cbbf913955fc540daf
|
4
|
+
data.tar.gz: bc280eced9a72446d0418bcff3c2464e3c96904a4c69e85cd048d662ed74bdd8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a5e6bb7266b18476b9adb053b2bacaf92222f0247a1dd04968a532b496681a36eb7284e2376b6811070b7ac819af7304485a2502db2b0394392ef978ef4b86d8
|
7
|
+
data.tar.gz: 0e88200ee8bdea4380aade2b96fef117617c8de731d139796192c5324bd02f75312e9aed092b984f16b0300bb200b65036f3ba4957a80ff826d4633747f18b97
|
data/examples/adder.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require_relative '../lib/ruby_rtl'
|
2
|
+
|
3
|
+
include RubyRTL
|
4
|
+
|
5
|
+
require_relative 'test_3_full_adder'
|
6
|
+
|
7
|
+
class Adder < Circuit
|
8
|
+
|
9
|
+
def initialize nbits
|
10
|
+
input :a => nbits
|
11
|
+
input :b => nbits
|
12
|
+
output :sum => nbits
|
13
|
+
output :cout
|
14
|
+
|
15
|
+
# create components
|
16
|
+
adders=[]
|
17
|
+
for i in 0..nbits-1
|
18
|
+
adders << component("fa_#{i}" => FullAdder)
|
19
|
+
end
|
20
|
+
|
21
|
+
# connect everything
|
22
|
+
for i in 0..nbits-1
|
23
|
+
assign(adders[i].a <= a[i])
|
24
|
+
assign(adders[i].b <= b[i])
|
25
|
+
if i==0
|
26
|
+
#assign(adders[0].cin <= Bit(0)) # no carry in for FA_0
|
27
|
+
assign(adders[0].cin <= 0) # even better.
|
28
|
+
else
|
29
|
+
assign(adders[i].cin <= adders[i-1].cout)
|
30
|
+
end
|
31
|
+
# final sum
|
32
|
+
assign(sum[i] <= adders[i].sum)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
if $PROGRAM_NAME==__FILE__
|
38
|
+
pp adder=Adder.new(8)
|
39
|
+
end
|
data/examples/and.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require_relative 'ruby_rtl'
|
2
|
+
|
3
|
+
include RubyRTL
|
4
|
+
|
5
|
+
class And < Circuit
|
6
|
+
def initialize
|
7
|
+
input :a => :bit # optional type for single :bit
|
8
|
+
input :b # default is :bit
|
9
|
+
output 'f' # alternative syntax
|
10
|
+
|
11
|
+
comment("simple assignment")
|
12
|
+
|
13
|
+
assign(f <= a & b)
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
circuit=And.new
|
19
|
+
Compiler.new.compile(circuit)
|
data/examples/counter.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require_relative '../lib/ruby_rtl'
|
2
|
+
|
3
|
+
include RubyRTL
|
4
|
+
|
5
|
+
class Counter < Circuit
|
6
|
+
def initialize
|
7
|
+
input :do_count
|
8
|
+
output :count => :byte
|
9
|
+
|
10
|
+
sequential(:strange_counting){
|
11
|
+
If(do_count==1){
|
12
|
+
If(count==255){
|
13
|
+
assign(count <= 0)
|
14
|
+
}
|
15
|
+
Elsif(count==42){
|
16
|
+
assign(count <= count + 42)
|
17
|
+
}
|
18
|
+
Else{
|
19
|
+
assign(count <= count + 1)
|
20
|
+
}
|
21
|
+
}
|
22
|
+
}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
circuit=Counter.new
|
27
|
+
Compiler.new.compile(circuit)
|
data/examples/fsm.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require_relative '../lib/ruby_rtl.rb'
|
2
|
+
|
3
|
+
include RubyRTL
|
4
|
+
|
5
|
+
class FSM1 < Circuit
|
6
|
+
def initialize
|
7
|
+
input :go,:b
|
8
|
+
output :f => :bv2
|
9
|
+
|
10
|
+
fsm(:simple){
|
11
|
+
|
12
|
+
assign(f <= 0)
|
13
|
+
|
14
|
+
state(:s0){
|
15
|
+
assign(f <= 1)
|
16
|
+
If(go==1){
|
17
|
+
next_state :s1
|
18
|
+
}
|
19
|
+
}
|
20
|
+
|
21
|
+
state(:s1){
|
22
|
+
assign(f <= 2)
|
23
|
+
next_state :s2
|
24
|
+
}
|
25
|
+
|
26
|
+
state(:s2){
|
27
|
+
assign(f <= 3)
|
28
|
+
next_state :s0
|
29
|
+
}
|
30
|
+
}
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
circuit=FSM1.new
|
35
|
+
|
36
|
+
compiler=Compiler.new
|
37
|
+
compiler.compile(circuit)
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require_relative '../lib/ruby_rtl'
|
2
|
+
|
3
|
+
include RubyRTL
|
4
|
+
|
5
|
+
require_relative 'test_2_half_adder'
|
6
|
+
|
7
|
+
class FullAdder < Circuit
|
8
|
+
def initialize
|
9
|
+
input :a,:b,:cin
|
10
|
+
output :sum,:cout
|
11
|
+
|
12
|
+
component :ha1 => HalfAdder # class...
|
13
|
+
component :ha2 => HalfAdder.new # or ...obj
|
14
|
+
|
15
|
+
assign(ha1.a <= a )
|
16
|
+
assign(ha1.b <= b )
|
17
|
+
assign(ha2.a <= cin)
|
18
|
+
assign(ha2.b <= ha1.sum)
|
19
|
+
assign(sum <= ha1.sum)
|
20
|
+
assign(cout <= ha1.cout | ha1.cout)
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
if $PROGRAM_NAME == __FILE__
|
26
|
+
pp fa=FullAdder.new
|
27
|
+
end
|
data/examples/gcd.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
require_relative '../lib/ruby_rtl'
|
2
|
+
|
3
|
+
include RubyRTL
|
4
|
+
|
5
|
+
class Gcd < Circuit
|
6
|
+
def initialize
|
7
|
+
input :go
|
8
|
+
output :done
|
9
|
+
input :valid_a,:valid_b
|
10
|
+
input :a => :uint32
|
11
|
+
input :b => :uint32
|
12
|
+
output :f => :uint32
|
13
|
+
|
14
|
+
wire :va => :uint32
|
15
|
+
wire :vb => :uint32
|
16
|
+
|
17
|
+
fsm(:gcd){
|
18
|
+
state(:s0){
|
19
|
+
If(go==1){
|
20
|
+
next_state :s1
|
21
|
+
}
|
22
|
+
}
|
23
|
+
state(:s1){
|
24
|
+
If(valid_a==1){
|
25
|
+
assign(va <= a)
|
26
|
+
next_state :s2
|
27
|
+
}
|
28
|
+
}
|
29
|
+
state(:s2){
|
30
|
+
If(valid_b==1){
|
31
|
+
assign(vb <= b)
|
32
|
+
next_state :s3
|
33
|
+
}
|
34
|
+
}
|
35
|
+
state(:s3){
|
36
|
+
If(va != vb){
|
37
|
+
If(va > vb){
|
38
|
+
assign(va <= va - vb)
|
39
|
+
}
|
40
|
+
Else{
|
41
|
+
assign(vb <= vb - va)
|
42
|
+
}
|
43
|
+
}
|
44
|
+
Else{
|
45
|
+
assign(f <= va)
|
46
|
+
assign(done <= 1)
|
47
|
+
next_state(:s0)
|
48
|
+
}
|
49
|
+
}
|
50
|
+
}
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
circuit=Gcd.new
|
55
|
+
|
56
|
+
compiler=Compiler.new
|
57
|
+
compiler.compile(circuit)
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require_relative '../lib/ruby_rtl'
|
2
|
+
|
3
|
+
include RubyRTL
|
4
|
+
|
5
|
+
class HalfAdder < Circuit
|
6
|
+
def initialize
|
7
|
+
input :a,:b
|
8
|
+
output :sum
|
9
|
+
output :cout
|
10
|
+
|
11
|
+
assign(sum <= a ^ b) #xor
|
12
|
+
assign(cout <= a & b) #cout
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
if $PROGRAM_NAME == __FILE__
|
18
|
+
pp ha=HalfAdder.new
|
19
|
+
end
|
data/lib/ruby_rtl/ast.rb
ADDED
@@ -0,0 +1,353 @@
|
|
1
|
+
require_relative 'ast_builder'
|
2
|
+
# reopen native class
|
3
|
+
class Integer
|
4
|
+
def accept(visitor, arg=nil)
|
5
|
+
name = "Integer"
|
6
|
+
visitor.send("visit#{name}".to_sym, self ,arg) # Metaprograming !
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
module RubyRTL
|
11
|
+
|
12
|
+
class Circuit < ASTBuilder
|
13
|
+
attr_accessor :has_sequential_statements
|
14
|
+
end
|
15
|
+
|
16
|
+
class Ast
|
17
|
+
attr_accessor :comments
|
18
|
+
def accept(visitor, arg=nil)
|
19
|
+
name = self.class.name.split(/::/)[1]
|
20
|
+
visitor.send("visit#{name}".to_sym, self ,arg) # Metaprograming !
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class Root < Ast
|
25
|
+
#attr_accessor :ios,:decls,:body
|
26
|
+
attr_accessor :decls,:body
|
27
|
+
def initialize
|
28
|
+
@ios,@decls,@body=[],[],Body.new
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class Comment < Ast
|
33
|
+
attr_accessor :str
|
34
|
+
def initialize str
|
35
|
+
@str=str
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# further defined in dsl.rb
|
40
|
+
# attributes :
|
41
|
+
# - type
|
42
|
+
# - subscript_of
|
43
|
+
class Sig < Ast
|
44
|
+
end
|
45
|
+
|
46
|
+
class Port < Sig
|
47
|
+
end
|
48
|
+
|
49
|
+
class Input < Port
|
50
|
+
end
|
51
|
+
|
52
|
+
class Output < Port
|
53
|
+
end
|
54
|
+
|
55
|
+
class TypeDecl < Ast
|
56
|
+
attr_accessor :name,:definition
|
57
|
+
def initialize name,definition
|
58
|
+
@name,@definition=name,definition
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
class SigDecl < Ast
|
63
|
+
attr_accessor :name,:sig
|
64
|
+
def initialize name,sig
|
65
|
+
@name,@sig=name,sig
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
class CompDecl < Ast
|
70
|
+
attr_accessor :name,:comp
|
71
|
+
def initialize name,comp
|
72
|
+
@name,@comp=name,comp
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
class CircuitPart < Ast
|
77
|
+
attr_accessor :label,:body
|
78
|
+
def initialize label,body
|
79
|
+
@label,@body=label,body
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
class Combinatorial < CircuitPart
|
84
|
+
end
|
85
|
+
|
86
|
+
class Sequential < CircuitPart
|
87
|
+
end
|
88
|
+
|
89
|
+
# === statements ===
|
90
|
+
class Body < Ast
|
91
|
+
include Enumerable
|
92
|
+
attr_accessor :stmts
|
93
|
+
def initialize stmts=[]
|
94
|
+
@stmts=stmts
|
95
|
+
end
|
96
|
+
|
97
|
+
def <<(e)
|
98
|
+
@stmts << e
|
99
|
+
@stmts.flatten!
|
100
|
+
end
|
101
|
+
|
102
|
+
def each &block
|
103
|
+
stmts.each(&block)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
class Statement < Ast
|
108
|
+
end
|
109
|
+
|
110
|
+
class Assign < Statement
|
111
|
+
attr_accessor :lhs,:rhs
|
112
|
+
def initialize lhs,rhs
|
113
|
+
@lhs,@rhs=lhs,rhs
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
class If < Statement
|
118
|
+
attr_accessor :cond,:body
|
119
|
+
attr_accessor :elsifs # feeded by ContextualAnalyzer
|
120
|
+
attr_accessor :else # idem
|
121
|
+
def initialize cond, body=nil
|
122
|
+
@cond=cond
|
123
|
+
@body=body
|
124
|
+
@elsifs=[]
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
class Else < Statement
|
129
|
+
attr_accessor :body
|
130
|
+
def initialize body=nil
|
131
|
+
@body=body
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
class Elsif < Statement
|
136
|
+
attr_accessor :cond,:body
|
137
|
+
def initialize cond, body=nil
|
138
|
+
@cond,@body=cond,body
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
# === FSM ===
|
143
|
+
class Fsm < Ast
|
144
|
+
attr_accessor :name,:body
|
145
|
+
attr_accessor :states # hash
|
146
|
+
attr_accessor :default_assigns
|
147
|
+
attr_accessor :assignments
|
148
|
+
def initialize name,body=nil
|
149
|
+
@name,@body=name,body
|
150
|
+
@default_assigns=[] # external to states structures
|
151
|
+
@assignments=[] # to generate VHDL
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
class State < Ast
|
156
|
+
attr_accessor :name,:body
|
157
|
+
def initialize name,body=nil
|
158
|
+
@name,@body=name,body
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
class Next < Ast
|
163
|
+
attr_accessor :name
|
164
|
+
def initialize name
|
165
|
+
@name=name
|
166
|
+
end
|
167
|
+
end
|
168
|
+
# case / switch
|
169
|
+
class Case < Ast
|
170
|
+
attr_accessor :cond,:body
|
171
|
+
def initialize condition,body=nil
|
172
|
+
@cond,@body=condition,body
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
class When < Ast
|
177
|
+
attr_accessor :value,:body
|
178
|
+
def initialize value,body
|
179
|
+
@value,@body=value,body
|
180
|
+
end
|
181
|
+
end
|
182
|
+
# === expressions ===
|
183
|
+
class Expr < Ast
|
184
|
+
attr_accessor :type
|
185
|
+
end
|
186
|
+
|
187
|
+
class Binary < Expr
|
188
|
+
attr_accessor :lhs,:op,:rhs
|
189
|
+
def initialize lhs,op,rhs
|
190
|
+
@lhs,@op,@rhs=lhs,op,rhs
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
class Unary < Expr
|
195
|
+
end
|
196
|
+
|
197
|
+
# func call
|
198
|
+
class FuncCall < Expr
|
199
|
+
attr_accessor :name,:args
|
200
|
+
def initialize name,args=[]
|
201
|
+
@name,@args=name,args
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
|
206
|
+
# ====== literals ===
|
207
|
+
class Literal < Ast
|
208
|
+
attr_accessor :val
|
209
|
+
attr_accessor :type
|
210
|
+
|
211
|
+
def initialize val,type=nil
|
212
|
+
@val,@type=val,type
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
class BitLit < Literal
|
217
|
+
end
|
218
|
+
|
219
|
+
class IntLit < Literal
|
220
|
+
def initialize val
|
221
|
+
val=val==0 ? 1 : val
|
222
|
+
bitwidth=Math.log2(val).floor+1
|
223
|
+
super(val,IntType.new)
|
224
|
+
end
|
225
|
+
|
226
|
+
def +(other)
|
227
|
+
ret=Binary.new(self,"+",other)
|
228
|
+
ret.type=@type
|
229
|
+
ret
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
class UIntLit < Literal
|
234
|
+
def initialize val
|
235
|
+
val=val==0 ? 1 : val
|
236
|
+
bitwidth=Math.log2(val).floor+1
|
237
|
+
super(val,UIntType.new(bitwidth))
|
238
|
+
end
|
239
|
+
|
240
|
+
def +(other)
|
241
|
+
ret=Binary.new(self,"+",other)
|
242
|
+
ret.type=@type
|
243
|
+
ret
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
class RIntLit < Literal
|
248
|
+
def initialize val
|
249
|
+
val=val==0 ? 1 : val
|
250
|
+
bitwidth=Math.log2(val).floor + 1
|
251
|
+
super(val,RIntType.new(bitwidth))
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
class RUIntLit < Literal
|
256
|
+
def initialize val
|
257
|
+
val=val==0 ? 1 : val
|
258
|
+
nbits=Math.log2(val).floor + 1
|
259
|
+
super(val,RUIntType.new(nbits))
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
# ====== types ======
|
264
|
+
class Type < Ast
|
265
|
+
end
|
266
|
+
|
267
|
+
class BitType < Type
|
268
|
+
def to_s
|
269
|
+
"bit"
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
class BitVectorType < Type
|
274
|
+
attr_accessor :bitwidth
|
275
|
+
def initialize bitwidth
|
276
|
+
@bitwidth=bitwidth
|
277
|
+
end
|
278
|
+
def to_s
|
279
|
+
"bv#{bitwidth}"
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
class RType < Type
|
284
|
+
attr_accessor :bitwidth
|
285
|
+
def initialize bitwidth
|
286
|
+
@bitwidth=bitwidth
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
class RIntType < RType # Ruby Int !
|
291
|
+
def to_s
|
292
|
+
"rint#{bitwidth}"
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
class RUIntType < RType # Ruby Int !
|
297
|
+
def to_s
|
298
|
+
"ruint#{bitwidth}"
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
class IntType < Type
|
303
|
+
attr_accessor :bitwidth
|
304
|
+
def initialize nbits=32
|
305
|
+
@bitwidth=nbits
|
306
|
+
end
|
307
|
+
|
308
|
+
def to_s
|
309
|
+
"int#{bitwidth}"
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
class UIntType < Type
|
314
|
+
attr_accessor :bitwidth
|
315
|
+
def initialize nbits
|
316
|
+
@bitwidth=nbits
|
317
|
+
end
|
318
|
+
|
319
|
+
def to_s
|
320
|
+
"uint#{bitwidth}"
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
class EnumType < Type
|
325
|
+
attr_accessor :items
|
326
|
+
def initialize items
|
327
|
+
@items=items
|
328
|
+
end
|
329
|
+
end
|
330
|
+
|
331
|
+
class RecordType < Type
|
332
|
+
attr_accessor :hash
|
333
|
+
def initialize h
|
334
|
+
@hash=h
|
335
|
+
end
|
336
|
+
|
337
|
+
def to_s
|
338
|
+
if (values=$typedefs.values).include?(self)
|
339
|
+
idx=values.index(self)
|
340
|
+
name=$typedefs.keys[idx]
|
341
|
+
"§#{name}"
|
342
|
+
end
|
343
|
+
end
|
344
|
+
end
|
345
|
+
|
346
|
+
class MemoryType < Type
|
347
|
+
attr_accessor :size,:type
|
348
|
+
def initialize size,type
|
349
|
+
@size,@type=size,type
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
end
|