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