ruby_rtl 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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