rtl_circuit 0.7 → 0.7.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ee25e08cf291db2381c60746dd1d654d4931bd0742cdd12f1f85b55b4065f694
4
- data.tar.gz: 6a39ac68ccf30ff37ab674dad83ff74686fe81d6e3cf6e1c8b1cca5d0d88c384
3
+ metadata.gz: 0a185b02649b8dccfde92ceddba567e41a0a0bd3996142e4d44390316be24873
4
+ data.tar.gz: 96085d10887cbe7d99b531ce56ab4a403d15a3da700d62baf064d216c7ea8925
5
5
  SHA512:
6
- metadata.gz: c5af6786663be64b4ff0dff83e240732a48ba17e0980ae7585f7a8d8967f107a81cf106608049829330f6aa094fd777bf9c26543595501ee469b4015ed6eecd2
7
- data.tar.gz: 6b633468fc83534bd1164ded8ed001154d378a37c4f37aecde60ec04b14c1ea5cdc762f21565f7291b09dd88eb070a89a7ed811a749a2463c10d905c0a815142
6
+ metadata.gz: afeef2e5c8b2a67b07f557bdc54f4bc76859d13f3898d3b88c15f4da41aae688207d6dc91b295eb6f19178cfc13b62b142957edc4311d4e0f2158e059b066d80
7
+ data.tar.gz: 6380f0c3470dda41a4cbca67520a947e71c7d96abe64c31b5549dad90e9a7dda3cd49b7e336c054004b8ca7fbc8d846f890159cf0daf969a8278cef097660f35
data/lib/rtl/canvas.rb ADDED
@@ -0,0 +1,49 @@
1
+
2
+ class Canvas < Gtk::DrawingArea
3
+ attr_accessor :running
4
+ def initialize
5
+ super()
6
+
7
+ @running=false
8
+ set_size_request(800,100)
9
+ signal_connect('draw') do
10
+ redraw @graph
11
+ end
12
+ end
13
+
14
+ def clear cr
15
+ cr.set_source_rgb(0.1, 0.1, 0.1)
16
+ cr.paint
17
+ end
18
+
19
+ def redraw graph=nil,zoom_factor=1,shift=Vector.new(0,0)
20
+ @graph=graph
21
+ cr = window.create_cairo_context
22
+ cr.set_line_width(0.8)
23
+
24
+ w = allocation.width
25
+ h = allocation.height
26
+
27
+ cr.translate(w/2, h/2)
28
+
29
+ clear cr
30
+
31
+ if graph
32
+ cr.set_source_rgb(0.4, 0.4, 0.4)
33
+ @graph.edges.each do |edge|
34
+ n1,n2=edge.source,edge.sink
35
+ cr.move_to(shift.x + n1.x*zoom_factor,shift.y + n1.y*zoom_factor)
36
+ cr.line_to(shift.x + n2.x*zoom_factor,shift.y + n2.y*zoom_factor)
37
+ cr.stroke
38
+ end
39
+
40
+ cr.set_source_rgb(0.9, 0.5, 0.2)
41
+ @graph.nodes.each do |node|
42
+ cr.arc(shift.x+node.x*zoom_factor, shift.y+node.y*zoom_factor, 10*zoom_factor, 0, 2.0 * Math::PI)
43
+ cr.fill_preserve()
44
+ cr.stroke
45
+ end
46
+ end
47
+
48
+ end
49
+ end
data/lib/rtl/circuit.rb CHANGED
@@ -8,7 +8,7 @@ module RTL
8
8
  attr_accessor :father
9
9
  attr_accessor :signals
10
10
  attr_accessor :properties
11
-
11
+ attr_accessor :color
12
12
  @@id=-1
13
13
 
14
14
  def initialize name=nil
