HDLRuby 3.9.1 → 3.9.5

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.
@@ -1,4 +1,4 @@
1
- # An IC netlist mrdel and SVG-based vizualizer for HDLRuby
1
+ # An IC netlist model and SVG-based vizualizer for HDLRuby
2
2
 
3
3
  # require 'stackprof'
4
4
 
@@ -12,6 +12,21 @@ module HDLRuby::Viz
12
12
  DOWN = 8
13
13
  BLOCKED = 16
14
14
 
15
+ # Get the base name of the port.
16
+ def self.port_base_name(name)
17
+ return name.sub(/\[.*\]\z/,"")
18
+ end
19
+
20
+ # Get the bit part of the port name if any.
21
+ def self.port_bit_name(name)
22
+ return name.match(/\[.*\]\z/)[0]
23
+ end
24
+
25
+ # Tell if a port name is for a sub port.
26
+ def self.port_bit_name?(name)
27
+ return name =~ /\[.*\]\z/
28
+ end
29
+
15
30
 
16
31
  # An IC Port
17
32
  class Port
@@ -71,6 +86,7 @@ module HDLRuby::Viz
71
86
  @cwidths = [] # The widths of each column in number of routes
72
87
  # @border = 2 # The IC border size for routing to external ports.
73
88
  @border = 4 # The IC border size for routing to external ports.
89
+ # @cell_border = 4 # The cell border size
74
90
  @cell_border = 4 # The cell border size
75
91
  @routes = [] # The connection routes.
76
92
  @port_width = 3 # The width in tiles for a port
@@ -110,6 +126,9 @@ module HDLRuby::Viz
110
126
 
111
127
  # Give the size of the IC in number of statements.
112
128
  def number_statements
129
+ if self.type == :instance then
130
+ return self.system.number_statements
131
+ end
113
132
  # Get the number from the branches.
114
133
  snum = @branches.reduce(0) do |sum,branch|
115
134
  sum + branch.number_statements
@@ -118,6 +137,7 @@ module HDLRuby::Viz
118
137
  snum += @children.reduce(0) do |sum,child|
119
138
  sum + child.number_statements
120
139
  end
140
+ return snum
121
141
  end
122
142
 
123
143
 
@@ -153,8 +173,8 @@ module HDLRuby::Viz
153
173
 
154
174
  # Compute the distance between to IC.
155
175
  def distance(ic0,ic1)
156
- res = Math.sqrt((ic0.xpos-ic1.xpos)**2+(ic0.ypos-ic1.ypos)**2)
157
- # res = (ic0.xpos-ic1.xpos).abs+(ic0.ypos-ic1.ypos).abs
176
+ # res = Math.sqrt((ic0.xpos-ic1.xpos)**2+(ic0.ypos-ic1.ypos)**2)
177
+ res = (ic0.xpos-ic1.xpos).abs+(ic0.ypos-ic1.ypos).abs
158
178
  return res
159
179
  end
160
180
 
@@ -269,43 +289,54 @@ module HDLRuby::Viz
269
289
  @uports.clear
270
290
  @rports.clear
271
291
  @dports.clear
292
+ # Ports sides by direction and base name.
293
+ @port_base_dir = {}
294
+ # Process the ports.
272
295
  @ports.each do |port|
273
- if port.targets.empty? then
274
- puts "Dangling port: #{port.name} (of #{port.ic.name})"
275
- # Not connected port, put it on the side with the less ports.
276
- if port.direction == :input then
277
- if lports.size <= uports.size then
278
- port.side = LEFT
279
- else
280
- port.side = UP
281
- end
282
- else
283
- if rports.size <= dports.size then
284
- port.side = RIGHT
285
- else
286
- port.side = DOWN
287
- end
288
- end
296
+ # Maybe there is a port with the same direction.
297
+ side = @port_base_dir[[HDLRuby::Viz.port_base_name(port.name),
298
+ port.direction]]
299
+ if side then
300
+ port.side = side
289
301
  else
290
- # The port is connected.
291
- if port.direction == :input then
292
- # For now, use the first target only for deciding.
293
- d_left = port.targets[0].ic.xpos - @box[0]
294
- d_up = @box[3] -
295
- port.targets[0].ic.ypos + port.targets[0].ic.height
296
- if d_left <= d_up then
297
- port.side = LEFT
302
+ # No, process to port.
303
+ if port.targets.empty? then
304
+ puts "Dangling port: #{port.name} (of #{port.ic.name})"
305
+ # Not connected port, put it on the side with the less ports.
306
+ if port.direction == :input then
307
+ if lports.size <= uports.size then
308
+ port.side = LEFT
309
+ else
310
+ port.side = UP
311
+ end
298
312
  else
299
- port.side = UP
313
+ if rports.size <= dports.size then
314
+ port.side = RIGHT
315
+ else
316
+ port.side = DOWN
317
+ end
300
318
  end
301
319
  else
302
- d_right = @box[2] -
303
- port.targets[0].ic.xpos + port.targets[0].ic.width
304
- d_down = port.targets[0].ic.ypos - @box[1]
305
- if d_right <= d_down then
306
- port.side = RIGHT
320
+ # The port is connected.
321
+ if port.direction == :input then
322
+ # For now, use the first target only for deciding.
323
+ d_left = port.targets[0].ic.xpos - @box[0]
324
+ d_up = @box[3] -
325
+ port.targets[0].ic.ypos + port.targets[0].ic.height
326
+ if d_left <= d_up then
327
+ port.side = LEFT
328
+ else
329
+ port.side = UP
330
+ end
307
331
  else
308
- port.side = DOWN
332
+ d_right = @box[2] -
333
+ port.targets[0].ic.xpos + port.targets[0].ic.width
334
+ d_down = port.targets[0].ic.ypos - @box[1]
335
+ if d_right <= d_down then
336
+ port.side = RIGHT
337
+ else
338
+ port.side = DOWN
339
+ end
309
340
  end
310
341
  end
311
342
  end
@@ -321,13 +352,17 @@ module HDLRuby::Viz
321
352
  when DOWN
322
353
  @dports << port
323
354
  end
355
+ # Also for the handling of bits.
356
+ @port_base_dir[[HDLRuby::Viz.port_base_name(port.name),
357
+ port.direction]] = port.side
324
358
  end
325
359
  end
326
360
 
327
361
 
328
362
  # Select the side of the ports of the children according to the
329
363
  # position of their targets.
330
- def side_children
364
+ # def side_children
365
+ def side_children(ic_matrix_coordinates)
331
366
  @children.each do |child|
332
367
  puts "side_children for child=#{child.name} with #{child.ports.size} ports"
333
368
  # Resets the port sides.
@@ -339,8 +374,9 @@ module HDLRuby::Viz
339
374
  # (Information used for certain types of IC).
340
375
  left_for, up_for, right_for, down_for = nil, nil, nil, nil
341
376
  # Recompute the ports sides.
342
- cx = child.xpos
343
- cy = child.ypos
377
+ # cx = child.xpos
378
+ # cy = child.ypos
379
+ cx,cy = ic_matrix_coordinates[child]
344
380
  child.ports.each do |port|
345
381
  puts "For port: #{port.name} (of #{port.ic.name})"
346
382
  unless left_for || up_for || right_for || down_for then
@@ -365,58 +401,89 @@ module HDLRuby::Viz
365
401
  # Current IC, do not use its position, but the side.
366
402
  case port.targets[0].side
367
403
  when LEFT
368
- tx = cx + 1.0
404
+ # tx = cx + 1.0
405
+ tx = cx + 1
369
406
  ty = cy
370
407
  when UP
371
408
  tx = cx
372
- ty = -cy - 1.0
409
+ # ty = -cy - 1.0
410
+ ty = -cy - 1
373
411
  when RIGHT
374
- tx = -cx - 1.0
412
+ # tx = -cx - 1.0
413
+ tx = -cx - 1
375
414
  ty = cy
376
415
  when DOWN
377
416
  tx = cx
378
- ty = cy + 1.0
417
+ # ty = cy + 1.0
418
+ ty = cy + 1
379
419
  end
380
420
  else
381
- tx = port.targets[0].ic.xpos
382
- ty = port.targets[0].ic.ypos
421
+ # tx = port.targets[0].ic.xpos
422
+ # ty = port.targets[0].ic.ypos
423
+ tx,ty = ic_matrix_coordinates[port.targets[0].ic]
383
424
  end
384
425
  dx = cx-tx
385
426
  dy = cy-ty
386
- if dx > 0 then
427
+ puts "cx=#{cx} cy=#{cy} tx=#{tx} ty=#{ty} dx=#{dx} dy=#{dy}"
428
+ if dx == 0 then
429
+ if dy > 0 then
430
+ port.side = this_port ? UP : DOWN
431
+ else
432
+ port.side = this_port ? DOWN : UP
433
+ end
434
+ elsif dy == 0 then
435
+ if dx > 0 then
436
+ port.side = this_port ? RIGHT : LEFT
437
+ else
438
+ port.side = this_port ? LEFT : RIGHT
439
+ end
440
+
441
+ # if dx > 0 then
442
+ elsif dx > 0 then
443
+ # if dy > 0 then
444
+ # if dx > dy then
445
+ # port.side = this_port ? RIGHT : LEFT
446
+ # else
447
+ # port.side = this_port ? UP : DOWN
448
+ # end
449
+ # else
450
+ # if dx > -dy then
451
+ # port.side = this_port ? RIGHT : LEFT
452
+ # else
453
+ # port.side = this_port ? DOWN : UP
454
+ # end
455
+ # end
387
456
  if dy > 0 then
388
- if dx > dy then
389
- port.side = this_port ? RIGHT : LEFT
390
- else
391
- port.side = this_port ? UP : DOWN
392
- end
457
+ port.side = this_port ? RIGHT : LEFT
393
458
  else
394
- if dx > -dy then
395
- port.side = this_port ? RIGHT : LEFT
396
- else
397
- port.side = this_port ? DOWN : UP
398
- end
459
+ # port.side = this_port ? UP : DOWN
460
+ port.side = this_port ? DOWN : UP
399
461
  end
400
462
  else
463
+ # if dy > 0 then
464
+ # if -dx > dy then
465
+ # port.side = this_port ? LEFT : RIGHT
466
+ # else
467
+ # port.side = this_port ? UP : DOWN
468
+ # end
469
+ # else
470
+ # if -dx > -dy then
471
+ # port.side = this_port ? LEFT : RIGHT
472
+ # else
473
+ # port.side = this_port ? DOWN : UP
474
+ # end
475
+ # end
401
476
  if dy > 0 then
402
- if -dx > dy then
403
- port.side = this_port ? LEFT : RIGHT
404
- else
405
- port.side = this_port ? UP : DOWN
406
- end
477
+ port.side = this_port ? LEFT : RIGHT
407
478
  else
408
- if -dx > -dy then
409
- port.side = this_port ? LEFT : RIGHT
410
- else
411
- port.side = this_port ? DOWN : UP
412
- end
479
+ port.side = this_port ? DOWN : UP
413
480
  end
414
481
  end
415
482
  end
416
483
  end
417
484
  # Case of IC of type assign or register if a side is used for
418
485
  # output, the opposite must be used for input, and vice versa.
419
- if child.type == :assign or child.type == :register then
486
+ if child.type == :assign then # or child.type == :register then
420
487
  # puts "left_for=#{left_for} up_for=#{up_for} right_for=#{right_for} down_for=#{down_for}"
421
488
  if left_for then
422
489
  if port.direction == left_for then
@@ -675,6 +742,7 @@ module HDLRuby::Viz
675
742
  nd = child.dports.size * @port_width
676
743
  child.height = nl > nr ? nl : nr
677
744
  child.width = nu > nd ? nu : nd
745
+ puts "For assign" if child.type == :assign
678
746
  puts "First width=#{child.width} height=#{child.height} [#{child.lports.size},#{child.uports.size},#{child.rports.size},#{child.dports.size}]"
679
747
  # Ensure IC have some thickness.
680
748
  if child.type != :register then
@@ -684,15 +752,17 @@ module HDLRuby::Viz
684
752
  child.width = @port_width if child.width < @port_width
685
753
  # But enlarge if more than one port horizontally or
686
754
  # vertically for easier routing and readability.
687
- if child.lports.size + child.rports.size > 1 and
688
- child.height == @port_width and
689
- child.width == @port_width then
690
- child.width *= 2
691
- end
692
- if child.uports.size + child.dports.size > 1 and
693
- child.width == @port_width and
694
- child.height == @port_width then
695
- child.height *= 2
755
+ if child.type != :assign then # However assign are treated appart
756
+ if child.lports.size + child.rports.size > 1 and
757
+ child.height == @port_width and
758
+ child.width == @port_width then
759
+ child.width *= 2
760
+ end
761
+ if child.uports.size + child.dports.size > 1 and
762
+ child.width == @port_width and
763
+ child.height == @port_width then
764
+ child.height *= 2
765
+ end
696
766
  end
697
767
  # Also ensure the chip is wide enough.
698
768
  if child.type == :assign then
@@ -728,8 +798,9 @@ module HDLRuby::Viz
728
798
  child.height = 3 if child.height < @port_width
729
799
  child.width = 3 if child.width < @port_width
730
800
  end
731
- puts "for register: #{child.name} ports.size=#{child.ports.size}, width=#{child.width} height=#{child.height}"
801
+ # puts "for register: #{child.name} ports.size=#{child.ports.size}, width=#{child.width} height=#{child.height}"
732
802
  end
803
+ puts "Then width=#{child.width} height=#{child.height} [#{child.lports.size},#{child.uports.size},#{child.rports.size},#{child.dports.size}]"
733
804
 
734
805
  end
735
806
  end
@@ -759,6 +830,7 @@ module HDLRuby::Viz
759
830
  puts "With number of statements: #{num} are base area=#{area}"
760
831
  # First compute the target area, and width and height of each type.
761
832
  ics.each do |ic|
833
+ puts "For ic=#{ic.name}"
762
834
  # Update the target area.
763
835
  n_area = ic.width * ic.height
764
836
  area = n_area if n_area > area
@@ -782,11 +854,13 @@ module HDLRuby::Viz
782
854
  pH = ic.height if ic.height > pH
783
855
  # Ensure the target area is reached.
784
856
  if ic.branches[0].type == :par then
785
- # For par processes, increase squarely.
786
- if pW <= pH then
787
- pW += 1
788
- else
789
- pH += 1
857
+ while pW*pW < area do
858
+ # For par processes, increase squarely.
859
+ if pW <= pH then
860
+ pW += 1
861
+ else
862
+ pH += 1
863
+ end
790
864
  end
791
865
  else
792
866
  # For non par processes, increase vertically.
@@ -804,7 +878,7 @@ module HDLRuby::Viz
804
878
  if ic.type == :instance then
805
879
  ic.width = iW
806
880
  ic.height = iH
807
- else
881
+ elsif [:process, :clocked_process, :timed_process]. include?(ic.type) then
808
882
  puts "For process #{ic.name} setting size from #{ic.width},#{ic.height} to #{pW},#{pH}"
809
883
  ic.width = pW
810
884
  ic.height = pH
@@ -829,6 +903,10 @@ module HDLRuby::Viz
829
903
  cw = @cwidths[j]
830
904
  @cwidths[j] = child.width if child.width > cw
831
905
  @rheights[i] = child.height if child.height > rh
906
+ # fix_size = child.width > child.height ? child.width : child.height
907
+ # @cwidths[j] = fix_size if fix_size > cw
908
+ # @rheights[i] = fix_size if fix_size > rh
909
+
832
910
  end
833
911
  end
834
912
  # Increase the space to allow placing the routes.
@@ -885,9 +963,9 @@ module HDLRuby::Viz
885
963
  elsif child.lports.any? then
886
964
  step = child.height / child.lports.size
887
965
  child.lports.each_with_index do |port,i|
888
- puts "Preplace left port=#{port.name}"
889
966
  port.xpos = xpos
890
967
  port.ypos = ypos + i*step + step/2
968
+ puts "Preplace left port=#{port.name} ypos=#{port.ypos}"
891
969
  end
892
970
  end
893
971
  # The up ports.
@@ -899,9 +977,9 @@ module HDLRuby::Viz
899
977
  elsif child.uports.any? then
900
978
  step = child.width / child.uports.size
901
979
  child.uports.each_with_index do |port,i|
902
- puts "Preplace up port=#{port.name}"
903
980
  port.xpos = xpos + i*step + step/2
904
981
  port.ypos = ypos + height - 1
982
+ puts "Preplace up port=#{port.name} xpos=#{port.xpos}"
905
983
  end
906
984
  end
907
985
  # The right ports.
@@ -913,9 +991,9 @@ module HDLRuby::Viz
913
991
  elsif child.rports.any? then
914
992
  step = child.height / child.rports.size
915
993
  child.rports.each_with_index do |port,i|
916
- puts "Preplace right port=#{port.name}"
917
994
  port.xpos = xpos + width - 1
918
995
  port.ypos = ypos + i*step + step/2
996
+ puts "Preplace right port=#{port.name} ypos=#{port.ypos}"
919
997
  end
920
998
  end
921
999
  # The down ports.
@@ -927,13 +1005,14 @@ module HDLRuby::Viz
927
1005
  elsif child.dports.any? then
928
1006
  step = child.width / child.dports.size
929
1007
  child.dports.each_with_index do |port,i|
930
- puts "Preplace down port=#{port.name}"
931
1008
  port.xpos = xpos + i*step + step/2
932
1009
  port.ypos = ypos
1010
+ puts "Preplace down port=#{port.name} xpos=#{port.xpos}"
933
1011
  end
934
1012
  end
935
1013
  end
936
1014
 
1015
+ # TRUCMUCHE
937
1016
  # Optimize the place.
938
1017
  @children.each do |child|
939
1018
  xpos = child.xpos
@@ -946,11 +1025,11 @@ module HDLRuby::Viz
946
1025
  step = child.height / child.lports.size
947
1026
  lefts = child.lports.clone
948
1027
 
949
- # Sort the ports by reverse order y difference with their
1028
+ # Sort the ports by reverse order in difference with their
950
1029
  # targets.
951
1030
  lefts.sort! do |p0,p1|
952
- p0.targets.uniq {|t| t.ic }.reduce(0) {|sum,t| sum + t.ypos - p0.ypos } <=>
953
- p1.targets.uniq {|t| t.ic }.reduce(0) {|sum,t| sum + t.ypos - p1.ypos }
1031
+ p0.targets.uniq {|t| t.ic }.reduce(0) {|sum,t| sum + (t.ypos - p0.ypos).abs } <=>
1032
+ p1.targets.uniq {|t| t.ic }.reduce(0) {|sum,t| sum + (t.ypos - p1.ypos).abs }
954
1033
  end
955
1034
  # Apply the order.
956
1035
  lefts.each_with_index do |port,i|
@@ -967,8 +1046,8 @@ module HDLRuby::Viz
967
1046
  # Sort the ports by reverse order x difference with their
968
1047
  # targets.
969
1048
  ups.sort! do |p0,p1|
970
- p0.targets.uniq {|t| t.ic }.reduce(0) {|sum,t| sum + t.xpos - p0.xpos } <=>
971
- p1.targets.uniq {|t| t.ic }.reduce(0) {|sum,t| sum + t.xpos - p1.xpos }
1049
+ p0.targets.uniq {|t| t.ic }.reduce(0) {|sum,t| sum + (t.xpos - p0.xpos).abs } <=>
1050
+ p1.targets.uniq {|t| t.ic }.reduce(0) {|sum,t| sum + (t.xpos - p1.xpos).abs }
972
1051
  end
973
1052
  # Apply the order.
974
1053
  ups.each_with_index do |port,i|
@@ -986,8 +1065,8 @@ module HDLRuby::Viz
986
1065
  # targets.
987
1066
  rights.sort! do |p0,p1|
988
1067
  # puts "p0=#{p0.name} p1=#{p1.name}"
989
- p0.targets.uniq {|t| t.ic }.reduce(0) {|sum,t| sum + t.ypos - p0.ypos } <=>
990
- p1.targets.uniq {|t| t.ic }.reduce(0) {|sum,t| sum + t.ypos - p1.ypos }
1068
+ p0.targets.uniq {|t| t.ic }.reduce(0) {|sum,t| sum + (t.ypos - p0.ypos).abs } <=>
1069
+ p1.targets.uniq {|t| t.ic }.reduce(0) {|sum,t| sum + (t.ypos - p1.ypos).abs }
991
1070
  end
992
1071
  # Apply the order.
993
1072
  rights.each_with_index do |port,i|
@@ -1004,8 +1083,8 @@ module HDLRuby::Viz
1004
1083
  # Sort the ports by reverse order x difference with their
1005
1084
  # targets.
1006
1085
  downs.sort! do |p0,p1|
1007
- p0.targets.uniq {|t| t.ic }.reduce(0) {|sum,t| sum + t.xpos - p0.xpos } <=>
1008
- p1.targets.uniq {|t| t.ic }.reduce(0) {|sum,t| sum + t.xpos - p1.xpos }
1086
+ p0.targets.uniq {|t| t.ic }.reduce(0) {|sum,t| sum + (t.xpos - p0.xpos).abs } <=>
1087
+ p1.targets.uniq {|t| t.ic }.reduce(0) {|sum,t| sum + (t.xpos - p1.xpos).abs }
1009
1088
  end
1010
1089
  # Apply the order.
1011
1090
  downs.each_with_index do |port,i|
@@ -1021,112 +1100,8 @@ module HDLRuby::Viz
1021
1100
  # Also fine-place the ports of the current IC to also increase the
1022
1101
  # aligment of connected ports.
1023
1102
  def place_children_port_matrix
