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,183 @@
|
|
1
|
+
module RubyRTL
|
2
|
+
|
3
|
+
class ASTBuilder
|
4
|
+
|
5
|
+
attr_accessor :ast
|
6
|
+
|
7
|
+
# no 'initialize' :
|
8
|
+
# - @ast is not initialized here
|
9
|
+
# - this allows to avoid calling "super" in every circuit.
|
10
|
+
#
|
11
|
+
# - dont forget the parenthesis !
|
12
|
+
|
13
|
+
def input *arg
|
14
|
+
@ast||=Root.new
|
15
|
+
process_sig_decl(:input,*arg)
|
16
|
+
end
|
17
|
+
|
18
|
+
def output *arg
|
19
|
+
@ast||=Root.new
|
20
|
+
@last=@ast
|
21
|
+
process_sig_decl(:output,*arg)
|
22
|
+
end
|
23
|
+
|
24
|
+
# define a type
|
25
|
+
def typedef h
|
26
|
+
@ast||=Root.new
|
27
|
+
@last=@ast
|
28
|
+
name_sym,definition=h.first
|
29
|
+
@ast.decls << decl=TypeDecl.new(name_sym,definition)
|
30
|
+
@last=decl
|
31
|
+
$typedefs||={} # Global var !
|
32
|
+
$typedefs[name_sym]=definition
|
33
|
+
decl
|
34
|
+
end
|
35
|
+
|
36
|
+
def wire *arg
|
37
|
+
process_sig_decl(:sig,*arg)
|
38
|
+
end
|
39
|
+
|
40
|
+
alias :signal :wire
|
41
|
+
|
42
|
+
def comment str
|
43
|
+
(@last.comments||=[]) << Comment.new(str)
|
44
|
+
end
|
45
|
+
|
46
|
+
def component name_obj_or_class_h
|
47
|
+
comp_name,obj_or_klass=name_obj_or_class_h.first
|
48
|
+
comp_name=comp_name.to_sym if comp_name.is_a? String
|
49
|
+
case klass=comp=obj_or_klass
|
50
|
+
when Class
|
51
|
+
comp=klass.new # but no parameters :-(
|
52
|
+
end
|
53
|
+
cname="@#{comp_name}"
|
54
|
+
instance_variable_set(cname,comp)
|
55
|
+
self.class.__send__(:attr_accessor, comp_name)
|
56
|
+
@ast.body << CompDecl.new(comp_name,comp)
|
57
|
+
comp
|
58
|
+
end
|
59
|
+
|
60
|
+
# syntax : ASSIGN( y <= e), instead of ASSIGN(y,e)
|
61
|
+
def assign(var_expr_leq)
|
62
|
+
@ast||=Root.new
|
63
|
+
var,expr=var_expr_leq.lhs,var_expr_leq.rhs
|
64
|
+
@ast.body << Assign.new(var,expr)
|
65
|
+
end
|
66
|
+
|
67
|
+
def differential_ast &block
|
68
|
+
before=@ast.body.stmts.clone
|
69
|
+
instance_eval(&block)
|
70
|
+
after=@ast.body.stmts
|
71
|
+
diff=after-before
|
72
|
+
@ast.body.stmts=before
|
73
|
+
return diff
|
74
|
+
end
|
75
|
+
|
76
|
+
def If(cond,&block)
|
77
|
+
diff=differential_ast(&block)
|
78
|
+
@ast.body << If.new(cond,Body.new(diff))
|
79
|
+
end
|
80
|
+
|
81
|
+
def Elsif(cond,&block)
|
82
|
+
diff=differential_ast(&block)
|
83
|
+
@ast.body << Elsif.new(cond,Body.new(diff))
|
84
|
+
end
|
85
|
+
|
86
|
+
def Else(&block)
|
87
|
+
diff=differential_ast(&block)
|
88
|
+
@ast.body << Else.new(Body.new(diff))
|
89
|
+
end
|
90
|
+
|
91
|
+
# here, we need a trick to evaluate the block.
|
92
|
+
# we ask the current ast builder object to evaluate
|
93
|
+
# the block, in its current context.
|
94
|
+
# We then try to find the difference between ast before and after
|
95
|
+
# the evaluation.
|
96
|
+
def combinatorial(label=nil,&block)
|
97
|
+
diff=differential_ast(&block)
|
98
|
+
@ast.body << Combinatorial.new(name,Body.new(diff))
|
99
|
+
end
|
100
|
+
|
101
|
+
alias :comb :combinatorial
|
102
|
+
|
103
|
+
def sequential(label=nil,&block)
|
104
|
+
@has_sequential_statements=true
|
105
|
+
diff=differential_ast(&block)
|
106
|
+
@ast.body << Sequential.new(label,Body.new(diff))
|
107
|
+
end
|
108
|
+
|
109
|
+
alias :seq :sequential
|
110
|
+
|
111
|
+
def name
|
112
|
+
self.class.to_s
|
113
|
+
end
|
114
|
+
# === fsm stuff
|
115
|
+
def fsm name, &block
|
116
|
+
@has_sequential_statements=true
|
117
|
+
diff=differential_ast(&block)
|
118
|
+
@ast.body << Fsm.new(name,Body.new(diff))
|
119
|
+
end
|
120
|
+
|
121
|
+
def state name, &block
|
122
|
+
@has_sequential_statements=true
|
123
|
+
diff=differential_ast(&block)
|
124
|
+
@ast.body << State.new(name,Body.new(diff))
|
125
|
+
end
|
126
|
+
|
127
|
+
def next_state name
|
128
|
+
@ast.body << Next.new(name)
|
129
|
+
end
|
130
|
+
|
131
|
+
private
|
132
|
+
def process_sig_decl kind,*arg
|
133
|
+
case arg
|
134
|
+
when String
|
135
|
+
decl_sig(kind,vname=arg.to_sym,type=:bit)
|
136
|
+
when Symbol
|
137
|
+
decl_sig(kind,vname=arg,type=:bit)
|
138
|
+
when Array
|
139
|
+
# strange ! recursivity seems to fail
|
140
|
+
# output(element) # FAILS.
|
141
|
+
arg.each do |element|
|
142
|
+
case element
|
143
|
+
when String
|
144
|
+
decl_sig(kind,vname=element.to_sym,type=:bit)
|
145
|
+
when Symbol
|
146
|
+
decl_sig(kind,vname=element,type=:bit)
|
147
|
+
when Hash
|
148
|
+
element.each do |vname,type|
|
149
|
+
decl_sig(kind,vname,type)
|
150
|
+
end
|
151
|
+
else
|
152
|
+
"ERROR : wrong output declaration in list : '#{arg}'"
|
153
|
+
end
|
154
|
+
end
|
155
|
+
when Record
|
156
|
+
decl_sig(:input,vname=arg,type)
|
157
|
+
else
|
158
|
+
raise "ERROR : wrong input declaration '#{arg}'"
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def decl_sig kind,vname_sym,type=:bit
|
163
|
+
@ast||=Root.new
|
164
|
+
klass=Object.const_get(kind.capitalize)
|
165
|
+
io=klass.new(vname_sym,type)
|
166
|
+
vname="@#{vname_sym}"
|
167
|
+
instance_variable_set(vname, io)
|
168
|
+
self.class.__send__(:attr_accessor, vname_sym)
|
169
|
+
@ast.decls << sig=SigDecl.new(vname_sym.to_s,io)
|
170
|
+
sig
|
171
|
+
end
|
172
|
+
|
173
|
+
def Case(arg,&block)
|
174
|
+
diff=differential_ast(&block)
|
175
|
+
@ast.body << Case.new(arg,Body.new(diff))
|
176
|
+
end
|
177
|
+
|
178
|
+
def When(arg,&block)
|
179
|
+
diff=differential_ast(&block)
|
180
|
+
@ast.body << When.new(arg,Body.new(diff))
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module RubyRTL
|
2
|
+
|
3
|
+
class ASTPrinter
|
4
|
+
|
5
|
+
attr_accessor :code,:nodes_decl,:nodes_cnx
|
6
|
+
|
7
|
+
def run ast,suffix=nil
|
8
|
+
puts "[+] printing ast in dot file"
|
9
|
+
@verbose=false
|
10
|
+
@nodes_decl=Code.new
|
11
|
+
@nodes_cnx=Code.new
|
12
|
+
@printed_cnx={} #Cosmetic ! to keep track of already printed cnx source->sink
|
13
|
+
@code=Code.new
|
14
|
+
code << "digraph G {"
|
15
|
+
code.indent=2
|
16
|
+
code << "ordering=out;"
|
17
|
+
code << "ranksep=.4;"
|
18
|
+
code << "bgcolor=\"lightgrey\";"
|
19
|
+
code.newline
|
20
|
+
code << "node [shape=box, fixedsize=false, fontsize=12, fontname=\"Helvetica-bold\", fontcolor=\"blue\""
|
21
|
+
code << " width=.25, height=.25, color=\"black\", fillcolor=\"white\", style=\"filled, solid, bold\"];"
|
22
|
+
code << "edge [arrowsize=.5, color=\"black\", style=\"bold\"]"
|
23
|
+
@visited=[]
|
24
|
+
process(ast)
|
25
|
+
code << @nodes_decl
|
26
|
+
code << @nodes_cnx
|
27
|
+
code.indent=0
|
28
|
+
code << "}"
|
29
|
+
clean(code)
|
30
|
+
dot_filename="#{ast.name}_ast#{suffix}.dot"
|
31
|
+
File.open(dot_filename,'w'){|f| f.puts code.finalize}
|
32
|
+
end
|
33
|
+
|
34
|
+
def process node,level=1
|
35
|
+
kname=node.class.name.split("::")[1] || "#{node.class}"
|
36
|
+
id=node.object_id
|
37
|
+
indent=" "*level
|
38
|
+
|
39
|
+
#puts indent+"processing #{node}"
|
40
|
+
(nodes_decl << "#{id} [label=\"#{kname}\"]")
|
41
|
+
unless @visited.include?(id)
|
42
|
+
node.instance_variables.each{|vname|
|
43
|
+
#puts indent+"-"+vname.to_s
|
44
|
+
ivar=node.instance_variable_get(vname)
|
45
|
+
vname=vname.to_s[1..-1]
|
46
|
+
if ivar
|
47
|
+
case ivar
|
48
|
+
when Array
|
49
|
+
ivar.each_with_index{|e,idx|
|
50
|
+
sink=process(e,level+1)
|
51
|
+
@printed_cnx[id]||=[]
|
52
|
+
nodes_cnx << "#{id} -> #{sink} [label=\"#{vname}[#{idx}]\"]" if not @printed_cnx[id].include? sink
|
53
|
+
@printed_cnx[id] << sink
|
54
|
+
}
|
55
|
+
when Symbol,Integer,String
|
56
|
+
val=ivar.to_s
|
57
|
+
sink="#{ivar.object_id}"
|
58
|
+
nodes_decl << "#{sink} [label=\"#{val}\",color=\"red\"]"
|
59
|
+
@printed_cnx[id]||=[]
|
60
|
+
nodes_cnx << "#{id} -> #{sink} [label=\"#{vname}\"]" if not @printed_cnx[id].include? sink
|
61
|
+
@printed_cnx[id] << sink
|
62
|
+
else
|
63
|
+
sink=process(ivar,level+1)
|
64
|
+
@printed_cnx[id]||=[]
|
65
|
+
nodes_cnx << "#{id} -> #{sink} [label=\"#{vname}\"]" if not @printed_cnx[id].include? sink
|
66
|
+
@printed_cnx[id] << sink
|
67
|
+
end
|
68
|
+
end
|
69
|
+
}
|
70
|
+
end
|
71
|
+
@visited << id
|
72
|
+
return id
|
73
|
+
end
|
74
|
+
|
75
|
+
# suppress syndrom : name=""not correct""
|
76
|
+
def clean code
|
77
|
+
#puts "=> cleaning dot code"
|
78
|
+
code.lines.each_with_index do |line,idx|
|
79
|
+
if line=~/\"\"(.*)\"\"/
|
80
|
+
code.lines[idx].gsub!(/\"\"(.*)\"\"/,"\"#{$1}\"")
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
class Code
|
2
|
+
|
3
|
+
attr_accessor :indent,:lines
|
4
|
+
|
5
|
+
def initialize str=nil
|
6
|
+
@lines=[]
|
7
|
+
(@lines << str) if str
|
8
|
+
@indent=0
|
9
|
+
end
|
10
|
+
|
11
|
+
def size
|
12
|
+
@lines.size
|
13
|
+
end
|
14
|
+
|
15
|
+
def <<(thing)
|
16
|
+
if (code=thing).is_a? Code
|
17
|
+
code.lines.each do |line|
|
18
|
+
@lines << " "*@indent+line.to_s
|
19
|
+
end
|
20
|
+
elsif thing.is_a? Array
|
21
|
+
thing.each do |kode|
|
22
|
+
@lines << kode
|
23
|
+
end
|
24
|
+
elsif thing.nil?
|
25
|
+
else
|
26
|
+
@lines << " "*@indent+thing.to_s
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def finalize
|
31
|
+
return @lines.join("\n") if @lines.any?
|
32
|
+
""
|
33
|
+
end
|
34
|
+
|
35
|
+
def newline
|
36
|
+
@lines << " "
|
37
|
+
end
|
38
|
+
|
39
|
+
def save_as filename,verbose=true,sep="\n"
|
40
|
+
str=self.finalize
|
41
|
+
File.open(filename,'w'){|f| f.puts(str)}
|
42
|
+
return filename
|
43
|
+
end
|
44
|
+
|
45
|
+
def size
|
46
|
+
@lines.size
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require_relative 'ast_printer'
|
2
|
+
require_relative 'dsl_printer'
|
3
|
+
require_relative 'contextual_analyzer'
|
4
|
+
require_relative 'type_checker'
|
5
|
+
require_relative 'vhdl_generator'
|
6
|
+
require_relative 'sexp_generator'
|
7
|
+
|
8
|
+
module RubyRTL
|
9
|
+
|
10
|
+
class Compiler
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
header
|
14
|
+
@printer=DSLPrinter.new
|
15
|
+
@dot_printer=ASTPrinter.new
|
16
|
+
@analyzer=ContextualAnalyzer.new
|
17
|
+
@checker=TypeChecker.new
|
18
|
+
@vgen=VhdlGenerator.new
|
19
|
+
@sexp_gen=SexpGenerator.new
|
20
|
+
end
|
21
|
+
|
22
|
+
def header
|
23
|
+
puts "RubyRTL compiler "
|
24
|
+
end
|
25
|
+
|
26
|
+
def compile circuit
|
27
|
+
print_ast(circuit)
|
28
|
+
analyze(circuit)
|
29
|
+
print_dsl(circuit)
|
30
|
+
type_check(circuit)
|
31
|
+
print_dsl(circuit)
|
32
|
+
generate(circuit)
|
33
|
+
generate_sexp(circuit)
|
34
|
+
end
|
35
|
+
|
36
|
+
def print_dsl circuit
|
37
|
+
@printer.print circuit
|
38
|
+
end
|
39
|
+
|
40
|
+
def print_ast circuit,file_suffix=""
|
41
|
+
@dot_printer.run(circuit,file_suffix)
|
42
|
+
end
|
43
|
+
|
44
|
+
def analyze circuit
|
45
|
+
@analyzer.analyze(circuit)
|
46
|
+
end
|
47
|
+
|
48
|
+
def type_check circuit
|
49
|
+
@checker.check circuit
|
50
|
+
end
|
51
|
+
|
52
|
+
def generate circuit
|
53
|
+
@vgen.generate(circuit)
|
54
|
+
end
|
55
|
+
|
56
|
+
def generate_sexp circuit
|
57
|
+
@sexp_gen.generate(circuit)
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require_relative 'code'
|
2
|
+
require_relative 'visitor'
|
3
|
+
|
4
|
+
module RubyRTL
|
5
|
+
|
6
|
+
class ContextualAnalyzer < Visitor
|
7
|
+
|
8
|
+
def analyze circuit
|
9
|
+
puts "[+] contextual analysis"
|
10
|
+
root=circuit.ast
|
11
|
+
if root
|
12
|
+
#root.ios.each{|io| io.accept(self)}
|
13
|
+
root.decls.each{|decl| decl.accept(self)}
|
14
|
+
root.body.accept(self)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def visitBody body,args=nil
|
19
|
+
#reconnect Else/Elsifs objects to their parent If
|
20
|
+
reconnectElseParts(body)
|
21
|
+
#attach comments to their adequate Ast nodes
|
22
|
+
attachComments(body)
|
23
|
+
body.stmts.each{|stmt| stmt.accept(self,args)}
|
24
|
+
end
|
25
|
+
|
26
|
+
def reconnectElseParts body
|
27
|
+
ifs=body.select{|stmt| stmt.is_a? If}
|
28
|
+
to_delete=[]
|
29
|
+
ifs.each do |if_|
|
30
|
+
index_if=body.stmts.index(if_)
|
31
|
+
do_iterate=true
|
32
|
+
index=index_if
|
33
|
+
while do_iterate
|
34
|
+
case elsei=body.stmts[index+1]
|
35
|
+
when Else
|
36
|
+
if_.else=elsei
|
37
|
+
to_delete << elsei
|
38
|
+
elsei.accept(self) # dont forget to visit it
|
39
|
+
when Elsif
|
40
|
+
if_.elsifs << elsei
|
41
|
+
to_delete << elsei
|
42
|
+
elsei.accept(self)
|
43
|
+
else
|
44
|
+
do_iterate=false
|
45
|
+
end
|
46
|
+
index+=1
|
47
|
+
end
|
48
|
+
end
|
49
|
+
to_delete.each{|stmt| body.stmts.delete(stmt)}
|
50
|
+
end
|
51
|
+
|
52
|
+
def attachComments body
|
53
|
+
#niy
|
54
|
+
end
|
55
|
+
|
56
|
+
def visitFsm fsm,args=nil
|
57
|
+
@fsm=fsm
|
58
|
+
@tmp_ary=[] #helper
|
59
|
+
puts " |-[+] visiting fsm '#{fsm.name}'"
|
60
|
+
# default assignements
|
61
|
+
fsm.default_assigns=fsm.body.select{|e| e.is_a? Assign}
|
62
|
+
# build a state hash : state_name => state
|
63
|
+
state_nodes=fsm.body.select{|e| e.is_a? State}
|
64
|
+
# fsm.states=states_nodes.inject({}){|hash,state| hash.merge!( state.name=> state)}
|
65
|
+
# build a state array
|
66
|
+
fsm.states=state_nodes
|
67
|
+
# don't forget to visit the states
|
68
|
+
@in_state=true
|
69
|
+
fsm.states.each{|state| state.accept(self)}
|
70
|
+
@in_state=false
|
71
|
+
end
|
72
|
+
|
73
|
+
def visitState state,args=nil
|
74
|
+
state.body.accept(self)
|
75
|
+
end
|
76
|
+
|
77
|
+
def visitAssign assign,args=nil
|
78
|
+
if @in_state
|
79
|
+
puts "pushing #{assign}"
|
80
|
+
unless @tmp_ary.include?(id=assign.lhs.object_id)
|
81
|
+
@tmp_ary << id
|
82
|
+
@fsm.assignments << assign
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
end
|
data/lib/ruby_rtl/dsl.rb
ADDED
@@ -0,0 +1,198 @@
|
|
1
|
+
require_relative 'ast'
|
2
|
+
require_relative 'ast_builder'
|
3
|
+
|
4
|
+
module RubyRTL
|
5
|
+
|
6
|
+
def build_type arg
|
7
|
+
case arg
|
8
|
+
when Symbol
|
9
|
+
case sym=arg.to_s
|
10
|
+
when "bit"
|
11
|
+
sym="bit"
|
12
|
+
ret=BitType.new
|
13
|
+
when "byte"
|
14
|
+
ret=IntType.new(8)
|
15
|
+
when /\Abv(\d+)/
|
16
|
+
ret=BitVectorType.new($1.to_i)
|
17
|
+
when /\Auint(\d+)?/
|
18
|
+
nbits=($1 || 32).to_i
|
19
|
+
ret=UIntType.new(nbits)
|
20
|
+
when /\Aint(\d+)?/
|
21
|
+
nbits=($1 || 32).to_i
|
22
|
+
ret=IntType.new(nbits)
|
23
|
+
else
|
24
|
+
unless ret=$typedefs[arg] # global var !
|
25
|
+
raise "DSL syntax error : unknow type '#{sym}'"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
$typedefs||={}
|
29
|
+
$typedefs[sym]||=ret
|
30
|
+
when Integer
|
31
|
+
val=arg
|
32
|
+
if val==1
|
33
|
+
name="bit"
|
34
|
+
ret=BitType.new if val==1
|
35
|
+
else
|
36
|
+
name="bv#{val}"
|
37
|
+
ret=BitVectorType.new(val)
|
38
|
+
end
|
39
|
+
$typedefs||={}
|
40
|
+
$typedefs[name]||=ret
|
41
|
+
when Hash
|
42
|
+
ret=arg
|
43
|
+
when IntType,UIntType,BitType,BitVectorType
|
44
|
+
ret=arg
|
45
|
+
else
|
46
|
+
raise "ERROR : DSL syntax error. build_type for #{arg} (#{arg.class})"
|
47
|
+
end
|
48
|
+
ret
|
49
|
+
end
|
50
|
+
|
51
|
+
class Sig < Ast
|
52
|
+
attr_accessor :name
|
53
|
+
attr_accessor :type
|
54
|
+
attr_accessor :subscript_of
|
55
|
+
attr_accessor :subsignals
|
56
|
+
|
57
|
+
def initialize name,type=:bit
|
58
|
+
@name=name
|
59
|
+
@type=build_type(type)
|
60
|
+
end
|
61
|
+
|
62
|
+
def treat_int(other)
|
63
|
+
case other
|
64
|
+
when Integer
|
65
|
+
if other >=0
|
66
|
+
#return UIntLit.new(other)
|
67
|
+
return RUIntLit.new(other)
|
68
|
+
else
|
69
|
+
#return IntLit.new(other)
|
70
|
+
return RIntLit.new(other)
|
71
|
+
end
|
72
|
+
else
|
73
|
+
return other
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def |(other)
|
78
|
+
other=treat_int(other)
|
79
|
+
Binary.new(self,"|",other)
|
80
|
+
end
|
81
|
+
|
82
|
+
def &(other)
|
83
|
+
other=treat_int(other)
|
84
|
+
Binary.new(self,"&",other)
|
85
|
+
end
|
86
|
+
|
87
|
+
def ^(other)
|
88
|
+
other=treat_int(other)
|
89
|
+
Binary.new(self,"^",other)
|
90
|
+
end
|
91
|
+
|
92
|
+
# comparison
|
93
|
+
def <(other)
|
94
|
+
other=treat_int(other)
|
95
|
+
Binary.new(self,"<",other)
|
96
|
+
end
|
97
|
+
|
98
|
+
def <=(other)
|
99
|
+
other=treat_int(other)
|
100
|
+
Binary.new(self,"<=",other)
|
101
|
+
end
|
102
|
+
|
103
|
+
def >(other)
|
104
|
+
other=treat_int(other)
|
105
|
+
Binary.new(self,"<",other)
|
106
|
+
end
|
107
|
+
|
108
|
+
def >=(other)
|
109
|
+
other=treat_int(other)
|
110
|
+
Binary.new(self,"<=",other)
|
111
|
+
end
|
112
|
+
|
113
|
+
def ==(other)
|
114
|
+
other=treat_int(other)
|
115
|
+
Binary.new(self,"==",other)
|
116
|
+
end
|
117
|
+
# arith
|
118
|
+
def +(other)
|
119
|
+
other=treat_int(other)
|
120
|
+
Binary.new(self,"+",other)
|
121
|
+
end
|
122
|
+
|
123
|
+
def -(other)
|
124
|
+
other=treat_int(other)
|
125
|
+
Binary.new(self,"-",other)
|
126
|
+
end
|
127
|
+
|
128
|
+
def *(other)
|
129
|
+
other=treat_int(other)
|
130
|
+
Binary.new(self,"*",other)
|
131
|
+
end
|
132
|
+
|
133
|
+
def /(other)
|
134
|
+
other=treat_int(other)
|
135
|
+
Binary.new(self,"/",other)
|
136
|
+
end
|
137
|
+
|
138
|
+
def !=(other)
|
139
|
+
other=treat_int(other)
|
140
|
+
Binary.new(self,"!=",other)
|
141
|
+
end
|
142
|
+
|
143
|
+
# unary expressions
|
144
|
+
def !@
|
145
|
+
Unary.new("!",self)
|
146
|
+
end
|
147
|
+
|
148
|
+
def -@
|
149
|
+
Unary.new("-",self)
|
150
|
+
end
|
151
|
+
|
152
|
+
def [](index)
|
153
|
+
@indexed||={}
|
154
|
+
index=treat_int(index)
|
155
|
+
@indexed[index.to_s]||=Indexed.new(self,index,@type.type)
|
156
|
+
end
|
157
|
+
|
158
|
+
def coerce(other)
|
159
|
+
[IntLit.new(other), self]
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
class Indexed < Sig
|
164
|
+
attr_accessor :lhs,:rhs
|
165
|
+
def initialize lhs,rhs,type
|
166
|
+
super("foo",type)
|
167
|
+
@lhs,@rhs=lhs,rhs
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def Memory size,type
|
172
|
+
p type=build_type(type)
|
173
|
+
MemoryType.new(size,type)
|
174
|
+
end
|
175
|
+
|
176
|
+
def Record hash
|
177
|
+
h={}
|
178
|
+
hash.each do |name,type|
|
179
|
+
type||=$typedefs[type]
|
180
|
+
type=build_type(type)
|
181
|
+
h[name]=type
|
182
|
+
end
|
183
|
+
RecordType.new(h)
|
184
|
+
end
|
185
|
+
|
186
|
+
def Struct hash
|
187
|
+
Record(hash) # call to method Record
|
188
|
+
end
|
189
|
+
|
190
|
+
def Enum *elems
|
191
|
+
EnumType.new(elems)
|
192
|
+
end
|
193
|
+
|
194
|
+
def Bit val
|
195
|
+
BitLit.new(val)
|
196
|
+
end
|
197
|
+
|
198
|
+
end
|