@@ -0,0 +1,99 @@
1
+ <defs>
2
+ <symbol id="and2">
3
+ <path d="M 10 2
4
+ l 19 0
5
+ A 13 13 0 1 1 29 28
6
+ l -19 0
7
+ z
8
+ M 0 6 l 10 0
9
+ M 0 24 l 10 0
10
+ M 42 15 L 60 15"
11
+ fill="transparent"
12
+ stroke="black"/>
13
+ </symbol>
14
+
15
+ <symbol id="nand2">
16
+ <path d="M 10 2
17
+ l 19 0
18
+ A 13 13 0 1 1 29 28
19
+ l -19 0
20
+ z
21
+ M 0 6 l 10 0
22
+ M 0 24 l 10 0
23
+ M 42 15 A 4 4 0 0 0 50 15
24
+ M 42 15 A 4 4 0 0 1 50 15
25
+
26
+ M 50 15 L 60 15"
27
+ fill="transparent"
28
+ stroke="black"/>
29
+ </symbol>
30
+
31
+ <symbol id="or2">
32
+ <path d="M 10 2
33
+ l 13.484 0
34
+ A 26 26 0 0 1 46 15
35
+ A 26 26 0 0 1 23.484 28
36
+ L 10 28
37
+ A 26 26 0 0 0 10 2
38
+ M 0 6 l 11.5 0
39
+ M 0 24 l 11.5 0
40
+ M 46 15 L 60 15
41
+ "
42
+ stroke-linecap="round"
43
+ fill="transparent"
44
+ stroke="black"/>
45
+ </symbol>
46
+
47
+ <symbol id="nor2">
48
+ <path d="M 10 2
49
+ l 13.484 0
50
+ A 26 26 0 0 1 46 15
51
+ A 26 26 0 0 1 23.484 28
52
+ L 10 28
53
+ A 26 26 0 0 0 10 2
54
+ M 0 6 l 11.5 0
55
+ M 0 24 l 11.5 0
56
+ M 54 15 L 60 15
57
+ M 46 15 A 4 4 0 0 0 54 15
58
+ M 46 15 A 4 4 0 0 1 54 15
59
+
60
+ "
61
+ stroke-linecap="round"
62
+ fill="transparent"
63
+ stroke="black"/>
64
+ </symbol>
65
+
66
+ <symbol id="xor2">
67
+ <path d="M 10 2
68
+ l 13.484 0
69
+ A 26 26 0 0 1 46 15
70
+ A 26 26 0 0 1 23.484 28
71
+ L 10 28
72
+ A 26 26 0 0 0 10 2
73
+ M 0 6 l 12 0
74
+ M 0 24 l 12 0
75
+ M 46 15 L 60 15
76
+ M 6 2 A 26 26 0 0 1 6 28
77
+ "
78
+ stroke-linecap="round"
79
+ fill="transparent"
80
+ stroke="black"/>
81
+ </symbol>
82
+
83
+ <symbol id="not">
84
+ <path d="M 10 2
85
+ L 32.516 15
86
+ L 10 28
87
+ Z
88
+ M 33 15 A 4 4 0 0 0 41 15
89
+ M 33 15 A 4 4 0 0 1 41 15
90
+ M 41 15 L 60 15
91
+ M 0 15 L 10 15
92
+ "
93
+ stroke-linecap="round"
94
+ fill="transparent"
95
+ stroke="black"/>
96
+ </symbol>
97
+
98
+
99
+ </defs>
data/lib/rtl/fdgd.rb ADDED
@@ -0,0 +1,110 @@
1
+ require_relative 'graph'
2
+ require_relative 'vector'
3
+
4
+
5
+ class Fdgd
6
+
7
+ attr_accessor :graph
8
+ attr_accessor :stop
9
+
10
+ def initialize graph=nil
11
+ puts "FDGD: force-directed graph drawer"
12
+ @graph=graph
13
+ @l0=80
14
+ @c1=30
15
+ @epsilon=10
16
+ @damping=0.92
17
+ @timestep=0.1
18
+ @stop=false
19
+ end
20
+
21
+ def dist a,b
22
+ Math.sqrt((a.x - b.x)**2 + (a.y - b.y)**2)
23
+ end
24
+
25
+ def angle a,b
26
+ if dist(a,b)!=0
27
+ if b.x > a.x
28
+ angle = Math.asin((b.y-a.y)/dist(a,b))
29
+ else
30
+ angle = Math::PI - Math.asin((b.y-a.y)/dist(a,b))
31
+ end
32
+ else
33
+ angle =0
34
+ end
35
+ return angle
36
+ end
37
+
38
+ def coulomb_repulsion a,b
39
+ angle = angle(a,b)
40
+ dab = dist(a,b)
41
+ c= -0.2*(a.radius*b.radius)/Math.sqrt(dab)
42
+ [c*Math.cos(angle),c*Math.sin(angle)]
43
+ end
44
+
45
+ def sign_minus(a,b)
46
+ a>b ? 1 : -1
47
+ end
48
+
49
+ def hooke_attraction a,b #,c1=10#,l0=40
50
+ angle = angle(a,b)
51
+ dab = dist(a,b)
52
+ c = @c1*Math.log((dab-@l0).abs)*sign_minus(dab,@l0)
53
+ [c*Math.cos(angle),c*Math.sin(angle)]
54
+ end
55
+
56
+ def run iter=2
57
+ if @graph
58
+ Thread.new do
59
+ step = 0
60
+ total_kinetic_energy=1000
61
+ next_pos={}
62
+ next_speed={}
63
+ until total_kinetic_energy < @epsilon or step==iter do
64
+
65
+ step+=1
66
+ total_kinetic_energy = 0
67
+
68
+ for node in graph.nodes
69
+ net_force = Vector.new(0, 0)
70
+
71
+ for other in graph.nodes-[node]
72
+ rep = coulomb_repulsion( node, other)
73
+ net_force += rep
74
+ end
75
+
76
+ for edge in graph.edges.select{|e| e.source==node or e.sink==node}
77
+ other = edge.sink==node ? edge.source : edge.sink
78
+ attr = hooke_attraction(node, other) #, c1=30,@l0)
79
+ net_force += attr
80
+ end
81
+
82
+ # without damping, it moves forever
83
+ speed = (node.speed + net_force.scale(@timestep)).scale(@damping)
84
+ next_pos[node.id] = node.pos + speed.scale(@timestep)
85
+ next_speed[node.id] = speed
86
+ total_kinetic_energy += node.radius * speed.squared
87
+ end
88
+
89
+ #puts total_kinetic_energy
90
+ yield if block_given?
91
+ #update nodes position
92
+ for node in graph.nodes
93
+ unless node.fixed.x
94
+ node.pos.x = next_pos[node.id].x
95
+ node.speed.x = next_speed[node.id].x
96
+ end
97
+ unless node.fixed.y
98
+ node.pos.y = next_pos[node.id].y
99
+ node.speed.y = next_speed[node.id].y
100
+ end
101
+ end
102
+ break if @stop
103
+ end
104
+ puts "algorithm end"
105
+ puts "reached epsilon" if total_kinetic_energy < @epsilon
106
+ puts "reached max iterations" if step==iter
107
+ end #thread
108
+ end
109
+ end
110
+ end
data/lib/rtl/graph.rb ADDED
@@ -0,0 +1,156 @@
1
+ require_relative 'vector'
2
+ require_relative 'json_parser'
3
+
4
+ class Node
5
+ attr_accessor :id,:pos,:dims,:speed,:fixed,:radius
6
+ def initialize params={}
7
+ puts "creating node #{params}"
8
+ @id =params["id"]
9
+ @radius=params["radius"] || rand(5..10)
10
+ @pos =Vector.new *params["pos"]
11
+ @speed =Vector.new *(params["speed"] || [0,0])
12
+ @fixed =Vector.new *(params["fixed"] || [false,false])
13
+ @dims =Vector.new *(params["dims"] || [10,5])
14
+ end
15
+
16
+ def x=(v)
17
+ @pos[0]=v
18
+ end
19
+
20
+ def y=(v)
21
+ @pos[1]=v
22
+ end
23
+
24
+ def x
25
+ @pos.first
26
+ end
27
+
28
+ def y
29
+ @pos.last
30
+ end
31
+
32
+ def print_info
33
+ pp "node #{@id} : pos=#{@pos},dims=#{@dims},v=#{@velocity}"
34
+ end
35
+ end
36
+
37
+ class Edge
38
+ attr_accessor :source,:sink
39
+ def initialize params={}
40
+ unless params.empty?
41
+ @source=params["source"]
42
+ @sink =params["sink"]
43
+ puts "creating edge #{@source.id}-->#{@sink.id}"
44
+ end
45
+ end
46
+ end
47
+
48
+ class Graph
49
+
50
+ attr_accessor :nodes,:id,:edges,:map
51
+
52
+ def initialize id=nil,nodes=[],edges=[]
53
+ @id=id
54
+ @nodes,@edges=nodes,edges
55
+ end
56
+
57
+ def self.read_file filename
58
+ Parser.new.parse filename
59
+ end
60
+
61
+ def write_file filename
62
+ json=Code.new
63
+ json << "{"
64
+ json.indent=2
65
+ json << "\"id\" : \"#{id}\","
66
+ json << "\"nodes\" : ["
67
+ json.indent=4
68
+ nodes.each{|node| json << json_node(node)}
69
+ json.indent=2
70
+ json << "],"
71
+ json << "\"edges\" : ["
72
+ json.indent=4
73
+ edges.each{|edge| json << json_edge(edge)}
74
+ json.indent=2
75
+ json << "]"
76
+ json.indent=0
77
+ json << "}"
78
+ code=json.finalize
79
+ code.gsub!(/\,\s*\]/,']')
80
+ json=Code.new(code)
81
+ json.save_as filename
82
+ end
83
+
84
+ def json_node node
85
+ fixed=node.fixed.to_s
86
+ "{\"id\":\"#{node.id}\",\"pos\":#{node.pos.to_s},\"speed\":#{node.speed.to_s},\"fixed\":#{fixed}},"
87
+ end
88
+
89
+ def json_edge edge
90
+ "{\"source\":\"#{edge.source.id}\",\"sink\":\"#{edge.sink.id}\"},"
91
+ end
92
+
93
+ def self.random(nbVertex,maxNbEdgesPerVertex=2)
94
+ nodes=(1..nbVertex).map{|i|
95
+ h={
96
+ "id" => "#{i}",
97
+ "pos"=> [rand(1000),rand(1000)]
98
+ }
99
+ Node.new(h)
100
+ }
101
+ edges=[]
102
+ nodes.each_with_index do |node,idx|
103
+ nb_edges=rand(0..maxNbEdgesPerVertex)
104
+ nb_edges.times do
105
+ edge=Edge.new
106
+ edge.source=node
107
+ edge.sink=sink=nodes.sample
108
+ (edges << edge) unless nodes.index(sink)==idx
109
+ end
110
+ end
111
+ Graph.new("g",nodes,edges)
112
+ end
113
+
114
+ def shuffle range=0..800
115
+ @nodes.each do |node|
116
+ nx,ny=rand(range),rand(range)
117
+ node.pos=Vector.new(nx,ny)
118
+ end
119
+ end
120
+
121
+ def print_info
122
+ puts "graph info".center(40,"=")
123
+ puts "#vertices".ljust(30,'.')+nodes.size.to_s
124
+ puts "#edges".ljust(30,'.')+edges.size.to_s
125
+
126
+ puts "nodes".center(40,'-')
127
+ nodes.each do |node|
128
+ puts "#{node.id.ljust(10)} #{node.pos.x} #{node.pos.y}"
129
+ end
130
+ puts "edges".center(40,'-')
131
+ edges.each do |edge|
132
+ puts "#{edge.source.id} --> #{edge.sink.id}"
133
+ end
134
+ end
135
+
136
+ def self.rand_between min,max
137
+ (min..max).to_a.sample
138
+ end
139
+
140
+ def self.random_pos(maxx=800,maxy=600)
141
+ x,y=maxx/2,maxy/2
142
+ [self.rand_between(-x,x),self.rand_between(-y,y)]
143
+ end
144
+
145
+ def each_vertex &block
146
+ @nodes.each do |node|
147
+ yield node
148
+ end
149
+ end
150
+
151
+ def each_edge &block
152
+ @edges.each do |edge|
153
+ yield edge
154
+ end
155
+ end
156
+ end
@@ -0,0 +1,49 @@
1
+ require "json"
2
+
3
+ require_relative 'graph'
4
+
5
+ class Parser
6
+ def parse filename
7
+ puts "parsing '#{filename}'"
8
+ json=JSON.parse(IO.read(filename))
9
+ gen_graph json
10
+ end
11
+
12
+ def gen_graph json
13
+ @sym={}
14
+ graph=Graph.new
15
+ json.each do |key,val|
16
+ case key
17
+ when "id"
18
+ graph.id=val
19
+ when "nodes"
20
+ graph.nodes=gen_nodes(val)
21
+ when "edges"
22
+ graph.edges=gen_edges(val)
23
+ end
24
+ end
25
+ return graph
26
+ end
27
+
28
+ def gen_nodes json
29
+ json.map{|j| gen_node(j)}
30
+ end
31
+
32
+ def gen_node json
33
+ node=Node.new(json)
34
+ @sym[node.id]=node
35
+ node
36
+ end
37
+
38
+ def gen_edges json
39
+ json.map{|j| gen_edge(j)}
40
+ end
41
+
42
+ def gen_edge json
43
+ a=json.map{|k,v| {k => @sym[v]}}
44
+ Edge.new(a.inject(:merge))
45
+ end
46
+
47
+ end
48
+
49
+ #pp Parser.new.parse("line.sexp")
data/lib/rtl/placer.rb ADDED
@@ -0,0 +1,179 @@
1
+ require_relative "fdgd"
2
+ require_relative 'code'
3
+
4
+ module RTL
5
+
6
+ class Placer
7
+
8
+ attr_accessor :circuit
9
+
10
+ def place circuit
11
+ puts "placing '#{circuit.name}'"
12
+ @circuit=circuit
13
+ puts "creating p&r graph"
14
+ nodes=gen_pnr_nodes(circuit)
15
+ edges=gen_pnr_edges(circuit)
16
+ graph=Graph.new(circuit.name,nodes,edges)
17
+ graph.print_info
18
+ drawer=Fdgd.new(graph)
19
+ drawer.run 100
20
+ puts "final placement".center(40,'=')
21
+ graph.write_file "#{circuit.name}.json"
22
+ gen_svg graph
23
+ end
24
+
25
+
26
+ def gen_pnr_nodes circuit
27
+ nodes=[]
28
+ @sym={} # internal references for p&r
29
+ @map={} # link to RTL::Circuit objects
30
+ circuit.inputs.each_with_index do |port,idx|
31
+ id=port.object_id.to_s
32
+ dy=600.0/circuit.inputs.size
33
+ params={"id" => id,
34
+ "pos" => [10,idx*dy],
35
+ "fixed" => [true,false],
36
+ }
37
+ nodes << node=Node.new(params)
38
+ @sym[id]=node
39
+ @map[node]=port
40
+ end
41
+ circuit.outputs.each_with_index do |port,idx|
42
+ id=port.object_id.to_s
43
+ dy=600.0/circuit.outputs.size
44
+ params={"id" => id,
45
+ "pos" => [500,dy*idx],
46
+ "fixed" => [true,false],
47
+ }
48
+ nodes << node=Node.new(params)
49
+ @sym[id]=node
50
+ @map[node]=port
51
+ end
52
+ circuit.signals.each do |port|
53
+ id=port.object_id.to_s
54
+ params={"id" => id,
55
+ "pos" => [rand(600),rand(600)]
56
+ }
57
+ nodes << node=Node.new(params)
58
+ @sym[id]=node
59
+ @map[node]=port
60
+ end
61
+ circuit.components.each do |comp|
62
+ id=comp.object_id.to_s
63
+ params={"id" => id,
64
+ "pos" => [rand(300),rand(300)],
65
+ }
66
+ nodes << node=Node.new(params)
67
+ @sym[id]=node
68
+ @map[node]=comp
69
+ end
70
+ nodes
71
+ end
72
+
73
+ def gen_pnr_edges circuit
74
+ edges=[]
75
+ circuit.inputs.each do |input|
76
+ input.fanout.each do |wire|
77
+ psource=wire.source
78
+ if psource.circuit==circuit #psink is a port of current circuit
79
+ source=psource
80
+ else
81
+ source=psource.circuit # one of the components
82
+ end
83
+ psink=wire.sink
84
+ if psink.circuit==circuit #psink is a port of current circuit
85
+ sink=psink
86
+ else
87
+ sink=psink.circuit # one of the components
88
+ end
89
+ id_source=source.object_id.to_s
90
+ id_sink =sink.object_id.to_s
91
+ node_source=@sym[id_source]
92
+ node_sink=@sym[id_sink]
93
+ params={"source" => node_source,
94
+ "sink" => node_sink
95
+ }
96
+ edges << Edge.new(params)
97
+ end
98
+ end
99
+ circuit.signals.each do |sig|
100
+ sig.fanout.each do |wire|
101
+ psource=wire.source
102
+ if psource.circuit==circuit #psink is a port of current circuit
103
+ source=psource
104
+ else
105
+ source=psource.circuit # one of the components
106
+ end
107
+ psink=wire.sink
108
+ if psink.circuit==circuit #psink is a port of current circuit
109
+ sink=psink
110
+ else
111
+ sink=psink.circuit # one of the components
112
+ end
113
+ id_source=source.object_id.to_s
114
+ id_sink =sink.object_id.to_s
115
+ node_source=@sym[id_source]
116
+ node_sink=@sym[id_sink]
117
+ params={"source" => node_source,
118
+ "sink" => node_sink
119
+ }
120
+ edges << Edge.new(params)
121
+ end
122
+ end
123
+ circuit.components.each do |comp|
124
+ comp.outputs.each do |output|
125
+ output.fanout.each do |wire|
126
+ psource=wire.source
127
+ if psource.circuit==circuit #psink is a port of current circuit
128
+ source=psource
129
+ else
130
+ source=psource.circuit # one of the components
131
+ end
132
+ psink=wire.sink
133
+ if psink.circuit==circuit #psink is a port of current circuit
134
+ sink=psink
135
+ else
136
+ sink=psink.circuit # one of the components
137
+ end
138
+ id_source=source.object_id.to_s
139
+ id_sink =sink.object_id.to_s
140
+ node_source=@sym[id_source]
141
+ node_sink=@sym[id_sink]
142
+ params={"source" => node_source,
143
+ "sink" => node_sink
144
+ }
145
+ edges << Edge.new(params)
146
+ end
147
+ end
148
+ end
149
+ edges
150
+ end
151
+
152
+ SVG_ELEMENT={
153
+ "and" => "and2",
154
+ "nand" => "nand2",
155
+ "or" => "or2",
156
+ "nor" => "nor2",
157
+ "xor" => "xor2",
158
+ "not" => "not",
159
+ }
160
+ def gen_svg graph
161
+ svg=Code.new
162
+ svg << "<svg width=\"600\" height=\"300\""
163
+ svg << " xmlns=\"http://www.w3.org/2000/svg\""
164
+ svg << " xmlns:xlink=\"http://www.w3.org/1999/xlink\">"
165
+ svg << IO.read("/home/jcll/JCLL/dev/EDA-ESL/rtl/lib/rtl/def_gates.svg")
166
+ graph.nodes.each do |node|
167
+ circuit=@map[node]
168
+ klass=circuit.class.to_s.split("::").last.downcase
169
+ element=SVG_ELEMENT[klass] || "not"
170
+ pos=node.pos
171
+ x,y=pos.x,pos.y
172
+ svg << "<use xlink:href=\"##{element}\" x=\"#{x}\" y=\"#{y}\"/>"
173
+ end
174
+ svg << "</svg>"
175
+ filename="#{circuit.name}_pnr.svg"
176
+ svg.save_as filename
177
+ end
178
+ end
179
+ end
data/lib/rtl/printer.rb CHANGED
@@ -12,7 +12,7 @@ module RTL
12
12
  circuit.components.each do |comp|