1024
- # xpos, ypos = 0, 0
1025
- # @matrix.each_with_index do |row,i|
1026
- # xpos = 0
1027
- # mypos = ypos + @rheights[i]
1028
- # row.each_with_index do |child,j|
1029
- # mxpos = xpos + @cwidths[j]
1030
- # if child then
1031
- # # Tune x position.
1032
- # # Find the best delta.
1033
- # bdx = 0 # Best y delta
1034
- # bcost = 1/0.0 # Best score
1035
- # xpos_in_cell = child.xpos - xpos # Initial position in cell
1036
- # xpos_in_cell -= @border if j == 0 # Do not go inside the border
1037
- # (@cwidths[j]-child.width).times do |dx|
1038
- # dx = dx - xpos_in_cell # Adjust delta x to the initial position
1039
- # cost = child.ports.reduce(0) do |sum,port|
1040
- # pxpos = port.xpos + dx
1041
- # sum + port.targets.reduce(0) do |subsum,tport|
1042
- # # There is cost when the port is not align with the target.
1043
- # if (port.side == LEFT and tport.side == RIGHT) or
1044
- # (port.side == UP and tport.side == UP) then
1045
- # # For left to right or up yo up connections,
1046
- # # the first side should be 2 tiles on the left for
1047
- # # straight wire or avoiding routing conjestion.
1048
- # subsum + (pxpos-tport.xpos-2) != 0 ? 1 : 0
1049
- # elsif (port.side == RIGHT and tport.side == LEFT) or
1050
- # (port.side == DOWN and tport.side == DOWN) then
1051
- # # For right to left or down to down connections,
1052
- # # the first side should be 2 tiles on the right for
1053
- # # straight wire or avoiding routing conjestion.
1054
- # subsum + (pxpos-tport.xpos+2) != 0 ? 1 : 0
1055
- # else
1056
- # # Otherwise, perfect aligment is the best.
1057
- # subsum + (pxpos-tport.xpos) != 0 ? 1 : 0
1058
- # end
1059
- # end
1060
- # end
1061
- # if cost < bcost then
1062
- # bcost = cost
1063
- # bdx = dx
1064
- # end
1065
- # end
1066
- # # Ensure the child does not goes out of its cell.
1067
- # if child.xpos + bdx < xpos then
1068
- # bdx = xpos - child.xpos
1069
- # elsif child.xpos + child.width + bdx >= mxpos then
1070
- # bdx = mxpos - child.xpos - child.width - 1
1071
- # end
1072
- # # Apply the best delta.
1073
- # child.xpos += bdx
1074
- # # Update the ports position.
1075
- # child.ports.each {|port| port.xpos += bdx }
1076
-
1077
- # # Tune y position.
1078
- # puts "for child=#{child.name}"
1079
- # # Find the best delta.
1080
- # bdy = 0 # Best x delta
1081
- # bcost = 1/0.0 # Best score
1082
- # ypos_in_cell = child.ypos - ypos # Initial position in cell
1083
- # ypos_in_cell -= @border if i == 0 # Do not go to the outer border
1084
- # (@rheights[i]-child.height).times do |dy|
1085
- # dy = dy - ypos_in_cell # Adjust dela y with initial position
1086
- # cost = child.ports.reduce(0) do |sum,port|
1087
- # pypos = port.ypos + dy
1088
- # sum + port.targets.reduce(0) do |subsum,tport|
1089
- # # There is cost when the port is not align with the target.
1090
- # if (port.side == UP and tport.side == DOWN) or
1091
- # (port.side == RIGHT and tport.side == RIGHT) then
1092
- # # For up to down or right to right connections,
1093
- # # the first side should be 2 tiles on the right for
1094
- # # straight wire or avoiding routing conjestion.
1095
- # subsum + (pypos-tport.ypos+2) != 0 ? 1 : 0
1096
- # elsif (port.side == DOWN and tport.side == UP) or
1097
- # (port.side == LEFT and tport.side == LEFT) then
1098
- # # For down to up or left to left connections,
1099
- # # the forst side should be 2 tiles on the down for
1100
- # # straight wire or avoiding routing conjestion.
1101
- # subsum + (pypos-tport.ypos-2) != 0 ? 1 : 0
1102
- # else
1103
- # subsum + (pypos-tport.ypos) != 0 ? 1 : 0
1104
- # end
1105
- # end
1106
- # end
1107
- # if cost < bcost then
1108
- # bcost = cost
1109
- # bdy = dy
1110
- # end
1111
- # end
1112
- # # puts "mypos=#{mypos} child.ypos=#{child.ypos} bdy=#{bdy}"
1113
- # # Ensure the child does not goes out of its cell.
1114
- # if child.ypos + bdy < ypos then
1115
- # bdy = ypos - child.ypos
1116
- # elsif child.ypos + child.height + bdy >= mypos then
1117
- # bdy = mypos - child.ypos - child.height - 1
1118
- # end
1119
- # # Apply the best delta.
1120
- # child.ypos += bdy
1121
- # # Update the ports position.
1122
- # child.ports.each {|port| port.ypos += bdy }
1123
- # end
1124
- # xpos += @cwidths[j]
1125
- # end
1126
- # ypos += @rheights[i]
1127
- # end
1128
1103
 
1129
- # First prepare the algorthims: sort the children for
1104
+ # First prepare the algorthms: sort the children for
1130
1105
  # vertical and horizontal processing and locate their
1131
1106
  # respective row and column intervals.
1132
1107
  # Sort the children by decreasing number of left and right ports,
@@ -1278,6 +1253,7 @@ module HDLRuby::Viz
1278
1253
  # Also place the ports of the current IC.
1279
1254
  poses = []
1280
1255
  @lports.each do |lport|
1256
+ next unless lport.targets[0] # Skip dangling port.
1281
1257
  lport.ypos = lport.targets[0].ypos
1282
1258
  lport.ypos += 1 if lport.targets[0].side == UP
1283
1259
  lport.ypos -= 1 if lport.targets[0].side == DOWN
@@ -1290,10 +1266,10 @@ module HDLRuby::Viz
1290
1266
  end
1291
1267
  poses = []
1292
1268
  @uports.each do |uport|
1269
+ next unless uport.targets[0] # Skip dangling port.
1293
1270
  uport.xpos = uport.targets[0].xpos
1294
1271
  uport.xpos -= 1 if uport.targets[0].side == LEFT
1295
1272
  uport.xpos += 1 if uport.targets[0].side == RIGHT
1296
- puts "Now uport.xpos=#{uport.xpos}"
1297
1273
  # Ensure ports do not overlap.
1298
1274
  while poses[uport.xpos] do
1299
1275
  uport.xpos += 1
@@ -1303,6 +1279,7 @@ module HDLRuby::Viz
1303
1279
  end
1304
1280
  poses = []
1305
1281
  @rports.each do |rport|
1282
+ next unless rport.targets[0] # Skip dangling port.
1306
1283
  rport.ypos = rport.targets[0].ypos
1307
1284
  rport.ypos += 1 if rport.targets[0].side == UP
1308
1285
  rport.ypos -= 1 if rport.targets[0].side == DOWN
@@ -1315,6 +1292,7 @@ module HDLRuby::Viz
1315
1292
  end
1316
1293
  poses = []
1317
1294
  @dports.each do |dport|
1295
+ next unless dport.targets[0] # Skip dangling port.
1318
1296
  dport.xpos = dport.targets[0].xpos
1319
1297
  dport.xpos -= 1 if dport.targets[0].side == LEFT
1320
1298
  dport.xpos += 1 if dport.targets[0].side == RIGHT
@@ -1504,68 +1482,344 @@ module HDLRuby::Viz
1504
1482
  return (pos0[0] - pos1[0]).abs + (pos0[1] - pos1[1]).abs
1505
1483
  end
1506
1484
 
1485
+ # Build a can for wire conflicting with port.
1486
+ def build_port_conflict_cache
1487
+ @port_conflict_cache = {}
1488
+ @route_matrix.each do |row|
1489
+ row.each do |elem|
1490
+ next unless elem&.ic
1491
+ ic = elem.ic
1492
+ ic.lports.each do |p|
1493
+ key = p.xpos + p.ypos * 10000 + LEFT * 100000000
1494
+ @port_conflict_cache[key] = p
1495
+ end
1496
+ ic.uports.each do |p|
1497
+ key = p.xpos + p.ypos * 10000 + UP * 100000000
1498
+ @port_conflict_cache[key] = p
1499
+ end
1500
+ ic.rports.each do |p|
1501
+ key = p.xpos + p.ypos * 10000 + RIGHT * 100000000
1502
+ @port_conflict_cache[key] = p
1503
+ end
1504
+ ic.dports.each do |p|
1505
+ key = p.xpos + p.ypos * 10000 + DOWN * 100000000
1506
+ @port_conflict_cache[key] = p
1507
+ end
1508
+ end
1509
+ end
1510
+ end
1511
+
1507
1512
  # Check if there is a port at location +pos+ in +side+ that conflict
1508
1513
  # with both +port0+ and +port1+.
1509
- def ic_port_conflict(port0,port1,pos,side)
1510
- return false unless @route_matrix[pos[1]]
1511
- return false unless @route_matrix[pos[1]][pos[0]]
1512
- ic = @route_matrix[pos[1]][pos[0]].ic
1513
- return false unless ic # No IC here, so not possible port to conflict
1514
- # There is an IC get the port at pos from side if any.
1515
- p = nil
1516
- case side
1517
- when LEFT
1518
- port = ic.lports.find {|p| p.xpos==pos[0] && p.ypos==pos[1] }
1519
- when UP
1520
- port = ic.uports.find {|p| p.xpos==pos[0] && p.ypos==pos[1] }
1521
- when RIGHT
1522
- port = ic.rports.find {|p| p.xpos==pos[0] && p.ypos==pos[1] }
1523
- when DOWN
1524
- port = ic.dports.find {|p| p.xpos==pos[0] && p.ypos==pos[1] }
1525
- end
1526
- if port and port != port0 and port != port1 then
1527
- return true
1528
- else
1529
- return false
1530
- end
1514
+ # def ic_port_conflict(port0,port1,pos,side)
1515
+ ic_port = nil
1516
+ def ic_port_conflict(port0,port1,pos0,pos1,side)
1517
+ # return false unless @route_matrix[pos[1]]
1518
+ # return false unless @route_matrix[pos[1]][pos[0]]
1519
+ # ic = @route_matrix[pos[1]][pos[0]].ic
1520
+ # return false unless ic # No IC here, so not possible port to conflict
1521
+ # # There is an IC get the port at pos from side if any.
1522
+ # p = nil
1523
+ # case side
1524
+ # when LEFT
1525
+ # port = ic.lports.find {|p| p.xpos==pos[0] && p.ypos==pos[1] }
1526
+ # when UP
1527
+ # port = ic.uports.find {|p| p.xpos==pos[0] && p.ypos==pos[1] }
1528
+ # when RIGHT
1529
+ # port = ic.rports.find {|p| p.xpos==pos[0] && p.ypos==pos[1] }
1530
+ # when DOWN
1531
+ # port = ic.dports.find {|p| p.xpos==pos[0] && p.ypos==pos[1] }
1532
+ # end
1533
+ # if port and port != port0 and port != port1 then
1534
+ # return true
1535
+ # else
1536
+ # return false
1537
+ # end
1538
+
1539
+ ic_port = @port_conflict_cache[pos0 + pos1 * 10000 + side * 100000000]
1540
+ return ic_port && ic_port != port0 && ic_port != port1
1531
1541
  end
1532
1542
 
1543
+ # # Get the neighbor free positions for port.
1544
+ # def free_neighbors(port0,port1,cpos)
1545
+ # res = []
1546
+ # # For cosmetic reasons of the wires, the order of processing depends
1547
+ # # on the relative position of the ports.
1548
+ # if port0.xpos < port1.xpos and port0.ypos < port1.ypos then
1549
+ # # Left neighbor.
1550
+ # lpos = [cpos[0]-1,cpos[1]]
1551
+ # if lpos[0] >= 0 then
1552
+ # elem = @route_matrix[lpos[1]][lpos[0]]
1553
+ # res << lpos if elem.free_from_right?(port0,port1) and
1554
+ # # !ic_port_conflict(port0,port1,[lpos[0]-1,lpos[1]],RIGHT)
1555
+ # !ic_port_conflict(port0,port1,lpos[0]-1,lpos[1],RIGHT)
1556
+ # end
1557
+ # # Up neighbor.
1558
+ # upos = [cpos[0],cpos[1]+1]
1559
+ # if upos[1] < @route_height then
1560
+ # elem = @route_matrix[upos[1]][upos[0]]
1561
+ # res << upos if elem.free_from_down?(port0,port1) and
1562
+ # # !ic_port_conflict(port0,port1,[upos[0],upos[1]+1],DOWN)
1563
+ # !ic_port_conflict(port0,port1,upos[0],upos[1]+1,DOWN)
1564
+ # end
1565
+ # # Right neighbor.
1566
+ # rpos = [cpos[0]+1,cpos[1]]
1567
+ # if rpos[0] < @route_width then
1568
+ # elem = @route_matrix[rpos[1]][rpos[0]]
1569
+ # res << rpos if elem.free_from_left?(port0,port1) and
1570
+ # # !ic_port_conflict(port0,port1,[rpos[0]+1,rpos[1]],LEFT)
1571
+ # !ic_port_conflict(port0,port1,rpos[0]+1,rpos[1],LEFT)
1572
+ # end
1573
+ # # Down neighbor.
1574
+ # dpos = [cpos[0],cpos[1]-1]
1575
+ # if dpos[1] >= 0 then
1576
+ # elem = @route_matrix[dpos[1]][dpos[0]]
1577
+ # res << dpos if elem.free_from_up?(port0,port1) and
1578
+ # # !ic_port_conflict(port0,port1,[dpos[0],dpos[1]-1],UP)
1579
+ # !ic_port_conflict(port0,port1,dpos[0],dpos[1]-1,UP)
1580
+ # end
1581
+ # elsif port0.xpos < port1.xpos and port0.ypos > port1.ypos then
1582
+ # # Left neighbor.
1583
+ # lpos = [cpos[0]-1,cpos[1]]
1584
+ # if lpos[0] >= 0 then
1585
+ # elem = @route_matrix[lpos[1]][lpos[0]]
1586
+ # res << lpos if elem.free_from_right?(port0,port1) and
1587
+ # # !ic_port_conflict(port0,port1,[lpos[0]-1,lpos[1]],RIGHT)
1588
+ # !ic_port_conflict(port0,port1,lpos[0]-1,lpos[1],RIGHT)
1589
+ # end
1590
+ # # Down neighbor.
1591
+ # dpos = [cpos[0],cpos[1]-1]
1592
+ # if dpos[1] >= 0 then
1593
+ # elem = @route_matrix[dpos[1]][dpos[0]]
1594
+ # res << dpos if elem.free_from_up?(port0,port1) and
1595
+ # # !ic_port_conflict(port0,port1,[dpos[0],dpos[1]-1],UP)
1596
+ # !ic_port_conflict(port0,port1,dpos[0],dpos[1]-1,UP)
1597
+ # end
1598
+ # # Right neighbor.
1599
+ # rpos = [cpos[0]+1,cpos[1]]
1600
+ # if rpos[0] < @route_width then
1601
+ # elem = @route_matrix[rpos[1]][rpos[0]]
1602
+ # res << rpos if elem.free_from_left?(port0,port1) and
1603
+ # # !ic_port_conflict(port0,port1,[rpos[0]+1,rpos[1]],LEFT)
1604
+ # !ic_port_conflict(port0,port1,rpos[0]+1,rpos[1],LEFT)
1605
+ # end
1606
+ # # Up neighbor.
1607
+ # upos = [cpos[0],cpos[1]+1]
1608
+ # if upos[1] < @route_height then
1609
+ # elem = @route_matrix[upos[1]][upos[0]]
1610
+ # res << upos if elem.free_from_down?(port0,port1) and
1611
+ # # !ic_port_conflict(port0,port1,[upos[0],upos[1]+1],DOWN)
1612
+ # !ic_port_conflict(port0,port1,upos[0],upos[1]+1,DOWN)
1613
+ # end
1614
+ # elsif port0.xpos > port1.xpos and port0.ypos > port1.ypos then
1615
+ # # Right neighbor.
1616
+ # rpos = [cpos[0]+1,cpos[1]]
1617
+ # if rpos[0] < @route_width then
1618
+ # elem = @route_matrix[rpos[1]][rpos[0]]
1619
+ # res << rpos if elem.free_from_left?(port0,port1) and
1620
+ # # !ic_port_conflict(port0,port1,[rpos[0]+1,rpos[1]],LEFT)
1621
+ # !ic_port_conflict(port0,port1,rpos[0]+1,rpos[1],LEFT)
1622
+ # end
1623
+ # # Down neighbor.
1624
+ # dpos = [cpos[0],cpos[1]-1]
1625
+ # if dpos[1] >= 0 then
1626
+ # elem = @route_matrix[dpos[1]][dpos[0]]
1627
+ # res << dpos if elem.free_from_up?(port0,port1) and
1628
+ # # !ic_port_conflict(port0,port1,[dpos[0],dpos[1]-1],UP)
1629
+ # !ic_port_conflict(port0,port1,dpos[0],dpos[1]-1,UP)
1630
+ # end
1631
+ # # Left neighbor.
1632
+ # lpos = [cpos[0]-1,cpos[1]]
1633
+ # if lpos[0] >= 0 then
1634
+ # elem = @route_matrix[lpos[1]][lpos[0]]
1635
+ # res << lpos if elem.free_from_right?(port0,port1) and
1636
+ # # !ic_port_conflict(port0,port1,[lpos[0]-1,lpos[1]],RIGHT)
1637
+ # !ic_port_conflict(port0,port1,lpos[0]-1,lpos[1],RIGHT)
1638
+ # end
1639
+ # # Up neighbor.
1640
+ # upos = [cpos[0],cpos[1]+1]
1641
+ # if upos[1] < @route_height then
1642
+ # elem = @route_matrix[upos[1]][upos[0]]
1643
+ # res << upos if elem.free_from_down?(port0,port1) and
1644
+ # # !ic_port_conflict(port0,port1,[upos[0],upos[1]+1],DOWN)
1645
+ # !ic_port_conflict(port0,port1,upos[0],upos[1]+1,DOWN)
1646
+ # end
1647
+ # else
1648
+ # # Right neighbor.
1649
+ # rpos = [cpos[0]+1,cpos[1]]
1650
+ # if rpos[0] < @route_width then
1651
+ # elem = @route_matrix[rpos[1]][rpos[0]]
1652
+ # res << rpos if elem.free_from_left?(port0,port1) and
1653
+ # # !ic_port_conflict(port0,port1,[rpos[0]+1,rpos[1]],LEFT)
1654
+ # !ic_port_conflict(port0,port1,rpos[0]+1,rpos[1],LEFT)
1655
+ # end
1656
+ # # Up neighbor.
1657
+ # upos = [cpos[0],cpos[1]+1]
1658
+ # if upos[1] < @route_height then
1659
+ # elem = @route_matrix[upos[1]][upos[0]]
1660
+ # res << upos if elem.free_from_down?(port0,port1) and
1661
+ # # !ic_port_conflict(port0,port1,[upos[0],upos[1]+1],DOWN)
1662
+ # !ic_port_conflict(port0,port1,upos[0],upos[1]+1,DOWN)
1663
+ # end
1664
+ # # Left neighbor.
1665
+ # lpos = [cpos[0]-1,cpos[1]]
1666
+ # if lpos[0] >= 0 then
1667
+ # elem = @route_matrix[lpos[1]][lpos[0]]
1668
+ # res << lpos if elem.free_from_right?(port0,port1) and
1669
+ # # !ic_port_conflict(port0,port1,[lpos[0]-1,lpos[1]],RIGHT)
1670
+ # !ic_port_conflict(port0,port1,lpos[0]-1,lpos[1],RIGHT)
1671
+ # end
1672
+ # # Down neighbor.
1673
+ # dpos = [cpos[0],cpos[1]-1]
1674
+ # if dpos[1] >= 0 then
1675
+ # elem = @route_matrix[dpos[1]][dpos[0]]
1676
+ # res << dpos if elem.free_from_up?(port0,port1) and
1677
+ # # !ic_port_conflict(port0,port1,[dpos[0],dpos[1]-1],UP)
1678
+ # !ic_port_conflict(port0,port1,dpos[0],dpos[1]-1,UP)
1679
+ # end
1680
+ # end
1681
+ # # Return the free neigbor positions.
1682
+ # return res
1683
+ # end
1533
1684
  # Get the neighbor free positions for port.
1534
- # def free_neighbors(port,cpos)
1685
+ res = p0 = p1 = nil
1535
1686
  def free_neighbors(port0,port1,cpos)
1536
1687
  res = []
