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