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.
@@ -0,0 +1,267 @@
1
+ require_relative 'code'
2
+ require_relative 'visitor'
3
+
4
+ module RubyRTL
5
+
6
+ class DSLPrinter < Visitor
7
+
8
+ def print circuit
9
+ code=Code.new
10
+ code << "# code generated by DSL printer"
11
+ if root=circuit.ast
12
+ code << "circuit #{circuit.name}"
13
+ #root.ios.each{|io| code << io.accept(self)}
14
+ root.decls.each{|decl| code << decl.accept(self)}
15
+ code << root.body.accept(self)
16
+ puts code.finalize
17
+ end
18
+ end
19
+
20
+ def visitComment node,args=nil
21
+ end
22
+
23
+ def visitSig sig,args=nil
24
+ sig.name
25
+ end
26
+
27
+ def visitInput input,args=nil
28
+ input.name
29
+ end
30
+
31
+ def visitOutput output,args=nil
32
+ output.name
33
+ end
34
+
35
+ def visitTypeDecl decl,args=nil
36
+ definition=decl.definition.accept(self)
37
+ return "typedef #{decl.name} => #{definition}"
38
+ end
39
+
40
+ def visitSigDecl decl,args=nil
41
+ name=(sig=decl.sig).accept(self)
42
+ type=sig.type.accept(self)
43
+ if (values=$typedefs.values).include?(sig.type)
44
+ idx=values.index(sig.type)
45
+ type=$typedefs.keys[idx]
46
+ end
47
+ case sig
48
+ when Input
49
+ kind="input "
50
+ when Output
51
+ kind="output"
52
+ when Sig
53
+ kind="wire"
54
+ end
55
+ "#{kind} #{name} => #{type}"
56
+ end
57
+
58
+ def visitCompDecl decl,args=nil
59
+ "component #{decl.name} => #{decl.comp}"
60
+ end
61
+
62
+ def visitCombinatorial comb,args=nil
63
+ body=comb.body.accept(self)
64
+ code=Code.new
65
+ code << "combinatorial(#{comb.label}){"
66
+ code.indent=2
67
+ code << body
68
+ code.indent=0
69
+ code << "}"
70
+ code
71
+ end
72
+
73
+ def visitSequential seq,args=nil
74
+ body=seq.body.accept(self)
75
+ code=Code.new
76
+ code << "sequential(#{seq.label}){"
77
+ code.indent=2
78
+ code << body
79
+ code.indent=0
80
+ code << "}"
81
+ code
82
+ end
83
+
84
+ # === statements
85
+ def visitBody body,args=nil
86
+ code=Code.new
87
+ body.each{|stmt| code << stmt.accept(self,args)}
88
+ code
89
+ end
90
+
91
+ def visitAssign node,args=nil
92
+ lhs=node.lhs.accept(self)
93
+ rhs=node.rhs.accept(self)
94
+ "assign(#{lhs} <= #{rhs})"
95
+ end
96
+
97
+ def visitIf node,args=nil
98
+ cond=node.cond.accept(self)
99
+ body=node.body.accept(self)
100
+ elsifs_=Code.new
101
+ node.elsifs.collect{|elsif_| elsifs_ << elsif_.accept(self)}
102
+ else_=node.else.accept(self) if node.else
103
+ code=Code.new
104
+ code << "if #{cond}{"
105
+ code.indent=2
106
+ code << body
107
+ code.indent=0
108
+ if elsifs_.size>0 or node.else
109
+ code << "}"
110
+ end
111
+ code << elsifs_
112
+ code << else_ if node.else
113
+ code << "}" unless node.else or elsifs_.size>0
114
+ code
115
+ end
116
+
117
+ def visitElse else_,args=nil
118
+ body=else_.body.accept(self)
119
+ code=Code.new
120
+ code << "else {"
121
+ code.indent=2
122
+ code << body
123
+ code.indent=0
124
+ code << "}"
125
+ code
126
+ end
127
+
128
+ def visitElsif elsif_,args=nil
129
+ cond=elsif_.cond.accept(self)
130
+ body=elsif_.body.accept(self)
131
+ code=Code.new
132
+ code << "elsif #{cond}{"
133
+ code.indent=2
134
+ code << body
135
+ code.indent=0
136
+ code << "}"
137
+ code
138
+ end
139
+
140
+ # === fsm
141
+ def visitFsm fsm,args=nil
142
+ code=Code.new
143
+ code << "fsm(#{fsm.name}){"
144
+ code.indent=2
145
+ code << fsm.body.accept(self)
146
+ code.indent=0
147
+ code << "}"
148
+ code
149
+ end
150
+
151
+ def visitState state,args=nil
152
+ code=Code.new
153
+ code << "state(#{state.name}){"
154
+ code.indent=2
155
+ code << state.body.accept(self)
156
+ code.indent=0
157
+ code << "}"
158
+ code
159
+ end
160
+
161
+ def visitNext node,args=nil
162
+ "next_state #{node.name}"
163
+ end
164
+
165
+ # === expr ===
166
+ def visitBinary node,args=nil
167
+ lhs=node.lhs.accept(self)
168
+ op=node.op
169
+ rhs=node.rhs.accept(self)
170
+ "(#{lhs} #{op} #{rhs})"
171
+ end
172
+
173
+ def visitUnary node,args=nil
174
+ expr=node.expr.accept(self)
175
+ "(#{node.op} #{expr})"
176
+ end
177
+
178
+ def visitFuncCall func,args=nil
179
+ name=func.name
180
+ argus=func.args.collect{|arg| arg.accept(self)}.join(',')
181
+ "#{name}(#{argus})"
182
+ end
183
+
184
+ def visitIndexed indexed,args=nil
185
+ lhs=indexed.lhs.accept(self)
186
+ rhs=indexed.rhs.accept(self)
187
+ "#{lhs}[#{rhs}]"
188
+ end
189
+
190
+ # === literals ===
191
+ def visitLiteral node,args=nil
192
+ node.val
193
+ end
194
+
195
+ def visitBitLit node,args=nil
196
+ node.super.accept(self)
197
+ end
198
+
199
+ def visitIntLit lit,args=nil
200
+ lit.val
201
+ end
202
+
203
+ def visitUIntLit lit,args=nil
204
+ lit.val
205
+ end
206
+
207
+ def visitRIntLit lit,args=nil
208
+ lit.val
209
+ end
210
+
211
+ def visitRUIntLit lit,args=nil
212
+ lit.val
213
+ end
214
+ # === types ===
215
+
216
+ def visitBitType node,args=nil
217
+ "bit"
218
+ end
219
+
220
+ def visitBitVectorType bvt,args=nil
221
+ "bv#{bvt.bitwidth}"
222
+ end
223
+
224
+ def visitIntType node,args=nil
225
+ "int#{node.bitwidth}"
226
+ end
227
+
228
+ def visitRIntType node,args=nil
229
+ "rint#{node.bitwidth}"
230
+ end
231
+
232
+ def visitRUintType node,args=nil
233
+ "ruint#{node.bitwidth}"
234
+ end
235
+
236
+ def visitUIntType node,args=nil
237
+ "uint#{node.bitwidth}"
238
+ end
239
+
240
+ def visitRecordType rec_type,args=nil
241
+ items=[]
242
+ rec_type.hash.each{|item,type|
243
+ items << "#{item} => #{type}"
244
+ }
245
+ "Record(#{items.join(",")})"
246
+ end
247
+
248
+ def visitEnumType enum_type,args=nil
249
+ "Enum(#{enum_type.items.join(",")})"
250
+ end
251
+
252
+ def visitMemoryType mem_type,args=nil
253
+ typename=mem_type.type
254
+ "Memory(#{mem_type.size},#{typename})"
255
+ end
256
+
257
+ def visitCase case_,args=nil
258
+ code=Code.new
259
+ code << "Case(){"
260
+ code.indent=2
261
+ code << case_.body.accept(self)
262
+ code.indent=0
263
+ code << "}"
264
+ code
265
+ end
266
+ end
267
+ end
@@ -0,0 +1,77 @@
1
+ library ieee;
2
+ use ieee.std_logic_1164.all;
3
+ use ieee.numeric_std.all;
4
+
5
+ package ruby_rtl_package is
6
+
7
+ function to_bit( v:integer ; n:natural) return std_logic;
8
+
9
+ function to_uint(v:std_logic; n:natural) return unsigned;
10
+
11
+ function to_int( v:std_logic; n:natural) return signed;
12
+ function to_int( v:integer ; n:natural) return signed;
13
+ function to_int(v : signed; n:natural) return signed;
14
+
15
+ function to_bv(v: unsigned;n : natural) return std_logic_vector;
16
+ function to_bv(v: integer ;n : natural) return std_logic_vector;
17
+
18
+ end package;
19
+
20
+ package body ruby_rtl_package is
21
+
22
+ function to_bit(v:integer;n:natural) return std_logic is
23
+ begin
24
+ if v=0 then
25
+ return '0';
26
+ else
27
+ return '1';
28
+ end if;
29
+ end function;
30
+
31
+ function to_uint(v : std_logic; n:natural) return unsigned is
32
+ variable ret : unsigned(n-1 downto 0) := (others=>'0');
33
+ begin
34
+ ret(0):=v;
35
+ return ret;
36
+ end function;
37
+
38
+ function to_int(v : std_logic; n:natural) return signed is
39
+ variable ret : signed(n-1 downto 0) := (others=>'0');
40
+ begin
41
+ ret(0):=v;
42
+ return ret;
43
+ end function;
44
+
45
+ function to_int(v : integer; n:natural) return signed is
46
+ variable ret : signed(n-1 downto 0) := (others=>'0');
47
+ begin
48
+ ret:=to_signed(v,n);
49
+ return ret;
50
+ end function;
51
+
52
+ function to_int(v : signed; n:natural) return signed is
53
+ variable ret : signed(n-1 downto 0) := (others=>'0');
54
+ begin
55
+ ret:=resize(v,n);
56
+ return ret;
57
+ end function;
58
+
59
+ function to_bv(v: unsigned;n : natural) return std_logic_vector is
60
+ variable resize_v : unsigned(n-1 downto 0);
61
+ variable tmp : std_logic_vector(n-1 downto 0);
62
+ begin
63
+ resize_v:=resize(v,n);
64
+ tmp := std_logic_vector(resize_v);
65
+ return tmp;
66
+ end function;
67
+
68
+ function to_bv(v: integer ;n : natural) return std_logic_vector is
69
+ variable s1 : signed(n-1 downto 0);
70
+ variable tmp : std_logic_vector(n-1 downto 0);
71
+ begin
72
+ s1:=to_signed(v,n);
73
+ tmp:=std_logic_vector(s1);
74
+ return tmp;
75
+ end function;
76
+
77
+ end package body;
@@ -0,0 +1,132 @@
1
+ require_relative 'code'
2
+
3
+ module RubyRTL
4
+
5
+ class SexpGenerator < DSLPrinter
6
+
7
+ def generate circuit
8
+ puts "[+] S-exp code generation"
9
+ root=circuit.ast
10
+ code=Code.new
11
+ code << "(circuit #{circuit.name}"
12
+ code.indent=2
13
+ root.decls.each{|decl| code << decl.accept(self)}
14
+ code << root.body.accept(self)
15
+ code.indent=0
16
+ code << ")"
17
+ puts code.finalize
18
+ end
19
+
20
+ def visitSigDecl sig_decl,args=nil
21
+ name=sig_decl.name
22
+ type=sig_decl.sig.type.accept(self)
23
+ "(input #{name} #{type})"
24
+ end
25
+
26
+ # statements
27
+ def visitBody body,args=nil
28
+ code=Code.new
29
+ body.each{|stmt| code << stmt.accept(self)}
30
+ code
31
+ end
32
+
33
+ def visitAssign assign,args=nil
34
+ lhs=assign.lhs.accept(self)
35
+ rhs=assign.rhs.accept(self)
36
+ "(assign #{lhs} #{rhs})"
37
+ end
38
+
39
+ def visitIf if_,args=nil
40
+ code=Code.new
41
+ cond=if_.cond.accept(self)
42
+ code << "(if #{cond}"
43
+ code.indent=2
44
+ code << "(then"
45
+ code.indent=4
46
+ code << if_.body.accept(self)
47
+ code.indent=2
48
+ code << ")"
49
+ code.indent=0
50
+ code << ")"
51
+ code
52
+ end
53
+
54
+ # fsm
55
+ def visitFsm fsm,args=nil
56
+ code=Code.new
57
+ code << "(fsm #{fsm.name}"
58
+ code.indent=2
59
+ fsm.states.each{|state| code << state.accept(self)}
60
+ code.indent=0
61
+ code << ")"
62
+ code
63
+ end
64
+
65
+ def visitState state,args=nil
66
+ code=Code.new
67
+ code << "(state #{state.name}"
68
+ code.indent=2
69
+ code << state.body.accept(self)
70
+ code.indent=0
71
+ code << ")"
72
+ code
73
+ end
74
+
75
+ def visitNext node,args=nil
76
+ "(next_state #{node.name})"
77
+ end
78
+
79
+ # === expr ===
80
+ def visitBinary node,args=nil
81
+ lhs=node.lhs.accept(self)
82
+ op=node.op
83
+ rhs=node.rhs.accept(self)
84
+ "(#{op} #{lhs} #{rhs})"
85
+ end
86
+
87
+ def visitUnary node,args=nil
88
+ expr=node.expr.accept(self)
89
+ "(#{node.op} #{expr})"
90
+ end
91
+
92
+ def visitFuncCall func,args=nil
93
+ name=func.name
94
+ argus=func.args.collect{|arg| arg.accept(self)}.join(" ")
95
+ "(call #{name} #{argus})"
96
+ end
97
+
98
+ def visitIndexed indexed,args=nil
99
+ lhs=indexed.lhs.accept(self)
100
+ rhs=indexed.rhs.accept(self)
101
+ "(indexed #{lhs} #{rhs})"
102
+ end
103
+
104
+
105
+ def visitRecordType rec_type,args=nil
106
+ items=[]
107
+ rec_type.hash.each{|item,type|
108
+ items << "#{item} => #{type}"
109
+ }
110
+ "Record(#{items.join(",")})"
111
+ end
112
+
113
+ def visitEnumType enum_type,args=nil
114
+ "Enum(#{enum_type.items.join(",")})"
115
+ end
116
+
117
+ def visitMemoryType mem_type,args=nil
118
+ typename=mem_type.type
119
+ "Memory(#{mem_type.size},#{typename})"
120
+ end
121
+
122
+ def visitCase case_,args=nil
123
+ code=Code.new
124
+ code << "Case(){"
125
+ code.indent=2
126
+ code << case_.body.accept(self)
127
+ code.indent=0
128
+ code << "}"
129
+ code
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,209 @@
1
+ require_relative 'code'
2
+ require_relative 'visitor'
3
+
4
+ module RubyRTL
5
+ class TypeChecker < Visitor
6
+ def initialize
7
+ @ppr=DSLPrinter.new
8
+ end
9
+
10
+ def check circuit
11
+ puts "[+] type checking"
12
+ root=circuit.ast
13
+ if root=circuit.ast
14
+ #root.ios.each{|io| io.accept(self)}
15
+ root.decls.each{|decl| decl.accept(self)}
16
+ root.body.accept(self)
17
+ end
18
+ end
19
+
20
+ def cast t1,t2
21
+ pair=[t1.class,t2.class]
22
+ cast=nil
23
+ case pair
24
+ when [BitType,BitType]
25
+ when [BitType,UIntType]
26
+ cast=[:to_bit,1]
27
+ when [BitType,IntType]
28
+ cast=[:to_bit,1]
29
+
30
+ when [BitType,RUIntType]
31
+ cast=[:to_bit,1]
32
+
33
+ when [IntType,BitType]
34
+ cast=[:to_bit,1]
35
+ when [IntType,IntType]
36
+ if t1.bitwidth==t2.bitwidth
37
+ return #nothing to do
38
+ else
39
+ cast=[:to_int,t1.bitwidth]
40
+ end
41
+ when [IntType,UIntType]
42
+ unless t1.bitwidth==t2.bitwidth
43
+ cast=[:to_int,t1.bitwidth]
44
+ end
45
+ when [IntType,RUIntType]
46
+ unless t1.bitwidth == t2.bitwidth
47
+ cast=[:to_int,t1.bitwidth]
48
+ end
49
+ when [UIntType,BitType]
50
+ cast=[:to_uint,t1.bitwidth]
51
+ when [UIntType,RIntType]
52
+ cast=[:to_uint,t1.bitwidth]
53
+ when [UIntType,RUIntType]
54
+ cast=[:to_uint,t1.bitwidth]
55
+
56
+ when [UIntType,IntType]
57
+ u_bw,s_bw=t1.bitwidth,t2.bitwidth
58
+ cast=[:to_uint,u_bw]
59
+ when [UIntType,UIntType]
60
+ if t1.bitwidth==t2.bitwidth
61
+ return #nothing to do
62
+ else
63
+ cast=[:to_uint,t1.bitwidth]
64
+ end
65
+ #============ bit vector =============
66
+ when [BitVectorType,UIntType]
67
+ cast=[:to_bv,t1.bitwidth]
68
+ when [BitVectorType,RUIntType]
69
+ cast=[:to_bv,t1.bitwidth]
70
+ when [RecordType,RecordType]
71
+ else
72
+ raise "NIY cast #{pair}"
73
+ end
74
+ return cast
75
+ end
76
+
77
+ def visitAssign assign,args=nil
78
+ puts "- assign : #{assign.accept(@ppr)}"
79
+ lhs=assign.lhs.accept(self)
80
+ rhs=assign.rhs.accept(self)
81
+ puts "\ttypes : #{lhs.to_s} <= #{rhs.to_s}"
82
+ cast_func=cast(lhs,rhs)
83
+ if cast_func
84
+ name,bw=*cast_func
85
+ assign.rhs=FuncCall.new(name,[assign.rhs,bw])
86
+ end
87
+ end
88
+
89
+ def homogenize t1,op,t2
90
+ pair=[t1.class,t2.class]
91
+ conv=[nil,nil,t1]
92
+ case pair
93
+ when [BitType,BitType]
94
+ unless ["&","|","^"].include?(op)
95
+ raise "illegal operation '#{op}' between 2 bits"
96
+ end
97
+ when [BitType,UIntType]
98
+ conv=[["to_uint",t2.bitwidth],nil,t2]
99
+ when [BitType,IntType]
100
+ conv=[["to_int",t2.bitwidth],nil,t2]
101
+ when [BitType,RIntType]
102
+ conv=[["to_int",t2.bitwidth],nil,t2]
103
+ when [BitType,RUIntType]
104
+ conv=[["to_uint",t2.bitwidth],nil,t2]
105
+
106
+ when [IntType,BitType]
107
+ conv=[nil,["to_int",t1.bitwidth],t1]
108
+ when [IntType,IntType]
109
+ unless t1.bitwidth==t2.bitwidth
110
+ max=[t1.bitwidth,t2.bitwidth].max
111
+ if t1==max
112
+ conv=[nil,["to_int",max],t1]
113
+ else
114
+ conv=[["to_int",max],nil,t2]
115
+ end
116
+ end
117
+ when [IntType,UIntType]
118
+ max=[t1.bitwidth,t2.bitwidth].max
119
+ if t1==max
120
+ conv=[nil,["to_int",max],t1]
121
+ else
122
+ conv=[["to_uint",max],nil,t2]
123
+ end
124
+ when [IntType,RUIntType]
125
+ unless t1.bitwidth >= t2.bitwidth # note >=
126
+ max=[t1.bitwidth,t2.bitwidth].max
127
+ if t1==max
128
+ conv=[nil,["to_int",max],t1]
129
+ else
130
+ conv=[["to_int",max],nil,t2]
131
+ end
132
+ end
133
+ when [UIntType,BitType]
134
+ conv=[nil,["to_uint",t1.bitwidth],t1]
135
+ when [UIntType,IntType]
136
+ u_bw,s_bw=t1.bitwidth,t2.bitwidth
137
+ max=[u_bw,s_bw].max
138
+ type=IntType.new(max)
139
+ conv=[["to_int",max],["to_int",max],type]
140
+ when [UIntType,UIntType]
141
+ unless t1.bitwidth==t2.bitwidth
142
+ max=[t1.bitwidth,t2.bitwidth].max
143
+ if t1==max
144
+ conv=[nil,["to_uint",max],t1]
145
+ else
146
+ conv=[["to_uint",max],nil,t2]
147
+ end
148
+ end
149
+ when [RecordType,RecordType]
150
+ else
151
+ raise "NIY homogenize #{pair}"
152
+ end
153
+ pp conv
154
+ return conv
155
+ end
156
+
157
+ def visitBinary bin,args=nil
158
+ puts "- binary #{bin.accept(@ppr)}"
159
+ lhs_t=bin.lhs.accept(self)
160
+ rhs_t=bin.rhs.accept(self)
161
+ puts "\ttypes : #{lhs_t} #{bin.op} #{rhs_t}"
162
+ conv_funcs=homogenize(lhs_t,bin.op,rhs_t)
163
+ pp conv_funcs
164
+ if conv=conv_funcs[0]
165
+ name,bitwidth=*conv
166
+ bin.lhs=FuncCall.new(name,[bin.lhs,bitwidth])
167
+ end
168
+ if conv=conv_funcs[1]
169
+ name,bitwidth=*conv
170
+ bin.rhs=FuncCall.new(name,[bin.rhs,bitwidth])
171
+ end
172
+ bin.type=conv_funcs[2]
173
+ end
174
+
175
+ def visitSig sig,args=nil
176
+ sig.type
177
+ end
178
+
179
+ def visitIndexed indexed, args=nil
180
+ indexed.type
181
+ end
182
+
183
+ def visitInput input,args=nil
184
+ input.type
185
+ end
186
+
187
+ def visitOutput output,args=nil
188
+ output.type
189
+ end
190
+
191
+ # literals
192
+ def visitIntLit lit,args=nil
193
+ lit.type
194
+ end
195
+
196
+ def visitUIntLit lit,args=nil
197
+ lit.type
198
+ end
199
+
200
+ def visitRIntLit lit,args=nil
201
+ lit.type
202
+ end
203
+
204
+ def visitRUIntLit lit,args=nil
205
+ lit.type
206
+ end
207
+
208
+ end
209
+ end
@@ -0,0 +1,3 @@
1
+ module RubyRTL
2
+ VERSION="0.0.1"
3
+ end