1537
- # Left neighbor.
1538
- lpos = [cpos[0]-1,cpos[1]]
1539
- if lpos[0] >= 0 then
1540
- elem = @route_matrix[lpos[1]][lpos[0]]
1541
- # res << lpos if elem.free_from_right?(port)
1542
- res << lpos if elem.free_from_right?(port0,port1) and
1543
- !ic_port_conflict(port0,port1,[lpos[0]-1,lpos[1]],RIGHT)
1544
- end
1545
- # Up neighbor.
1546
- upos = [cpos[0],cpos[1]+1]
1547
- if upos[1] < @route_height then
1548
- elem = @route_matrix[upos[1]][upos[0]]
1549
- # res << upos if elem.free_from_down?(port)
1550
- res << upos if elem.free_from_down?(port0,port1) and
1551
- !ic_port_conflict(port0,port1,[upos[0],upos[1]+1],DOWN)
1552
- end
1553
- # Right neighbor.
1554
- rpos = [cpos[0]+1,cpos[1]]
1555
- if rpos[0] < @route_width then
1556
- elem = @route_matrix[rpos[1]][rpos[0]]
1557
- # res << rpos if elem.free_from_left?(port)
1558
- res << rpos if elem.free_from_left?(port0,port1) and
1559
- !ic_port_conflict(port0,port1,[rpos[0]+1,rpos[1]],LEFT)
1560
- end
1561
- # Down neighbor.
1562
- dpos = [cpos[0],cpos[1]-1]
1563
- if dpos[1] >= 0 then
1564
- elem = @route_matrix[dpos[1]][dpos[0]]
1565
- # res << dpos if elem.free_from_up?(port)
1566
- res << dpos if elem.free_from_up?(port0,port1) and
1567
- !ic_port_conflict(port0,port1,[dpos[0],dpos[1]-1],UP)
1568
- end
1688
+ # For cosmetic reasons of the wires, the order of processing depends
1689
+ # on the relative position of the ports.
1690
+ if port0.xpos < port1.xpos and port0.ypos < port1.ypos then
1691
+ # Left neighbor.
1692
+ p0 = cpos[0]-1
1693
+ p1 = cpos[1]
1694
+ if p0 >= 0 then
1695
+ elem = @route_matrix[p1][p0]
1696
+ res << [p0,p1] if elem.free_from_right?(port0,port1) and
1697
+ !ic_port_conflict(port0,port1,p0-1,p1,RIGHT)
1698
+ end
1699
+ # Up neighbor.
1700
+ p0 = cpos[0]
1701
+ p1 = cpos[1]+1
1702
+ if p1 < @route_height then
1703
+ elem = @route_matrix[p1][p0]
1704
+ res << [p0,p1] if elem.free_from_down?(port0,port1) and
1705
+ !ic_port_conflict(port0,port1,p0,p1+1,DOWN)
1706
+ end
1707
+ # Right neighbor.
1708
+ p0 = cpos[0]+1
1709
+ p1 = cpos[1]
1710
+ if p0 < @route_width then
1711
+ elem = @route_matrix[p1][p0]
1712
+ res << [p0,p1] if elem.free_from_left?(port0,port1) and
1713
+ !ic_port_conflict(port0,port1,p0+1,p1,LEFT)
1714
+ end
1715
+ # Down neighbor.
1716
+ p0 = cpos[0]
1717
+ p1 = cpos[1]-1
1718
+ if p1 >= 0 then
1719
+ elem = @route_matrix[p1][p0]
1720
+ res << [p0,p1] if elem.free_from_up?(port0,port1) and
1721
+ !ic_port_conflict(port0,port1,p0,p1-1,UP)
1722
+ end
1723
+ elsif port0.xpos < port1.xpos and port0.ypos > port1.ypos then
1724
+ # Left neighbor.
1725
+ p0 = cpos[0]-1
1726
+ p1 = cpos[1]
1727
+ if p0 >= 0 then
1728
+ elem = @route_matrix[p1][p0]
1729
+ res << [p0,p1] if elem.free_from_right?(port0,port1) and
1730
+ !ic_port_conflict(port0,port1,p0-1,p1,RIGHT)
1731
+ end
1732
+ # Down neighbor.
1733
+ p0 = cpos[0]
1734
+ p1 = cpos[1]-1
1735
+ if p1 >= 0 then
1736
+ elem = @route_matrix[p1][p0]
1737
+ res << [p0,p1] if elem.free_from_up?(port0,port1) and
1738
+ !ic_port_conflict(port0,port1,p0,p1-1,UP)
1739
+ end
1740
+ # Right neighbor.
1741
+ p0 = cpos[0]+1
1742
+ p1 = cpos[1]
1743
+ if p0 < @route_width then
1744
+ elem = @route_matrix[p1][p0]
1745
+ res << [p0,p1] if elem.free_from_left?(port0,port1) and
1746
+ !ic_port_conflict(port0,port1,p0+1,p1,LEFT)
1747
+ end
1748
+ # Up neighbor.
1749
+ p0 = cpos[0]
1750
+ p1 = cpos[1]+1
1751
+ if p1 < @route_height then
1752
+ elem = @route_matrix[p1][p0]
1753
+ res << [p0,p1] if elem.free_from_down?(port0,port1) and
1754
+ !ic_port_conflict(port0,port1,p0,p1+1,DOWN)
1755
+ end
1756
+ elsif port0.xpos > port1.xpos and port0.ypos > port1.ypos then
1757
+ # Right neighbor.
1758
+ p0 = cpos[0]+1
1759
+ p1 = cpos[1]
1760
+ if p0 < @route_width then
1761
+ elem = @route_matrix[p1][p0]
1762
+ res << [p0,p1] if elem.free_from_left?(port0,port1) and
1763
+ !ic_port_conflict(port0,port1,p0+1,p1,LEFT)
1764
+ end
1765
+ # Down neighbor.
1766
+ p0 = cpos[0]
1767
+ p1 = cpos[1]-1
1768
+ if p1 >= 0 then
1769
+ elem = @route_matrix[p1][p0]
1770
+ res << [p0,p1] if elem.free_from_up?(port0,port1) and
1771
+ !ic_port_conflict(port0,port1,p0,p1-1,UP)
1772
+ end
1773
+ # Left neighbor.
1774
+ p0 = cpos[0]-1
1775
+ p1 = cpos[1]
1776
+ if p0 >= 0 then
1777
+ elem = @route_matrix[p1][p0]
1778
+ res << [p0,p1] if elem.free_from_right?(port0,port1) and
1779
+ !ic_port_conflict(port0,port1,p0-1,p1,RIGHT)
1780
+ end
1781
+ # Up neighbor.
1782
+ p0 = cpos[0]
1783
+ p1 = cpos[1]+1
1784
+ if p1 < @route_height then
1785
+ elem = @route_matrix[p1][p0]
1786
+ res << [p0,p1] if elem.free_from_down?(port0,port1) and
1787
+ !ic_port_conflict(port0,port1,p0,p1+1,DOWN)
1788
+ end
1789
+ else
1790
+ # Right neighbor.
1791
+ p0 = cpos[0]+1
1792
+ p1 = cpos[1]
1793
+ if p0 < @route_width then
1794
+ elem = @route_matrix[p1][p0]
1795
+ res << [p0,p1] if elem.free_from_left?(port0,port1) and
1796
+ !ic_port_conflict(port0,port1,p0+1,p1,LEFT)
1797
+ end
1798
+ # Up neighbor.
1799
+ p0 = cpos[0]
1800
+ p1 = cpos[1]+1
1801
+ if p1 < @route_height then
1802
+ elem = @route_matrix[p1][p0]
1803
+ res << [p0,p1] if elem.free_from_down?(port0,port1) and
1804
+ !ic_port_conflict(port0,port1,p0,p1+1,DOWN)
1805
+ end
1806
+ # Left neighbor.
1807
+ p0 = cpos[0]-1
1808
+ p1 = cpos[1]
1809
+ if p0 >= 0 then
1810
+ elem = @route_matrix[p1][p0]
1811
+ res << [p0,p1] if elem.free_from_right?(port0,port1) and
1812
+ !ic_port_conflict(port0,port1,p0-1,p1,RIGHT)
1813
+ end
1814
+ # Down neighbor.
1815
+ p0 = cpos[0]
1816
+ p1 = cpos[1]-1
1817
+ if p1 >= 0 then
1818
+ elem = @route_matrix[p1][p0]
1819
+ res << [p0,p1] if elem.free_from_up?(port0,port1) and
1820
+ !ic_port_conflict(port0,port1,p0,p1-1,UP)
1821
+ end
1822
+ end
1569
1823
  # Return the free neigbor positions.
1570
1824
  return res
1571
1825
  end
@@ -1643,6 +1897,20 @@ module HDLRuby::Viz
1643
1897
  ((pos0[1]-pos1[1]).abs < 2 and pos0[0] == pos1[0]))
1644
1898
  end
1645
1899
 
1900
+ #BENDCOST
1901
+ # Compute the direction between two positions in a path.
1902
+ def path_dir(pos0, pos1)
1903
+ if pos0[0] > pos1[0] then
1904
+ return LEFT
1905
+ elsif pos0[0] < pos1[0] then
1906
+ return RIGHT
1907
+ elsif pos0[1] > pos1[1] then
1908
+ return UP
1909
+ else
1910
+ return DOWN
1911
+ end
1912
+ end
1913
+
1646
1914
  # Route from +port0+ to +port1.
1647
1915
  # NOTE: uses the A* algorithm with taxi cab distance.
1648
1916
  def connection_route(port0,port1)
@@ -1651,60 +1919,55 @@ module HDLRuby::Viz
1651
1919
  pos0 = [port0.xpos,port0.ypos]
1652
1920
  pos1 = [port1.xpos,port1.ypos]
1653
1921
  oset = [pos0]
1654
- # oset = Set.new
1655
- oset << pos0
1656
1922
  from = { }
1657
- # gscore = Hash.new(1/0.0)
1658
- # gscore[pos0] = 0
1659
1923
  gscore = Array.new(@route_matrix.size) { Array.new(@route_matrix[0].size) { 1/0.0 } }
1660
1924
  gscore[pos0[1]][pos0[0]] = 0
1661
- # fscore = Hash.new(1/0.0)
1662
- # fscore[pos0] = taxi_distance(pos0,pos1)
1663
- fscore = Array.new(@route_matrix.size) { [] }
1925
+ # fscore = Array.new(@route_matrix.size) { [] }
1926
+ fscore = Array.new(@route_matrix.size) { Array.new(@route_matrix[0].size) { 1/0.0 } }
1664
1927
  fscore[pos0[1]][pos0[0]] = taxi_distance(pos0,pos1)
1928
+
1929
+ closed = { } # Closed set
1665
1930
  while oset.any? do
1666
1931
  # Pick the position from oset with the minimum fscore.
1667
- cpos = nil # Current position
1668
- mscore = 1/0.0 # Minimum score
1669
- # oset.each do |pos|
1670
- # # score = fscore[pos]
1671
- # score = fscore[pos[1]][pos[0]]
1672
- # if score < mscore then
1673
- # mscore = score
1674
- # cpos = pos
1675
- # end
1676
- # end
1932
+ # cpos = nil # Current position
1933
+ # mscore = 1/0.0 # Minimum score
1677
1934
  # The best score is necessily at the end of oset.
1678
1935
  cpos = oset.pop
1936
+ next if closed[cpos] # Skip already teated position
1937
+ closed[cpos] = true
1679
1938
  # puts "cpos=#{cpos}"
1680
1939
  if touch?(cpos,pos1) then
1681
1940
  # The goal is reached.
1682
1941
  from[pos1] = cpos
1683
1942
  return reconstruct_path(port0,port1,from,pos1)
1684
1943
  end
1685
- # oset.delete(cpos) # No need anymore since pop
1686
1944
  # Get the neighbor positions for port.
1687
- # poses = free_neighbors(port0,cpos)
1688
1945
  poses = free_neighbors(port0,port1,cpos)
1946
+ #BENDCOST
1947
+ ppos = poses.first
1948
+ pdir = nil
1689
1949
  poses.each do |pos|
1690
1950
  # Try it.
1691
- # tscore = gscore[cpos] + cost_position(port0,pos)
1692
- tscore = gscore[cpos[1]][cpos[0]] + cost_position(port0,pos)
1693
- # if tscore < gscore[pos] then
1951
+ # tscore = gscore[cpos[1]][cpos[0]] + cost_position(port0,pos)
1952
+ # BENDCOST
1953
+ dir = path_dir(ppos,pos)
1954
+ tscore = gscore[cpos[1]][cpos[0]] + cost_position(port0,pos) +
1955
+ ((dir != pdir) ? 1024 : 0)
1694
1956
  if tscore < gscore[pos[1]][pos[0]] then
1695
1957
  # This path to neigbor is better than any previous one, keep it.
1696
1958
  from[pos] = cpos
1697
- # gscore[pos] = tscore
1698
1959
  gscore[pos[1]][pos[0]] = tscore
1699
- # fscore[pos] = tscore + taxi_distance(pos,pos1)
1700
1960
  fscore[pos[1]][pos[0]] = tscore + taxi_distance(pos,pos1)
1701
- # oset << pos unless oset.include?(pos)
1702
- idx = oset.bsearch_index {|p| fscore[p[1]][p[0]] <= fscore[pos[1]][pos[0]] }
1961
+ # idx = oset.bsearch_index {|p| fscore[p[1]][p[0]] <= fscore[pos[1]][pos[0]] }
1962
+ idx = oset.bsearch_index {|p| fscore[p[1]][p[0]] < fscore[pos[1]][pos[0]] }
1703
1963
  if idx then
1704
1964
  oset.insert(idx,pos)
1705
1965
  else
1706
1966
  oset << pos
1707
1967
  end
1968
+ #BENDCOST
1969
+ ppos = pos
1970
+ pdir = dir
1708
1971
  end
1709
1972
  end
1710
1973
  end
@@ -1747,6 +2010,7 @@ module HDLRuby::Viz
1747
2010
  (to_route.size/2).times do |epoch|
1748
2011
  puts "Routing epoch=#{epoch}..."
1749
2012
  self.init_route # Reinitialize the route matrix.
2013
+ build_port_conflict_cache
1750
2014
  routed_pairs = [] # The list of already routed pair of ports.
1751
2015
  @routes = [] # The list of created routes.
1752
2016
  # Do the routing.
@@ -1838,6 +2102,7 @@ module HDLRuby::Viz
1838
2102
  route.path.append([eport.xpos,eport.ypos-1])
1839
2103
  end
1840
2104
  end
2105
+ # Add the wires to the tiles.
1841
2106
  route.path.each_cons(3).with_index do |((x0,y0),(x1,y1),(x2,y2)),i|
1842
2107
  # puts "x0,y0=#{x0},#{y0} x1,y1=#{x1},#{y1} x2,y2=#{x2},#{y2}"
1843
2108
  # puts "i=#{i} dir=#{dir}"
@@ -2076,6 +2341,14 @@ module HDLRuby::Viz
2076
2341
  puts "matrix:"
2077
2342
  matrix.each { |row| puts "#{row.map{|ic| ic ? ic.name : " " }}" }
2078
2343
 
2344
+ # And the ic to coordinate table. TRUCMUCHE
2345
+ ic_matrix_coordinates = {}
2346
+ matrix.each_with_index do |row,y|
2347
+ row.each_with_index do |ic,x|
2348
+ ic_matrix_coordinates[ic] = [x,y] if ic
2349
+ end
2350
+ end
2351
+
2079
2352
  # Compute the side of the ports.
2080
2353
  self.bounding_children
2081
2354
 
@@ -2092,7 +2365,8 @@ module HDLRuby::Viz
2092
2365
  end
2093
2366
 
2094
2367
  # For the children.
2095
- self.side_children
2368
+ # self.side_children
2369
+ self.side_children(ic_matrix_coordinates)
2096
2370
 
2097
2371
  puts "Children ports side results: "
2098
2372
  self.children.each_with_index do |child|
@@ -2205,51 +2479,54 @@ module HDLRuby::Viz
2205
2479
  # Generate a system description SVG text for +ic+
2206
2480
  def system_svg(ic)
2207
2481
  return "<rect fill=\"#fff\" stroke=\"#000\" " +
2208
- "stroke-width=\"#{@scale/8.0}\" " +
2209
- "x=\"#{ic.xpos*@scale}\" y=\"#{ic.ypos*@scale}\" " +
2210
- "width=\"#{ic.width*@scale}\" "+
2211
- "height=\"#{ic.height*@scale}\"/>\n"
2482
+ "stroke-width=\"#{(@scale/8.0).round(3)}\" " +
2483
+ "x=\"#{(ic.xpos*@scale).round(3)}\" y=\"#{(ic.ypos*@scale).round(3)}\" " +
2484
+ "width=\"#{(ic.width*@scale).round(3)}\" "+
2485
+ "height=\"#{(ic.height*@scale).round(3)}\"/>\n"
2212
2486
  end
2213
2487
 
2214
2488
  # Generate an instance description SVG text for +ic+
2215
2489
  def instance_svg(ic)
2216
- id = Viz.to_svg_id(ic.name)
2490
+ # id = Viz.to_svg_id(ic.name)
2491
+ id = ic.__id__.to_s
2217
2492
  # The rectangle representing the instance.
2218
2493
  res = "<rect id=\"#{id}\" fill=\"#eee\" stroke=\"#000\" " +
2219
- "stroke-width=\"#{@scale/12.0}\" " +
2220
- "x=\"#{ic.xpos*@scale}\" y=\"#{ic.ypos*@scale}\" " +
2221
- "width=\"#{ic.width*@scale}\" "+
2222
- "height=\"#{ic.height*@scale}\"/>\n"
2494
+ "stroke-width=\"#{(@scale/12.0).round(3)}\" " +
2495
+ "x=\"#{(ic.xpos*@scale).round(3)}\" y=\"#{(ic.ypos*@scale).round(3)}\" " +
2496
+ "width=\"#{(ic.width*@scale).round(3)}\" "+
2497
+ "height=\"#{(ic.height*@scale).round(3)}\"/>\n"
2223
2498
  # Its name.
2224
2499
  sy = (ic.lports.size.even? and ic.rports.size.even? ) ? 0 : -0.5 # Shift to avoid ports
2225
2500
  res += "<text id=\"text#{id}\" " +
2226
2501
  "style=\"text-anchor: middle; dominant-baseline: middle;\" " +
2227
2502
  "font-family=\"monospace\" font-size=\"1px\" " +
2228
- "x=\"#{(ic.xpos + ic.width/2.0)*@scale}\" "+
2229
- "y=\"#{(ic.ypos + ic.height/2.0 + sy)*@scale}\">" +
2503
+ "x=\"#{((ic.xpos + ic.width/2.0)*@scale).round(3)}\" "+
2504
+ "y=\"#{((ic.ypos + ic.height/2.0 + sy)*@scale).round(3)}\">" +
2230
2505
  ic.name + "</text>\n"
2231
2506
  # Its text resizing.
2232
- res += Viz.svg_text_fit("text#{id}",(ic.width-0.6)*@scale,
2233
- 0.6*@scale)
2507
+ res += Viz.svg_text_fit("text#{id}",
2508
+ ((ic.width-0.6)*@scale).round(3),
2509
+ (0.6*@scale).round(3))
2234
2510
  return res
2235
2511
  end
2236
2512
 
2237
2513
  # Generate a process description SVG text for +ic+
2238
2514
  def process_svg(ic)
2239
- id = Viz.to_svg_id(ic.name)
2515
+ # id = Viz.to_svg_id(ic.name)
2516
+ id = ic.__id__.to_s
2240
2517
  res = "<rect id=\"#{id}\" fill=\"#eee\" stroke=\"#000\" " +
2241
- "stroke-width=\"#{@scale/16.0}\" " +
2242
- "x=\"#{ic.xpos*@scale}\" y=\"#{ic.ypos*@scale}\" " +
2243
- "rx=\"#{@scale}\" " +
2244
- "width=\"#{ic.width*@scale}\" "+
2245
- "height=\"#{ic.height*@scale}\"/>\n"
2518
+ "stroke-width=\"#{(@scale/16.0).round(3)}\" " +
2519
+ "x=\"#{(ic.xpos*@scale).round(3)}\" y=\"#{(ic.ypos*@scale).round(3)}\" " +
2520
+ "rx=\"#{@scale.round(3)}\" " +
2521
+ "width=\"#{(ic.width*@scale).round(3)}\" "+
2522
+ "height=\"#{(ic.height*@scale).round(3)}\"/>\n"
2246
2523
  # Its name.
2247
2524
  sy = (ic.lports.size.even? and ic.rports.size.even? ) ? 0 : -0.5 # Shift to avoid ports
2248
2525
  res += "<text id=\"text#{id}\" " +
2249
2526
  "style=\"text-anchor: middle; dominant-baseline: middle;\" " +
2250
2527
  "font-family=\"monospace\" font-size=\"1px\" " +
2251
- "x=\"#{(ic.xpos + ic.width/2.0)*@scale}\" "+
2252
- "y=\"#{(ic.ypos + ic.height/2.0 + sy)*@scale}\">" +
2528
+ "x=\"#{((ic.xpos + ic.width/2.0)*@scale).round(3)}\" "+
2529
+ "y=\"#{((ic.ypos + ic.height/2.0 + sy)*@scale).round(3)}\">" +
2253
2530
  ic.name + "</text>\n"
2254
2531
  # Its text resizing.
