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