sexpir 0.0.2

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 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: []