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
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
|