@@ -129,6 +129,10 @@ class Device:
129
129
extra_func : Dict [Tuple [int , int ], Dict [str , Any ]] = field (default_factory = dict )
130
130
# Chip features currently related to block memory like "HAS_SP32", "NEED_SP_FIX", etc
131
131
chip_flags : List [str ] = field (default_factory = list )
132
+ # Segmented clock columns description
133
+ # { (y, x, idx) : {min_x, min_y, max_x, max_y, top_row, bottom_row, top_wire, bottom_wire,
134
+ # top_gate_wire[name, ], bottom_gate_wire[name,]}}
135
+ segments : Dict [Tuple [int , int , int ], Dict [str , Any ]] = field (default_factory = dict )
132
136
133
137
@property
134
138
def rows (self ):
@@ -1832,6 +1836,169 @@ def fse_create_clocks(dev, device, dat: Datfile, fse):
1832
1836
dcs [f'selforce' ] = 'D3'
1833
1837
dcs ['clksel' ] = ['D2' , 'A3' , 'B3' , 'C3' ]
1834
1838
1839
+ # Segmented wires are those that run along each column of the chip and have
1840
+ # taps in each row about 4 cells wide. The height of the segment wires varies
1841
+ # from chip to chip: from full chip height for GW1N-1 to two strips in GW1N-9
1842
+ # and three strips in GW2A-18.
1843
+ # The MUXes for the sources on these wires can switch between signals from
1844
+ # "spines" (long horizontal wires up to half a chip in length) or from input
1845
+ # points from the logic.
1846
+ # These MUXes are placed on both ends of the segmented wire, which is very
1847
+ # flexible but at the same time requires some care not to signal both ends of
1848
+ # the wire.
1849
+ # The coverage areas between segment wires i and i + 4 are the same, only the
1850
+ # MUXes differ, so we create a pair of segments at once.
1851
+
1852
+ # tap_start = describes where in the 4-cell area the main wire column with index is located
1853
+ # rows = top and bottom rows of segments
1854
+ # top_wires = [(MUX wire for i segment, MUX wire for i + 4 segment), next_row]
1855
+ # bottom_wires = [(MUX wire for i segment, MUX wire for i + 4 segment), next_row]
1856
+ # top_gate_wires = [(MUX wire for i segment, MUX wire for i + 4 segment), next_row][2]
1857
+ # bottom_gate_wires = [(MUX wire for i segment, MUX wire for i + 4 segment), next_row][2]
1858
+ _segment_data = {
1859
+ 'GW1N-1' : { 'tap_start' : [1 , 0 , 3 , 2 ], 'rows' : [(0 , 10 )],
1860
+ 'top_wires' : [('LT02' , 'LT13' )], 'bottom_wires' : [('LT02' , 'LT13' )],
1861
+ 'top_gate_wires' : [[('A6' , 'A7' )], [('B6' , 'B7' )]],
1862
+ 'bottom_gate_wires' : [[('A6' , 'A7' )], [('B6' , 'B7' )]],
1863
+ 'reserved_wires' : {(0 , 17 , 'A6' ), (0 , 18 , 'A6' ), (0 , 17 , 'A7' ), (0 , 18 , 'A7' ),
1864
+ (0 , 17 , 'B6' ), (0 , 18 , 'B6' ), (0 , 17 , 'B7' ), (0 , 18 , 'B7' )}},
1865
+ 'GW1NZ-1' : { 'tap_start' : [1 , 0 , 3 , 2 ], 'rows' : [(0 , 10 )],
1866
+ 'top_wires' : [('LT02' , 'LT13' )], 'bottom_wires' : [('LT02' , 'LT13' )],
1867
+ 'top_gate_wires' : [[('A6' , 'A7' )], [('B6' , 'B7' )]],
1868
+ 'bottom_gate_wires' : [[('A6' , 'A7' )], [('B6' , 'B7' )]],
1869
+ 'reserved_wires' : {(0 , 17 , 'A6' ), (0 , 18 , 'A6' ), (0 , 17 , 'A7' ), (0 , 18 , 'A7' ),
1870
+ (0 , 17 , 'B6' ), (0 , 18 , 'B6' ), (0 , 17 , 'B7' ), (0 , 18 , 'B7' )}},
1871
+ 'GW1N-4' : { 'tap_start' : [2 , 1 , 0 , 3 ], 'rows' : [(0 , 19 )],
1872
+ 'top_wires' : [('LT02' , 'LT13' )], 'bottom_wires' : [('LT02' , 'LT13' )],
1873
+ 'top_gate_wires' : [[('A6' , 'A7' )], [('B6' , 'B7' )]],
1874
+ 'bottom_gate_wires' : [[('A6' , 'A7' )], [('B6' , 'B7' )]],
1875
+ 'reserved_wires' : {(0 , 9 , 'A6' ), (0 , 10 , 'A6' ), (0 , 9 , 'A7' ), (0 , 10 , 'A7' ),
1876
+ (0 , 9 , 'B6' ), (0 , 10 , 'B6' ), (0 , 9 , 'B7' ), (0 , 10 , 'B7' ),
1877
+ (0 , 27 , 'A6' ), (0 , 28 , 'A6' ), (0 , 27 , 'A7' ), (0 , 28 , 'A7' ),
1878
+ (0 , 27 , 'B6' ), (0 , 28 , 'B6' ), (0 , 27 , 'B7' ), (0 , 28 , 'B7' )}},
1879
+ 'GW1NS-4' : { 'tap_start' : [2 , 1 , 0 , 3 ], 'rows' : [(0 , 19 )],
1880
+ 'top_wires' : [('LT02' , 'LT13' )], 'bottom_wires' : [('LT02' , 'LT13' )],
1881
+ 'top_gate_wires' : [[('A6' , 'A7' )], [('B6' , 'B7' )]],
1882
+ 'bottom_gate_wires' : [[('A6' , 'A7' )], [('B6' , 'B7' )]],
1883
+ 'reserved_wires' : {(0 , 27 , 'A6' ), (0 , 36 , 'A6' ), (0 , 27 , 'A7' ), (0 , 36 , 'A7' ),
1884
+ (0 , 27 , 'B6' ), (0 , 36 , 'B6' ), (0 , 27 , 'B7' ), (0 , 36 , 'B7' )}},
1885
+ 'GW1N-9' : { 'tap_start' : [3 , 2 , 1 , 0 ], 'rows' : [(0 , 18 ), (19 , 28 )],
1886
+ 'top_wires' : [('LT02' , 'LT13' ), ('LT00' , 'LT10' )],
1887
+ 'bottom_wires' : [('LT20' , 'LT30' ), ('LT02' , 'LT13' )],
1888
+ 'top_gate_wires' : [[('A6' , 'A7' ), (None , None )], [('B6' , 'B7' ), None ]],
1889
+ 'bottom_gate_wires' : [[(None , 'B7' ), (None , 'A7' )], [None , None ]],
1890
+ 'reserved_wires' : {}},
1891
+ 'GW1N-9C' : { 'tap_start' : [3 , 2 , 1 , 0 ], 'rows' : [(0 , 18 ), (19 , 28 )],
1892
+ 'top_wires' : [('LT02' , 'LT13' ), ('LT00' , 'LT10' )],
1893
+ 'bottom_wires' : [('LT20' , 'LT30' ), ('LT02' , 'LT13' )],
1894
+ 'top_gate_wires' : [[('A6' , 'A7' ), (None , None )], [('B6' , 'B7' ), None ]],
1895
+ 'bottom_gate_wires' : [[(None , 'B7' ), ('A6' , 'A7' )], [None , None ]],
1896
+ 'reserved_wires' : {}},
1897
+ 'GW2A-18' : { 'tap_start' : [3 , 2 , 1 , 0 ], 'rows' : [(0 , 18 ), (19 , 36 ), (37 , 54 )],
1898
+ 'top_wires' : [('LT02' , 'LT13' ), ('LT00' , 'LT10' ), ('LT00' , 'LT10' )],
1899
+ 'bottom_wires' : [('LT20' , 'LT30' ), ('LT20' , 'LT30' ), ('LT02' , 'LT13' )],
1900
+ 'top_gate_wires' : [[('A6' , 'A7' ), (None , None ), (None , None )], [('B6' , 'B7' ), None , None ]],
1901
+ 'bottom_gate_wires' : [[(None , 'B7' ), (None , 'B7' ), ('A6' , 'A7' )], [None , None , ('B6' , 'B7' )]],
1902
+ 'reserved_wires' : {}},
1903
+ 'GW2A-18C' : { 'tap_start' : [3 , 2 , 1 , 0 ], 'rows' : [(0 , 18 ), (19 , 36 ), (37 , 54 )],
1904
+ 'top_wires' : [('LT02' , 'LT13' ), ('LT00' , 'LT10' ), ('LT00' , 'LT10' )],
1905
+ 'bottom_wires' : [('LT20' , 'LT30' ), ('LT20' , 'LT30' ), ('LT02' , 'LT13' )],
1906
+ 'top_gate_wires' : [[('A6' , 'A7' ), (None , None ), (None , None )], [('B6' , 'B7' ), None , None ]],
1907
+ 'bottom_gate_wires' : [[(None , 'B7' ), (None , 'B7' ), ('A6' , 'A7' )], [None , None , ('B6' , 'B7' )]],
1908
+ 'reserved_wires' : {}},
1909
+ }
1910
+ def create_segments (dev , device ):
1911
+ if device not in _segment_data :
1912
+ return
1913
+
1914
+ dev_desc = _segment_data [device ]
1915
+ top_gate_row = dev_desc ['rows' ][0 ][0 ]
1916
+ for row_idx , tb_row in enumerate (dev_desc ['rows' ]):
1917
+ t_row , b_row = tb_row
1918
+ for s_col in range (dev .cols ):
1919
+ # new segment i
1920
+ seg_idx = dev_desc ['tap_start' ][s_col % 4 ]
1921
+ seg = dev .segments .setdefault ((top_gate_row , s_col , seg_idx ), {})
1922
+ # controlled area
1923
+ seg ['min_x' ] = max (0 , s_col - 1 )
1924
+ seg ['min_y' ] = t_row
1925
+ seg ['max_x' ] = min (dev .cols - 1 , s_col + 2 )
1926
+ if dev .cols - 1 - seg ['max_x' ] == 1 :
1927
+ # The main wire of the segment is repeated every 4 cells, if
1928
+ # there is no space on the right side for the next wire, the
1929
+ # service area is extended to the very edge
1930
+ seg ['max_x' ] = dev .cols - 1
1931
+ seg ['max_y' ] = b_row
1932
+ # MUX's positions and wires
1933
+ seg ['top_row' ] = top_gate_row
1934
+ seg ['bottom_row' ] = b_row
1935
+ seg ['top_wire' ] = dev_desc ['top_wires' ][row_idx ][0 ]
1936
+ seg ['bottom_wire' ] = dev_desc ['bottom_wires' ][row_idx ][0 ]
1937
+ # gate wires
1938
+ seg ['top_gate_wire' ] = [dev_desc ['top_gate_wires' ][0 ][row_idx ][0 ]]
1939
+ second_gate = dev_desc ['top_gate_wires' ][1 ][row_idx ]
1940
+ seg ['top_gate_wire' ].append (second_gate )
1941
+ if second_gate :
1942
+ seg ['top_gate_wire' ][1 ] = second_gate [0 ]
1943
+ seg ['bottom_gate_wire' ] = [dev_desc ['bottom_gate_wires' ][0 ][row_idx ][0 ]]
1944
+ second_gate = dev_desc ['bottom_gate_wires' ][1 ][row_idx ]
1945
+ seg ['bottom_gate_wire' ].append (second_gate )
1946
+ if second_gate :
1947
+ seg ['bottom_gate_wire' ][1 ] = second_gate [0 ]
1948
+ # check reserved
1949
+ if (top_gate_row , s_col , seg ['top_gate_wire' ][0 ]) in dev_desc ['reserved_wires' ]:
1950
+ seg ['top_gate_wire' ][0 ] = None
1951
+ if (top_gate_row , s_col , seg ['top_gate_wire' ][1 ]) in dev_desc ['reserved_wires' ]:
1952
+ seg ['top_gate_wire' ][1 ] = None
1953
+ if (b_row , s_col , seg ['bottom_gate_wire' ][0 ]) in dev_desc ['reserved_wires' ]:
1954
+ seg ['bottom_gate_wire' ][0 ] = None
1955
+ if (b_row , s_col , seg ['bottom_gate_wire' ][1 ]) in dev_desc ['reserved_wires' ]:
1956
+ seg ['bottom_gate_wire' ][1 ] = None
1957
+
1958
+ # new segment i + 1
1959
+ seg_idx += 4
1960
+ seg_1 = dev .segments .setdefault ((top_gate_row , s_col , seg_idx ), {})
1961
+ # controlled area
1962
+ seg_1 ['min_x' ] = seg ['min_x' ]
1963
+ seg_1 ['min_y' ] = seg ['min_y' ]
1964
+ seg_1 ['max_x' ] = seg ['max_x' ]
1965
+ seg_1 ['max_y' ] = seg ['max_y' ]
1966
+ # MUX's positions and wires
1967
+ seg_1 ['top_row' ] = seg ['top_row' ]
1968
+ seg_1 ['bottom_row' ] = seg ['bottom_row' ]
1969
+ seg_1 ['top_wire' ] = dev_desc ['top_wires' ][row_idx ][1 ]
1970
+ seg_1 ['bottom_wire' ] = dev_desc ['bottom_wires' ][row_idx ][1 ]
1971
+ # gate wires
1972
+ seg_1 ['top_gate_wire' ] = [dev_desc ['top_gate_wires' ][0 ][row_idx ][1 ]]
1973
+ second_gate = dev_desc ['top_gate_wires' ][1 ][row_idx ]
1974
+ seg_1 ['top_gate_wire' ].append (second_gate )
1975
+ if second_gate :
1976
+ seg_1 ['top_gate_wire' ][1 ] = second_gate [1 ]
1977
+ seg_1 ['bottom_gate_wire' ] = [dev_desc ['bottom_gate_wires' ][0 ][row_idx ][1 ]]
1978
+ second_gate = dev_desc ['bottom_gate_wires' ][1 ][row_idx ]
1979
+ seg_1 ['bottom_gate_wire' ].append (second_gate )
1980
+ if second_gate :
1981
+ seg_1 ['bottom_gate_wire' ][1 ] = second_gate [1 ]
1982
+ # check reserved
1983
+ if (top_gate_row , s_col , seg_1 ['top_gate_wire' ][0 ]) in dev_desc ['reserved_wires' ]:
1984
+ seg_1 ['top_gate_wire' ][0 ] = None
1985
+ if (top_gate_row , s_col , seg_1 ['top_gate_wire' ][1 ]) in dev_desc ['reserved_wires' ]:
1986
+ seg_1 ['top_gate_wire' ][1 ] = None
1987
+ if (b_row , s_col , seg_1 ['bottom_gate_wire' ][0 ]) in dev_desc ['reserved_wires' ]:
1988
+ seg_1 ['bottom_gate_wire' ][0 ] = None
1989
+ if (b_row , s_col , seg_1 ['bottom_gate_wire' ][1 ]) in dev_desc ['reserved_wires' ]:
1990
+ seg_1 ['bottom_gate_wire' ][1 ] = None
1991
+
1992
+ # remove isolated segments (these are in the DSP area of -9, -9C, -18, -18C)
1993
+ if (not seg ['top_gate_wire' ][0 ] and not seg ['top_gate_wire' ][1 ]
1994
+ and not seg ['bottom_gate_wire' ][0 ] and not seg ['bottom_gate_wire' ][1 ]):
1995
+ del dev .segments [(top_gate_row , s_col , seg_idx - 4 )]
1996
+ if (not seg_1 ['top_gate_wire' ][0 ] and not seg_1 ['top_gate_wire' ][1 ]
1997
+ and not seg_1 ['bottom_gate_wire' ][0 ] and not seg_1 ['bottom_gate_wire' ][1 ]):
1998
+ del dev .segments [(top_gate_row , s_col , seg_idx )]
1999
+
2000
+ top_gate_row = b_row
2001
+
1835
2002
# These features of IO on the underside of the chip were revealed during
1836
2003
# operation. The first (normal) mode was found in a report by @LoneTech on
1837
2004
# 4/1/2022, when it turned out that the pins on the bottom edge of the GW1NR-9
@@ -2554,9 +2721,10 @@ def from_fse(device, fse, dat: Datfile):
2554
2721
fse_create_emcu (dev , device , dat )
2555
2722
fse_create_logic2clk (dev , device , dat )
2556
2723
fse_create_dhcen (dev , device , fse , dat )
2724
+ create_segments (dev , device )
2557
2725
disable_plls (dev , device )
2558
2726
sync_extra_func (dev )
2559
- set_chip_flags (dev , device );
2727
+ set_chip_flags (dev , device )
2560
2728
return dev
2561
2729
2562
2730
# get fuses for attr/val set using short/longval table
0 commit comments