2255
2532
  res += Viz.svg_text_fit("text#{id}",(ic.width-0.6)*@scale,
@@ -2259,26 +2536,27 @@ module HDLRuby::Viz
2259
2536
 
2260
2537
  # Generate a clocked process description SVG text for +ic+
2261
2538
  def clocked_process_svg(ic)
2262
- id = Viz.to_svg_id(ic.name)
2539
+ # id = Viz.to_svg_id(ic.name)
2540
+ id = ic.__id__.to_s
2263
2541
  res = "<rect fill=\"#ddd\" stroke=\"#000\" " +
2264
- "stroke-width=\"#{@scale/32.0}\" " +
2265
- "x=\"#{(ic.xpos-1/16.0)*@scale}\" y=\"#{(ic.ypos-1/16.0)*@scale}\" " +
2266
- "rx=\"#{(1+1/16.0)*@scale}\" " +
2267
- "width=\"#{(ic.width+1/8.0)*@scale}\" "+
2268
- "height=\"#{(ic.height+1/8.0)*@scale}\"/>\n"
2542
+ "stroke-width=\"#{(@scale/32.0).round(3)}\" " +
2543
+ "x=\"#{((ic.xpos-1/16.0)*@scale).round(3)}\" y=\"#{((ic.ypos-1/16.0)*@scale).round(3)}\" " +
2544
+ "rx=\"#{((1+1/16.0)*@scale).round(3)}\" " +
2545
+ "width=\"#{((ic.width+1/8.0)*@scale).round(3)}\" "+
2546
+ "height=\"#{((ic.height+1/8.0)*@scale).round(3)}\"/>\n"
2269
2547
  res += "<rect id=\"#{id}\" fill=\"#ddd\" stroke=\"#000\" " +
2270
- "stroke-width=\"#{@scale/32.0}\" " +
2271
- "x=\"#{ic.xpos*@scale}\" y=\"#{ic.ypos*@scale}\" " +
2272
- "rx=\"#{@scale}\" " +
2273
- "width=\"#{ic.width*@scale}\" "+
2274
- "height=\"#{ic.height*@scale}\"/>\n"
2548
+ "stroke-width=\"#{(@scale/32.0).round(3)}\" " +
2549
+ "x=\"#{(ic.xpos*@scale).round(3)}\" y=\"#{(ic.ypos*@scale).round(3)}\" " +
2550
+ "rx=\"#{@scale.round(3)}\" " +
2551
+ "width=\"#{(ic.width*@scale).round(3)}\" "+
2552
+ "height=\"#{(ic.height*@scale).round(3)}\"/>\n"
2275
2553
  # Its name.
2276
2554
  sy = (ic.lports.size.even? and ic.rports.size.even? ) ? 0 : -0.5 # Shift to avoid ports
2277
2555
  res += "<text id=\"text#{id}\" " +
2278
2556
  "style=\"text-anchor: middle; dominant-baseline: middle;\" " +
2279
2557
  "font-family=\"monospace\" font-size=\"1px\" " +
2280
- "x=\"#{(ic.xpos + ic.width/2.0)*@scale}\" "+
2281
- "y=\"#{(ic.ypos + ic.height/2.0 + sy)*@scale}\">" +
2558
+ "x=\"#{((ic.xpos + ic.width/2.0)*@scale).round(3)}\" "+
2559
+ "y=\"#{((ic.ypos + ic.height/2.0 + sy)*@scale).round(3)}\">" +
2282
2560
  ic.name + "</text>\n"
2283
2561
  # Its text resizing.
2284
2562
  res += Viz.svg_text_fit("text#{id}",(ic.width-0.6)*@scale,
@@ -2288,20 +2566,21 @@ module HDLRuby::Viz
2288
2566
 
2289
2567
  # Generate a timed process description SVG text for +ic+
2290
2568
  def timed_process_svg(ic)
2291
- id = Viz.to_svg_id(ic.name)
2569
+ # id = Viz.to_svg_id(ic.name)
2570
+ id = ic.__id__.to_s
2292
2571
  res = "<rect id=\"#{id}\" fill=\"#bbb\" stroke=\"#000\" " +
2293
- "stroke-width=\"#{@scale/8.0}\" " +
2294
- "x=\"#{ic.xpos*@scale}\" y=\"#{ic.ypos*@scale}\" " +
2295
- "rx=\"#{@scale}\" " +
2296
- "width=\"#{ic.width*@scale}\" "+
2297
- "height=\"#{ic.height*@scale}\"/>\n"
2572
+ "stroke-width=\"#{(@scale/8.0).round(3)}\" " +
2573
+ "x=\"#{(ic.xpos*@scale).round(3)}\" y=\"#{(ic.ypos*@scale).round(3)}\" " +
2574
+ "rx=\"#{@scale.round(3)}\" " +
2575
+ "width=\"#{(ic.width*@scale).round(3)}\" "+
2576
+ "height=\"#{(ic.height*@scale).round(3)}\"/>\n"
2298
2577
  # Its name.
2299
2578
  sy = (ic.lports.size.even? and ic.rports.size.even? ) ? 0 : -0.5 # Shift to avoid ports
2300
2579
  res += "<text id=\"text#{id}\" " +
2301
2580
  "style=\"text-anchor: middle; dominant-baseline: middle;\" " +
2302
2581
  "font-family=\"monospace\" font-size=\"1px\" " +
2303
- "x=\"#{(ic.xpos + ic.width/2.0)*@scale}\" "+
2304
- "y=\"#{(ic.ypos + ic.height/2.0 + sy)*@scale}\">" +
2582
+ "x=\"#{((ic.xpos + ic.width/2.0)*@scale).round(3)}\" "+
2583
+ "y=\"#{((ic.ypos + ic.height/2.0 + sy)*@scale).round(3)}\">" +
2305
2584
  ic.name + "</text>\n"
2306
2585
  # Its text resizing.
2307
2586
  res += Viz.svg_text_fit("text#{id}",(ic.width-0.6)*@scale,
@@ -2311,20 +2590,21 @@ module HDLRuby::Viz
2311
2590
 
2312
2591
  # Generate a register description SVG text for +ic+
2313
2592
  def register_svg(ic)
2314
- id = Viz.to_svg_id(ic.name)
2593
+ # id = Viz.to_svg_id(ic.name)
2594
+ id = ic.__id__.to_s
2315
2595
  res = "<rect id=\"#{id}\" fill=\"#fff\" stroke=\"#000\" " +
2316
- "stroke-width=\"#{@scale/16.0}\" " +
2317
- "x=\"#{ic.xpos*@scale}\" y=\"#{ic.ypos*@scale}\" " +
2318
- "rx=\"#{@scale/4}\" " +
2319
- "width=\"#{ic.width*@scale}\" "+
2320
- "height=\"#{ic.height*@scale}\"/>\n"
2596
+ "stroke-width=\"#{(@scale/16.0).round(3)}\" " +
2597
+ "x=\"#{(ic.xpos*@scale).round(3)}\" y=\"#{(ic.ypos*@scale).round(3)}\" " +
2598
+ "rx=\"#{(@scale/4).round(3)}\" " +
2599
+ "width=\"#{(ic.width*@scale).round(3)}\" "+
2600
+ "height=\"#{(ic.height*@scale).round(3)}\"/>\n"
2321
2601
  # Its name.
2322
2602
  sy = (ic.lports.size <= 2 or ic.lports.size.even?) ? 0 : -0.5 # Shift to avoid ports (Note: register prots are symetrics, so check left only).
2323
2603
  res += "<text id=\"text#{id}\" " +
2324
2604
  "style=\"text-anchor: middle; dominant-baseline: middle;\" " +
2325
2605
  "font-family=\"monospace\" font-size=\"1px\" " +
2326
- "x=\"#{(ic.xpos + ic.width/2.0)*@scale}\" "+
2327
- "y=\"#{(ic.ypos + ic.height/2.0+sy)*@scale}\">" +
2606
+ "x=\"#{((ic.xpos + ic.width/2.0)*@scale).round(3)}\" "+
2607
+ "y=\"#{((ic.ypos + ic.height/2.0+sy)*@scale).round(3)}\">" +
2328
2608
  ic.name + "</text>\n"
2329
2609
  # Its text resizing.
2330
2610
  res += Viz.svg_text_fit("text#{id}",(ic.width-0.6)*@scale,
@@ -2334,37 +2614,38 @@ module HDLRuby::Viz
2334
2614
 
2335
2615
  # Generate a memory description SVG text for +ic+
2336
2616
  def memory_svg(ic)
2337
- id = Viz.to_svg_id(ic.name)
2617
+ # id = Viz.to_svg_id(ic.name)
2618
+ id = ic.__id__.to_s
2338
2619
  res = "<rect id=\"#{id}\" fill=\"#fff\" stroke=\"#000\" " +
2339
- "stroke-width=\"#{@scale/16.0}\" " +
2340
- "x=\"#{ic.xpos*@scale}\" y=\"#{ic.ypos*@scale}\" " +
2341
- "rx=\"#{@scale/4}\" " +
2342
- "width=\"#{ic.width*@scale}\" "+
2343
- "height=\"#{ic.height*@scale}\"/>\n"
2620
+ "stroke-width=\"#{(@scale/16.0).round(3)}\" " +
2621
+ "x=\"#{(ic.xpos*@scale).round(3)}\" y=\"#{(ic.ypos*@scale).round(3)}\" " +
2622
+ "rx=\"#{(@scale/4).round(3)}\" " +
2623
+ "width=\"#{(ic.width*@scale).round(3)}\" "+
2624
+ "height=\"#{(ic.height*@scale).round(3)}\"/>\n"
2344
2625
  res += "<rect fill=\"#fff\" stroke=\"#333\" " +
2345
- "stroke-width=\"#{@scale/16.0}\" " +
2346
- "x=\"#{(ic.xpos+1/4.0)*@scale}\" "+
2347
- "y=\"#{(ic.ypos+1/4.0)*@scale}\" " +
2348
- "width=\"#{(ic.width-1/2.0)*@scale}\" "+
2349
- "height=\"#{(ic.height-1/2.0)*@scale}\"/>\n"
2626
+ "stroke-width=\"#{(@scale/16.0).round(3)}\" " +
2627
+ "x=\"#{((ic.xpos+1/4.0)*@scale).round(3)}\" "+
2628
+ "y=\"#{((ic.ypos+1/4.0)*@scale).round(3)}\" " +
2629
+ "width=\"#{((ic.width-1/2.0)*@scale).round(3)}\" "+
2630
+ "height=\"#{((ic.height-1/2.0)*@scale).round(3)}\"/>\n"
2350
2631
  res += "<line stroke=\"#333\" " +
2351
- "stroke-width=\"#{@scale/16.0}\" " +
2352
- "x1=\"#{(ic.xpos+1/4.0+1/8.0)*@scale}\" "+
2353
- "y1=\"#{(ic.ypos+1/4.0)*@scale}\" " +
2354
- "x2=\"#{(ic.xpos+1/4.0+1/8.0)*@scale}\" "+
2355
- "y2=\"#{(ic.ypos+ic.height-1/4.0)*@scale}\"/>\n"
2632
+ "stroke-width=\"#{(@scale/16.0).round(3)}\" " +
2633
+ "x1=\"#{((ic.xpos+1/4.0+1/8.0)*@scale).round(3)}\" "+
2634
+ "y1=\"#{((ic.ypos+1/4.0)*@scale).round(3)}\" " +
2635
+ "x2=\"#{((ic.xpos+1/4.0+1/8.0)*@scale).round(3)}\" "+
2636
+ "y2=\"#{((ic.ypos+ic.height-1/4.0)*@scale).round(3)}\"/>\n"
2356
2637
  res += "<line stroke=\"#333\" " +
2357
- "stroke-width=\"#{@scale/16.0}\" " +
2358
- "x1=\"#{(ic.xpos+1/4.0)*@scale}\" "+
2359
- "y1=\"#{(ic.ypos+1/4.0+1/8.0)*@scale}\" " +
2360
- "x2=\"#{(ic.xpos+ic.width-1/4.0)*@scale}\" "+
2361
- "y2=\"#{(ic.ypos+1/4.0+1/8.0)*@scale}\"/>\n"
2638
+ "stroke-width=\"#{(@scale/16.0).round(3)}\" " +
2639
+ "x1=\"#{((ic.xpos+1/4.0)*@scale).round(3)}\" "+
2640
+ "y1=\"#{((ic.ypos+1/4.0+1/8.0)*@scale).round(3)}\" " +
2641
+ "x2=\"#{((ic.xpos+ic.width-1/4.0)*@scale).round(3)}\" "+
2642
+ "y2=\"#{((ic.ypos+1/4.0+1/8.0)*@scale).round(3)}\"/>\n"
2362
2643
  # Its name.
2363
2644
  res += "<text id=\"text#{id}\" " +
2364
2645
  "style=\"text-anchor: middle; dominant-baseline: middle;\" " +
2365
2646
  "font-family=\"monospace\" font-size=\"1px\" " +
2366
- "x=\"#{(ic.xpos + ic.width/2.0 + 1/10.0)*@scale}\" "+
2367
- "y=\"#{(ic.ypos + ic.height/2.0)*@scale}\">" +
2647
+ "x=\"#{((ic.xpos + ic.width/2.0 + 1/10.0)*@scale).round(3)}\" "+
2648
+ "y=\"#{((ic.ypos + ic.height/2.0)*@scale).round(3)}\">" +
2368
2649
  ic.name + "</text>\n"
2369
2650
  # Its text resizing.
2370
2651
  res += Viz.svg_text_fit("text#{id}",(ic.width-1.0)*@scale,
@@ -2374,17 +2655,30 @@ module HDLRuby::Viz
2374
2655
 
2375
2656
  # Generate an ALU description SVG text for +ic+
2376
2657
  def alu_svg(ic)
2377
- id = Viz.to_svg_id(ic.name)
2658
+ # id = Viz.to_svg_id(ic.name)
2659
+ id = ic.__id__.to_s
2378
2660
  # Determine the side of the inputs (and consequently of the outputs),
2379
2661
  # and the number of inputs.
2380
- iside = LEFT # Default side: left
2662
+ iside = nil
2381
2663
  inum = 0
2382
2664
  ic.ports.each do |port|
2383
2665
  if port.direction == :input then
2384
2666
  iside = port.side
2385
2667
  inum += 1
2668
+ elsif port.direction == :output then
2669
+ case port.side
2670
+ when LEFT
2671
+ iside = RIGHT
2672
+ when RIGHT
2673
+ iside = LEFT
2674
+ when UP
2675
+ iside = DOWN
2676
+ when DOWN
2677
+ iside = UP
2678
+ end
2386
2679
  end
2387
2680
  end
2681
+ raise "Connection with no port for #{ic.name}" unless iside
2388
2682
  # NOTE: inum is zero in case of a constant, force at least 1.
2389
2683
  inum = 1 if inum < 1
2390
2684
  # The length of a leg
@@ -2395,80 +2689,72 @@ module HDLRuby::Viz
2395
2689
  end
2396
2690
  # Generate the resulting polygon.
2397
2691
  res = "<polygon id=\"#{id}\" fill=\"#eee\" stroke=\"#000\" " +
2398
- "stroke-width=\"#{@scale/16.0}\" " +
2692
+ "stroke-width=\"#{(@scale/16.0).round(3)}\" " +
2399
2693
  "points=\""
2400
2694
  # The result depends on the size of the input.
2401
2695
  case(iside)
2402
2696
  when LEFT
2403
2697
  # The left side
2404
- res += "#{ic.xpos*@scale} #{(ic.ypos)*@scale} "
2698
+ res += "#{(ic.xpos*@scale).round(3)} #{((ic.ypos)*@scale).round(3)} "
2405
2699
  (inum-1).times do |i|
2406
- res += "#{(ic.xpos)*@scale} #{(ic.ypos+i*leg+0.25)*@scale} "
2407
- res += "#{(ic.xpos)*@scale} #{(ic.ypos+(i+1)*leg-0.25)*@scale} "
2408
- res += "#{(ic.xpos+0.25)*@scale} #{(ic.ypos+(i+1)*leg)*@scale} "
2409
- res += "#{(ic.xpos)*@scale} #{(ic.ypos+(i+1)*leg+0.25)*@scale} "
2700
+ res += "#{((ic.xpos)*@scale).round(3)} #{((ic.ypos+i*leg+0.25)*@scale).round(3)} "
2701
+ res += "#{((ic.xpos)*@scale).round(3)} #{((ic.ypos+(i+1)*leg-0.25)*@scale).round(3)} "
2702
+ res += "#{((ic.xpos+0.25)*@scale).round(3)} #{((ic.ypos+(i+1)*leg)*@scale).round(3)} "
2703
+ res += "#{((ic.xpos)*@scale).round(3)} #{((ic.ypos+(i+1)*leg+0.25)*@scale).round(3)} "
2410
2704
  end
2411
- res += "#{(ic.xpos)*@scale} #{(ic.ypos+inum*leg)*@scale} "
2705
+ res += "#{((ic.xpos)*@scale).round(3)} #{((ic.ypos+inum*leg)*@scale).round(3)} "
2412
2706
  # The up side
2413
- # res += "#{(ic.xpos+ic.width)*@scale} #{(ic.ypos+inum*leg-1)*@scale} "
2414
- res += "#{(ic.xpos+ic.width)*@scale} #{(ic.ypos+ic.height*0.7)*@scale} "
2707
+ res += "#{((ic.xpos+ic.width)*@scale).round(3)} #{((ic.ypos+ic.height*0.7)*@scale).round(3)} "
2415
2708
  # The right side.
2416
- # res += "#{(ic.xpos+ic.width)*@scale} #{(ic.ypos+1)*@scale}"
2417
- res += "#{(ic.xpos+ic.width)*@scale} #{(ic.ypos+ic.height*0.3)*@scale}"
2709
+ res += "#{((ic.xpos+ic.width)*@scale).round(3)} #{((ic.ypos+ic.height*0.3)*@scale).round(3)}"
2418
2710
  # The down side is not necessary, close the shape.
2419
2711
  res += "\"/>"
2420
2712
  when UP
2421
2713
  # The right side
2422
- res += "#{(ic.xpos)*@scale} #{(ic.ypos+ic.height)*@scale} "
2714
+ res += "#{((ic.xpos)*@scale).round(3)} #{((ic.ypos+ic.height)*@scale).round(3)} "
2423
2715
  (inum-1).times do |i|
2424
- res += "#{(ic.xpos+i*leg+0.25)*@scale} #{(ic.ypos+ic.height)*@scale} "
2425
- res += "#{(ic.xpos+(i+1)*leg-0.25)*@scale} #{(ic.ypos+ic.height)*@scale} "
2426
- res += "#{(ic.xpos+(i+1)*leg)*@scale} #{(ic.ypos-0.25+ic.height)*@scale} "
2427
- res += "#{(ic.xpos+(i+1)*leg+0.25)*@scale} #{(ic.ypos+ic.height)*@scale} "
2716
+ res += "#{((ic.xpos+i*leg+0.25)*@scale).round(3)} #{((ic.ypos+ic.height)*@scale).round(3)} "
2717
+ res += "#{((ic.xpos+(i+1)*leg-0.25)*@scale).round(3)} #{((ic.ypos+ic.height)*@scale).round(3)} "
2718
+ res += "#{((ic.xpos+(i+1)*leg)*@scale).round(3)} #{((ic.ypos-0.25+ic.height)*@scale).round(3)} "
2719
+ res += "#{((ic.xpos+(i+1)*leg+0.25)*@scale).round(3)} #{((ic.ypos+ic.height)*@scale).round(3)} "
2428
2720
  end
2429
- res += "#{(ic.xpos+inum*leg)*@scale} #{(ic.ypos+ic.height)*@scale} "
2721
+ res += "#{((ic.xpos+inum*leg)*@scale).round(3)} #{((ic.ypos+ic.height)*@scale).round(3)} "
2430
2722
  # The up side
2431
- # res += "#{(ic.xpos+inum*leg-1)*@scale} #{(ic.ypos)*@scale} "
2432
- res += "#{(ic.xpos+ic.width*0.7)*@scale} #{(ic.ypos)*@scale} "
2723
+ res += "#{((ic.xpos+ic.width*0.7)*@scale).round(3)} #{((ic.ypos)*@scale).round(3)} "
2433
2724
  # The right side.
2434
- # res += "#{(ic.xpos+1)*@scale} #{(ic.ypos)*@scale}"
2435
- res += "#{(ic.xpos+ic.width*0.3)*@scale} #{(ic.ypos)*@scale}"
2725
+ res += "#{((ic.xpos+ic.width*0.3)*@scale).round(3)} #{((ic.ypos)*@scale).round(3)}"
2436
2726
  # The down side is not necessary, close the shape.
2437
2727
  res += "\"/>"
2438
2728
  when RIGHT
2439
2729
  # The right side
2440
- res += "#{(ic.xpos+ic.width)*@scale} #{(ic.ypos)*@scale} "
2730
+ res += "#{((ic.xpos+ic.width)*@scale).round(3)} #{((ic.ypos)*@scale).round(3)} "
2441
2731
  (inum-1).times do |i|
2442
- res += "#{(ic.xpos+ic.width)*@scale} #{(ic.ypos+i*leg+0.25)*@scale} "
2443
- res += "#{(ic.xpos+ic.width)*@scale} #{(ic.ypos+(i+1)*leg-0.25)*@scale} "
2444
- res += "#{(ic.xpos-0.25+ic.width)*@scale} #{(ic.ypos+(i+1)*leg)*@scale} "
2445
- res += "#{(ic.xpos+ic.width)*@scale} #{(ic.ypos+(i+1)*leg+0.25)*@scale} "
2732
+ res += "#{((ic.xpos+ic.width)*@scale).round(3)} #{((ic.ypos+i*leg+0.25)*@scale).round(3)} "
2733
+ res += "#{((ic.xpos+ic.width)*@scale).round(3)} #{((ic.ypos+(i+1)*leg-0.25)*@scale).round(3)} "
2734
+ res += "#{((ic.xpos-0.25+ic.width)*@scale).round(3)} #{((ic.ypos+(i+1)*leg)*@scale).round(3)} "
2735
+ res += "#{((ic.xpos+ic.width)*@scale).round(3)} #{((ic.ypos+(i+1)*leg+0.25)*@scale).round(3)} "
2446
2736
  end
2447
- res += "#{(ic.xpos+ic.width)*@scale} #{(ic.ypos+inum*leg)*@scale} "
2737
+ res += "#{((ic.xpos+ic.width)*@scale).round(3)} #{((ic.ypos+inum*leg)*@scale).round(3)} "
2448
2738
  # The up side
2449
- # res += "#{(ic.xpos)*@scale} #{(ic.ypos+inum*leg-1)*@scale} "
2450
- res += "#{(ic.xpos)*@scale} #{(ic.ypos+ic.height*0.7)*@scale} "
2739
+ res += "#{((ic.xpos)*@scale).round(3)} #{((ic.ypos+ic.height*0.7)*@scale).round(3)} "
2451
2740
  # The right side.
2452
- # res += "#{(ic.xpos)*@scale} #{(ic.ypos+1)*@scale}"
2453
- res += "#{(ic.xpos)*@scale} #{(ic.ypos+ic.height*0.3)*@scale}"
2741
+ res += "#{((ic.xpos)*@scale).round(3)} #{((ic.ypos+ic.height*0.3)*@scale).round(3)}"
2454
2742
  # The down side is not necessary, close the shape.
2455
2743
  res += "\"/>"
2456
2744
  when DOWN
2457
2745
  # The down side
2458
- res += "#{ic.xpos*@scale} #{(ic.ypos)*@scale} "
2746
+ res += "#{(ic.xpos*@scale).round(3)} #{((ic.ypos)*@scale).round(3)} "
2459
2747
  (inum-1).times do |i|
2460
- res += "#{(ic.xpos+i*leg+0.25)*@scale} #{(ic.ypos)*@scale} "
2461
- res += "#{(ic.xpos+(i+1)*leg-0.25)*@scale} #{(ic.ypos)*@scale} "
2462
- res += "#{(ic.xpos+(i+1)*leg)*@scale} #{(ic.ypos+0.25)*@scale} "
2463
- res += "#{(ic.xpos+(i+1)*leg+0.25)*@scale} #{(ic.ypos)*@scale} "
2748
+ res += "#{((ic.xpos+i*leg+0.25)*@scale).round(3)} #{((ic.ypos)*@scale).round(3)} "
2749
+ res += "#{((ic.xpos+(i+1)*leg-0.25)*@scale).round(3)} #{((ic.ypos)*@scale).round(3)} "
2750
+ res += "#{((ic.xpos+(i+1)*leg)*@scale).round(3)} #{((ic.ypos+0.25)*@scale).round(3)} "
2751
+ res += "#{((ic.xpos+(i+1)*leg+0.25)*@scale).round(3)} #{((ic.ypos)*@scale).round(3)} "
2464
2752
  end
2465
- res += "#{(ic.xpos+inum*leg)*@scale} #{(ic.ypos)*@scale} "
2753
+ res += "#{((ic.xpos+inum*leg)*@scale).round(3)} #{((ic.ypos)*@scale).round(3)} "
2466
2754
  # The up side
2467
- # res += "#{(ic.xpos+inum*leg-1)*@scale} #{(ic.ypos+ic.height)*@scale} "
2468
- res += "#{(ic.xpos+ic.width*0.7)*@scale} #{(ic.ypos+ic.height)*@scale} "
2755
+ res += "#{((ic.xpos+ic.width*0.7)*@scale).round(3)} #{((ic.ypos+ic.height)*@scale).round(3)} "
2469
2756
  # The right side.
2470
- # res += "#{(ic.xpos+1)*@scale} #{(ic.ypos+ic.height)*@scale}"
2471
- res += "#{(ic.xpos+ic.width*0.3)*@scale} #{(ic.ypos+ic.height)*@scale}"
2757
+ res += "#{((ic.xpos+ic.width*0.3)*@scale).round(3)} #{((ic.ypos+ic.height)*@scale).round(3)}"
2472
2758
  # The down side is not necessary, close the shape.
2473
2759
  res += "\"/>"
2474
2760
  else
@@ -2480,8 +2766,8 @@ module HDLRuby::Viz
2480
2766
  res += "<text id=\"text#{id}\" " +
2481
2767
  "style=\"text-anchor: middle; dominant-baseline: middle;\" " +
2482
2768
  "font-family=\"monospace\" font-size=\"1px\" " +
2483
- "x=\"#{(ic.xpos + ic.width/2.0)*@scale}\" "+
2484
- "y=\"#{(ic.ypos + ic.height/2.0 + sy)*@scale}\">" +
2769
+ "x=\"#{((ic.xpos + ic.width/2.0)*@scale).round(3)}\" "+
2770
+ "y=\"#{((ic.ypos + ic.height/2.0 + sy)*@scale).round(3)}\">" +
2485
2771
  ic.name + "</text>\n"
2486
2772
  # Its text resizing.
2487
2773
  res += Viz.svg_text_fit("text#{id}",(ic.width-0.6)*@scale,
@@ -2498,15 +2784,17 @@ module HDLRuby::Viz
2498
2784
  res = "<rect fill=\"#88f\" stroke=\"#000\" "
2499
2785
  when :negedge
2500
2786
  res = "<rect fill=\"#f88\" stroke=\"#000\" "
2787
+ when :anyedge
2788
+ res = "<rect fill=\"#888\" stroke=\"#000\" "
2501
2789
  else
2502
2790
  res = "<rect fill=\"#ff0\" stroke=\"#000\" "
2503
2791
  end
2504
- res += "x=\"#{xpos}\" y=\"#{ypos}\" " +
2505
- "stroke-width=\"#{@scale/16.0}\" " +
2506
- "width=\"#{width}\" height=\"#{height}\"/>\n"
2792
+ res += "x=\"#{xpos.round(3)}\" y=\"#{ypos.round(3)}\" " +
2793
+ "stroke-width=\"#{(@scale/16.0).round(3)}\" " +
2794
+ "width=\"#{width.round(3)}\" height=\"#{height.round(3)}\"/>\n"
2507
2795
  res += "<polygon fill=\"#000\" stroke=\"none\" " +
2508
- "points=\"#{xpos},#{ypos+height/2.0} #{xpos+width},#{ypos} " +
2509
- "#{xpos+width},#{ypos+height}\"/>\n"
2796
+ "points=\"#{xpos.round(3)},#{(ypos+height/2.0).round(3)} #{(xpos+width).round(3)},#{ypos.round(3)} " +
2797
+ "#{(xpos+width).round(3)},#{(ypos+height).round(3)}\"/>\n"
2510
2798
  return res
2511
2799
  end
2512
2800
 
@@ -2517,30 +2805,32 @@ module HDLRuby::Viz
2517
2805
  res = "<rect fill=\"#88f\" stroke=\"#000\" "
2518
2806
  when :negedge
2519
2807
  res = "<rect fill=\"#f88\" stroke=\"#000\" "
2808
+ when :anyedge
2809
+ res = "<rect fill=\"#888\" stroke=\"#000\" "
2520
2810
  else
2521
2811
  res = "<rect fill=\"#ff0\" stroke=\"#000\" "
2522
2812
  end
2523
- res += "x=\"#{xpos}\" y=\"#{ypos}\" " +
2524
- "stroke-width=\"#{@scale/16.0}\" " +
2525
- "width=\"#{width}\" height=\"#{height}\"/>\n"
2813
+ res += "x=\"#{xpos.round(3)}\" y=\"#{ypos.round(3)}\" " +
2814
+ "stroke-width=\"#{(@scale/16.0).round(3)}\" " +
2815
+ "width=\"#{width.round(3)}\" height=\"#{height.round(3)}\"/>\n"
2526
2816
  res += "<polygon fill=\"#000\" stroke=\"none\" " +
2527
- "points=\"#{xpos},#{ypos} #{xpos+width},#{ypos+height/2.0} " +
2528
- "#{xpos},#{ypos+height}\"/>\n"
2817
+ "points=\"#{xpos.round(3)},#{ypos.round(3)} #{(xpos+width).round(3)},#{(ypos+height/2.0).round(3)} " +
2818
+ "#{xpos.round(3)},#{(ypos+height).round(3)}\"/>\n"
2529
2819
  return res
2530
2820
  end
2531
2821
 
2532
2822
  # Generate a left-right port description SVG text.
2533
2823
  def left_right_port_svg(name,type,xpos,ypos,width,height)
2534
2824
  res = "<rect fill=\"#FF0\" stroke=\"#000\" " +
2535
- "x=\"#{xpos}\" y=\"#{ypos}\" " +
2825
+ "x=\"#{xpos.round(3)}\" y=\"#{ypos.round(3)}\" " +
2536
2826
  "stroke-width=\"#{@scale/16.0}\" " +
2537
- "width=\"#{width}\" height=\"#{height}\"/>\n"
2827
+ "width=\"#{width.round(3)}\" height=\"#{height.round(3)}\"/>\n"
2538
2828
  res += "<polygon fill=\"#000\" stroke=\"none\" " +
2539
- "points=\"#{xpos},#{ypos+height/2} #{xpos+width},#{ypos} " +
2540
- "#{xpos+width},#{ypos+height}\"/>\n"
2829
+ "points=\"#{xpos.round(3)},#{(ypos+height/2).round(3)} #{(xpos+width).round(3)},#{ypos.round(3)} " +
2830
+ "#{(xpos+width).round(3)},#{(ypos+height).round(3)}\"/>\n"
2541
2831
  res += "<polygon fill=\"#000\" stroke=\"none\" " +
2542
- "points=\"#{xpos},#{ypos} #{xpos+width},#{ypos+height/2.0} " +
2543
- "#{xpos},#{ypos+height}\"/>\n"
2832
+ "points=\"#{xpos.round(3)},#{ypos.round(3)} #{(xpos+width).round(3)},#{(ypos+height/2.0).round(3)} " +
2833
+ "#{xpos.round(3)},#{(ypos+height).round(3)}\"/>\n"
2544
2834
  return res
2545
2835
  end
2546
2836
 
@@ -2551,15 +2841,17 @@ module HDLRuby::Viz
2551
2841
  res = "<rect fill=\"#88f\" stroke=\"#000\" "
2552
2842
  when :negedge
2553
2843
  res = "<rect fill=\"#f88\" stroke=\"#000\" "
2844
+ when :anyedge
2845
+ res = "<rect fill=\"#888\" stroke=\"#000\" "
2554
2846
  else
2555
2847
  res = "<rect fill=\"#ff0\" stroke=\"#000\" "
2556
2848
  end
2557
- res += "x=\"#{xpos}\" y=\"#{ypos}\" " +
2558
- "stroke-width=\"#{@scale/16.0}\" " +
2559
- "width=\"#{width}\" height=\"#{height}\"/>\n"
2849
+ res += "x=\"#{xpos.round(3)}\" y=\"#{ypos.round(3)}\" " +
2850
+ "stroke-width=\"#{(@scale/16.0).round(3)}\" " +
2851
+ "width=\"#{width.round(3)}\" height=\"#{height.round(3)}\"/>\n"
2560
2852
  res += "<polygon fill=\"#000\" stroke=\"none\" " +
2561
- "points=\"#{xpos},#{ypos} #{xpos+width/2.0},#{ypos+height} " +
2562
- "#{xpos+width},#{ypos}\"/>\n"
2853
+ "points=\"#{xpos.round(3)},#{ypos.round(3)} #{(xpos+width/2.0).round(3)},#{(ypos+height).round(3)} " +
2854
+ "#{(xpos+width).round(3)},#{ypos.round(3)}\"/>\n"
2563
2855
  return res
2564
2856
  end
2565
2857
 
@@ -2570,30 +2862,32 @@ module HDLRuby::Viz
2570
2862
  res = "<rect fill=\"#88f\" stroke=\"#000\" "
2571
2863
  when :negedge
2572
2864
  res = "<rect fill=\"#f88\" stroke=\"#000\" "
2865
+ when :anyedge
2866
+ res = "<rect fill=\"#888\" stroke=\"#000\" "
2573
2867
  else
2574
2868
  res = "<rect fill=\"#ff0\" stroke=\"#000\" "
2575
2869
  end
2576
- res += "x=\"#{xpos}\" y=\"#{ypos}\" " +
2577
- "stroke-width=\"#{@scale/16.0}\" " +
2578
- "width=\"#{width}\" height=\"#{height}\"/>\n"
2870
+ res += "x=\"#{xpos.round(3)}\" y=\"#{ypos.round(3)}\" " +
2871
+ "stroke-width=\"#{(@scale/16.0).round(3)}\" " +
2872
+ "width=\"#{width.round(3)}\" height=\"#{height.round(3)}\"/>\n"
2579
2873
  res += "<polygon fill=\"#000\" stroke=\"none\" " +
2580
- "points=\"#{xpos+width/2.0},#{ypos} #{xpos},#{ypos+height} " +
2581
- "#{xpos+width},#{ypos+height}\"/>\n"
2874
+ "points=\"#{(xpos+width/2.0).round(3)},#{ypos.round(3)} #{xpos.round(3)},#{(ypos+height).round(3)} " +
2875
+ "#{(xpos+width).round(3)},#{(ypos+height).round(3)}\"/>\n"
2582
2876
  return res
2583
2877
  end
2584
2878
 
2585
2879
  # Generate an up-down port description SVG text.
2586
2880
  def up_down_port_svg(name,type,xpos,ypos,width,height)
2587
2881
  res = "<rect fill=\"#FF0\" stroke=\"#000\" " +
2588
- "x=\"#{xpos}\" y=\"#{ypos}\" " +
2589
- "stroke-width=\"#{@scale/16.0}\" " +
2590
- "width=\"#{width}\" height=\"#{height}\"/>\n"
2882
+ "x=\"#{xpos.round(3)}\" y=\"#{ypos.round(3)}\" " +
2883
+ "stroke-width=\"#{(@scale/16.0).round(3)}\" " +
2884
+ "width=\"#{width.round(3)}\" height=\"#{height.round(3)}\"/>\n"
2591
2885
  res += "<polygon fill=\"#000\" stroke=\"none\" " +
2592
- "points=\"#{xpos},#{ypos} #{xpos+width/2},#{ypos+height} " +
2593
- "#{xpos+width},#{ypos}\"/>\n"
2886
+ "points=\"#{xpos.round(3)},#{ypos.round(3)} #{(xpos+width/2).round(3)},#{(ypos+height).round(3)} " +
2887
+ "#{(xpos+width).round(3)},#{ypos.round(3)}\"/>\n"
2594
2888
  res += "<polygon fill=\"#000\" stroke=\"none\" " +
2595
- "points=\"#{xpos+width/2.0},#{ypos} #{xpos},#{ypos+height} " +
2596
- "#{xpos+width},#{ypos+height}\"/>\n"
2889
+ "points=\"#{(xpos+width/2.0).round(3)},#{ypos.round(3)} #{xpos.round(3)},#{(ypos+height).round(3)} " +
2890
+ "#{(xpos+width).round(3)},#{(ypos+height).round(3)}\"/>\n"
2597
2891
  return res
2598
2892
  end
2599
2893
 
@@ -2605,15 +2899,22 @@ module HDLRuby::Viz
2605
2899
  # Generate the string representing a port for display in the SVG
2606
2900
  def port_str(port)
2607
2901
  # Generate the port name (strip everything before the last ".")
2608
- name = port.name.sub(/^.*\./,"")
2902
+ # name = port.name.sub(/^.*\./,"")
2903
+ name = port.name.split(/(?<!\.)\.(?!\.)/).last
2609
2904
  # Strip the suffix $I and $O
2610
2905
  name = name.sub(/\$(I|O)$/,"")
2906
+ # For registers' bit ports, only keep the bit number.
2907
+ if port.ic.type==:register and HDLRuby::Viz.port_bit_name?(name) then
2908
+ name = HDLRuby::Viz.port_bit_name(name)
2909
+ end
2611
2910
  # Add a suffix for edge properties.
2612
2911
  case port.type
2613
2912
  when :posedge
2614
2913
  return name + " \u2197"
2615
2914
  when :negedge
2616
2915
  return name + " \u2198"
2916
+ when :anyedge
2917
+ return name + " \u2195"
2617
2918
  else
2618
2919
  return name
2619
2920
  end
@@ -2660,23 +2961,28 @@ module HDLRuby::Viz
2660
2961
  # Sets the styles.
2661
2962
  res += "<style>\n"
2662
2963
  # Fonts
2663
- res += ".small#{self.idC} { font: #{sF}px sans-serif; }\n"
2964
+ res += ".small#{self.idC} { font: #{sF}px sans-serif; " # }\n" # +
2965
+ res += "stroke=\"yellow\"; stroke-width=\"6\"; paint-order=\"stroke fill;\" }\n"
2966
+ # "border: 2px solid black; padding: 10px; display: inline-block; " +
2967
+ # " background-color: rgba(0, 128, 255, 0.2); }\n"
2664
2968
  res += ".medium#{self.idC} { font: #{mF}px sans-serif; }\n"
2665
2969
  res += ".large#{self.idC} { font: #{lF}px sans-serif; }\n"
2666
2970
  res += "</style>\n"
2667
2971
 
2668
2972
  # Generate the group containing all the IC description.
2669
- res += "<g id=\"#{self.name}\" visibility=\"#{visibility}\" " +
2973
+ # res += "<g id=\"#{self.name}\" visibility=\"#{visibility}\" " +
2974
+ # "transform=\"translate(#{tx},#{ty})\">\n"
2975
+ res += "<g id=\"#{self.__id__}\" visibility=\"#{visibility}\" " +
2670
2976
  "transform=\"translate(#{tx},#{ty})\">\n"
2671
2977
  # Generate the rectangle of the bounding box.
2672
2978
  res += "<rect fill=\"#bbb\" stroke=\"#555\" " +
2673
- "stroke-width=\"#{@scale/4.0}\" " +
2979
+ "stroke-width=\"#{(@scale/4.0).round(3)}\" " +
2674
2980
  # "x=\"#{x0-bT*2.5}\" y=\"#{y0-bT*2.5}\" "+
2675
- "x=\"#{x0}\" y=\"#{y0}\" "+
2981
+ "x=\"#{x0.round(3)}\" y=\"#{y0.round(3)}\" "+
2676
2982
  "width=\"#{width}\" height=\"#{height}\"/>\n"
2677
2983
 
2678
2984
  # Generate the group containing the top system and its contents.
2679
- res += "<g transform=\"translate(#{stx},#{sty})\">\n"
2985
+ res += "<g transform=\"translate(#{stx.round(3)},#{sty.round(3)})\">\n"
2680
2986
 
2681
2987
  # Generate current IC's box.
2682
2988
  # The SVG object representing a system.
@@ -2687,9 +2993,9 @@ module HDLRuby::Viz
2687
2993
  row.each_with_index do |tile,x|
2688
2994
  # # Draw the tiles contour for debug.
2689
2995
  # res += "<rect fill=\"none\" stroke=\"#00F\" " +
2690
- # "x=\"#{x*@scale}\" " +
2691
- # "y=\"#{y*@scale}\" " +
2692
- # "width=\"#{@scale}\" height=\"#{@scale}\"/>\n"
2996
+ # "x=\"#{(x*@scale).round(3)}\" " +
2997
+ # "y=\"#{(y*@scale).round(3)}\" " +
2998
+ # "width=\"#{@scale.round(3)}\" height=\"#{@scale.round(3)}\"/>\n"
2693
2999
  #
2694
3000
  # Draw the wires.
2695
3001
  tile.wires.each do |wire_dir|
@@ -2697,69 +3003,69 @@ module HDLRuby::Viz
2697
3003
  # Draw the wire (as a thin rectangle).
2698
3004
  case wire_dir
2699
3005
  when LEFT|RIGHT
2700
- res += "<line stroke=\"#000\" stroke-width=\"#{wT}\" " +
3006
+ res += "<line stroke=\"#000\" stroke-width=\"#{wT.round(3)}\" " +
2701
3007
  "stroke-linecap=\"round\" " +
2702
- "x1=\"#{(x)*@scale}\" " +
2703
- "y1=\"#{(y+0.5)*@scale}\" " +
2704
- "x2=\"#{(x+1)*@scale}\" " +
2705
- "y2=\"#{(y+0.5)*@scale}\" />\n"
3008
+ "x1=\"#{((x)*@scale).round(3)}\" " +
3009
+ "y1=\"#{((y+0.5)*@scale).round(3)}\" " +
3010
+ "x2=\"#{((x+1)*@scale).round(3)}\" " +
3011
+ "y2=\"#{((y+0.5)*@scale).round(3)}\" />\n"
2706
3012
  when RIGHT|DOWN
2707
- res += "<line stroke=\"#000\" stroke-width=\"#{wT}\" " +
3013
+ res += "<line stroke=\"#000\" stroke-width=\"#{wT.round(3)}\" " +
2708
3014
  "stroke-linecap=\"round\" " +
2709
- "x1=\"#{(x+1)*@scale}\" " +
2710
- "y1=\"#{(y+0.5)*@scale}\" " +
2711
- "x2=\"#{(x+0.5)*@scale}\" " +
2712
- "y2=\"#{(y)*@scale}\" />\n"
3015
+ "x1=\"#{((x+1)*@scale).round(3)}\" " +
3016
+ "y1=\"#{((y+0.5)*@scale).round(3)}\" " +
3017
+ "x2=\"#{((x+0.5)*@scale).round(3)}\" " +
3018
+ "y2=\"#{((y)*@scale).round(3)}\" />\n"
2713
3019
  when RIGHT|UP
2714
- res += "<line stroke=\"#000\" stroke-width=\"#{wT}\" " +
3020
+ res += "<line stroke=\"#000\" stroke-width=\"#{wT.round(3)}\" " +
2715
3021
  "stroke-linecap=\"round\" " +
2716
- "x1=\"#{(x+1)*@scale}\" " +
2717
- "y1=\"#{(y+0.5)*@scale}\" " +
2718
- "x2=\"#{(x+0.5)*@scale}\" " +
2719
- "y2=\"#{(y+1)*@scale}\" />\n"
3022
+ "x1=\"#{((x+1)*@scale).round(3)}\" " +
3023
+ "y1=\"#{((y+0.5)*@scale).round(3)}\" " +
3024
+ "x2=\"#{((x+0.5)*@scale).round(3)}\" " +
3025
+ "y2=\"#{((y+1)*@scale).round(3)}\" />\n"
2720
3026
  when LEFT|DOWN
2721
- res += "<line stroke=\"#000\" stroke-width=\"#{wT}\" " +
3027
+ res += "<line stroke=\"#000\" stroke-width=\"#{wT.round(3)}\" " +
2722
3028
  "stroke-linecap=\"round\" " +
2723
- "x1=\"#{(x+0.5)*@scale}\" " +
2724
- "y1=\"#{(y)*@scale}\" " +
2725
- "x2=\"#{(x)*@scale}\" " +
2726
- "y2=\"#{(y+0.5)*@scale}\" />\n"
3029
+ "x1=\"#{((x+0.5)*@scale).round(3)}\" " +
3030
+ "y1=\"#{((y)*@scale).round(3)}\" " +
3031
+ "x2=\"#{((x)*@scale).round(3)}\" " +
3032
+ "y2=\"#{((y+0.5)*@scale).round(3)}\" />\n"
2727
3033
  when LEFT|UP
2728
- res += "<line stroke=\"#000\" stroke-width=\"#{wT}\" " +
3034
+ res += "<line stroke=\"#000\" stroke-width=\"#{wT.round(3)}\" " +
2729
3035
  "stroke-linecap=\"round\" " +
2730
- "x1=\"#{(x+0.5)*@scale}\" " +
2731
- "y1=\"#{(y+1)*@scale}\" " +
2732
- "x2=\"#{(x)*@scale}\" " +
2733
- "y2=\"#{(y+0.5)*@scale}\" />\n"
3036
+ "x1=\"#{((x+0.5)*@scale).round(3)}\" " +
3037
+ "y1=\"#{((y+1)*@scale).round(3)}\" " +
3038
+ "x2=\"#{((x)*@scale).round(3)}\" " +
3039
+ "y2=\"#{((y+0.5)*@scale).round(3)}\" />\n"
2734
3040
  when UP|DOWN
2735
- res += "<line stroke=\"#000\" stroke-width=\"#{wT}\" " +
3041
+ res += "<line stroke=\"#000\" stroke-width=\"#{wT.round(3)}\" " +
2736
3042
  "stroke-linecap=\"round\" " +
2737
- "x1=\"#{(x+0.5)*@scale}\" " +
2738
- "y1=\"#{(y)*@scale}\" " +
2739
- "x2=\"#{(x+0.5)*@scale}\" " +
2740
- "y2=\"#{(y+1)*@scale}\" />\n"
3043
+ "x1=\"#{((x+0.5)*@scale).round(3)}\" " +
3044
+ "y1=\"#{((y)*@scale).round(3)}\" " +
3045
+ "x2=\"#{((x+0.5)*@scale).round(3)}\" " +
3046
+ "y2=\"#{((y+1)*@scale).round(3)}\" />\n"
2741
3047
  end
2742
3048
  end
2743
3049
 
2744
3050
  # Draw the connection points.
2745
3051
  tile.dots.each do |dot_pos|
2746
3052
  res += "<rect fill=\"#000\" stroke=\"#000\" " +
2747
- "stroke-width=\"#{wT}\" "
3053
+ "stroke-width=\"#{wT.round(3)}\" "
2748
3054
  case dot_pos
2749
3055
  when LEFT
2750
- res += "x=\"#{(x+0.0)*@scale-wT*2}\" " +
2751
- "y=\"#{(y+0.5)*@scale-wT*2}\" "
3056
+ res += "x=\"#{((x+0.0)*@scale-wT*2).round(3)}\" " +
3057
+ "y=\"#{((y+0.5)*@scale-wT*2).round(3)}\" "
2752
3058
  when UP
2753
- res += "x=\"#{(x+0.5)*@scale-wT*2}\" " +
2754
- "y=\"#{(y+1.0)*@scale-wT*2}\" "
3059
+ res += "x=\"#{((x+0.5)*@scale-wT*2).round(3)}\" " +
3060
+ "y=\"#{((y+1.0)*@scale-wT*2).round(3)}\" "
2755
3061
  when RIGHT
2756
- res += "x=\"#{(x+1.0)*@scale-wT*2}\" " +
2757
- "y=\"#{(y+0.5)*@scale-wT*2}\" "
3062
+ res += "x=\"#{((x+1.0)*@scale-wT*2).round(3)}\" " +
3063
+ "y=\"#{((y+0.5)*@scale-wT*2).round(3)}\" "
2758
3064
  when DOWN
2759
- res += "x=\"#{(x+0.5)*@scale-wT*2}\" " +
2760
- "y=\"#{(y+0.0)*@scale-wT*2}\" "
3065
+ res += "x=\"#{((x+0.5)*@scale-wT*2).round(3)}\" " +
3066
+ "y=\"#{((y+0.0)*@scale-wT*2).round(3)}\" "
2761
3067
  end
2762
- res += "width=\"#{wT*4}\" height=\"#{wT*4}\"/>\n"
3068
+ res += "width=\"#{(wT*4).round(3)}\" height=\"#{(wT*4).round(3)}\"/>\n"
2763
3069
  end
2764
3070
  end
2765
3071
  end
@@ -2817,12 +3123,20 @@ module HDLRuby::Viz
2817
3123
  port.direction != :none) or child.sub_port?(port) then
2818
3124
  if child == self then
2819
3125
  res += "<text class=\"small#{self.idC}\" style=\"text-anchor: end\" " +
2820
- "x=\"#{(port.xpos)*@scale-pT}\" "+
2821
- "y=\"#{(port.ypos+0.5)*@scale+sF/2.5}\">" + # port.name +
3126
+ "x=\"#{((port.xpos)*@scale-pT).round(3)}\" "+
3127
+ "y=\"#{((port.ypos+0.5)*@scale+sF/2.5).round(3)}\">" +
3128
+ self.port_str(port) + "</text>\n"
3129
+ elsif (child.type == :assign and port.direction == :input and
3130
+ child.ports.size.even? and child.ports.index(port) == child.ports.size/2) then
3131
+ # Middle input of an alu, slide it bellow to avoid collision
3132
+ # with the output port.
3133
+ res += "<text class=\"small#{self.idC}\" x=\"#{((port.xpos)*@scale+pT).round(3)}\" "+
3134
+ "y=\"#{((port.ypos+0.8)*@scale+sF/2.5).round(3)}\">" +
2822
3135
  self.port_str(port) + "</text>\n"
2823
3136
  else
2824
- res += "<text class=\"small#{self.idC}\" x=\"#{(port.xpos)*@scale+pT}\" "+
2825
- "y=\"#{(port.ypos+0.5)*@scale+sF/2.5}\">" + # port.name +
3137
+ # General case.
3138
+ res += "<text class=\"small#{self.idC}\" x=\"#{((port.xpos)*@scale+pT).round(3)}\" "+
3139
+ "y=\"#{((port.ypos+0.45)*@scale+sF/2.5).round(3)}\">" +
2826
3140
  self.port_str(port) + "</text>\n"
2827
3141
  end
2828
3142
  end
@@ -2850,13 +3164,13 @@ module HDLRuby::Viz
2850
3164
  port.direction != :none) or child.sub_port?(port) then
2851
3165
  if child == self then
2852
3166
  res += "<text class=\"small#{self.idC}\" style=\"text-anchor: middle\" " +
2853
- "x=\"#{(port.xpos+0.5)*@scale}\" "+
2854
- "y=\"#{(port.ypos+1.0)*@scale+pT+sF/2}\">" + # port.name +
3167
+ "x=\"#{((port.xpos+0.5)*@scale).round(3)}\" "+
3168
+ "y=\"#{((port.ypos+1.0)*@scale+pT+sF/2).round(3)}\">" + # port.name +
2855
3169
  self.port_str(port) + "</text>\n"
2856
3170
  else
2857
3171
  res += "<text class=\"small#{self.idC}\" style=\"text-anchor: middle\" " +
2858
- "x=\"#{(port.xpos+0.5)*@scale}\" "+
2859
- "y=\"#{(port.ypos+1.0)*@scale-pT}\">" + # port.name +
3172
+ "x=\"#{((port.xpos+0.5)*@scale).round(3)}\" "+
3173
+ "y=\"#{((port.ypos+1.0)*@scale-pT).round(3)}\">" + # port.name +
2860
3174
  self.port_str(port) + "</text>\n"
2861
3175
  end
2862
3176
  end
@@ -2883,13 +3197,21 @@ module HDLRuby::Viz
2883
3197
  port.direction != :none) or child.sub_port?(port) then
2884
3198
  if child == self then
2885
3199
  res += "<text class=\"small#{self.idC}\" " +
2886
- "x=\"#{(port.xpos+1)*@scale+pT}\" " +
2887
- "y=\"#{(port.ypos+0.5)*@scale+sF/2.5}\">" + # port.name +
3200
+ "x=\"#{((port.xpos+1)*@scale+pT).round(3)}\" " +
3201
+ "y=\"#{((port.ypos+0.5)*@scale+sF/2.5).round(3)}\">" + # port.name +
3202
+ self.port_str(port) + "</text>\n"
3203
+ elsif (child.type == :assign and port.direction == :input and
3204
+ child.ports.size.even? and child.ports.index(port) == child.ports.size/2) then
3205
+ # Middle input of an alu, slide it bellow to avoid collision
3206
+ # with the output port.
3207
+ res += "<text class=\"small#{self.idC}\" style=\"text-anchor: end\" " +
3208
+ "x=\"#{((port.xpos+1)*@scale-pT).round(3)}\" "+
3209
+ "y=\"#{((port.ypos+0.8)*@scale+sF/2.5).round(3)}\">" + # port.name +
2888
3210
  self.port_str(port) + "</text>\n"
2889
3211
  else
2890
3212
  res += "<text class=\"small#{self.idC}\" style=\"text-anchor: end\" " +
2891
- "x=\"#{(port.xpos+1)*@scale-pT}\" "+
2892
- "y=\"#{(port.ypos+0.5)*@scale+sF/2.5}\">" + # port.name +
3213
+ "x=\"#{((port.xpos+1)*@scale-pT).round(3)}\" "+
3214
+ "y=\"#{((port.ypos+0.45)*@scale+sF/2.5).round(3)}\">" + # port.name +
2893
3215
  self.port_str(port) + "</text>\n"
2894
3216
  end
2895
3217
  end
@@ -2916,14 +3238,13 @@ module HDLRuby::Viz
2916
3238
  port.direction != :none) or child.sub_port?(port) then
2917
3239
  if child == self then
2918
3240
  res += "<text class=\"small#{self.idC}\" style=\"text-anchor: middle\" " +
2919
- "x=\"#{(port.xpos+0.5)*@scale}\" "+
2920
- "y=\"#{(port.ypos)*@scale-pT}\">" + # port.name +
3241
+ "x=\"#{((port.xpos+0.5)*@scale).round(3)}\" "+
3242
+ "y=\"#{((port.ypos)*@scale-pT).round(3)}\">" + # port.name +
2921
3243
  self.port_str(port) + "</text>\n"
2922
3244
  else
2923
3245
  res += "<text class=\"small#{self.idC}\" style=\"text-anchor: middle\" " +
2924
- "x=\"#{(port.xpos+0.5)*@scale}\" "+
2925
- # "y=\"#{(port.ypos)*@scale+pT+sF}\">" + # port.name +
2926
- "y=\"#{(port.ypos)*@scale+pT+sF/2.0}\">" + # port.name +
3246
+ "x=\"#{((port.xpos+0.5)*@scale).round(3)}\" "+
3247
+ "y=\"#{((port.ypos)*@scale+pT+sF/2.0).round(3)}\">" + # port.name +
2927
3248
  self.port_str(port) + "</text>\n"
2928
3249
  end
2929
3250
  end
@@ -2973,14 +3294,15 @@ module HDLRuby::Viz
2973
3294
  cty += 1
2974
3295
  end
2975
3296
  end
2976
- # Leave a space for left or right ports if any.
2977
- sl = child.ports.any? {|p| p.side == LEFT } ? 1.0 : 0.0
2978
- sr = child.ports.any? {|p| p.side == RIGHT } ? 1.0 : 0.0
3297
+ # # Leave a space for left or right ports if any.
3298
+ # sl = (child.ports.any? {|p| p.side == LEFT }) ? 1.0 : 0.0
3299
+ # sr = (child.ports.any? {|p| p.side == RIGHT }) ? 1.0 : 0.0
2979
3300
  # Recompute the scale.
2980
3301
  fit = [
2981
- (target.width+sl+sr+(bT/@scale)) / (cwidth),
2982
- (target.height+(bT/@scale)) / (cheight),
2983
- 3.0
3302
+ # (target.width+sl+sr+(bT/@scale/2.0)) / (cwidth),
3303
+ (target.width+(bT/@scale/2.0)) / (cwidth),
3304
+ (target.height+(bT/@scale/2.0)) / (cheight),
3305
+ 1.0# 3.0
2984
3306
  ].max
2985
3307
  target.scale = @scale / fit
2986
3308
  puts "fit=#{fit} target.scale=#{target.scale}"
@@ -2988,7 +3310,8 @@ module HDLRuby::Viz
2988
3310
  res += target.to_svg(false,ctx*@scale,cty*@scale,
2989
3311
  cwidth*scale,cheight*scale)
2990
3312
  # Generate the closing button element.
2991
- res += Viz.closing_svg(target.name + '_close',pT,(ctx+cwidth)*@scale-pT,cty*@scale)
3313
+ # res += Viz.closing_svg(target.name + '_close',pT,(ctx+cwidth)*@scale-pT,cty*@scale)
3314
+ res += Viz.closing_svg(target.__id__.to_s + '_close',pT,(ctx+cwidth)*@scale-pT,cty*@scale)
2992
3315
  end
2993
3316
 
2994
3317
  # Close the group containing the top system and its content.
@@ -3012,20 +3335,20 @@ module HDLRuby::Viz
3012
3335
  next unless target # No target? Skip.
3013
3336
  res += <<~SCRIPT
3014
3337
  <script>
3015
- diagram.getElementById('#{child.name}').addEventListener("click", (e) => {
3338
+ diagram.getElementById('#{child.__id__}').addEventListener("click", (e) => {
3016
3339
  // For the element.
3017
- let elem = diagram.getElementById('#{target.name}');
3340
+ let elem = diagram.getElementById('#{target.__id__}');
3018
3341
  elem.setAttribute('visibility','visible');
3019
3342
  // And its closing button.
3020
- elem = diagram.getElementById('#{target.name}_close');
3343
+ elem = diagram.getElementById('#{target.__id__}_close');
3021
3344
  elem.setAttribute('visibility','visible');
3022
3345
  });
3023
- diagram.getElementById('#{target.name}_close').addEventListener("click", (e) => {
3346
+ diagram.getElementById('#{target.__id__}_close').addEventListener("click", (e) => {
3024
3347
  // For the element.
3025
- let elem = diagram.getElementById('#{target.name}');
3348
+ let elem = diagram.getElementById('#{target.__id__}');
3026
3349
  elem.setAttribute('visibility','hidden');
3027
3350
  // And its closing button.
3028
- elem = diagram.getElementById('#{target.name}_close');
3351
+ elem = diagram.getElementById('#{target.__id__}_close');
3029
3352
  elem.setAttribute('visibility','hidden');
3030
3353
  });
3031
3354
 
@@ -3550,27 +3873,22 @@ diagram.getElementById('#{target.name}_close').addEventListener("click", (e) =>
3550
3873
  def assign_svg(n)
3551
3874
  # The shape representing the instance.
3552
3875
  res = "<path fill=\"#B0E2FF\" stroke=\"#000\" " +
3553
- "stroke-width=\"#{@scale/12.0}\" " +
3554
- # "d=\"M #{n.xpos*@scale} #{(n.ypos + n.height/2.0)*@scale} " +
3555
- # "L #{(n.xpos + 1.0)*@scale} #{n.ypos*@scale} " +
3556
- # "L #{(n.xpos + n.width-n.height/2.0)*@scale} #{n.ypos*@scale} " +
3557
- # "A #{n.height/2.0*@scale} #{n.height/2.0*@scale} 0 0 1 " +
3558
- # "#{(n.xpos + n.width-n.height/2.0)*@scale} #{(n.ypos+n.height)*@scale} " +
3559
- # "L #{(n.xpos + 1.0)*@scale} #{(n.ypos+n.height)*@scale} " +
3560
- "d=\"M #{n.xpos*@scale} #{(n.ypos + n.height)*@scale} " +
3561
- "L #{(n.xpos + 1.0)*@scale} #{n.ypos*@scale} " +
3562
- "L #{(n.xpos + n.width)*@scale} #{n.ypos*@scale} " +
3563
- "L #{(n.xpos + n.width-1.0)*@scale} #{(n.ypos+n.height)*@scale} " +
3876
+ "stroke-width=\"#{(@scale/12.0).round(3)}\" " +
3877
+ "d=\"M #{(n.xpos*@scale).round(3)} #{((n.ypos + n.height)*@scale).round(3)} " +
3878
+ "L #{((n.xpos + 1.0)*@scale).round(3)} #{(n.ypos*@scale).round(3)} " +
3879
+ "L #{((n.xpos + n.width)*@scale).round(3)} #{(n.ypos*@scale).round(3)} " +
3880
+ "L #{((n.xpos + n.width-1.0)*@scale).round(3)} #{((n.ypos+n.height)*@scale).round(3)} " +
3564
3881
  "Z \" />\n"
3565
3882
  # Its text.
3566
- res += "<text id=\"text#{n.name}\" " +
3883
+ # res += "<text id=\"text#{n.name}\" " +
3884
+ res += "<text id=\"text#{n.__id__}\" " +
3567
3885
  "style=\"text-anchor: middle; dominant-baseline: middle;\" " +
3568
3886
  "font-family=\"monospace\" font-size=\"1px\" " +
3569
- "x=\"#{(n.xpos + n.width/2.0)*@scale}\" "+
3570
- "y=\"#{(n.ypos + n.height/2.0)*@scale}\">" +
3887
+ "x=\"#{((n.xpos + n.width/2.0)*@scale).round(3)}\" "+
3888
+ "y=\"#{((n.ypos + n.height/2.0)*@scale).round(3)}\">" +
3571
3889
  n.to_s + "</text>\n"
3572
3890
  # Its text resizing.
3573
- res += Viz.svg_text_fit("text#{n.name}",(n.width-2)*@scale,
3891
+ res += Viz.svg_text_fit("text#{n.__id__}",(n.width-2)*@scale,
3574
3892
  0.6*@scale)
3575
3893
  return res
3576
3894
  end
@@ -3578,35 +3896,12 @@ diagram.getElementById('#{target.name}_close').addEventListener("click", (e) =>
3578
3896
  # Generate a block description SVG text for node +n+
3579
3897
  def block_svg(n)
3580
3898
  res = "<rect fill=\"#fff\" fill-opacity=\"0.4\" stroke=\"#000\" " +
3581
- "stroke-width=\"#{@scale/10.0}\" " +
3582
- "stroke-dasharray=\"#{@scale/10.0},#{@scale/10.0}\" " +
3583
- # "x=\"#{n.xpos*@scale}\" y=\"#{n.ypos*@scale}\" " +
3584
- # "rx=\"#{@scale*2.0}\" " +
3585
- # "width=\"#{n.width*@scale}\" "+
3586
- # "height=\"#{n.height*@scale}\"/>\n"
3587
- "x=\"#{(n.xpos-0.3)*@scale}\" y=\"#{(n.ypos-0.3)*@scale}\" " +
3588
- "rx=\"#{@scale*0.6}\" " +
3589
- "width=\"#{(n.width+0.6)*@scale}\" "+
3590
- "height=\"#{(n.height+0.6)*@scale}\"/>\n"
3591
- return res
3592
- end
3593
-
3594
- # Generate an operator description SVG text for node +n+
3595
- def operator_svg(n)
3596
- ICIICI
3597
- res = "<rect fill=\"#eee\" stroke=\"#000\" " +
3598
- "stroke-width=\"#{@scale/16.0}\" " +
3599
- "x=\"#{ic.xpos*@scale}\" y=\"#{ic.ypos*@scale}\" " +
3600
- "rx=\"#{@scale}\" " +
3601
- "width=\"#{ic.width*@scale}\" "+
3602
- "height=\"#{ic.height*@scale}\"/>\n"
3603
- # Its name.
3604
- res += "<text class=\"medium#{self.idC}\" " +
3605
- "style=\"inline-size=#{ic.width*@scale}px; text-anchor: middle; " +
3606
- "dominant-baseline: middle;\" " +
3607
- "x=\"#{(ic.xpos + ic.width/2.0)*@scale}\" "+
3608
- "y=\"#{(ic.ypos + ic.height/2.0)*@scale}\">" +
3609
- ic.name + "</text>\n"
3899
+ "stroke-width=\"#{(@scale/10.0).round(3)}\" " +
3900
+ "stroke-dasharray=\"#{(@scale/10.0).round(3)},#{(@scale/10.0).round(3)}\" " +
3901
+ "x=\"#{((n.xpos-0.3)*@scale).round(3)}\" y=\"#{((n.ypos-0.3)*@scale).round(3)}\" " +
3902
+ "rx=\"#{(@scale*0.6).round(3)}\" " +
3903
+ "width=\"#{((n.width+0.6)*@scale).round(3)}\" "+
3904
+ "height=\"#{((n.height+0.6)*@scale).round(3)}\"/>\n"
3610
3905
  return res
3611
3906
  end
3612
3907
 
@@ -3614,23 +3909,23 @@ diagram.getElementById('#{target.name}_close').addEventListener("click", (e) =>
3614
3909
  def terminal_svg(n)
3615
3910
  ICIICI
3616
3911
  res = "<rect fill=\"#ddd\" stroke=\"#000\" " +
3617
- "stroke-width=\"#{@scale/32.0}\" " +
3618
- "x=\"#{(ic.xpos-1/16.0)*@scale}\" y=\"#{(ic.ypos-1/16.0)*@scale}\" " +
3619
- "rx=\"#{(1+1/16.0)*@scale}\" " +
3620
- "width=\"#{(ic.width+1/8.0)*@scale}\" "+
3621
- "height=\"#{(ic.height+1/8.0)*@scale}\"/>\n"
3912
+ "stroke-width=\"#{(@scale/32.0).round(3)}\" " +
3913
+ "x=\"#{((ic.xpos-1/16.0)*@scale).round(3)}\" y=\"#{((ic.ypos-1/16.0)*@scale).round(3)}\" " +
3914
+ "rx=\"#{((1+1/16.0)*@scale).round(3)}\" " +
3915
+ "width=\"#{((ic.width+1/8.0)*@scale).round(3)}\" "+
3916
+ "height=\"#{((ic.height+1/8.0)*@scale).round(3)}\"/>\n"
3622
3917
  res += "<rect fill=\"#ddd\" stroke=\"#000\" " +
3623
- "stroke-width=\"#{@scale/32.0}\" " +
3624
- "x=\"#{ic.xpos*@scale}\" y=\"#{ic.ypos*@scale}\" " +
3625
- "rx=\"#{@scale}\" " +
3626
- "width=\"#{ic.width*@scale}\" "+
3627
- "height=\"#{ic.height*@scale}\"/>\n"
3918
+ "stroke-width=\"#{(@scale/32.0).round(3)}\" " +
3919
+ "x=\"#{(ic.xpos*@scale).round(3)}\" y=\"#{(ic.ypos*@scale).round(3)}\" " +
3920
+ "rx=\"#{@scale.round(3)}\" " +
3921
+ "width=\"#{(ic.width*@scale).round(3)}\" "+
3922
+ "height=\"#{(ic.height*@scale).round(3)}\"/>\n"
3628
3923
  # Its name.
3629
3924
  res += "<text class=\"medium#{self.idC}\" " +
3630
3925
  "style=\"inline-size=#{ic.width*@scale}px; text-anchor: middle; " +
3631
3926
  "dominant-baseline: middle;\" " +
3632
- "x=\"#{(ic.xpos + ic.width/2.0)*@scale}\" "+
3633
- "y=\"#{(ic.ypos + ic.height/2.0)*@scale}\">" +
3927
+ "x=\"#{((ic.xpos + ic.width/2.0)*@scale).round(3)}\" "+
3928
+ "y=\"#{((ic.ypos + ic.height/2.0)*@scale).round(3)}\">" +
3634
3929
  ic.name + "</text>\n"
3635
3930
  return res
3636
3931
  end
@@ -3640,36 +3935,39 @@ diagram.getElementById('#{target.name}_close').addEventListener("click", (e) =>
3640
3935
  def if_svg(n,no=false)
3641
3936
  # The shape representing the instance.
3642
3937
  res = "<path fill=\"#B0E2FF\" stroke=\"#000\" " +
3643
- "stroke-width=\"#{@scale/12.0}\" " +
3644
- "d=\"M #{(n.xpos)*@scale} #{(n.ypos+n.height/2.0)*@scale} " +
3645
- "L #{(n.xpos+n.width/2.0)*@scale} #{(n.ypos+n.height)*@scale} " +
3646
- "L #{(n.xpos+n.width)*@scale} #{(n.ypos+n.height/2.0)*@scale} " +
3647
- "L #{(n.xpos+n.width/2.0)*@scale} #{(n.ypos)*@scale} " +
3938
+ "stroke-width=\"#{(@scale/12.0).round(3)}\" " +
3939
+ "d=\"M #{((n.xpos)*@scale).round(3)} #{((n.ypos+n.height/2.0)*@scale).round(3)} " +
3940
+ "L #{((n.xpos+n.width/2.0)*@scale).round(3)} #{((n.ypos+n.height)*@scale).round(3)} " +
3941
+ "L #{((n.xpos+n.width)*@scale).round(3)} #{((n.ypos+n.height/2.0)*@scale).round(3)} " +
3942
+ "L #{((n.xpos+n.width/2.0)*@scale).round(3)} #{((n.ypos)*@scale).round(3)} " +
3648
3943
  "Z \" />\n"
3649
3944
  # Its text.
3650
- res += "<text id=\"text#{n.name}\" " +
3945
+ # res += "<text id=\"text#{n.name}\" " +
3946
+ res += "<text id=\"text#{n.__id__}\" " +
3651
3947
  "style=\"text-anchor: middle; dominant-baseline: middle;\" " +
3652
3948
  "font-family=\"monospace\" font-size=\"1px\" " +
3653
- "x=\"#{(n.xpos + n.width/2.0)*@scale}\" "+
3654
- "y=\"#{(n.ypos + n.height/2.0)*@scale}\">" +
3949
+ "x=\"#{((n.xpos + n.width/2.0)*@scale).round(3)}\" "+
3950
+ "y=\"#{((n.ypos + n.height/2.0)*@scale).round(3)}\">" +
3655
3951
  n.to_s + "</text>\n"
3656
3952
  # Its text resizing.
3657
- res += Viz.svg_text_fit("text#{n.name}",(n.width-3)*@scale,
3953
+ # res += Viz.svg_text_fit("text#{n.name}",(n.width-3)*@scale,
3954
+ # 0.6*@scale)
3955
+ res += Viz.svg_text_fit("text#{n.__id__}",(n.width-3)*@scale,
3658
3956
  0.6*@scale)
3659
3957
  # The yes text.
3660
3958
  res += "<text " +
3661
3959
  "style=\"text-anchor: middle; dominant-baseline: middle;\" " +
3662
- "font-family=\"monospace\" font-size=\"#{@scale/2.0}px\" " +
3663
- "x=\"#{(n.xpos + n.width+0.1)*@scale}\" "+
3664
- "y=\"#{(n.ypos + n.height/2.0+0.5)*@scale}\">" +
3960
+ "font-family=\"monospace\" font-size=\"#{(@scale/2.0).round(3)}px\" " +
3961
+ "x=\"#{((n.xpos + n.width+0.1)*@scale).round(3)}\" "+
3962
+ "y=\"#{((n.ypos + n.height/2.0+0.5)*@scale).round(3)}\">" +
3665
3963
  "Yes" + "</text>\n"
3666
3964
  # The no text if any.
3667
3965
  if no then
3668
3966
  res += "<text " +
3669
3967
  "style=\"text-anchor: middle; dominant-baseline: middle;\" " +
3670
- "font-family=\"monospace\" font-size=\"#{@scale/2.0}px\" " +
3671
- "x=\"#{(n.xpos + n.width/2.0+0.7)*@scale}\" "+
3672
- "y=\"#{(n.ypos + n.height+0.3)*@scale}\">" +
3968
+ "font-family=\"monospace\" font-size=\"#{(@scale/2.0).round(3)}px\" " +
3969
+ "x=\"#{((n.xpos + n.width/2.0+0.7)*@scale).round(3)}\" "+
3970
+ "y=\"#{((n.ypos + n.height+0.3)*@scale).round(3)}\">" +
3673
3971
  "No" + "</text>\n"
3674
3972
  end
3675
3973
  return res
@@ -3680,36 +3978,39 @@ diagram.getElementById('#{target.name}_close').addEventListener("click", (e) =>
3680
3978
  def case_svg(n,no=false)
3681
3979
  # The shape representing the instance.
3682
3980
  res = "<path fill=\"#B0E2FF\" stroke=\"#000\" " +
3683
- "stroke-width=\"#{@scale/12.0}\" " +
3684
- "d=\"M #{(n.xpos)*@scale} #{(n.ypos+n.height/2.0)*@scale} " +
3685
- "L #{(n.xpos+n.width/2.0)*@scale} #{(n.ypos+n.height)*@scale} " +
3686
- "L #{(n.xpos+n.width)*@scale} #{(n.ypos+n.height/2.0)*@scale} " +
3687
- "L #{(n.xpos+n.width/2.0)*@scale} #{(n.ypos)*@scale} " +
3981
+ "stroke-width=\"#{(@scale/12.0).round(3)}\" " +
3982
+ "d=\"M #{((n.xpos)*@scale).round(3)} #{((n.ypos+n.height/2.0)*@scale).round(3)} " +
3983
+ "L #{((n.xpos+n.width/2.0)*@scale).round(3)} #{((n.ypos+n.height)*@scale).round(3)} " +
3984
+ "L #{((n.xpos+n.width)*@scale).round(3)} #{((n.ypos+n.height/2.0)*@scale).round(3)} " +
3985
+ "L #{((n.xpos+n.width/2.0)*@scale).round(3)} #{((n.ypos)*@scale).round(3)} " +
3688
3986
  "Z \" />\n"
3689
3987
  # Its text.
3690
- res += "<text id=\"text#{n.name}\" " +
3988
+ # res += "<text id=\"text#{n.name}\" " +
3989
+ res += "<text id=\"text#{n.__id__}\" " +
3691
3990
  "style=\"text-anchor: middle; dominant-baseline: middle;\" " +
3692
3991
  "font-family=\"monospace\" font-size=\"1px\" " +
3693
- "x=\"#{(n.xpos + n.width/2.0)*@scale}\" "+
3694
- "y=\"#{(n.ypos + n.height/2.0)*@scale}\">" +
3992
+ "x=\"#{((n.xpos + n.width/2.0)*@scale).round(3)}\" "+
3993
+ "y=\"#{((n.ypos + n.height/2.0)*@scale).round(3)}\">" +
3695
3994
  n.to_s + "</text>\n"
3696
3995
  # Its text resizing.
3697
- res += Viz.svg_text_fit("text#{n.name}",(n.width-3)*@scale,
3996
+ # res += Viz.svg_text_fit("text#{n.name}",(n.width-3)*@scale,
3997
+ # 0.6*@scale)
3998
+ res += Viz.svg_text_fit("text#{n.__id__}",(n.width-3)*@scale,
3698
3999
  0.6*@scale)
3699
4000
  # The yes text.
3700
4001
  res += "<text " +
3701
4002
  "style=\"text-anchor: middle; dominant-baseline: middle;\" " +
3702
- "font-family=\"monospace\" font-size=\"#{@scale/2.0}px\" " +
3703
- "x=\"#{(n.xpos + n.width+0.1)*@scale}\" "+
3704
- "y=\"#{(n.ypos + n.height/2.0+0.5)*@scale}\">" +
4003
+ "font-family=\"monospace\" font-size=\"#{(@scale/2.0).round(3)}px\" " +
4004
+ "x=\"#{((n.xpos + n.width+0.1)*@scale).round(3)}\" "+
4005
+ "y=\"#{((n.ypos + n.height/2.0+0.5)*@scale).round(3)}\">" +
3705
4006
  "Yes" + "</text>\n"
3706
4007
  # The no text if any.
3707
4008
  if no then
3708
4009
  res += "<text " +
3709
4010
  "style=\"text-anchor: middle; dominant-baseline: middle;\" " +
3710
- "font-family=\"monospace\" font-size=\"#{@scale/2.0}px\" " +
3711
- "x=\"#{(n.xpos + n.width/2.0+0.7)*@scale}\" "+
3712
- "y=\"#{(n.ypos + n.height+0.3)*@scale}\">" +
4011
+ "font-family=\"monospace\" font-size=\"#{(@scale/2.0).round(3)}px\" " +
4012
+ "x=\"#{((n.xpos + n.width/2.0+0.7)*@scale).round(3)}\" "+
4013
+ "y=\"#{((n.ypos + n.height+0.3)*@scale).round(3)}\">" +
3713
4014
  "No" + "</text>\n"
3714
4015
  end
3715
4016
  return res
@@ -3719,22 +4020,25 @@ diagram.getElementById('#{target.name}_close').addEventListener("click", (e) =>
3719
4020
  def wait_svg(n)
3720
4021
  # The shape representing the instance.
3721
4022
  res = "<path fill=\"#B0E2FF\" stroke=\"#000\" " +
3722
- "stroke-width=\"#{@scale/12.0}\" " +
3723
- "d=\"M #{n.xpos*@scale} #{(n.ypos)*@scale} " +
3724
- "L #{(n.xpos + n.width-n.height/2.0)*@scale} #{n.ypos*@scale} " +
3725
- "A #{n.height/2.0*@scale} #{n.height/2.0*@scale} 0 0 1 " +
3726
- "#{(n.xpos + n.width-n.height/2.0)*@scale} #{(n.ypos+n.height)*@scale} " +
3727
- "L #{(n.xpos)*@scale} #{(n.ypos+n.height)*@scale} " +
4023
+ "stroke-width=\"#{(@scale/12.0).round(3)}\" " +
4024
+ "d=\"M #{(n.xpos*@scale).round(3)} #{((n.ypos)*@scale).round(3)} " +
4025
+ "L #{((n.xpos + n.width-n.height/2.0)*@scale).round(3)} #{(n.ypos*@scale).round(3)} " +
4026
+ "A #{(n.height/2.0*@scale).round(3)} #{(n.height/2.0*@scale).round(3)} 0 0 1 " +
4027
+ "#{((n.xpos + n.width-n.height/2.0)*@scale).round(3)} #{((n.ypos+n.height)*@scale).round(3)} " +
4028
+ "L #{((n.xpos)*@scale).round(3)} #{((n.ypos+n.height)*@scale).round(3)} " +
3728
4029
  "Z \" />\n"
3729
4030
  # Its text.
3730
- res += "<text id=\"text#{n.name}\" " +
4031
+ # res += "<text id=\"text#{n.name}\" " +
4032
+ res += "<text id=\"text#{n.__id__}\" " +
3731
4033
  "style=\"text-anchor: middle; dominant-baseline: middle;\" " +
3732
4034
  "font-family=\"monospace\" font-size=\"1px\" " +
3733
- "x=\"#{(n.xpos + n.width/2.0)*@scale}\" "+
3734
- "y=\"#{(n.ypos + n.height/2.0)*@scale}\">" +
4035
+ "x=\"#{((n.xpos + n.width/2.0)*@scale).round(3)}\" "+
4036
+ "y=\"#{((n.ypos + n.height/2.0)*@scale).round(3)}\">" +
3735
4037
  n.to_s + "</text>\n"
3736
4038
  # Its text resizing.
3737
- res += Viz.svg_text_fit("text#{n.name}",(n.width-1)*@scale,
4039
+ # res += Viz.svg_text_fit("text#{n.name}",(n.width-1)*@scale,
4040
+ # 0.6*@scale)
4041
+ res += Viz.svg_text_fit("text#{n.__id__}",(n.width-1)*@scale,
3738
4042
  0.6*@scale)
3739
4043
  return res
3740
4044
  end
@@ -3749,21 +4053,24 @@ diagram.getElementById('#{target.name}_close').addEventListener("click", (e) =>
3749
4053
  def terminate_svg(n)
3750
4054
  # The shape representing the instance.
3751
4055
  res = "<ellipse fill=\"#CC0202\" stroke=\"#000\" " +
3752
- "stroke-width=\"#{@scale/12.0}\" " +
3753
- "cx=\"#{n.xpos*@scale+n.width*@scale/2.0}\" " +
3754
- "cy=\"#{(n.ypos)*@scale+n.height*@scale/2.0}\" " +
3755
- "rx=\"#{n.width*@scale/2.0}\" ry=\"#{n.height*@scale/2.0}\" " +
4056
+ "stroke-width=\"#{(@scale/12.0).round(3)}\" " +
4057
+ "cx=\"#{(n.xpos*@scale+n.width*@scale/2.0).round(3)}\" " +
4058
+ "cy=\"#{((n.ypos)*@scale+n.height*@scale/2.0).round(3)}\" " +
4059
+ "rx=\"#{(n.width*@scale/2.0).round(3)}\" ry=\"#{(n.height*@scale/2.0).round(3)}\" " +
3756
4060
  "/>\n"
3757
4061
  # Its text.
3758
- res += "<text id=\"text#{n.name}\" " +
4062
+ # res += "<text id=\"text#{n.name}\" " +
4063
+ res += "<text id=\"text#{n.__id__}\" " +
3759
4064
  "style=\"text-anchor: middle; dominant-baseline: middle;\" " +
3760
4065
  "font-family=\"monospace\" font-size=\"1px\" " +
3761
4066
  "fill=\"white\" " +
3762
- "x=\"#{(n.xpos + n.width/2.0)*@scale}\" " +
3763
- "y=\"#{(n.ypos + n.height/2.0)*@scale}\">" +
4067
+ "x=\"#{((n.xpos + n.width/2.0)*@scale).round(3)}\" " +
4068
+ "y=\"#{((n.ypos + n.height/2.0)*@scale).round(3)}\">" +
3764
4069
  "Terminate" + "</text>\n"
3765
4070
  # Its text resizing.
3766
- res += Viz.svg_text_fit("text#{n.name}",(n.width-1)*@scale,
4071
+ # res += Viz.svg_text_fit("text#{n.name}",(n.width-1)*@scale,
4072
+ # 0.6*@scale)
4073
+ res += Viz.svg_text_fit("text#{n.__id__}",(n.width-1)*@scale,
3767
4074
  0.6*@scale)
3768
4075
  return res
3769
4076
  end
@@ -3772,19 +4079,22 @@ diagram.getElementById('#{target.name}_close').addEventListener("click", (e) =>
3772
4079
  def print_svg(n)
3773
4080
  # The shape representing the instance.
3774
4081
  res = "<rect fill=\"#B0E2FF\" stroke=\"#000\" " +
3775
- "stroke-width=\"#{@scale/12.0}\" " +
3776
- "x=\"#{n.xpos*@scale}\" y=\"#{(n.ypos)*@scale}\" " +
3777
- "width=\"#{n.width*@scale}\" height=\"#{n.height*@scale}\" " +
4082
+ "stroke-width=\"#{(@scale/12.0).round(3)}\" " +
4083
+ "x=\"#{(n.xpos*@scale).round(3)}\" y=\"#{((n.ypos)*@scale).round(3)}\" " +
4084
+ "width=\"#{(n.width*@scale).round(3)}\" height=\"#{(n.height*@scale).round(3)}\" " +
3778
4085
  "/>\n"
3779
4086
  # Its text.
3780
- res += "<text id=\"text#{n.name}\" " +
4087
+ # res += "<text id=\"text#{n.name}\" " +
4088
+ res += "<text id=\"text#{n.__id__}\" " +
3781
4089
  "style=\"text-anchor: middle; dominant-baseline: middle;\" " +
3782
4090
  "font-family=\"monospace\" font-size=\"1px\" " +
3783
- "x=\"#{(n.xpos + n.width/2.0)*@scale}\" "+
3784
- "y=\"#{(n.ypos + n.height/2.0)*@scale}\">" +
4091
+ "x=\"#{((n.xpos + n.width/2.0)*@scale).round(3)}\" "+
4092
+ "y=\"#{((n.ypos + n.height/2.0)*@scale).round(3)}\">" +
3785
4093
  n.to_s + "</text>\n"
3786
4094
  # Its text resizing.
3787
- res += Viz.svg_text_fit("text#{n.name}",(n.width-1)*@scale,
4095
+ # res += Viz.svg_text_fit("text#{n.name}",(n.width-1)*@scale,
4096
+ # 0.6*@scale)
4097
+ res += Viz.svg_text_fit("text#{n.__id__}",(n.width-1)*@scale,
3788
4098
  0.6*@scale)
3789
4099
  return res
3790
4100
  end
@@ -3795,39 +4105,39 @@ diagram.getElementById('#{target.name}_close').addEventListener("click", (e) =>
3795
4105
  # Draw the line.
3796
4106
  # Vertical part
3797
4107
  res = "<line stroke=\"#000\" " +
3798
- "stroke-width=\"#{@scale/12.0}\" stroke-linecap=\"round\" " +
3799
- "x1=\"#{x0*@scale}\" " +
3800
- "y1=\"#{y0*@scale}\" " +
3801
- "x2=\"#{x0*@scale}\" " +
3802
- "y2=\"#{y1*@scale}\" " +
4108
+ "stroke-width=\"#{(@scale/12.0).round(3)}\" stroke-linecap=\"round\" " +
4109
+ "x1=\"#{(x0*@scale).round(3)}\" " +
4110
+ "y1=\"#{(y0*@scale).round(3)}\" " +
4111
+ "x2=\"#{(x0*@scale).round(3)}\" " +
4112
+ "y2=\"#{(y1*@scale).round(3)}\" " +
3803
4113
  "/>\n"
3804
4114
  # Horizontal part
3805
4115
  res += "<line stroke=\"#000\" " +
3806
- "stroke-width=\"#{@scale/12.0}\" stroke-linecap=\"round\" " +
3807
- "x1=\"#{x0*@scale}\" " +
3808
- "y1=\"#{y1*@scale}\" " +
3809
- "x2=\"#{x1*@scale}\" " +
3810
- "y2=\"#{y1*@scale}\" " +
4116
+ "stroke-width=\"#{(@scale/12.0).round(3)}\" stroke-linecap=\"round\" " +
4117
+ "x1=\"#{(x0*@scale).round(3)}\" " +
4118
+ "y1=\"#{(y1*@scale).round(3)}\" " +
4119
+ "x2=\"#{(x1*@scale).round(3)}\" " +
4120
+ "y2=\"#{(y1*@scale).round(3)}\" " +
3811
4121
  "/>\n"
3812
4122
  # The head.
3813
4123
  if x0 == x1 then
3814
4124
  # Vertical case
3815
4125
  res += "<polygon fill=\"#000\" stroke=\"none\" " +
3816
- "points=\"#{(x1-1/4.0)*@scale},#{(y1-1/2.0-1/8.0)*@scale} " +
3817
- "#{(x1+1/4.0)*@scale},#{(y1-1/2.0-1/8.0)*@scale} " +
3818
- "#{(x1)*@scale},#{(y1)*@scale}\"/>\n"
4126
+ "points=\"#{((x1-1/4.0)*@scale).round(3)},#{((y1-1/2.0-1/8.0)*@scale).round(3)} " +
4127
+ "#{((x1+1/4.0)*@scale).round(3)},#{((y1-1/2.0-1/8.0)*@scale).round(3)} " +
4128
+ "#{((x1)*@scale).round(3)},#{((y1)*@scale).round(3)}\"/>\n"
3819
4129
  elsif x0 < x1 then
3820
4130
  # Horizontal left case: always end horizontally.
3821
4131
  res += "<polygon fill=\"#000\" stroke=\"none\" " +
3822
- "points=\"#{(x1-1/2.0)*@scale},#{(y1-1/4.0)*@scale} " +
3823
- "#{(x1-1/2.0)*@scale},#{(y1+1/4.0)*@scale} " +
3824
- "#{(x1+1/8.0)*@scale},#{(y1)*@scale}\"/>\n"
4132
+ "points=\"#{((x1-1/2.0)*@scale).round(3)},#{((y1-1/4.0)*@scale).round(3)} " +
4133
+ "#{((x1-1/2.0)*@scale).round(3)},#{((y1+1/4.0)*@scale).round(3)} " +
4134
+ "#{((x1+1/8.0)*@scale).round(3)},#{((y1)*@scale).round(3)}\"/>\n"
3825
4135
  else
3826
4136
  # Horizontal right case: always end horizontally.
3827
4137
  res += "<polygon fill=\"#000\" stroke=\"none\" " +
3828
- "points=\"#{(x1)*@scale},#{(y1+1/4.0)*@scale} " +
3829
- "#{(x1)*@scale},#{(y1-1/4.0)*@scale} " +
3830
- "#{(x1-1/8.0-1/2.0)*@scale},#{(y1)*@scale}\"/>\n"
4138
+ "points=\"#{((x1)*@scale).round(3)},#{((y1+1/4.0)*@scale).round(3)} " +
4139
+ "#{((x1)*@scale).round(3)},#{((y1-1/4.0)*@scale).round(3)} " +
4140
+ "#{((x1-1/8.0-1/2.0)*@scale).round(3)},#{((y1)*@scale).round(3)}\"/>\n"
3831
4141
  end
3832
4142
  return res
3833
4143
  end
@@ -3920,17 +4230,18 @@ diagram.getElementById('#{target.name}_close').addEventListener("click", (e) =>
3920
4230
  # res += "</style>\n"
3921
4231
 
3922
4232
  # Generate the group containing all the flow description.
3923
- res += "<g id=\"#{self.name}\" visibility=\"#{visibility}\" " +
3924
- "transform=\"translate(#{tx},#{ty})\">\n"
4233
+ # res += "<g id=\"#{self.name}\" visibility=\"#{visibility}\" " +
4234
+ # "transform=\"translate(#{tx},#{ty})\">\n"
4235
+ res += "<g id=\"#{self.__id__}\" visibility=\"#{visibility}\" " +
4236
+ "transform=\"translate(#{tx.round(3)},#{ty.round(3)})\">\n"
3925
4237
  # Generate the rectangle of the bounding box.
3926
4238
  res += "<rect fill=\"#4682B4\" stroke=\"#007\" " +
3927
- "stroke-width=\"#{@scale/4.0}\" " +
3928
- # "x=\"#{x0-bT*2.5}\" y=\"#{y0-bT*2.5}\" "+
3929
- "x=\"#{x0}\" y=\"#{y0}\" "+
3930
- "width=\"#{width}\" height=\"#{height}\"/>\n"
4239
+ "stroke-width=\"#{(@scale/4.0).round(3)}\" " +
4240
+ "x=\"#{x0.round(3)}\" y=\"#{y0.round(3)}\" "+
4241
+ "width=\"#{width.round(3)}\" height=\"#{height.round(3)}\"/>\n"
3931
4242
 
3932
4243
  # Generate the group containing the top system and its contents.
3933
- res += "<g transform=\"translate(#{stx},#{sty})\">\n"
4244
+ res += "<g transform=\"translate(#{stx.round(3)},#{sty.round(3)})\">\n"
3934
4245
 
3935
4246
  # Generate the node boxes.
3936
4247
  puts "Generate node box for self.type=#{self.type}"
@@ -4087,19 +4398,19 @@ SVG
4087
4398
  res = "<g id=\"#{name}\" visibility=\"#{visibility}\">\n"
4088
4399
  end
4089
4400
  res += "<rect fill=\"#cd5c5c\" "+
4090
- "stroke=\"#000\" stroke-width=\"#{side/8.0}\" " +
4091
- "x=\"#{xpos}\" y=\"#{ypos}\" " +
4092
- "width=\"#{side}\" height=\"#{side}\" />\n"
4401
+ "stroke=\"#000\" stroke-width=\"#{(side/8.0).round(3)}\" " +
4402
+ "x=\"#{xpos.round(3)}\" y=\"#{ypos.round(3)}\" " +
4403
+ "width=\"#{side.round(3)}\" height=\"#{side.round(3)}\" />\n"
4093
4404
  # The cross lines.
4094
- res += "<line stroke=\"#000\" stroke-width=\"#{side/8.0}\" " +
4405
+ res += "<line stroke=\"#000\" stroke-width=\"#{(side/8.0).round(3)}\" " +
4095
4406
  "stroke-linecap=\"butt\" " +
4096
- "x1=\"#{xpos}\" y1=\"#{ypos}\" " +
4097
- "x2=\"#{xpos+side}\" y2=\"#{ypos+side}\" " +
4407
+ "x1=\"#{xpos.round(3)}\" y1=\"#{ypos.round(3)}\" " +
4408
+ "x2=\"#{(xpos+side).round(3)}\" y2=\"#{(ypos+side).round(3)}\" " +
4098
4409
  " />\n"
4099
- res += "<line stroke=\"#000\" stroke-width=\"#{side/8.0}\" " +
4410
+ res += "<line stroke=\"#000\" stroke-width=\"#{(side/8.0).round(3)}\" " +
4100
4411
  "stroke-linecap=\"butt\" " +
4101
- "x1=\"#{xpos+side}\" y1=\"#{ypos}\" " +
4102
- "x2=\"#{xpos}\" y2=\"#{ypos+side}\" " +
4412
+ "x1=\"#{(xpos+side).round(3)}\" y1=\"#{ypos.round(3)}\" " +
4413
+ "x2=\"#{xpos.round(3)}\" y2=\"#{(ypos+side).round(3)}\" " +
4103
4414
  " />\n"
4104
4415
  res += "</g>"
4105
4416
  end
@@ -4112,10 +4423,10 @@ SVG
4112
4423
  // Helping button.
4113
4424
  <g id="$help$_open">
4114
4425
  <rect fill="yellow" stroke="#000" stroke-width="3"
4115
- x="#{x0+width-62/fit}" y="#{y0+2/fit}" width="#{60/fit}" height="#{30/fit}" />
4426
+ x="#{(x0+width-62/fit).round(3)}" y="#{(y0+2/fit).round(3)}" width="#{(60/fit).round(3)}" height="#{(30/fit).round(3)}" />
4116
4427
  <text style="text-anchor: middle; dominant-baseline: middle;"
4117
- font-family="monospace" font-size="#{20/fit}px"
4118
- x="#{x0+width-32/fit}" y="#{y0+17/fit}" >
4428
+ font-family="monospace" font-size="#{(20/fit).round(3)}px"
4429
+ x="#{(x0+width-32/fit).round(3)}" y="#{(y0+17/fit).round(3)}" >
4119
4430
  Help
4120
4431
  </text>
4121
4432
  </g>
@@ -4123,53 +4434,46 @@ SVG
4123
4434
  // Helping panel.
4124
4435
  <g id="$help$" visibility="hidden">
4125
4436
  <rect fill="#ffffd7" stroke="#000" stroke-width="6"
4126
- x="#{x0}" y="#{y0}" width="#{width}" height="#{height}" />
4127
- <text font-size="#{40/fit}px" font-family="serif" font-weight="bold"
4128
- x="#{x0+width/2}" y="#{y0+40/fit}" >
4437
+ x="#{x0.round(3)}" y="#{y0.round(3)}" width="#{width.round(3)}" height="#{height.round(3)}" />
4438
+ <text font-size="#{(40/fit).round(3)}px" font-family="serif" font-weight="bold"
4439
+ x="#{(x0+width/2).round(3)}" y="#{(y0+40/fit).round(3)}" >
4129
4440
  Help
4130
4441
  </text>
4131
4442
 
4132
- <text font-size="#{30/fit}px" font-family="serif" font-weight="bold"
4133
- x="#{x0+15/fit}" y="#{y0+100/fit}" >
4443
+ <text font-size="#{(30/fit).round(3)}px" font-family="serif" font-weight="bold"
4444
+ x="#{(x0+15/fit).round(3)}" y="#{(y0+100/fit).round(3)}" >
4134
4445
  Navigation:
4135
4446
  </text>
4136
- <text font-size="#{25/fit}px" font-family="serif" x="#{x0+25/fit}" y="#{y0+140/fit}" >
4447
+ <text font-size="#{(25/fit).round(3)}px" font-family="serif" x="#{(x0+25/fit).round(3)}" y="#{(y0+140/fit).round(3)}" >
4137
4448
  Zoom in/out:
4138
4449
  </text>
4139
- <text font-size="#{25/fit}px" font-family="serif" x="#{x0+190/fit}" y="#{y0+140/fit}" >
4450
+ <text font-size="#{(25/fit).round(3)}px" font-family="serif" x="#{(x0+190/fit).round(3)}" y="#{(y0+140/fit).round(3)}" >
4140
4451
  mouse wheel.
4141
4452
  </text>
4142
- <text font-size="#{25/fit}px" font-family="serif" x="#{x0+25/fit}" y="#{y0+170/fit}" >
4453
+ <text font-size="#{(25/fit).round(3)}px" font-family="serif" x="#{(x0+25/fit).round(3)}" y="#{(y0+170/fit).round(3)}" >
4143
4454
  Move diagram:
4144
4455
  </text>
4145
- <text font-size="#{25/fit}px" font-family="serif" x="#{x0+190/fit}" y="#{y0+170/fit}" >
4456
+ <text font-size="#{(25/fit).round(3)}px" font-family="serif" x="#{(x0+190/fit).round(3)}" y="#{(y0+170/fit).round(3)}" >
4146
4457
  left click and drag, or arrow keys.
4147
4458
  </text>
4148
- <text font-size="#{25/fit}px" font-family="serif" x="#{x0+25/fit}" y="#{y0+200/fit}" >
4459
+ <text font-size="#{(25/fit).round(3)}px" font-family="serif" x="#{(x0+25/fit).round(3)}" y="#{(y0+200/fit).round(3)}" >
4149
4460
  Open element:
4150
4461
  </text>
4151
- <text font-size="#{25/fit}px" font-family="serif" x="#{x0+190/fit}" y="#{y0+200/fit}" >
4462
+ <text font-size="#{(25/fit).round(3)}px" font-family="serif" x="#{(x0+190/fit).round(3)}" y="#{(y0+200/fit).round(3)}" >
4152
4463
  left click on element.
4153
4464
  </text>
4154
- <text font-size="#{25/fit}px" font-family="serif" x="#{x0+25/fit}" y="#{y0+230/fit}" >
4465
+ <text font-size="#{(25/fit).round(3)}px" font-family="serif" x="#{(x0+25/fit).round(3)}" y="#{(y0+230/fit).round(3)}" >
4155
4466
  Close element:
4156
4467
  </text>
4157
- <text font-size="#{25/fit}px" font-family="serif" x="#{x0+190/fit}" y="#{y0+230/fit}" >
4468
+ <text font-size="#{(25/fit).round(3)}px" font-family="serif" x="#{(x0+190/fit).round(3)}" y="#{(y0+230/fit).round(3)}" >
4158
4469
  left click on the close button at the top right of the element.
4159
4470
  </text>
4160
4471
 
4161
- <text font-size="#{30/fit}px" font-family="serif" font-weight="bold"
4162
- x="#{x0+15/fit}" y="#{y0+300/fit}" >
4472
+ <text font-size="#{(30/fit).round(3)}px" font-family="serif" font-weight="bold"
4473
+ x="#{(x0+15/fit).round(3)}" y="#{(y0+300/fit).round(3)}" >
4163
4474
  Types of elements:
4164
4475
  </text>
4165
4476
  #{
4166
- # ic = IC.new("Instance",:instance)
4167
- # ic.scale = 35.0
4168
- # ic.xpos = (x0+15/fit) / ic.scale
4169
- # ic.ypos = 330/fit / ic.scale
4170
- # ic.width = 300/fit / ic.scale
4171
- # ic.height = 100/fit / ic.scale
4172
- # ic.instance_svg(ic)
4173
4477
  ic = IC.new("Instance",:instance)
4174
4478
  ic.scale = 35.0/fit
4175
4479
  ic.xpos = (x0+15)/fit / ic.scale
@@ -4179,23 +4483,6 @@ SVG
4179
4483
  ic.instance_svg(ic)
4180
4484
  }
4181
4485
  #{
4182
- # ic = IC.new("Continuous assignment",:alu)
4183
- # ic.scale = 35.0
4184
- # ic.xpos = (x0+(15+300+15)/fit) / ic.scale
4185
- # ic.ypos = 305/fit / ic.scale
4186
- # ic.width = 300/fit / ic.scale
4187
- # ic.height = 150/fit / ic.scale
4188
- # p0 = Port.new("in0",ic,:input)
4189
- # p0.side = LEFT
4190
- # ic.ports << p0
4191
- # p1 = Port.new("in1",ic,:input)
4192
- # p1.side = LEFT
4193
- # ic.ports << p1
4194
- # p2 = Port.new("out",ic,:output)
4195
- # p2.side = RIGHT
4196
- # ic.alu_svg(ic)
4197
- # ic.ports << p2
4198
- # ic.alu_svg(ic)
4199
4486
  ic = IC.new("Continuous assignment",:alu)
4200
4487
  ic.scale = 35.0/fit
4201
4488
  ic.xpos = (x0+(15+300+15))/fit / ic.scale
@@ -4215,13 +4502,6 @@ SVG
4215
4502
  ic.alu_svg(ic)
4216
4503
  }
4217
4504
  #{
4218
- # ic = IC.new("Combinatorial process",:process)
4219
- # ic.scale = 35.0
4220
- # ic.xpos = (x0+15/fit) / ic.scale
4221
- # ic.ypos = 480/fit / ic.scale
4222
- # ic.width = 300/fit / ic.scale
4223
- # ic.height = 100/fit / ic.scale
4224
- # ic.process_svg(ic)
4225
4505
  ic = IC.new("Combinatorial process",:process)
4226
4506
  ic.scale = 35.0/fit
4227
4507
  ic.xpos = (x0+15)/fit / ic.scale
@@ -4231,13 +4511,6 @@ SVG
4231
4511
  ic.process_svg(ic)
4232
4512
  }
4233
4513
  #{
4234
- # ic = IC.new("Clocked process",:clocked_process)
4235
- # ic.scale = 35.0
4236
- # ic.xpos = (x0+(15+300+15)/fit) / ic.scale
4237
- # ic.ypos = 480/fit / ic.scale
4238
- # ic.width = 300/fit / ic.scale
4239
- # ic.height = 100/fit / ic.scale
4240
- # ic.clocked_process_svg(ic)
4241
4514
  ic = IC.new("Clocked process",:clocked_process)
4242
4515
  ic.scale = 35.0/fit
4243
4516
  ic.xpos = (x0+(15+300+15))/fit / ic.scale
@@ -4247,13 +4520,6 @@ SVG
4247
4520
  ic.clocked_process_svg(ic)
4248
4521
  }
4249
4522
  #{
4250
- # ic = IC.new("Time process",:timed_process)
4251
- # ic.scale = 35.0
4252
- # ic.xpos = (x0+(15+300+15+300+15)/fit) / ic.scale
4253
- # ic.ypos = 480/fit / ic.scale
4254
- # ic.width = 300/fit / ic.scale
4255
- # ic.height = 100/fit / ic.scale
4256
- # ic.timed_process_svg(ic)
4257
4523
  ic = IC.new("Time process",:timed_process)
4258
4524
  ic.scale = 35.0/fit
4259
4525
  ic.xpos = (x0+(15+300+15+300+15))/fit / ic.scale
@@ -4263,13 +4529,6 @@ SVG
4263
4529
  ic.timed_process_svg(ic)
4264
4530
  }
4265
4531
  #{
4266
- # ic = IC.new("Signal",:register)
4267
- # ic.scale = 35.0
4268
- # ic.xpos = (x0+15/fit) / ic.scale
4269
- # ic.ypos = 600/fit / ic.scale
4270
- # ic.width = 150/fit / ic.scale
4271
- # ic.height = 75/fit / ic.scale
4272
- # ic.register_svg(ic)
4273
4532
  ic = IC.new("Signal",:register)
4274
4533
  ic.scale = 35.0/fit
4275
4534
  ic.xpos = (x0+15)/fit / ic.scale
@@ -4279,13 +4538,6 @@ SVG
4279
4538
  ic.register_svg(ic)
4280
4539
  }
4281
4540
  #{
4282
- # ic = IC.new("Memory",:memory)
4283
- # ic.scale = 35.0
4284
- # ic.xpos = (x0+(15+200+15)/fit) / ic.scale
4285
- # ic.ypos = 600/fit / ic.scale
4286
- # ic.width = 200/fit / ic.scale
4287
- # ic.height = 100/fit / ic.scale
4288
- # ic.memory_svg(ic)
4289
4541
  ic = IC.new("Memory",:memory)
4290
4542
  ic.scale = 35.0/fit
4291
4543
  ic.xpos = (x0+(15+200+15))/fit / ic.scale
@@ -4295,11 +4547,11 @@ SVG
4295
4547
  ic.memory_svg(ic)
4296
4548
  }
4297
4549
 
4298
- <text font-size="#{30/fit}px" font-family="serif" font-weight="bold"
4299
- x="#{x0+15/fit}" y="#{y0+800/fit}" >
4550
+ <text font-size="#{(30/fit).round(3)}px" font-family="serif" font-weight="bold"
4551
+ x="#{(x0+15/fit).round(3)}" y="#{(y0+800/fit).round(3)}" >
4300
4552
  Contents of processes and assigments:
4301
4553
  </text>
4302
- <text font-size="#{25/fit}px" font-family="serif" x="#{x0+25/fit}" y="#{y0+840/fit}" >
4554
+ <text font-size="#{(25/fit).round(3)}px" font-family="serif" x="#{(x0+25/fit).round(3)}" y="#{(y0+840/fit).round(3)}" >
4303
4555
  Represented as sets of parallel flow charts.
4304
4556
  </text>
4305
4557
 
@@ -4329,11 +4581,11 @@ SVG
4329
4581
  def self.svg_text_fit(name,width,max_size)
4330
4582
  return <<~SCRIPT
4331
4583
  <script>
4332
- fitWidth=#{width};
4584
+ fitWidth=#{width.round(3)};
4333
4585
  textNode = document.getElementById("#{self.to_svg_id(name)}");
4334
4586
  textBB = textNode.getBBox();
4335
4587
  fitSize = fitWidth / textBB.width;
4336
- if (fitSize > #{max_size}) fitSize = #{max_size};
4588
+ if (fitSize > #{max_size.round(3)}) fitSize = #{max_size.round(3)};
4337
4589
  textNode.setAttribute("font-size", fitSize + "px")
4338
4590
  </script>
4339
4591
  SCRIPT
@@ -4382,7 +4634,7 @@ class HDLRuby::Low::SystemT
4382
4634
  # ports.each_value do |subs|
4383
4635
  ports.each do |name,subs|
4384
4636
  # Skip connection to registers, they are processed later.
4385
- next if regs[name]
4637
+ next if regs[HDLRuby::Viz.port_base_name(name)]
4386
4638
  # Not a register, can go on.
4387
4639
  subs.each do |p0|
4388
4640
  subs.each do |p1|
@@ -4400,15 +4652,17 @@ class HDLRuby::Low::SystemT
4400
4652
  # Check if there is a register corresponding to the port
4401
4653
  # (full port or sub port of the register).
4402
4654
  next if name.include?("$") # Skip register ports which are targets.
4403
- rname = name
4655
+ # rname = name
4656
+ rname = HDLRuby::Viz.port_base_name(name)
4404
4657
  while !regs.key?(rname) do
4405
4658
  break unless rname.include?(".")
4406
4659
  rname = rname.gsub(/\.[^.]*$/,"")
4407
4660
  end
4408
4661
  reg = regs[rname]
4409
4662
  next unless reg
4410
- # Connect the register, once per ic and direction.
4411
- subs.uniq {|p| [p.ic,p.direction] }.each do |p|
4663
+ # # Connect the register, once per ic and direction.
4664
+ # Connect the register, once per ic, direction and type.
4665
+ subs.uniq {|p| [p.ic,p.direction,p.type] }.each do |p|
4412
4666
  # puts "Connect to register port name #{name} in ic=#{world.name} with port=#{p.name}"
4413
4667
  if p.direction == :output then
4414
4668
  world.connect(p,ports[HDLRuby::Viz.reg2input_name(name)][0])
@@ -4444,16 +4698,48 @@ class HDLRuby::Low::SystemT
4444
4698
  # NOTE: p0 or p1 may be empty if outside current module.
4445
4699
  world.connect(p0,p1) unless (!p0 or !p1 or p0.targets.include?(p1))
4446
4700
  end
4447
- # Remove the dangling input ports in registers (they are ROMS).
4701
+ # # Remove the dangling input ports in registers (they are ROMS).
4702
+ # regs.each_value do |reg|
4703
+ # to_remove_input = reg.ports.select {|p| p.direction==:input }.all? do
4704
+ # |p|
4705
+ # p.targets.none?
4706
+ # end
4707
+ # if to_remove_input then
4708
+ # reg.ports.delete_if {|p| p.direction == :input }
4709
+ # end
4710
+ # end
4711
+ # Remove the dangling ports in registers (they are ROMS).
4448
4712
  regs.each_value do |reg|
4449
- to_remove_input = reg.ports.select {|p| p.direction==:input }.all? do
4450
- |p|
4451
- p.targets.none?
4713
+ reg.ports.delete_if {|p| p.targets.none? }
4714
+ end
4715
+
4716
+ # Gather the bit ports by owner port.
4717
+ port2bits = {}
4718
+ ports.each do |name,subs|
4719
+ subs.each do |port|
4720
+ port2bits[port.name] = []
4721
+ end
4722
+ end
4723
+ ports.each do |name,subs|
4724
+ subs.each do |port|
4725
+ if HDLRuby::Viz.port_bit_name?(port.name) then
4726
+ port2bits[HDLRuby::Viz.port_base_name(port.name)] << port
4727
+ end
4452
4728
  end
4453
- if to_remove_input then
4454
- reg.ports.delete_if {|p| p.direction == :input }
4729
+ end
4730
+ # Remove the dangling ports that are accessed by sub ports.
4731
+ ports.each do |name,subs|
4732
+ subs.each do |port|
4733
+ if port.targets.none? then
4734
+ # This is a dangling port, is it connected by bits.
4735
+ if port2bits[port.name].any? then
4736
+ # Yes, remove it.
4737
+ port.ic.ports.delete(port)
4738
+ end
4739
+ end
4455
4740
  end
4456
4741
  end
4742
+
4457
4743
  # Return the resulting visualization.
4458
4744
  return world
4459
4745
  end
@@ -4482,18 +4768,23 @@ class HDLRuby::Low::Scope
4482
4768
  # name = sname + inner.name.to_s
4483
4769
  # name = inner.name.to_s
4484
4770
  name = sname + inner.name.to_s
4485
- # Create the viz for the "register"
4486
- if typ.is_a?(HDLRuby::Low::TypeVector) and
4487
- typ.base.width > 1 then
4488
- puts "Adding scope register #{name} to #{world.name}"
4489
- # This is in fact a memory matrix.
4490
- reg = HDLRuby::Viz::IC.new(name,:memory,world)
4491
- else
4492
- puts "Adding plain register #{name} to #{world.name}"
4493
- # This is a plain register.
4494
- reg = HDLRuby::Viz::IC.new(name,:register,world)
4771
+ # But first cut of the index if any for the register.
4772
+ rname = HDLRuby::Viz.port_base_name(name)
4773
+ reg = regs[rname]
4774
+ unless reg then
4775
+ # Create the viz for the "register"
4776
+ if typ.is_a?(HDLRuby::Low::TypeVector) and
4777
+ typ.base.width > 1 then
4778
+ puts "Adding scope register #{rname} to #{world.name}"
4779
+ # This is in fact a memory matrix.
4780
+ reg = HDLRuby::Viz::IC.new(rname,:memory,world)
4781
+ else
4782
+ puts "Adding plain register #{rname} to #{world.name}"
4783
+ # This is a plain register.
4784
+ reg = HDLRuby::Viz::IC.new(rname,:register,world)
4785
+ end
4786
+ regs[reg.name] = reg
4495
4787
  end
4496
- regs[reg.name] = reg
4497
4788
  # Create the corresponding input and output ports.
4498
4789
  iname = HDLRuby::Viz.reg2input_name(name)
4499
4790
  puts "Adding input port #{iname} to reg #{reg.name}"
@@ -4546,21 +4837,11 @@ class HDLRuby::Low::Scope
4546
4837
  # Explicit port connect case.
4547
4838
  links << [ connection.left.to_viz_names[0],
4548
4839
  connection.right.to_viz_names[0] ]
4549
- # # Get the right refered name.
4550
- # rname = connection.right.to_viz_names[0]
4551
- # # If it is a register make the name its output.
4552
- # rname = HDLRuby::Viz.reg2output_name(rname) if regs[rname]
4553
- # # Get the left refered name.
4554
- # lname = connection.left.to_viz_names[0]
4555
- # # If it is a register make the name its input.
4556
- # lname = HDLRuby::Viz.reg2input_name(lname) if regs[lname]
4557
- # # Make the explicit port connect.
4558
- # links << [ lname, rname ]
4559
4840
  # Add the explicit port connection.
4560
4841
  puts "added link between #{links[-1][0]} and #{links[-1][1]}"
4561
4842
  next
4562
4843
  end
4563
- ic = HDLRuby::Viz::IC.new(HDLRuby.uniq_name("cxn"),:assign,world)
4844
+ ic = HDLRuby::Viz::IC.new(HDLRuby.uniq_name("cnx"),:assign,world)
4564
4845
  # Add its ports.
4565
4846
  # Output.
4566
4847
  name = connection.left.to_viz_names[0]
@@ -4595,14 +4876,15 @@ class HDLRuby::Low::Scope
4595
4876
  behavior.each_event do |ev|
4596
4877
  name = ev.ref.to_viz_names[0]
4597
4878
  next if ic.port?(name) # The port has already been added.
4598
- # Is it a clocked event?
4599
- if ev.on_edge? then
4600
- # Yes.
4601
- ports[name] << ic.add_port(name, :input, ev.type)
4602
- else
4603
- # No, use a standard port.
4604
- ports[name] << ic.add_port(name, :input)
4605
- end
4879
+ # # Is it a clocked event?
4880
+ # if ev.on_edge? then
4881
+ # # Yes.
4882
+ # ports[name] << ic.add_port(name, :input, ev.type)
4883
+ # else
4884
+ # # No, use a standard port.
4885
+ # ports[name] << ic.add_port(name, :input)
4886
+ # end
4887
+ ports[name] << ic.add_port(name, :input, ev.type)
4606
4888
  end
4607
4889
  # Recurse on its blocks.
4608
4890
  # behavior.block.to_viz(world,ic,ports)
@@ -4664,6 +4946,9 @@ class HDLRuby::Low::Case
4664
4946
  # self.default.to_viz_node(node) if self.default
4665
4947
  # return node
4666
4948
  node = parent
4949
+ # NOROM
4950
+ count = 0
4951
+ # END NOROM
4667
4952
  # Generate one node per possible value.
4668
4953
  self.each_when do |w|
4669
4954
  sub = HDLRuby::Viz::Node.new(:case,node)
@@ -4671,6 +4956,12 @@ class HDLRuby::Low::Case
4671
4956
  w.match.to_viz_node(sub)
4672
4957
  w.statement.to_viz_node(sub)
4673
4958
  node = sub if node == parent # Set the first node
4959
+ # NOROM
4960
+ count += 1
4961
+ if count > 16 then
4962
+ break
4963
+ end
4964
+ # END NOROM
4674
4965
  end
4675
4966
  self.default.to_viz_node(node) if self.default
4676
4967
  return node
@@ -4691,14 +4982,19 @@ class HDLRuby::Low::Block
4691
4982
  self.each_inner do |inner|
4692
4983
  name = bname + inner.name.to_s
4693
4984
  puts "Adding block register #{name} to #{world.name}"
4694
- # Create the viz for the "register"
4695
- if inner.type.base.width > 1 then
4696
- # This is in fact a memory matrix.
4697
- reg = HDLRuby::Viz::IC.new(name,:memory,world)
4698
- else
4699
- reg = HDLRuby::Viz::IC.new(name,:register,world)
4985
+ # But first cut of the index if any for the register.
4986
+ rname = HDLRuby::Viz.port_base_name(name)
4987
+ reg = regs[rname]
4988
+ unless reg then
4989
+ # Create the viz for the "register"
4990
+ if inner.type.base.width > 1 then
4991
+ # This is in fact a memory matrix.
4992
+ reg = HDLRuby::Viz::IC.new(rname,:memory,world)
4993
+ else
4994
+ reg = HDLRuby::Viz::IC.new(rname,:register,world)
4995
+ end
4996
+ regs[reg.name] = reg
4700
4997
  end
4701
- regs[reg.name] = reg
4702
4998
  # Create the corresponding input and output ports.
4703
4999
  iname = HDLRuby::Viz.reg2input_name(name)
4704
5000
  puts "Adding input port #{iname} to #{world.name}"
@@ -4767,20 +5063,22 @@ class HDLRuby::Low::Block
4767
5063
  end
4768
5064
 
4769
5065
  next unless stmnt.is_a?(HDLRuby::Low::Transmit)
4770
- name = stmnt.left.to_viz_names[0]
5066
+ lnames = stmnt.left.to_viz_names
5067
+ name = lnames[0]
4771
5068
  if iports.key?(name) then
4772
5069
  # Change to inout port.
4773
5070
  iports[name].direction = :inout
4774
- next
4775
- end
5071
+ # next
5072
+ # end
4776
5073
  # Add one port by output name.
4777
- unless oports.key?(name) then
5074
+ # unless oports.key?(name) then
5075
+ elsif !oports.key?(name) then
4778
5076
  puts "Adding output port #{name} to #{ic.name}"
4779
5077
  port = ic.add_port(name, :output)
4780
5078
  ports[name] << port
4781
5079
  oports[name] = port
4782
5080
  end
4783
- stmnt.right.to_viz_names.each do |name|
5081
+ (stmnt.right.to_viz_names+lnames[1..-1]).each do |name|
4784
5082
  if oports.key?(name) then
4785
5083
  # Change to inout port.
4786
5084
  oports[name].direction = :inout
@@ -4806,10 +5104,19 @@ class HDLRuby::Low::Block
4806
5104
  def to_viz_node(parent)
4807
5105
  node = HDLRuby::Viz::Node.new(self.mode,parent)
4808
5106
  prev = nil
5107
+ # NOROM
5108
+ count = 0
5109
+ # END NOROM
4809
5110
  self.each_statement do |stmnt|
4810
5111
  succ = stmnt.to_viz_node(node)
4811
5112
  prev.successor = succ if prev
4812
5113
  prev = succ
5114
+ # NOROM
5115
+ count += 1
5116
+ if count > 256 then
5117
+ break
5118
+ end
5119
+ # END NOROM
4813
5120
  end
4814
5121
  unless prev then
4815
5122
  # There were no statement in the block, create a dummy one