sexpir 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 682317cfd3be1aa8cbdefa505279d36be704c833b4f9cfc1165dbfe6f17777c0
4
+ data.tar.gz: 739265b361bf8d05fa41c827d1db2b2a858306832343189eba1c5f368110000f
5
+ SHA512:
6
+ metadata.gz: 60bff8d21a153e2c9f919b07d24647b55233f67170789ce247625f4f8e4024d5756dd85b200840a121df202441d1003505b9e31cda1003755d52e11fe6a03433
7
+ data.tar.gz: 0d501270fe47eaa5a1d46d71686ce1e0aba1dc19921fa579cedd6b029ea98faaf64102e2149bf6b8418c64abacfc6462eeedfa5eadbb16cc40ea294888dedd16
data/bin/sexpir ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative '../lib/sexpir'
4
+
5
+ Sexpir::Runner.run(*ARGV)
data/lib/sexpir/ast.rb ADDED
@@ -0,0 +1,98 @@
1
+ module Sexpir
2
+ class Ast
3
+ attr_accessor :node
4
+ def accept(visitor, arg=nil)
5
+ name = self.class.name.split(/::/).last
6
+ visitor.send("visit#{name}".to_sym, self ,arg) # Metaprograming !
7
+ end
8
+ end
9
+
10
+ class Circuit < Ast
11
+ attr_accessor :name,:signals,:inputs,:outputs,:body
12
+ def initialize
13
+ @signals=[]
14
+ @inputs,@outputs=[],[]
15
+ @body=Body.new
16
+ end
17
+ end
18
+
19
+ class Signal < Ast
20
+ attr_accessor :name,:type
21
+ end
22
+
23
+ class Io < Signal
24
+ end
25
+
26
+ class Port < Io
27
+ attr_accessor :component_name,:name
28
+ end
29
+
30
+ class Input < Io
31
+ end
32
+
33
+ class Output < Io
34
+ end
35
+
36
+ # statements
37
+ class Body < Ast
38
+ attr_accessor :stmts
39
+ def initialize
40
+ @stmts=[]
41
+ end
42
+
43
+ def << e
44
+ @stmts << e
45
+ end
46
+ end
47
+
48
+ class Combinatorial < Ast
49
+ attr_accessor :label,:body
50
+ end
51
+
52
+ class Sequential < Ast
53
+ attr_accessor :label,:body
54
+ end
55
+
56
+ class Assign < Ast
57
+ attr_accessor :lhs,:rhs
58
+ end
59
+
60
+ class If < Ast
61
+ attr_accessor :cond,:then,:elsifs,:else
62
+ def initialize
63
+ @elsifs=[]
64
+ end
65
+ end
66
+ #===============================
67
+ class Component < Ast
68
+ attr_accessor :name,:type
69
+ end
70
+
71
+ class Connect < Ast
72
+ attr_accessor :source,:sink
73
+ end
74
+ #================================
75
+ class Expression < Ast
76
+ end
77
+
78
+ class Binary < Expression
79
+ attr_accessor :lhs,:op,:rhs
80
+ end
81
+
82
+ class Term < Expression
83
+ end
84
+
85
+ class Var < Term
86
+ attr_accessor :name
87
+ def initialize name
88
+ @name=name
89
+ end
90
+ end
91
+
92
+ class Const < Expression
93
+ attr_accessor :value
94
+ def initialize value
95
+ @value=value
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,144 @@
1
+ require_relative 'code'
2
+
3
+ class Symbol
4
+ def sexp
5
+ self
6
+ end
7
+ end
8
+
9
+ module Sexpir
10
+
11
+ class Circuit < Ast
12
+ def sexp
13
+ code=Code.new
14
+ code << "(circuit #{name}"
15
+ code.indent=2
16
+ signals.each{|sig| code << sig.sexp}
17
+ inputs.each{|input | code << input.sexp}
18
+ outputs.each{|output| code << output.sexp}
19
+ code.newline
20
+ code << body.sexp
21
+ code.indent=0
22
+ code << ")"
23
+ code.finalize
24
+ end
25
+ end
26
+
27
+ class Signal < Ast
28
+ def sexp
29
+ "(signal #{name} #{type})"
30
+ end
31
+ end
32
+
33
+ class Port < Io
34
+ def sexp
35
+ "(port #{component_name} #{name})"
36
+ end
37
+ end
38
+
39
+ class Input < Io
40
+ def sexp
41
+ "(input #{name} #{type})"
42
+ end
43
+ end
44
+
45
+ class Output < Io
46
+ def sexp
47
+ "(output #{name} #{type})"
48
+ end
49
+ end
50
+
51
+ class Body < Ast
52
+ def sexp
53
+ code=Code.new
54
+ stmts.each{|stmt| code << stmt.sexp}
55
+ code
56
+ end
57
+ end
58
+
59
+ class Combinatorial < Ast
60
+ def sexp
61
+ code=Code.new
62
+ label_s=label ? label : "nil"
63
+ code << "(combinatorial #{label_s}"
64
+ code.indent=2
65
+ code << body.sexp
66
+ code.indent=0
67
+ code << ")"
68
+ code
69
+ end
70
+ end
71
+
72
+ class Sequential < Ast
73
+ def sexp
74
+ code=Code.new
75
+ label_s=label ? label : "nil"
76
+ code << "(sequential #{label_s}"
77
+ code.indent=2
78
+ code << body.sexp
79
+ code.indent=0
80
+ code << ")"
81
+ code
82
+ end
83
+ end
84
+
85
+ class Assign < Ast
86
+ def sexp
87
+ "(assign #{lhs.sexp} #{rhs.sexp})"
88
+ end
89
+ end
90
+
91
+ class If < Ast
92
+ def sexp
93
+ code=Code.new
94
+ code << "(if #{cond.sexp}"
95
+ code.indent=2
96
+ code << "(then"
97
+ code.indent=4
98
+ code << self.then.sexp
99
+ code.indent=2
100
+ code << ")"
101
+ if self.else
102
+ code << "(else"
103
+ code.indent=4
104
+ code << self.else.sexp
105
+ code.indent=2
106
+ code << ")"
107
+ end
108
+ code.indent=0
109
+ code << ")"
110
+ code
111
+ end
112
+ end
113
+ #===============================
114
+ class Component < Ast
115
+ def sexp
116
+ "(component #{name} #{type})"
117
+ end
118
+ end
119
+
120
+ class Connect < Ast
121
+ def sexp
122
+ "(connect #{source.sexp} #{sink.sexp})"
123
+ end
124
+ end
125
+
126
+ #================================
127
+ class Binary < Expression
128
+ def sexp
129
+ "(#{op} #{lhs.sexp} #{rhs.sexp})"
130
+ end
131
+ end
132
+
133
+ class Var < Term
134
+ def sexp
135
+ name
136
+ end
137
+ end
138
+
139
+ class Const < Expression
140
+ def sexp
141
+ value
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,14 @@
1
+ require_relative 'visitor'
2
+ require_relative 'printer'
3
+
4
+ module Sexpir
5
+
6
+ class Checker < Visitor
7
+ include Log
8
+ def check circuit
9
+ log"[+] checking circuit '#{circuit.name}'"
10
+ end
11
+
12
+ private
13
+ end
14
+ end
@@ -0,0 +1,46 @@
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 <<(thing)
12
+ if (code=thing).is_a? Code
13
+ code.lines.each do |line|
14
+ @lines << " "*@indent+line.to_s
15
+ end
16
+ elsif thing.is_a? Array
17
+ thing.each do |kode|
18
+ @lines << kode
19
+ end
20
+ elsif thing.nil?
21
+ else
22
+ @lines << " "*@indent+thing.to_s
23
+ end
24
+ end
25
+
26
+ def finalize
27
+ return @lines.join("\n") if @lines.any?
28
+ ""
29
+ end
30
+
31
+ def newline
32
+ @lines << " "
33
+ end
34
+
35
+ def save_as filename,verbose=true,sep="\n"
36
+ str=self.finalize
37
+ File.open(filename,'w'){|f| f.puts(str)}
38
+ return filename
39
+ end
40
+
41
+ def size
42
+ @lines.size
43
+ end
44
+
45
+
46
+ end
@@ -0,0 +1,8 @@
1
+ require_relative 'code'
2
+ module Sexpir
3
+ class CodeGenerator
4
+ def generate fsmd
5
+ puts "[+] code generation"
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,39 @@
1
+ require 'sxp'
2
+
3
+ require_relative 'version'
4
+ require_relative 'ast'
5
+ require_relative 'parser'
6
+ require_relative 'printer'
7
+ require_relative 'checker'
8
+ require_relative 'transformer'
9
+ require_relative 'ruby_rtl_generator'
10
+
11
+ module Sexpir
12
+
13
+ class Compiler
14
+
15
+ include Log
16
+ attr_accessor :options
17
+
18
+ def initialize
19
+ end
20
+
21
+ def header
22
+ log "Sexpir compiler - version #{VERSION}"
23
+ #log "author : jean-christophe.le_lann@ensta-bretagne.fr"
24
+ end
25
+
26
+ def compile sexpfile
27
+ header
28
+ circuit=Parser.new.parse(sexpfile)
29
+ Printer.new.print(circuit)
30
+ Checker.new.check(circuit)
31
+ RubyRTLGenerator.new.generate(circuit)
32
+ end
33
+
34
+ def close
35
+ log "[+] closing : log is #{$log.inspect}"
36
+ end
37
+
38
+ end
39
+ end
@@ -0,0 +1,116 @@
1
+ require_relative "code"
2
+
3
+ module GRAPH
4
+
5
+ class Graph
6
+
7
+ attr_accessor :name,:nodes
8
+ def initialize name
9
+ @name=name
10
+ @nodes=[]
11
+ end
12
+
13
+ def << node
14
+ @nodes << node
15
+ end
16
+
17
+ def size
18
+ @nodes.size
19
+ end
20
+
21
+ def include? node
22
+ @nodes.include? node
23
+ end
24
+
25
+ def connect source,sink,infos={}
26
+ raise "source nil" unless source
27
+ raise "sink nil" unless sink
28
+ @nodes << source unless @nodes.include? source
29
+ @nodes << sink unless @nodes.include? sink
30
+ source.to(sink,infos)
31
+ end
32
+
33
+ def connected? source,sink
34
+ source.succ_edges.select{|edge| edge.sink==sink}.any?
35
+ end
36
+
37
+ def unconnect source,sink
38
+ source.succ_edges.delete_if{|edge| edge.sink==sink}
39
+ sink.pred_edges.delete_if{|edge| edge.source==source}
40
+ end
41
+
42
+ def delete node
43
+ node.preds.each{|pred| unconnect(pred,node)}
44
+ node.succs.each{|succ| unconnect(node,succ)}
45
+ @nodes.delete(node)
46
+ end
47
+
48
+ def each_node &block
49
+ @nodes.each(&block)
50
+ end
51
+
52
+ def each_edge &block
53
+ edges.each(&block)
54
+ end
55
+
56
+ def edges
57
+ @nodes.collect{|n| n.succ_edges}.flatten
58
+ end
59
+
60
+ def to_dot
61
+ dot_code=Code.new
62
+ dot_code << "digraph #{name} {"
63
+ dot_code.indent=2
64
+
65
+ each_node do |node|
66
+ dot_code << "#{node.object_id};"
67
+ end
68
+ each_edge do |edge|
69
+ label=edge.infos.to_s
70
+ dot_code << "#{edge.object_id} -> #{edge.object_id} [label=\"#{label}\"];"
71
+ end
72
+ dot_code.indent=0
73
+ dot_code << "}"
74
+ return dot_code
75
+ end
76
+
77
+ def save_as dotfilename
78
+ dot_code||=to_dot()
79
+ dot_code.save_as dotfilename
80
+ end
81
+ end
82
+
83
+ class Node
84
+ attr_accessor :infos
85
+ attr_accessor :succ_edges,:pred_edges
86
+
87
+ def initialize infos={}
88
+ @infos=infos
89
+ @succ_edges=[]
90
+ @pred_edges=[]
91
+ end
92
+
93
+ def to node,infos={}
94
+ e=Edge.new(self,node,infos)
95
+ @succ_edges << e
96
+ node.pred_edges << e
97
+ end
98
+
99
+ def succs
100
+ @succ_edges.collect{|edge| edge.sink}
101
+ end
102
+
103
+ def preds
104
+ @pred_edges.collect{|edge| edge.source}
105
+ end
106
+ end
107
+
108
+ class Edge
109
+ attr_accessor :name,:source,:sink,:infos
110
+ def initialize source,sink,infos={}
111
+ @infos=infos
112
+ @source=source
113
+ @sink=sink
114
+ end
115
+ end
116
+ end
data/lib/sexpir/log.rb ADDED
@@ -0,0 +1,22 @@
1
+ module Log
2
+
3
+ def indent v,str
4
+ @indent=v
5
+ puts " "*@indent+str.to_s
6
+ end
7
+
8
+ def log msg
9
+ puts msg
10
+ #log_dbg msg
11
+ end
12
+
13
+ def log_dbg msg
14
+ puts msg
15
+ #$log.puts msg
16
+ end
17
+
18
+ def step
19
+ log "press any key"
20
+ key=$stdin.gets
21
+ end
22
+ end
@@ -0,0 +1,274 @@
1
+ require 'sxp'
2
+ require_relative 'ast'
3
+ require_relative 'log'
4
+
5
+ module Sexpir
6
+
7
+ class Parser
8
+
9
+ include Log
10
+
11
+ attr_accessor :options
12
+
13
+ def initialize
14
+ @type_table={}
15
+ @var_table ={}
16
+ end
17
+
18
+ def parse sexpfile
19
+ log "[+] parsing '#{sexpfile}'"
20
+ sexp=SXP.read IO.read(sexpfile)
21
+ ast=objectify(sexp)
22
+ end
23
+
24
+ def objectify sexp
25
+ circ=Circuit.new
26
+ sexp.shift
27
+ circ.name=sexp.shift
28
+ while sexp.any?
29
+ s=sexp.shift
30
+ case s.first
31
+ when :signal
32
+ circ.signals << parse_signal(s)
33
+ when :input
34
+ circ.inputs << parse_input(s)
35
+ when :output
36
+ circ.outputs << parse_output(s)
37
+ when :assign
38
+ circ.body << parse_assign(s)
39
+ when :component
40
+ circ.body << parse_component(s)
41
+ when :connect
42
+ circ.body << parse_connect(s)
43
+ when :comb,:combinatorial
44
+ circ.body << parse_comb(s)
45
+ when :seq,:sync,:sequential
46
+ circ.body << parse_seq(s)
47
+ else
48
+ raise "unknown car #{s}"
49
+ end
50
+ end
51
+ circ
52
+ end
53
+
54
+ def expect sexp,klass,value=nil
55
+ unless (kind=sexp.shift).is_a? klass
56
+ log "ERROR : expecting a #{klass}. Got a #{kind}."
57
+ raise "Syntax error"
58
+ end
59
+ if value
60
+ unless value==kind
61
+ log "ERROR : expecting value '#{value}'. Got '#{kind}'"
62
+ raise "Syntax error"
63
+ end
64
+ end
65
+ return kind
66
+ end
67
+
68
+ #======== IO & Signals ===========
69
+ def parse_signal sexp
70
+ sig=Signal.new
71
+ sexp.shift
72
+ sig.name=sexp.shift
73
+ sig.type=sexp.shift
74
+ sig
75
+ end
76
+
77
+ def parse_input sexp
78
+ input=Input.new
79
+ sexp.shift
80
+ input.name=sexp.shift
81
+ input.type=sexp.shift
82
+ input
83
+ end
84
+
85
+ def parse_output sexp
86
+ output=Output.new
87
+ sexp.shift
88
+ output.name=sexp.shift
89
+ output.type=sexp.shift
90
+ output
91
+ end
92
+
93
+
94
+
95
+ # ===== components stuff =====
96
+ def parse_component sexp
97
+ comp=Component.new
98
+ sexp.shift
99
+ comp.name=sexp.shift
100
+ comp.type=sexp.shift
101
+ comp
102
+ end
103
+
104
+ def parse_connect sexp
105
+ con=Connect.new
106
+ sexp.shift
107
+ con.source=parse_port(sexp.shift)
108
+ con.sink =parse_port(sexp.shift)
109
+ con
110
+ end
111
+
112
+ def parse_port sexp
113
+ case sexp
114
+ when Array
115
+ port=Port.new
116
+ sexp.shift
117
+ port.component_name=sexp.shift
118
+ port.name=sexp.shift
119
+ return port
120
+ else
121
+ return sexp
122
+ end
123
+ end
124
+
125
+ # statements
126
+ def parse_statement sexp
127
+ case sexp.first
128
+ when :if
129
+ parse_if(sexp)
130
+ when :assign
131
+ parse_assign(sexp)
132
+ else
133
+ raise "unknow statement starting with : #{sexp.first}"
134
+ end
135
+ end
136
+
137
+ def parse_comb sexp
138
+ comb=Combinatorial.new
139
+ sexp.shift
140
+ label=sexp.shift
141
+ comb.body=parse_body(sexp)
142
+ comb
143
+ end
144
+
145
+ def parse_body sexp
146
+ body=Body.new
147
+ while sexp.any?
148
+ body << parse_statement(sexp.shift)
149
+ end
150
+ body
151
+ end
152
+
153
+ def parse_if sexp
154
+ if_=If.new
155
+ sexp.shift
156
+ if_.cond = parse_expression(sexp.shift)
157
+ while sexp.any?
158
+ case sexp.first.first
159
+ when :then
160
+ if_.then = parse_then(sexp.shift)
161
+ when :elsif
162
+ if_.elsifs << parse_elsif(sexp.shift)
163
+ when :else
164
+ if_.else = parse_else(sexp.shift)
165
+ else
166
+ raise "error parsing 'if' : #{sexp.first.first}"
167
+ end
168
+ end
169
+ if_
170
+ end
171
+
172
+ def parse_then sexp
173
+ sexp.shift
174
+ body=parse_body(sexp)
175
+ body
176
+ end
177
+
178
+ def parse_elsif sexp
179
+ sexp.shift
180
+ body=parse_body(sexp)
181
+ body
182
+ end
183
+
184
+ def parse_else sexp
185
+ sexp.shift
186
+ body=parse_body(sexp)
187
+ body
188
+ end
189
+
190
+ def parse_assign sexp
191
+ assign=Assign.new
192
+ sexp.shift
193
+ assign.lhs=parse_expression(sexp.shift)
194
+ assign.rhs=parse_expression(sexp.shift)
195
+ assign
196
+ end
197
+
198
+ # expressions
199
+
200
+ def parse_expression sexp
201
+ case sexp
202
+ when Array
203
+ case sexp.size
204
+ when 1
205
+ case sexp
206
+ when Symbol
207
+ return Var.new(sexp)
208
+ when Integer
209
+ return Const.new(sexp)
210
+ else
211
+ raise "unknown expression '#{sexp}'"
212
+ end
213
+ when 2
214
+ ret=parse_unary(sexp)
215
+ when 3
216
+ ret=parse_binary(sexp)
217
+ else
218
+ raise "unknown expression '#{sexp}'(size = '#{sexp.size}')"
219
+ end
220
+ when Symbol
221
+ ret=Var.new(sexp)
222
+ when Integer
223
+ ret=Const.new(sexp)
224
+ else
225
+ raise "unknown expression '#{sexp}'"
226
+ end
227
+ ret
228
+ end
229
+
230
+ OP_TRANSLATE={
231
+ "gt" => ">",
232
+ "lt" => "<",
233
+ "eq" => "=",
234
+ "neq"=> "/=",
235
+ "gte"=> ">=",
236
+ "lte"=> "<=",
237
+ }
238
+
239
+ NORMALIZED_OP={
240
+ "*" => "mul",
241
+ "+" => "add",
242
+ "-" => "sub",
243
+ "/" => "div",
244
+ "=" => "eq",
245
+ ">=" => "gte",
246
+ "<=" => "lte",
247
+ "/=" => "neq"
248
+ }
249
+
250
+ def parse_binary sexp
251
+ case sexp.first
252
+ when :mread
253
+ ret=MRead.new
254
+ sexp.shift
255
+ ret.mem = Mem.new(sexp.shift) # memory name
256
+ ret.addr= parse_expression(sexp.shift)
257
+ else
258
+ ret=Binary.new
259
+ ret.op=sexp.shift
260
+ #ret.op=OP_TRANSLATE[ret.op.to_s]||ret.op.to_s
261
+ ret.op=NORMALIZED_OP[ret.op.to_s] || ret.op.to_s
262
+ ret.lhs=parse_expression(sexp.shift)
263
+ ret.rhs=parse_expression(sexp.shift)
264
+ end
265
+ ret
266
+ end
267
+
268
+ def parse_unary sexp
269
+ ret=Unary.new
270
+ ret.op=sexp.shift
271
+ ret
272
+ end
273
+ end
274
+ end
@@ -0,0 +1,10 @@
1
+ require_relative 'ast_sexp'
2
+
3
+ module Sexpir
4
+ class Printer
5
+ def print circuit
6
+ puts "[+] pretty printing"
7
+ puts circuit.sexp
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,169 @@
1
+ require_relative 'log'
2
+ class Symbol
3
+ def accept visitor,args=nil
4
+ self
5
+ end
6
+ end
7
+
8
+ module Sexpir
9
+ class RubyRTLGenerator < Visitor
10
+ include Log
11
+ def generate circuit
12
+ log "[+] generating RubyRTL '#{circuit.name}'"
13
+ code=circuit.accept(self)
14
+ puts code.finalize
15
+ end
16
+
17
+ def visitCircuit circuit,args=nil
18
+ code=Code.new
19
+ code << "require 'ruby_rtl'"
20
+ code << "class #{circuit.name.capitalize} < Circuit"
21
+ code.indent=2
22
+ circuit.inputs.each{|input| code << input.accept(self)}
23
+ circuit.outputs.each{|output| code << output.accept(self)}
24
+ circuit.signals.each{|signal| code << signal.accept(self)}
25
+ code.newline
26
+ code << circuit.body.accept(self)
27
+ code.indent=0
28
+ code << "end"
29
+ code
30
+ end
31
+
32
+ def gen_type(type)
33
+ case num=type
34
+ when Integer
35
+ case num
36
+ when 1
37
+ return "bit"
38
+ else
39
+ return "bv#{num}"
40
+ end
41
+ else
42
+ return type
43
+ end
44
+ end
45
+
46
+ def visitSignal sig,args=nil
47
+ sig.name
48
+ type=gen_type(sig.type)
49
+ "wire :#{sig.name} => :#{type}"
50
+ end
51
+
52
+ def visitIo io,args=nil
53
+ io.name
54
+ io.type
55
+ end
56
+
57
+ def visitPort port,args=nil
58
+ comp=port.component_name
59
+ name=port.name
60
+ "#{comp}.#{name}"
61
+ end
62
+
63
+ def visitInput input,args=nil
64
+ input.name
65
+ input.type
66
+ "input :#{input.name} => :#{input.type}"
67
+ end
68
+
69
+ def visitOutput output,args=nil
70
+ output.name
71
+ output.type
72
+ "output :#{output.name} => :#{output.type}"
73
+ end
74
+
75
+ # === statements ===
76
+ def visitBody body,args=nil
77
+ code=Code.new
78
+ body.stmts.each{|stmt| code << stmt.accept(self)}
79
+ code
80
+ end
81
+
82
+ def visitCombinatorial comb,args=nil
83
+ code=Code.new
84
+ code << "combinatorial(#{comb.label}){"
85
+ code.indent=2
86
+ code << comb.body.accept(self)
87
+ code.indent=0
88
+ code << "}"
89
+ code
90
+ end
91
+ def visitSequential seq,args=nil
92
+ code=Code.new
93
+ code << "sequential(#{seq.label}){"
94
+ code.indent=2
95
+ code << seq.body.accept(self)
96
+ code.indent=0
97
+ code << "}"
98
+ code
99
+ end
100
+
101
+ def visitAssign assign,args=nil
102
+ lhs=assign.lhs.accept(self)
103
+ rhs=assign.rhs.accept(self)
104
+ "assign(#{lhs} <= #{rhs})"
105
+ end
106
+
107
+ def visitIf if_,args=nil
108
+ cond=if_.cond.accept(self)
109
+ code=Code.new
110
+ code << "if (#{cond}"
111
+ code.indent=2
112
+ code << if_.then.accept(self)
113
+ if if_.else
114
+ code.indent=0
115
+ code << "else"
116
+ code.indent=2
117
+ code << if_.else.accept(self)
118
+ code.indent=0
119
+ end
120
+ code.indent=0
121
+ code << "end"
122
+ code
123
+ end
124
+
125
+ # === component stuff ====
126
+ def visitComponent component,args=nil
127
+ name=component.name
128
+ type=component.type
129
+ "component :#{name} => #{type.capitalize}"
130
+ end
131
+
132
+ def visitConnect connect,args=nil
133
+ source=connect.source.accept(self)
134
+ sink=connect.sink.accept(self)
135
+ "connect #{source} => #{sink}"
136
+ end
137
+
138
+ #===========
139
+ def visitExpression expr,args=nil
140
+ end
141
+
142
+ SEXPIR_TO_RUBY_OP={
143
+ "and" => "&",
144
+ "or" => "|",
145
+ "xor" => "^",
146
+ "not" => "!",
147
+ }
148
+ def visitBinary binary,args=nil
149
+ lhs=binary.lhs.accept(self)
150
+ rhs=binary.rhs.accept(self)
151
+ op=SEXPIR_TO_RUBY_OP[binary.op] || binary.op
152
+ "(#{lhs} #{op} #{rhs})"
153
+ end
154
+
155
+ def visitTerm term,args=nil
156
+ term
157
+ end
158
+
159
+ def visitVar var,args=nil
160
+ var.name
161
+ end
162
+
163
+ def visitConst const,args=nil
164
+ const.value
165
+ end
166
+
167
+
168
+ end
169
+ end
@@ -0,0 +1,64 @@
1
+ require "optparse"
2
+
3
+ require_relative "compiler"
4
+
5
+ module Sexpir
6
+
7
+ class Runner
8
+
9
+ def self.run *arguments
10
+ new.run(arguments)
11
+ end
12
+
13
+ def run arguments
14
+ compiler=Compiler.new
15
+ compiler.options = args = parse_options(arguments)
16
+ $options=compiler.options
17
+
18
+ if filename=args[:filename]
19
+ compiler.compile filename
20
+ else
21
+ puts "need an sexpir file : sexpir <file.sexp>"
22
+ end
23
+ end
24
+
25
+ private
26
+ def parse_options(arguments)
27
+
28
+ size=arguments.size
29
+
30
+ parser = OptionParser.new
31
+
32
+ options = {}
33
+
34
+ parser.on("-h", "--help", "Show help message") do
35
+ puts parser
36
+ exit(true)
37
+ end
38
+
39
+ parser.on("-v", "--version", "Show version number") do
40
+ puts VERSION
41
+ exit(true)
42
+ end
43
+
44
+ parser.on("--verbose", "verbose mode") do
45
+ options[:verbose]=true
46
+ $VERBOSE=true
47
+ end
48
+
49
+ parser.parse!(arguments)
50
+
51
+ options[:filename]=arguments.shift
52
+
53
+ if arguments.any?
54
+ puts "WARNING : superfluous arguments : #{arguments}"
55
+ end
56
+
57
+ if size==0
58
+ puts parser
59
+ end
60
+
61
+ options
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,9 @@
1
+ module Sexpir
2
+
3
+ class Transformer < Visitor
4
+
5
+ def visitCircuit circuit,args=nil
6
+ end
7
+
8
+ end
9
+ end
@@ -0,0 +1,3 @@
1
+ module Sexpir
2
+ VERSION="0.0.2"
3
+ end
@@ -0,0 +1,76 @@
1
+ module Sexpir
2
+
3
+ class Visitor
4
+
5
+ def visitCircuit circuit,args=nil
6
+ circuit.name
7
+ circuit.inputs.each{|input| input.accept(self)}
8
+ circuit.outputs.each{|output| output.accept(self)}
9
+ circuit.signals.each{|signal| signal.accept(self)}
10
+ circuit.body.accept(self)
11
+ end
12
+
13
+ def visitSignal sig,args=nil
14
+ signal.name
15
+ signal.type
16
+ end
17
+
18
+ def visitIo io,args=nil
19
+ io.name
20
+ io.type
21
+ end
22
+
23
+ def visitPort port,args=nil
24
+ port.name
25
+ port.type
26
+ end
27
+
28
+ def visitInput input,args=nil
29
+ input.name
30
+ input.type
31
+ end
32
+
33
+ def visitOutput output,args=nil
34
+ output.name
35
+ output.type
36
+ end
37
+
38
+ def visitBody body,args=nil
39
+ body.stmts.each{|stmt| stmt.accept(self)}
40
+ end
41
+
42
+ def visitAssign assign,args=nil
43
+ assign.lhs.accept(self)
44
+ assign.rhs.accept(self)
45
+ end
46
+
47
+ def visitComponent component,args=nil
48
+ name=component.name
49
+ type=component.type
50
+ "component #{name} => #{type}"
51
+ end
52
+
53
+ def visitConnect connect,args=nil
54
+ connect.source
55
+ connect.sink
56
+ end
57
+
58
+ #===========
59
+ def visitExpression expr,args=nil
60
+ end
61
+
62
+ def visitBinary binary,args=nil
63
+ binary.lhs.accept(self)
64
+ binary.rhs.accept(self)
65
+ end
66
+
67
+ def visitTerm term,args=nil
68
+ term
69
+ end
70
+
71
+ def visitVar var,args=nil
72
+ var.name
73
+ end
74
+
75
+ end
76
+ end
data/lib/sexpir.rb ADDED
@@ -0,0 +1,4 @@
1
+ require_relative './sexpir/compiler'
2
+ require_relative './sexpir/runner'
3
+ module Sexpir
4
+ end
metadata ADDED
@@ -0,0 +1,88 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sexpir
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Jean-Christophe Le Lann
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-01-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: distribution
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 0.7.3
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 0.7.3
27
+ - !ruby/object:Gem::Dependency
28
+ name: colorize
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '='
32
+ - !ruby/object:Gem::Version
33
+ version: 0.8.1
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '='
39
+ - !ruby/object:Gem::Version
40
+ version: 0.8.1
41
+ description: sexpir is a sexp-based interchange format for RTL design
42
+ email: lelannje@ensta-bretagne.fr
43
+ executables:
44
+ - sexpir
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - bin/sexpir
49
+ - lib/sexpir.rb
50
+ - lib/sexpir/ast.rb
51
+ - lib/sexpir/ast_sexp.rb
52
+ - lib/sexpir/checker.rb
53
+ - lib/sexpir/code.rb
54
+ - lib/sexpir/code_generator.rb
55
+ - lib/sexpir/compiler.rb
56
+ - lib/sexpir/graph.rb
57
+ - lib/sexpir/log.rb
58
+ - lib/sexpir/parser.rb
59
+ - lib/sexpir/printer.rb
60
+ - lib/sexpir/ruby_rtl_generator.rb
61
+ - lib/sexpir/runner.rb
62
+ - lib/sexpir/transformer.rb
63
+ - lib/sexpir/version.rb
64
+ - lib/sexpir/visitor.rb
65
+ homepage: https://github.com/JC-LL/sexpir
66
+ licenses:
67
+ - MIT
68
+ metadata: {}
69
+ post_install_message: Thanks for installing ! Homepage :https://github.com/JC-LL/sexpir
70
+ rdoc_options: []
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: 2.0.0
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ requirements: []
84
+ rubygems_version: 3.0.6
85
+ signing_key:
86
+ specification_version: 4
87
+ summary: interchange format for RTL designs
88
+ test_files: []