HDLRuby 3.9.0 → 3.9.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.html +4121 -4648
- data/README.md +117 -105
- data/ext/hruby_sim/hruby_rcsim_build.c +2 -0
- data/ext/hruby_sim/hruby_sim.h +6 -0
- data/ext/hruby_sim/hruby_sim_calc.c +67 -0
- data/lib/HDLRuby/hdr_samples/with_henumerable.rb +281 -258
- data/lib/HDLRuby/hdr_samples/with_to_svg.rb +37 -0
- data/lib/HDLRuby/hdr_samples/with_unary_reduction.rb +23 -0
- data/lib/HDLRuby/hdr_samples/with_values.rb +4 -0
- data/lib/HDLRuby/hdrcc.rb +3 -0
- data/lib/HDLRuby/hruby_bstr.rb +2 -1
- data/lib/HDLRuby/hruby_high.rb +35 -7
- data/lib/HDLRuby/hruby_low.rb +52 -87
- data/lib/HDLRuby/hruby_low_split_signals.rb +213 -0
- data/lib/HDLRuby/hruby_types.rb +6 -2
- data/lib/HDLRuby/hruby_viz.rb +359 -166
- data/lib/HDLRuby/std/hruby_enum.rb +104 -28
- data/lib/HDLRuby/std/sequencer.rb +17 -3
- data/lib/HDLRuby/verilog_hruby.rb +70 -28
- data/lib/HDLRuby/verilog_parser.rb +38 -18
- data/lib/HDLRuby/version.rb +1 -1
- metadata +5 -2
data/lib/HDLRuby/hruby_viz.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# An IC netlist
|
|
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
|
|
@@ -110,6 +125,9 @@ module HDLRuby::Viz
|
|
|
110
125
|
|
|
111
126
|
# Give the size of the IC in number of statements.
|
|
112
127
|
def number_statements
|
|
128
|
+
if self.type == :instance then
|
|
129
|
+
return self.system.number_statements
|
|
130
|
+
end
|
|
113
131
|
# Get the number from the branches.
|
|
114
132
|
snum = @branches.reduce(0) do |sum,branch|
|
|
115
133
|
sum + branch.number_statements
|
|
@@ -118,6 +136,7 @@ module HDLRuby::Viz
|
|
|
118
136
|
snum += @children.reduce(0) do |sum,child|
|
|
119
137
|
sum + child.number_statements
|
|
120
138
|
end
|
|
139
|
+
return snum
|
|
121
140
|
end
|
|
122
141
|
|
|
123
142
|
|
|
@@ -269,43 +288,54 @@ module HDLRuby::Viz
|
|
|
269
288
|
@uports.clear
|
|
270
289
|
@rports.clear
|
|
271
290
|
@dports.clear
|
|
291
|
+
# Ports sides by direction and base name.
|
|
292
|
+
@port_base_dir = {}
|
|
293
|
+
# Process the ports.
|
|
272
294
|
@ports.each do |port|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
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
|
|
295
|
+
# Maybe there is a port with the same direction.
|
|
296
|
+
side = @port_base_dir[[HDLRuby::Viz.port_base_name(port.name),
|
|
297
|
+
port.direction]]
|
|
298
|
+
if side then
|
|
299
|
+
port.side = side
|
|
289
300
|
else
|
|
290
|
-
#
|
|
291
|
-
if port.
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
301
|
+
# No, process to port.
|
|
302
|
+
if port.targets.empty? then
|
|
303
|
+
puts "Dangling port: #{port.name} (of #{port.ic.name})"
|
|
304
|
+
# Not connected port, put it on the side with the less ports.
|
|
305
|
+
if port.direction == :input then
|
|
306
|
+
if lports.size <= uports.size then
|
|
307
|
+
port.side = LEFT
|
|
308
|
+
else
|
|
309
|
+
port.side = UP
|
|
310
|
+
end
|
|
298
311
|
else
|
|
299
|
-
|
|
312
|
+
if rports.size <= dports.size then
|
|
313
|
+
port.side = RIGHT
|
|
314
|
+
else
|
|
315
|
+
port.side = DOWN
|
|
316
|
+
end
|
|
300
317
|
end
|
|
301
318
|
else
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
319
|
+
# The port is connected.
|
|
320
|
+
if port.direction == :input then
|
|
321
|
+
# For now, use the first target only for deciding.
|
|
322
|
+
d_left = port.targets[0].ic.xpos - @box[0]
|
|
323
|
+
d_up = @box[3] -
|
|
324
|
+
port.targets[0].ic.ypos + port.targets[0].ic.height
|
|
325
|
+
if d_left <= d_up then
|
|
326
|
+
port.side = LEFT
|
|
327
|
+
else
|
|
328
|
+
port.side = UP
|
|
329
|
+
end
|
|
307
330
|
else
|
|
308
|
-
|
|
331
|
+
d_right = @box[2] -
|
|
332
|
+
port.targets[0].ic.xpos + port.targets[0].ic.width
|
|
333
|
+
d_down = port.targets[0].ic.ypos - @box[1]
|
|
334
|
+
if d_right <= d_down then
|
|
335
|
+
port.side = RIGHT
|
|
336
|
+
else
|
|
337
|
+
port.side = DOWN
|
|
338
|
+
end
|
|
309
339
|
end
|
|
310
340
|
end
|
|
311
341
|
end
|
|
@@ -321,6 +351,9 @@ module HDLRuby::Viz
|
|
|
321
351
|
when DOWN
|
|
322
352
|
@dports << port
|
|
323
353
|
end
|
|
354
|
+
# Also for the handling of bits.
|
|
355
|
+
@port_base_dir[[HDLRuby::Viz.port_base_name(port.name),
|
|
356
|
+
port.direction]] = port.side
|
|
324
357
|
end
|
|
325
358
|
end
|
|
326
359
|
|
|
@@ -675,6 +708,7 @@ module HDLRuby::Viz
|
|
|
675
708
|
nd = child.dports.size * @port_width
|
|
676
709
|
child.height = nl > nr ? nl : nr
|
|
677
710
|
child.width = nu > nd ? nu : nd
|
|
711
|
+
puts "For assign" if child.type == :assign
|
|
678
712
|
puts "First width=#{child.width} height=#{child.height} [#{child.lports.size},#{child.uports.size},#{child.rports.size},#{child.dports.size}]"
|
|
679
713
|
# Ensure IC have some thickness.
|
|
680
714
|
if child.type != :register then
|
|
@@ -684,15 +718,17 @@ module HDLRuby::Viz
|
|
|
684
718
|
child.width = @port_width if child.width < @port_width
|
|
685
719
|
# But enlarge if more than one port horizontally or
|
|
686
720
|
# vertically for easier routing and readability.
|
|
687
|
-
if child.
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
721
|
+
if child.type != :assign then # However assign are treated appart
|
|
722
|
+
if child.lports.size + child.rports.size > 1 and
|
|
723
|
+
child.height == @port_width and
|
|
724
|
+
child.width == @port_width then
|
|
725
|
+
child.width *= 2
|
|
726
|
+
end
|
|
727
|
+
if child.uports.size + child.dports.size > 1 and
|
|
728
|
+
child.width == @port_width and
|
|
729
|
+
child.height == @port_width then
|
|
730
|
+
child.height *= 2
|
|
731
|
+
end
|
|
696
732
|
end
|
|
697
733
|
# Also ensure the chip is wide enough.
|
|
698
734
|
if child.type == :assign then
|
|
@@ -728,8 +764,9 @@ module HDLRuby::Viz
|
|
|
728
764
|
child.height = 3 if child.height < @port_width
|
|
729
765
|
child.width = 3 if child.width < @port_width
|
|
730
766
|
end
|
|
731
|
-
puts "for register: #{child.name} ports.size=#{child.ports.size}, width=#{child.width} height=#{child.height}"
|
|
767
|
+
# puts "for register: #{child.name} ports.size=#{child.ports.size}, width=#{child.width} height=#{child.height}"
|
|
732
768
|
end
|
|
769
|
+
puts "Then width=#{child.width} height=#{child.height} [#{child.lports.size},#{child.uports.size},#{child.rports.size},#{child.dports.size}]"
|
|
733
770
|
|
|
734
771
|
end
|
|
735
772
|
end
|
|
@@ -759,6 +796,7 @@ module HDLRuby::Viz
|
|
|
759
796
|
puts "With number of statements: #{num} are base area=#{area}"
|
|
760
797
|
# First compute the target area, and width and height of each type.
|
|
761
798
|
ics.each do |ic|
|
|
799
|
+
puts "For ic=#{ic.name}"
|
|
762
800
|
# Update the target area.
|
|
763
801
|
n_area = ic.width * ic.height
|
|
764
802
|
area = n_area if n_area > area
|
|
@@ -782,11 +820,13 @@ module HDLRuby::Viz
|
|
|
782
820
|
pH = ic.height if ic.height > pH
|
|
783
821
|
# Ensure the target area is reached.
|
|
784
822
|
if ic.branches[0].type == :par then
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
pW
|
|
788
|
-
|
|
789
|
-
|
|
823
|
+
while pW*pW < area do
|
|
824
|
+
# For par processes, increase squarely.
|
|
825
|
+
if pW <= pH then
|
|
826
|
+
pW += 1
|
|
827
|
+
else
|
|
828
|
+
pH += 1
|
|
829
|
+
end
|
|
790
830
|
end
|
|
791
831
|
else
|
|
792
832
|
# For non par processes, increase vertically.
|
|
@@ -804,7 +844,7 @@ module HDLRuby::Viz
|
|
|
804
844
|
if ic.type == :instance then
|
|
805
845
|
ic.width = iW
|
|
806
846
|
ic.height = iH
|
|
807
|
-
|
|
847
|
+
elsif [:process, :clocked_process, :timed_process]. include?(ic.type) then
|
|
808
848
|
puts "For process #{ic.name} setting size from #{ic.width},#{ic.height} to #{pW},#{pH}"
|
|
809
849
|
ic.width = pW
|
|
810
850
|
ic.height = pH
|
|
@@ -1278,6 +1318,7 @@ module HDLRuby::Viz
|
|
|
1278
1318
|
# Also place the ports of the current IC.
|
|
1279
1319
|
poses = []
|
|
1280
1320
|
@lports.each do |lport|
|
|
1321
|
+
next unless lport.targets[0] # Skip dangling port.
|
|
1281
1322
|
lport.ypos = lport.targets[0].ypos
|
|
1282
1323
|
lport.ypos += 1 if lport.targets[0].side == UP
|
|
1283
1324
|
lport.ypos -= 1 if lport.targets[0].side == DOWN
|
|
@@ -1290,10 +1331,10 @@ module HDLRuby::Viz
|
|
|
1290
1331
|
end
|
|
1291
1332
|
poses = []
|
|
1292
1333
|
@uports.each do |uport|
|
|
1334
|
+
next unless uport.targets[0] # Skip dangling port.
|
|
1293
1335
|
uport.xpos = uport.targets[0].xpos
|
|
1294
1336
|
uport.xpos -= 1 if uport.targets[0].side == LEFT
|
|
1295
1337
|
uport.xpos += 1 if uport.targets[0].side == RIGHT
|
|
1296
|
-
puts "Now uport.xpos=#{uport.xpos}"
|
|
1297
1338
|
# Ensure ports do not overlap.
|
|
1298
1339
|
while poses[uport.xpos] do
|
|
1299
1340
|
uport.xpos += 1
|
|
@@ -1303,6 +1344,7 @@ module HDLRuby::Viz
|
|
|
1303
1344
|
end
|
|
1304
1345
|
poses = []
|
|
1305
1346
|
@rports.each do |rport|
|
|
1347
|
+
next unless rport.targets[0] # Skip dangling port.
|
|
1306
1348
|
rport.ypos = rport.targets[0].ypos
|
|
1307
1349
|
rport.ypos += 1 if rport.targets[0].side == UP
|
|
1308
1350
|
rport.ypos -= 1 if rport.targets[0].side == DOWN
|
|
@@ -1315,6 +1357,7 @@ module HDLRuby::Viz
|
|
|
1315
1357
|
end
|
|
1316
1358
|
poses = []
|
|
1317
1359
|
@dports.each do |dport|
|
|
1360
|
+
next unless dport.targets[0] # Skip dangling port.
|
|
1318
1361
|
dport.xpos = dport.targets[0].xpos
|
|
1319
1362
|
dport.xpos -= 1 if dport.targets[0].side == LEFT
|
|
1320
1363
|
dport.xpos += 1 if dport.targets[0].side == RIGHT
|
|
@@ -1531,41 +1574,127 @@ module HDLRuby::Viz
|
|
|
1531
1574
|
end
|
|
1532
1575
|
|
|
1533
1576
|
# Get the neighbor free positions for port.
|
|
1534
|
-
# def free_neighbors(port,cpos)
|
|
1535
1577
|
def free_neighbors(port0,port1,cpos)
|
|
1536
1578
|
res = []
|
|
1537
|
-
#
|
|
1538
|
-
|
|
1539
|
-
if
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1579
|
+
# For cosmetic reasons of the wires, the order of processing depends
|
|
1580
|
+
# on the relative position of the ports.
|
|
1581
|
+
if 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
|
+
end
|
|
1589
|
+
# Up neighbor.
|
|
1590
|
+
upos = [cpos[0],cpos[1]+1]
|
|
1591
|
+
if upos[1] < @route_height then
|
|
1592
|
+
elem = @route_matrix[upos[1]][upos[0]]
|
|
1593
|
+
res << upos if elem.free_from_down?(port0,port1) and
|
|
1594
|
+
!ic_port_conflict(port0,port1,[upos[0],upos[1]+1],DOWN)
|
|
1595
|
+
end
|
|
1596
|
+
# Right neighbor.
|
|
1597
|
+
rpos = [cpos[0]+1,cpos[1]]
|
|
1598
|
+
if rpos[0] < @route_width then
|
|
1599
|
+
elem = @route_matrix[rpos[1]][rpos[0]]
|
|
1600
|
+
res << rpos if elem.free_from_left?(port0,port1) and
|
|
1601
|
+
!ic_port_conflict(port0,port1,[rpos[0]+1,rpos[1]],LEFT)
|
|
1602
|
+
end
|
|
1603
|
+
# Down neighbor.
|
|
1604
|
+
dpos = [cpos[0],cpos[1]-1]
|
|
1605
|
+
if dpos[1] >= 0 then
|
|
1606
|
+
elem = @route_matrix[dpos[1]][dpos[0]]
|
|
1607
|
+
res << dpos if elem.free_from_up?(port0,port1) and
|
|
1608
|
+
!ic_port_conflict(port0,port1,[dpos[0],dpos[1]-1],UP)
|
|
1609
|
+
end
|
|
1610
|
+
elsif port0.xpos < port1.xpos and port0.ypos > port1.ypos then
|
|
1611
|
+
# Left neighbor.
|
|
1612
|
+
lpos = [cpos[0]-1,cpos[1]]
|
|
1613
|
+
if lpos[0] >= 0 then
|
|
1614
|
+
elem = @route_matrix[lpos[1]][lpos[0]]
|
|
1615
|
+
res << lpos if elem.free_from_right?(port0,port1) and
|
|
1616
|
+
!ic_port_conflict(port0,port1,[lpos[0]-1,lpos[1]],RIGHT)
|
|
1617
|
+
end
|
|
1618
|
+
# Down neighbor.
|
|
1619
|
+
dpos = [cpos[0],cpos[1]-1]
|
|
1620
|
+
if dpos[1] >= 0 then
|
|
1621
|
+
elem = @route_matrix[dpos[1]][dpos[0]]
|
|
1622
|
+
res << dpos if elem.free_from_up?(port0,port1) and
|
|
1623
|
+
!ic_port_conflict(port0,port1,[dpos[0],dpos[1]-1],UP)
|
|
1624
|
+
end
|
|
1625
|
+
# Right neighbor.
|
|
1626
|
+
rpos = [cpos[0]+1,cpos[1]]
|
|
1627
|
+
if rpos[0] < @route_width then
|
|
1628
|
+
elem = @route_matrix[rpos[1]][rpos[0]]
|
|
1629
|
+
res << rpos if elem.free_from_left?(port0,port1) and
|
|
1630
|
+
!ic_port_conflict(port0,port1,[rpos[0]+1,rpos[1]],LEFT)
|
|
1631
|
+
end
|
|
1632
|
+
# Up neighbor.
|
|
1633
|
+
upos = [cpos[0],cpos[1]+1]
|
|
1634
|
+
if upos[1] < @route_height then
|
|
1635
|
+
elem = @route_matrix[upos[1]][upos[0]]
|
|
1636
|
+
res << upos if elem.free_from_down?(port0,port1) and
|
|
1637
|
+
!ic_port_conflict(port0,port1,[upos[0],upos[1]+1],DOWN)
|
|
1638
|
+
end
|
|
1639
|
+
elsif port0.xpos > port1.xpos and port0.ypos > port1.ypos then
|
|
1640
|
+
# Right neighbor.
|
|
1641
|
+
rpos = [cpos[0]+1,cpos[1]]
|
|
1642
|
+
if rpos[0] < @route_width then
|
|
1643
|
+
elem = @route_matrix[rpos[1]][rpos[0]]
|
|
1644
|
+
res << rpos if elem.free_from_left?(port0,port1) and
|
|
1645
|
+
!ic_port_conflict(port0,port1,[rpos[0]+1,rpos[1]],LEFT)
|
|
1646
|
+
end
|
|
1647
|
+
# Down neighbor.
|
|
1648
|
+
dpos = [cpos[0],cpos[1]-1]
|
|
1649
|
+
if dpos[1] >= 0 then
|
|
1650
|
+
elem = @route_matrix[dpos[1]][dpos[0]]
|
|
1651
|
+
res << dpos if elem.free_from_up?(port0,port1) and
|
|
1652
|
+
!ic_port_conflict(port0,port1,[dpos[0],dpos[1]-1],UP)
|
|
1653
|
+
end
|
|
1654
|
+
# Left neighbor.
|
|
1655
|
+
lpos = [cpos[0]-1,cpos[1]]
|
|
1656
|
+
if lpos[0] >= 0 then
|
|
1657
|
+
elem = @route_matrix[lpos[1]][lpos[0]]
|
|
1658
|
+
res << lpos if elem.free_from_right?(port0,port1) and
|
|
1659
|
+
!ic_port_conflict(port0,port1,[lpos[0]-1,lpos[1]],RIGHT)
|
|
1660
|
+
end
|
|
1661
|
+
# Up neighbor.
|
|
1662
|
+
upos = [cpos[0],cpos[1]+1]
|
|
1663
|
+
if upos[1] < @route_height then
|
|
1664
|
+
elem = @route_matrix[upos[1]][upos[0]]
|
|
1665
|
+
res << upos if elem.free_from_down?(port0,port1) and
|
|
1666
|
+
!ic_port_conflict(port0,port1,[upos[0],upos[1]+1],DOWN)
|
|
1667
|
+
end
|
|
1668
|
+
else
|
|
1669
|
+
# Right neighbor.
|
|
1670
|
+
rpos = [cpos[0]+1,cpos[1]]
|
|
1671
|
+
if rpos[0] < @route_width then
|
|
1672
|
+
elem = @route_matrix[rpos[1]][rpos[0]]
|
|
1673
|
+
res << rpos if elem.free_from_left?(port0,port1) and
|
|
1674
|
+
!ic_port_conflict(port0,port1,[rpos[0]+1,rpos[1]],LEFT)
|
|
1675
|
+
end
|
|
1676
|
+
# Up neighbor.
|
|
1677
|
+
upos = [cpos[0],cpos[1]+1]
|
|
1678
|
+
if upos[1] < @route_height then
|
|
1679
|
+
elem = @route_matrix[upos[1]][upos[0]]
|
|
1680
|
+
res << upos if elem.free_from_down?(port0,port1) and
|
|
1681
|
+
!ic_port_conflict(port0,port1,[upos[0],upos[1]+1],DOWN)
|
|
1682
|
+
end
|
|
1683
|
+
# Left neighbor.
|
|
1684
|
+
lpos = [cpos[0]-1,cpos[1]]
|
|
1685
|
+
if lpos[0] >= 0 then
|
|
1686
|
+
elem = @route_matrix[lpos[1]][lpos[0]]
|
|
1687
|
+
res << lpos if elem.free_from_right?(port0,port1) and
|
|
1688
|
+
!ic_port_conflict(port0,port1,[lpos[0]-1,lpos[1]],RIGHT)
|
|
1689
|
+
end
|
|
1690
|
+
# Down neighbor.
|
|
1691
|
+
dpos = [cpos[0],cpos[1]-1]
|
|
1692
|
+
if dpos[1] >= 0 then
|
|
1693
|
+
elem = @route_matrix[dpos[1]][dpos[0]]
|
|
1694
|
+
res << dpos if elem.free_from_up?(port0,port1) and
|
|
1695
|
+
!ic_port_conflict(port0,port1,[dpos[0],dpos[1]-1],UP)
|
|
1696
|
+
end
|
|
1697
|
+
end
|
|
1569
1698
|
# Return the free neigbor positions.
|
|
1570
1699
|
return res
|
|
1571
1700
|
end
|
|
@@ -1651,29 +1780,16 @@ module HDLRuby::Viz
|
|
|
1651
1780
|
pos0 = [port0.xpos,port0.ypos]
|
|
1652
1781
|
pos1 = [port1.xpos,port1.ypos]
|
|
1653
1782
|
oset = [pos0]
|
|
1654
|
-
# oset = Set.new
|
|
1655
1783
|
oset << pos0
|
|
1656
1784
|
from = { }
|
|
1657
|
-
# gscore = Hash.new(1/0.0)
|
|
1658
|
-
# gscore[pos0] = 0
|
|
1659
1785
|
gscore = Array.new(@route_matrix.size) { Array.new(@route_matrix[0].size) { 1/0.0 } }
|
|
1660
1786
|
gscore[pos0[1]][pos0[0]] = 0
|
|
1661
|
-
# fscore = Hash.new(1/0.0)
|
|
1662
|
-
# fscore[pos0] = taxi_distance(pos0,pos1)
|
|
1663
1787
|
fscore = Array.new(@route_matrix.size) { [] }
|
|
1664
1788
|
fscore[pos0[1]][pos0[0]] = taxi_distance(pos0,pos1)
|
|
1665
1789
|
while oset.any? do
|
|
1666
1790
|
# Pick the position from oset with the minimum fscore.
|
|
1667
1791
|
cpos = nil # Current position
|
|
1668
1792
|
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
|
|
1677
1793
|
# The best score is necessily at the end of oset.
|
|
1678
1794
|
cpos = oset.pop
|
|
1679
1795
|
# puts "cpos=#{cpos}"
|
|
@@ -1682,23 +1798,16 @@ module HDLRuby::Viz
|
|
|
1682
1798
|
from[pos1] = cpos
|
|
1683
1799
|
return reconstruct_path(port0,port1,from,pos1)
|
|
1684
1800
|
end
|
|
1685
|
-
# oset.delete(cpos) # No need anymore since pop
|
|
1686
1801
|
# Get the neighbor positions for port.
|
|
1687
|
-
# poses = free_neighbors(port0,cpos)
|
|
1688
1802
|
poses = free_neighbors(port0,port1,cpos)
|
|
1689
1803
|
poses.each do |pos|
|
|
1690
1804
|
# Try it.
|
|
1691
|
-
# tscore = gscore[cpos] + cost_position(port0,pos)
|
|
1692
1805
|
tscore = gscore[cpos[1]][cpos[0]] + cost_position(port0,pos)
|
|
1693
|
-
# if tscore < gscore[pos] then
|
|
1694
1806
|
if tscore < gscore[pos[1]][pos[0]] then
|
|
1695
1807
|
# This path to neigbor is better than any previous one, keep it.
|
|
1696
1808
|
from[pos] = cpos
|
|
1697
|
-
# gscore[pos] = tscore
|
|
1698
1809
|
gscore[pos[1]][pos[0]] = tscore
|
|
1699
|
-
# fscore[pos] = tscore + taxi_distance(pos,pos1)
|
|
1700
1810
|
fscore[pos[1]][pos[0]] = tscore + taxi_distance(pos,pos1)
|
|
1701
|
-
# oset << pos unless oset.include?(pos)
|
|
1702
1811
|
idx = oset.bsearch_index {|p| fscore[p[1]][p[0]] <= fscore[pos[1]][pos[0]] }
|
|
1703
1812
|
if idx then
|
|
1704
1813
|
oset.insert(idx,pos)
|
|
@@ -2377,14 +2486,26 @@ module HDLRuby::Viz
|
|
|
2377
2486
|
id = Viz.to_svg_id(ic.name)
|
|
2378
2487
|
# Determine the side of the inputs (and consequently of the outputs),
|
|
2379
2488
|
# and the number of inputs.
|
|
2380
|
-
iside =
|
|
2489
|
+
iside = nil
|
|
2381
2490
|
inum = 0
|
|
2382
2491
|
ic.ports.each do |port|
|
|
2383
2492
|
if port.direction == :input then
|
|
2384
2493
|
iside = port.side
|
|
2385
2494
|
inum += 1
|
|
2495
|
+
elsif port.direction == :output then
|
|
2496
|
+
case port.side
|
|
2497
|
+
when LEFT
|
|
2498
|
+
iside = RIGHT
|
|
2499
|
+
when RIGHT
|
|
2500
|
+
iside = LEFT
|
|
2501
|
+
when UP
|
|
2502
|
+
iside = DOWN
|
|
2503
|
+
when DOWN
|
|
2504
|
+
iside = UP
|
|
2505
|
+
end
|
|
2386
2506
|
end
|
|
2387
2507
|
end
|
|
2508
|
+
raise "Connection with no port for #{ic.name}" unless iside
|
|
2388
2509
|
# NOTE: inum is zero in case of a constant, force at least 1.
|
|
2389
2510
|
inum = 1 if inum < 1
|
|
2390
2511
|
# The length of a leg
|
|
@@ -2498,6 +2619,8 @@ module HDLRuby::Viz
|
|
|
2498
2619
|
res = "<rect fill=\"#88f\" stroke=\"#000\" "
|
|
2499
2620
|
when :negedge
|
|
2500
2621
|
res = "<rect fill=\"#f88\" stroke=\"#000\" "
|
|
2622
|
+
when :anyedge
|
|
2623
|
+
res = "<rect fill=\"#888\" stroke=\"#000\" "
|
|
2501
2624
|
else
|
|
2502
2625
|
res = "<rect fill=\"#ff0\" stroke=\"#000\" "
|
|
2503
2626
|
end
|
|
@@ -2517,6 +2640,8 @@ module HDLRuby::Viz
|
|
|
2517
2640
|
res = "<rect fill=\"#88f\" stroke=\"#000\" "
|
|
2518
2641
|
when :negedge
|
|
2519
2642
|
res = "<rect fill=\"#f88\" stroke=\"#000\" "
|
|
2643
|
+
when :anyedge
|
|
2644
|
+
res = "<rect fill=\"#888\" stroke=\"#000\" "
|
|
2520
2645
|
else
|
|
2521
2646
|
res = "<rect fill=\"#ff0\" stroke=\"#000\" "
|
|
2522
2647
|
end
|
|
@@ -2551,6 +2676,8 @@ module HDLRuby::Viz
|
|
|
2551
2676
|
res = "<rect fill=\"#88f\" stroke=\"#000\" "
|
|
2552
2677
|
when :negedge
|
|
2553
2678
|
res = "<rect fill=\"#f88\" stroke=\"#000\" "
|
|
2679
|
+
when :anyedge
|
|
2680
|
+
res = "<rect fill=\"#888\" stroke=\"#000\" "
|
|
2554
2681
|
else
|
|
2555
2682
|
res = "<rect fill=\"#ff0\" stroke=\"#000\" "
|
|
2556
2683
|
end
|
|
@@ -2570,6 +2697,8 @@ module HDLRuby::Viz
|
|
|
2570
2697
|
res = "<rect fill=\"#88f\" stroke=\"#000\" "
|
|
2571
2698
|
when :negedge
|
|
2572
2699
|
res = "<rect fill=\"#f88\" stroke=\"#000\" "
|
|
2700
|
+
when :anyedge
|
|
2701
|
+
res = "<rect fill=\"#888\" stroke=\"#000\" "
|
|
2573
2702
|
else
|
|
2574
2703
|
res = "<rect fill=\"#ff0\" stroke=\"#000\" "
|
|
2575
2704
|
end
|
|
@@ -2605,15 +2734,22 @@ module HDLRuby::Viz
|
|
|
2605
2734
|
# Generate the string representing a port for display in the SVG
|
|
2606
2735
|
def port_str(port)
|
|
2607
2736
|
# Generate the port name (strip everything before the last ".")
|
|
2608
|
-
name = port.name.sub(/^.*\./,"")
|
|
2737
|
+
# name = port.name.sub(/^.*\./,"")
|
|
2738
|
+
name = port.name.split(/(?<!\.)\.(?!\.)/).last
|
|
2609
2739
|
# Strip the suffix $I and $O
|
|
2610
2740
|
name = name.sub(/\$(I|O)$/,"")
|
|
2741
|
+
# For registers' bit ports, only keep the bit number.
|
|
2742
|
+
if port.ic.type==:register and HDLRuby::Viz.port_bit_name?(name) then
|
|
2743
|
+
name = HDLRuby::Viz.port_bit_name(name)
|
|
2744
|
+
end
|
|
2611
2745
|
# Add a suffix for edge properties.
|
|
2612
2746
|
case port.type
|
|
2613
2747
|
when :posedge
|
|
2614
2748
|
return name + " \u2197"
|
|
2615
2749
|
when :negedge
|
|
2616
2750
|
return name + " \u2198"
|
|
2751
|
+
when :anyedge
|
|
2752
|
+
return name + " \u2195"
|
|
2617
2753
|
else
|
|
2618
2754
|
return name
|
|
2619
2755
|
end
|
|
@@ -2660,7 +2796,10 @@ module HDLRuby::Viz
|
|
|
2660
2796
|
# Sets the styles.
|
|
2661
2797
|
res += "<style>\n"
|
|
2662
2798
|
# Fonts
|
|
2663
|
-
res += ".small#{self.idC} { font: #{sF}px sans-serif; }\n"
|
|
2799
|
+
res += ".small#{self.idC} { font: #{sF}px sans-serif; " # }\n" # +
|
|
2800
|
+
res += "stroke=\"yellow\"; stroke-width=\"6\"; paint-order=\"stroke fill;\" }\n"
|
|
2801
|
+
# "border: 2px solid black; padding: 10px; display: inline-block; " +
|
|
2802
|
+
# " background-color: rgba(0, 128, 255, 0.2); }\n"
|
|
2664
2803
|
res += ".medium#{self.idC} { font: #{mF}px sans-serif; }\n"
|
|
2665
2804
|
res += ".large#{self.idC} { font: #{lF}px sans-serif; }\n"
|
|
2666
2805
|
res += "</style>\n"
|
|
@@ -2818,11 +2957,19 @@ module HDLRuby::Viz
|
|
|
2818
2957
|
if child == self then
|
|
2819
2958
|
res += "<text class=\"small#{self.idC}\" style=\"text-anchor: end\" " +
|
|
2820
2959
|
"x=\"#{(port.xpos)*@scale-pT}\" "+
|
|
2821
|
-
"y=\"#{(port.ypos+0.5)*@scale+sF/2.5}\">" +
|
|
2960
|
+
"y=\"#{(port.ypos+0.5)*@scale+sF/2.5}\">" +
|
|
2961
|
+
self.port_str(port) + "</text>\n"
|
|
2962
|
+
elsif (child.type == :assign and port.direction == :input and
|
|
2963
|
+
child.ports.size.even? and child.ports.index(port) == child.ports.size/2) then
|
|
2964
|
+
# Middle input of an alu, slide it bellow to avoid collision
|
|
2965
|
+
# with the output port.
|
|
2966
|
+
res += "<text class=\"small#{self.idC}\" x=\"#{(port.xpos)*@scale+pT}\" "+
|
|
2967
|
+
"y=\"#{(port.ypos+0.8)*@scale+sF/2.5}\">" +
|
|
2822
2968
|
self.port_str(port) + "</text>\n"
|
|
2823
2969
|
else
|
|
2970
|
+
# General case.
|
|
2824
2971
|
res += "<text class=\"small#{self.idC}\" x=\"#{(port.xpos)*@scale+pT}\" "+
|
|
2825
|
-
"y=\"#{(port.ypos+0.
|
|
2972
|
+
"y=\"#{(port.ypos+0.45)*@scale+sF/2.5}\">" +
|
|
2826
2973
|
self.port_str(port) + "</text>\n"
|
|
2827
2974
|
end
|
|
2828
2975
|
end
|
|
@@ -2886,10 +3033,18 @@ module HDLRuby::Viz
|
|
|
2886
3033
|
"x=\"#{(port.xpos+1)*@scale+pT}\" " +
|
|
2887
3034
|
"y=\"#{(port.ypos+0.5)*@scale+sF/2.5}\">" + # port.name +
|
|
2888
3035
|
self.port_str(port) + "</text>\n"
|
|
3036
|
+
elsif (child.type == :assign and port.direction == :input and
|
|
3037
|
+
child.ports.size.even? and child.ports.index(port) == child.ports.size/2) then
|
|
3038
|
+
# Middle input of an alu, slide it bellow to avoid collision
|
|
3039
|
+
# with the output port.
|
|
3040
|
+
res += "<text class=\"small#{self.idC}\" style=\"text-anchor: end\" " +
|
|
3041
|
+
"x=\"#{(port.xpos+1)*@scale-pT}\" "+
|
|
3042
|
+
"y=\"#{(port.ypos+0.8)*@scale+sF/2.5}\">" + # port.name +
|
|
3043
|
+
self.port_str(port) + "</text>\n"
|
|
2889
3044
|
else
|
|
2890
3045
|
res += "<text class=\"small#{self.idC}\" style=\"text-anchor: end\" " +
|
|
2891
3046
|
"x=\"#{(port.xpos+1)*@scale-pT}\" "+
|
|
2892
|
-
"y=\"#{(port.ypos+0.
|
|
3047
|
+
"y=\"#{(port.ypos+0.45)*@scale+sF/2.5}\">" + # port.name +
|
|
2893
3048
|
self.port_str(port) + "</text>\n"
|
|
2894
3049
|
end
|
|
2895
3050
|
end
|
|
@@ -2973,14 +3128,15 @@ module HDLRuby::Viz
|
|
|
2973
3128
|
cty += 1
|
|
2974
3129
|
end
|
|
2975
3130
|
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
|
|
3131
|
+
# # Leave a space for left or right ports if any.
|
|
3132
|
+
# sl = (child.ports.any? {|p| p.side == LEFT }) ? 1.0 : 0.0
|
|
3133
|
+
# sr = (child.ports.any? {|p| p.side == RIGHT }) ? 1.0 : 0.0
|
|
2979
3134
|
# Recompute the scale.
|
|
2980
3135
|
fit = [
|
|
2981
|
-
(target.width+sl+sr+(bT/@scale)) / (cwidth),
|
|
2982
|
-
(target.
|
|
2983
|
-
|
|
3136
|
+
# (target.width+sl+sr+(bT/@scale/2.0)) / (cwidth),
|
|
3137
|
+
(target.width+(bT/@scale/2.0)) / (cwidth),
|
|
3138
|
+
(target.height+(bT/@scale/2.0)) / (cheight),
|
|
3139
|
+
1.0# 3.0
|
|
2984
3140
|
].max
|
|
2985
3141
|
target.scale = @scale / fit
|
|
2986
3142
|
puts "fit=#{fit} target.scale=#{target.scale}"
|
|
@@ -4382,7 +4538,7 @@ class HDLRuby::Low::SystemT
|
|
|
4382
4538
|
# ports.each_value do |subs|
|
|
4383
4539
|
ports.each do |name,subs|
|
|
4384
4540
|
# Skip connection to registers, they are processed later.
|
|
4385
|
-
next if regs[name]
|
|
4541
|
+
next if regs[HDLRuby::Viz.port_base_name(name)]
|
|
4386
4542
|
# Not a register, can go on.
|
|
4387
4543
|
subs.each do |p0|
|
|
4388
4544
|
subs.each do |p1|
|
|
@@ -4400,15 +4556,17 @@ class HDLRuby::Low::SystemT
|
|
|
4400
4556
|
# Check if there is a register corresponding to the port
|
|
4401
4557
|
# (full port or sub port of the register).
|
|
4402
4558
|
next if name.include?("$") # Skip register ports which are targets.
|
|
4403
|
-
rname = name
|
|
4559
|
+
# rname = name
|
|
4560
|
+
rname = HDLRuby::Viz.port_base_name(name)
|
|
4404
4561
|
while !regs.key?(rname) do
|
|
4405
4562
|
break unless rname.include?(".")
|
|
4406
4563
|
rname = rname.gsub(/\.[^.]*$/,"")
|
|
4407
4564
|
end
|
|
4408
4565
|
reg = regs[rname]
|
|
4409
4566
|
next unless reg
|
|
4410
|
-
# Connect the register, once per ic and direction.
|
|
4411
|
-
|
|
4567
|
+
# # Connect the register, once per ic and direction.
|
|
4568
|
+
# Connect the register, once per ic, direction and type.
|
|
4569
|
+
subs.uniq {|p| [p.ic,p.direction,p.type] }.each do |p|
|
|
4412
4570
|
# puts "Connect to register port name #{name} in ic=#{world.name} with port=#{p.name}"
|
|
4413
4571
|
if p.direction == :output then
|
|
4414
4572
|
world.connect(p,ports[HDLRuby::Viz.reg2input_name(name)][0])
|
|
@@ -4444,16 +4602,48 @@ class HDLRuby::Low::SystemT
|
|
|
4444
4602
|
# NOTE: p0 or p1 may be empty if outside current module.
|
|
4445
4603
|
world.connect(p0,p1) unless (!p0 or !p1 or p0.targets.include?(p1))
|
|
4446
4604
|
end
|
|
4447
|
-
# Remove the dangling input ports in registers (they are ROMS).
|
|
4605
|
+
# # Remove the dangling input ports in registers (they are ROMS).
|
|
4606
|
+
# regs.each_value do |reg|
|
|
4607
|
+
# to_remove_input = reg.ports.select {|p| p.direction==:input }.all? do
|
|
4608
|
+
# |p|
|
|
4609
|
+
# p.targets.none?
|
|
4610
|
+
# end
|
|
4611
|
+
# if to_remove_input then
|
|
4612
|
+
# reg.ports.delete_if {|p| p.direction == :input }
|
|
4613
|
+
# end
|
|
4614
|
+
# end
|
|
4615
|
+
# Remove the dangling ports in registers (they are ROMS).
|
|
4448
4616
|
regs.each_value do |reg|
|
|
4449
|
-
|
|
4450
|
-
|
|
4451
|
-
|
|
4617
|
+
reg.ports.delete_if {|p| p.targets.none? }
|
|
4618
|
+
end
|
|
4619
|
+
|
|
4620
|
+
# Gather the bit ports by owner port.
|
|
4621
|
+
port2bits = {}
|
|
4622
|
+
ports.each do |name,subs|
|
|
4623
|
+
subs.each do |port|
|
|
4624
|
+
port2bits[port.name] = []
|
|
4452
4625
|
end
|
|
4453
|
-
|
|
4454
|
-
|
|
4626
|
+
end
|
|
4627
|
+
ports.each do |name,subs|
|
|
4628
|
+
subs.each do |port|
|
|
4629
|
+
if HDLRuby::Viz.port_bit_name?(port.name) then
|
|
4630
|
+
port2bits[HDLRuby::Viz.port_base_name(port.name)] << port
|
|
4631
|
+
end
|
|
4455
4632
|
end
|
|
4456
4633
|
end
|
|
4634
|
+
# Remove the dangling ports that are accessed by sub ports.
|
|
4635
|
+
ports.each do |name,subs|
|
|
4636
|
+
subs.each do |port|
|
|
4637
|
+
if port.targets.none? then
|
|
4638
|
+
# This is a dangling port, is it connected by bits.
|
|
4639
|
+
if port2bits[port.name].any? then
|
|
4640
|
+
# Yes, remove it.
|
|
4641
|
+
port.ic.ports.delete(port)
|
|
4642
|
+
end
|
|
4643
|
+
end
|
|
4644
|
+
end
|
|
4645
|
+
end
|
|
4646
|
+
|
|
4457
4647
|
# Return the resulting visualization.
|
|
4458
4648
|
return world
|
|
4459
4649
|
end
|
|
@@ -4482,18 +4672,23 @@ class HDLRuby::Low::Scope
|
|
|
4482
4672
|
# name = sname + inner.name.to_s
|
|
4483
4673
|
# name = inner.name.to_s
|
|
4484
4674
|
name = sname + inner.name.to_s
|
|
4485
|
-
#
|
|
4486
|
-
|
|
4487
|
-
|
|
4488
|
-
|
|
4489
|
-
#
|
|
4490
|
-
|
|
4491
|
-
|
|
4492
|
-
|
|
4493
|
-
|
|
4494
|
-
|
|
4675
|
+
# But first cut of the index if any for the register.
|
|
4676
|
+
rname = HDLRuby::Viz.port_base_name(name)
|
|
4677
|
+
reg = regs[rname]
|
|
4678
|
+
unless reg then
|
|
4679
|
+
# Create the viz for the "register"
|
|
4680
|
+
if typ.is_a?(HDLRuby::Low::TypeVector) and
|
|
4681
|
+
typ.base.width > 1 then
|
|
4682
|
+
puts "Adding scope register #{rname} to #{world.name}"
|
|
4683
|
+
# This is in fact a memory matrix.
|
|
4684
|
+
reg = HDLRuby::Viz::IC.new(rname,:memory,world)
|
|
4685
|
+
else
|
|
4686
|
+
puts "Adding plain register #{rname} to #{world.name}"
|
|
4687
|
+
# This is a plain register.
|
|
4688
|
+
reg = HDLRuby::Viz::IC.new(rname,:register,world)
|
|
4689
|
+
end
|
|
4690
|
+
regs[reg.name] = reg
|
|
4495
4691
|
end
|
|
4496
|
-
regs[reg.name] = reg
|
|
4497
4692
|
# Create the corresponding input and output ports.
|
|
4498
4693
|
iname = HDLRuby::Viz.reg2input_name(name)
|
|
4499
4694
|
puts "Adding input port #{iname} to reg #{reg.name}"
|
|
@@ -4546,21 +4741,11 @@ class HDLRuby::Low::Scope
|
|
|
4546
4741
|
# Explicit port connect case.
|
|
4547
4742
|
links << [ connection.left.to_viz_names[0],
|
|
4548
4743
|
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
4744
|
# Add the explicit port connection.
|
|
4560
4745
|
puts "added link between #{links[-1][0]} and #{links[-1][1]}"
|
|
4561
4746
|
next
|
|
4562
4747
|
end
|
|
4563
|
-
ic = HDLRuby::Viz::IC.new(HDLRuby.uniq_name("
|
|
4748
|
+
ic = HDLRuby::Viz::IC.new(HDLRuby.uniq_name("cnx"),:assign,world)
|
|
4564
4749
|
# Add its ports.
|
|
4565
4750
|
# Output.
|
|
4566
4751
|
name = connection.left.to_viz_names[0]
|
|
@@ -4595,14 +4780,15 @@ class HDLRuby::Low::Scope
|
|
|
4595
4780
|
behavior.each_event do |ev|
|
|
4596
4781
|
name = ev.ref.to_viz_names[0]
|
|
4597
4782
|
next if ic.port?(name) # The port has already been added.
|
|
4598
|
-
# Is it a clocked event?
|
|
4599
|
-
if ev.on_edge? then
|
|
4600
|
-
|
|
4601
|
-
|
|
4602
|
-
else
|
|
4603
|
-
|
|
4604
|
-
|
|
4605
|
-
end
|
|
4783
|
+
# # Is it a clocked event?
|
|
4784
|
+
# if ev.on_edge? then
|
|
4785
|
+
# # Yes.
|
|
4786
|
+
# ports[name] << ic.add_port(name, :input, ev.type)
|
|
4787
|
+
# else
|
|
4788
|
+
# # No, use a standard port.
|
|
4789
|
+
# ports[name] << ic.add_port(name, :input)
|
|
4790
|
+
# end
|
|
4791
|
+
ports[name] << ic.add_port(name, :input, ev.type)
|
|
4606
4792
|
end
|
|
4607
4793
|
# Recurse on its blocks.
|
|
4608
4794
|
# behavior.block.to_viz(world,ic,ports)
|
|
@@ -4691,14 +4877,19 @@ class HDLRuby::Low::Block
|
|
|
4691
4877
|
self.each_inner do |inner|
|
|
4692
4878
|
name = bname + inner.name.to_s
|
|
4693
4879
|
puts "Adding block register #{name} to #{world.name}"
|
|
4694
|
-
#
|
|
4695
|
-
|
|
4696
|
-
|
|
4697
|
-
|
|
4698
|
-
|
|
4699
|
-
|
|
4880
|
+
# But first cut of the index if any for the register.
|
|
4881
|
+
rname = HDLRuby::Viz.port_base_name(name)
|
|
4882
|
+
reg = regs[rname]
|
|
4883
|
+
unless reg then
|
|
4884
|
+
# Create the viz for the "register"
|
|
4885
|
+
if inner.type.base.width > 1 then
|
|
4886
|
+
# This is in fact a memory matrix.
|
|
4887
|
+
reg = HDLRuby::Viz::IC.new(rname,:memory,world)
|
|
4888
|
+
else
|
|
4889
|
+
reg = HDLRuby::Viz::IC.new(rname,:register,world)
|
|
4890
|
+
end
|
|
4891
|
+
regs[reg.name] = reg
|
|
4700
4892
|
end
|
|
4701
|
-
regs[reg.name] = reg
|
|
4702
4893
|
# Create the corresponding input and output ports.
|
|
4703
4894
|
iname = HDLRuby::Viz.reg2input_name(name)
|
|
4704
4895
|
puts "Adding input port #{iname} to #{world.name}"
|
|
@@ -4767,20 +4958,22 @@ class HDLRuby::Low::Block
|
|
|
4767
4958
|
end
|
|
4768
4959
|
|
|
4769
4960
|
next unless stmnt.is_a?(HDLRuby::Low::Transmit)
|
|
4770
|
-
|
|
4961
|
+
lnames = stmnt.left.to_viz_names
|
|
4962
|
+
name = lnames[0]
|
|
4771
4963
|
if iports.key?(name) then
|
|
4772
4964
|
# Change to inout port.
|
|
4773
4965
|
iports[name].direction = :inout
|
|
4774
|
-
next
|
|
4775
|
-
end
|
|
4966
|
+
# next
|
|
4967
|
+
# end
|
|
4776
4968
|
# Add one port by output name.
|
|
4777
|
-
unless oports.key?(name) then
|
|
4969
|
+
# unless oports.key?(name) then
|
|
4970
|
+
elsif !oports.key?(name) then
|
|
4778
4971
|
puts "Adding output port #{name} to #{ic.name}"
|
|
4779
4972
|
port = ic.add_port(name, :output)
|
|
4780
4973
|
ports[name] << port
|
|
4781
4974
|
oports[name] = port
|
|
4782
4975
|
end
|
|
4783
|
-
stmnt.right.to_viz_names.each do |name|
|
|
4976
|
+
(stmnt.right.to_viz_names+lnames[1..-1]).each do |name|
|
|
4784
4977
|
if oports.key?(name) then
|
|
4785
4978
|
# Change to inout port.
|
|
4786
4979
|
oports[name].direction = :inout
|