rtl_circuit 0.7 → 0.7.4

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