13
13
  inputs_dot ="{"+comp.ports[:in].collect{|e| "<#{e.name}>#{e.name}"}.join("|")+"}"
14
14
  outputs_dot="{"+comp.ports[:out].collect{|e| "<#{e.name}>#{e.name}"}.join("|")+"}"
15
- p color=circuit.color
15
+ color=circuit.color
16
16
  dot << "#{comp.iname}[ shape=record; style=filled ; color=#{color} ; label=\"{ #{inputs_dot}| #{comp.name} | #{outputs_dot} }\"];"
17
17
  end
18
18
  circuit.ports[:in].each do |p|
data/lib/rtl/vector.rb ADDED
@@ -0,0 +1,66 @@
1
+ class Vector
2
+ def initialize x=nil,y=nil
3
+ @array=[x,y]
4
+ end
5
+
6
+ def x
7
+ return @array[0]
8
+ end
9
+
10
+ def y
11
+ return @array[1]
12
+ end
13
+
14
+ def x=(v)
15
+ @array[0]=v
16
+ end
17
+
18
+ def y=(v)
19
+ @array[1]=v
20
+ end
21
+
22
+ def first
23
+ @array.first
24
+ end
25
+
26
+ def last
27
+ @array.last
28
+ end
29
+
30
+ def [](idx)
31
+ @array[idx]
32
+ end
33
+
34
+ def []=(idx,val)
35
+ @array[idx]=val
36
+ end
37
+
38
+ def +(other)
39
+ res=Vector.new
40
+ @array.each_with_index do |e,i|
41
+ res[i]=e + other[i]
42
+ end
43
+ return res
44
+ end
45
+
46
+ def scale int
47
+ res=Vector.new
48
+ @array.each_with_index do |e,i|
49
+ res[i]=e*int
50
+ end
51
+ return res
52
+ end
53
+
54
+ def squared
55
+ res=0
56
+ @array.each do |e|
57
+ res+=e*e
58
+ end
59
+ return res
60
+ end
61
+
62
+ def to_s
63
+ "[#{@array.join(',')}]"
64
+ end
65
+
66
+ end
data/lib/rtl/viewer.rb ADDED
@@ -0,0 +1,267 @@
1
+ require 'gtk3'
2
+
3
+ require_relative 'fdgd'
4
+ require_relative 'canvas'
5
+
6
+ class Viewer < Gtk::Window
7
+
8
+ def initialize args={} # I want to show it's possible to pass some args
9
+ super() # mandatory parenthesis ! otherwise : wrong arguments: Gtk::Window#initialize({})
10
+ set_title 'jcll_3'
11
+ set_default_size 900,600
12
+ set_border_width 10
13
+ set_window_position :center
14
+ set_destroy_callback
15
+
16
+ @algorithm=Fdgd.new
17
+ @zoom_factor=1
18
+ @shift=Vector.new(0,0)
19
+
20
+ hbox = Gtk::Box.new(:horizontal, spacing=6)
21
+ add hbox
22
+ @canvas = Canvas.new
23
+ hbox.pack_start(@canvas,:expand=>true,:fill=> true)
24
+ #...instead of :
25
+ # hbox.add canvas
26
+
27
+ vbox = Gtk::Box.new(:vertical,spacing=6)
28
+ hbox.add vbox
29
+
30
+ button = Gtk::Button.new(label:"open")
31
+ button.signal_connect("clicked"){on_open_clicked(button)}
32
+ vbox.pack_start(button,:expand => false, :fill => false, :padding => 0)
33
+
34
+ button = Gtk::Button.new(label:"random graph")
35
+ button.signal_connect("clicked"){on_random_clicked(button)}
36
+ vbox.pack_start(button,:expand => false, :fill => false, :padding => 0)
37
+
38
+ label = Gtk::Label.new("number of nodes : ")
39
+
40
+ vbox.pack_start(label,:expand => false, :fill => false, :padding => 0)
41
+
42
+ spinner = Gtk::SpinButton.new(1,100,1)
43
+ spinner.value= @nb_value || 20
44
+ spinner.signal_connect("value-changed"){on_spin_changed(spinner)}
45
+ vbox.pack_start(spinner,:expand => false, :fill => false, :padding => 0)
46
+
47
+ button = Gtk::Button.new(:label => "run")
48
+ button.signal_connect("clicked"){on_run_clicked(button)}
49
+ vbox.pack_start(button,:expand => false, :fill => false, :padding => 0)
50
+
51
+ button = Gtk::Button.new(:label => "stop")
52
+ button.signal_connect("clicked"){on_stop_clicked(button)}
53
+ vbox.pack_start(button,:expand => false, :fill => false, :padding => 0)
54
+
55
+ button = Gtk::Button.new(:label => "step")
56
+ button.signal_connect("clicked"){on_step_clicked(button)}
57
+ vbox.pack_start(button,:expand => false, :fill => false, :padding => 0)
58
+
59
+ button = Gtk::Button.new(:label => "shuffle")
60
+ button.signal_connect("clicked"){on_shuffle_clicked(button)}
61
+ vbox.pack_start(button,:expand => false, :fill => false, :padding => 0)
62
+
63
+ button = Gtk::Button.new(:label => "center")
64
+ button.signal_connect("clicked"){on_center_clicked(button)}
65
+ vbox.pack_start(button,:expand => false, :fill => false, :padding => 0)
66
+
67
+ button = Gtk::Button.new(:label => "zoom+")
68
+ button.signal_connect("clicked"){on_zoom_clicked(button)}
69
+ vbox.pack_start(button,:expand => false, :fill => false, :padding => 0)
70
+
71
+ button = Gtk::Button.new(:label => "zoom-")
72
+ button.signal_connect("clicked"){on_unzoom_clicked(button)}
73
+ vbox.pack_start(button,:expand => false, :fill => false, :padding => 0)
74
+
75
+ button = Gtk::Button.new(:label => "zoom fit")
76
+ button.signal_connect("clicked"){on_fit_clicked(button)}
77
+ vbox.pack_start(button,:expand => false, :fill => false, :padding => 0)
78
+
79
+ button = Gtk::Button.new(:label => "save")
80
+ button.signal_connect("clicked"){on_save_clicked(button)}
81
+ vbox.pack_start(button,:expand => false, :fill => false, :padding => 0)
82
+
83
+ button = Gtk::Button.new(:label => "quit")
84
+ button.signal_connect("clicked"){on_quit_clicked(button)}
85
+ vbox.pack_start(button,:expand => false, :fill => false, :padding => 0)
86
+ show_all
87
+ end
88
+
89
+ def on_open_clicked button
90
+ puts '"open" button was clicked'
91
+ dialog=Gtk::FileChooserDialog.new(
92
+ :title => "choose",
93
+ :parent => self,
94
+ :action => Gtk::FileChooserAction::OPEN,
95
+ :buttons => [[Gtk::Stock::OPEN, Gtk::ResponseType::ACCEPT],
96
+ [Gtk::Stock::CANCEL, Gtk::ResponseType::CANCEL]])
97
+ filter_json = Gtk::FileFilter.new
98
+ filter_json.name = "json filter"
99
+ filter_json.add_pattern("*.json")
100
+ dialog.add_filter(filter_json)
101
+
102
+ dialog.show_all
103
+
104
+ case dialog.run
105
+ when Gtk::ResponseType::ACCEPT
106
+ puts "filename = #{dialog.filename}"
107
+ #puts "uri = #{dialog.uri}"
108
+ @graph=Graph.read_file dialog.filename
109
+ puts @graph
110
+ @canvas.redraw @graph
111
+ set_title @graph.id
112
+ dialog.destroy
113
+ else
114
+ dialog.destroy
115
+ end
116
+ end
117
+
118
+ def on_random_clicked button
119
+ puts 'button "random" clicked'
120
+ set_title "random"
121
+ @graph=Graph.random(@nb_nodes || 20)
122
+ @canvas.running=true
123
+ @canvas.redraw @graph,@zoom_factor,@shift
124
+ end
125
+
126
+ def on_spin_changed spinbutton
127
+ value=spinbutton.value
128
+ puts "spin button modified #{value}"
129
+ @nb_nodes=value.to_i
130
+ @graph=Graph.random(value.to_i)
131
+ @canvas.running=true
132
+ @canvas.redraw @graph
133
+ end
134
+
135
+ def on_run_clicked button
136
+ puts 'button "run" clicked'
137
+ @canvas.running=true
138
+ @algorithm.stop=false
139
+ @algorithm.graph=@graph
140
+ @algorithm.run(iter=1000){@canvas.redraw @graph,@zoom_factor,@shift}
141
+ end
142
+
143
+ def on_stop_clicked button
144
+ puts 'button "stop" clicked'
145
+ @algorithm.stop=true
146
+ end
147
+
148
+ def on_step_clicked button
149
+ puts 'button "step" clicked'
150
+ @algorithm.run(iter=1){@canvas.redraw @graph,@zoom_factor,@shift}
151
+ end
152
+
153
+ def on_shuffle_clicked button
154
+ puts 'button "shuffle" clicked'
155
+ if @graph
156
+ @graph.shuffle
157
+ @canvas.redraw @graph,@zoom_factor,@shift
158
+ end
159
+ end
160
+
161
+ def on_center_clicked button
162
+ puts 'button "center" clicked'
163
+ if @graph
164
+ compute_shift get_enclosing_rect
165
+ @canvas.redraw @graph,@zoom_factor,@shift
166
+ end
167
+ end
168
+
169
+ def on_zoom_clicked button
170
+ puts 'button "zoom" clicked'
171
+ if @graph
172
+ @zoom_factor*=1.2
173
+ @canvas.redraw @graph,@zoom_factor,@shift
174
+ end
175
+ end
176
+
177
+ def on_unzoom_clicked button
178
+ puts 'button "unzoom" clicked'
179
+ if @graph
180
+ @zoom_factor/=1.2
181
+ @canvas.redraw @graph,@zoom_factor,@shift
182
+ end
183
+ end
184
+
185
+ def on_fit_clicked button
186
+ puts 'button "fit" clicked'
187
+ if @graph
188
+ compute_zoom_and_shift
189
+ @canvas.redraw @graph,@zoom_factor,@shift
190
+ end
191
+ end
192
+
193
+ def get_enclosing_rect
194
+ min_x=@graph.nodes.min_by{|node| node.x}.x
195
+ min_y=@graph.nodes.min_by{|node| node.y}.y
196
+ max_x=@graph.nodes.max_by{|node| node.x}.x
197
+ max_y=@graph.nodes.max_by{|node| node.y}.y
198
+ [Vector.new(min_x,min_y),Vector.new(max_x,max_y)]
199
+ end
200
+
201
+ def compute_zoom_and_shift
202
+ enclosing_rect=get_enclosing_rect()
203
+ compute_zoom(enclosing_rect)
204
+ compute_shift(enclosing_rect)
205
+ end
206
+
207
+ def compute_zoom enclosing_rect
208
+ min_x=enclosing_rect.first.x
209
+ min_y=enclosing_rect.first.y
210
+ max_x=enclosing_rect.last.x
211
+ max_y=enclosing_rect.last.y
212
+
213
+ graph_size=[(max_x-min_x).abs,(max_y-min_y).abs]
214
+ canvas_size=[@canvas.allocation.width,@canvas.allocation.height]
215
+ ratios=[(canvas_size.first.to_f)/graph_size.first,(canvas_size.last.to_f)/graph_size.last]
216
+ @zoom_factor=ratios.min*0.8
217
+ puts "zoom=#{@zoom_factor}"
218
+ end
219
+
220
+ def compute_shift enclosing_rect
221
+ rect_center_x=(enclosing_rect.first.x+enclosing_rect.last.x)/2.0
222
+ rect_center_y=(enclosing_rect.first.y+enclosing_rect.last.y)/2.0
223
+ @shift=Vector.new(-rect_center_x,-rect_center_y)
224
+ end
225
+
226
+ def on_save_clicked button
227
+ puts 'button "save" clicked'
228
+
229
+ dialog=Gtk::FileChooserDialog.new(
230
+ :title => "choose",
231
+ :parent => self,
232
+ :action => Gtk::FileChooserAction::SAVE,
233
+ :buttons => [[Gtk::Stock::SAVE, Gtk::ResponseType::ACCEPT],
234
+ [Gtk::Stock::CANCEL, Gtk::ResponseType::CANCEL]])
235
+ filter_sexp = Gtk::FileFilter.new
236
+ filter_sexp.name = "s-expr filter"
237
+ filter_sexp.add_pattern("*.sexp")
238
+ filter_sexp.add_pattern("*.sxp")
239
+ dialog.add_filter(filter_sexp)
240
+
241
+ dialog.show_all
242
+
243
+ case dialog.run
244
+ when Gtk::ResponseType::ACCEPT
245
+ puts "filename = #{dialog.filename}"
246
+ #puts "uri = #{dialog.uri}"
247
+ @graph.id=File.basename(dialog.filename,'.sexp')
248
+ @graph.write_file dialog.filename
249
+ dialog.destroy
250
+ else
251
+ dialog.destroy
252
+ end
253
+ end
254
+
255
+ def on_quit_clicked button
256
+ puts "Closing application"
257
+ Gtk.main_quit
258
+ end
259
+
260
+ def set_destroy_callback
261
+ signal_connect("destroy"){Gtk.main_quit}
262
+ end
263
+
264
+ end
265
+
266
+ window=Viewer.new
267
+ Gtk.main
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rtl_circuit
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.7'
4
+ version: 0.7.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jean-Christophe Le Lann
@@ -17,10 +17,18 @@ extensions: []
17
17
  extra_rdoc_files: []
18
18
  files:
19
19
  - lib/rtl.rb
20
+ - lib/rtl/canvas.rb
20
21
  - lib/rtl/circuit.rb
21
22
  - lib/rtl/code.rb
23
+ - lib/rtl/def_gates.svg
24
+ - lib/rtl/fdgd.rb
25
+ - lib/rtl/graph.rb
26
+ - lib/rtl/json_parser.rb
22
27
  - lib/rtl/library.rb
28
+ - lib/rtl/placer.rb
23
29
  - lib/rtl/printer.rb
30
+ - lib/rtl/vector.rb
31
+ - lib/rtl/viewer.rb
24
32
  - tests/json/testing_json.rb
25
33
  - tests/pnr/pnr_0.rb
26
34
  - tests/pnr/pnr_1.rb