afterburner/utils/jtag/device.py

311 lines
11 KiB
Python

# Be careful modifying this file: line ranges from it are included in docs/jtag/as.rst.
import enum
from bitarray import bitarray
__all__ = ['ATF15xxInstr', 'ATF1502ASDevice', 'ATF1504ASDevice', 'ATF1508ASDevice']
class ATF15xxInstr(enum.IntEnum):
EXTEST = 0x000
SAMPLE = 0x055
IDCODE = 0x059
ISC_READ_UES = 0x270
ISC_CONFIG = 0x280
ISC_READ = 0x28c
ISC_DATA = 0x290
ISC_PROGRAM_ERASE = 0x29e
ISC_ADDRESS = 0x2a1
ISC_LATCH_ERASE = 0x2b3
ISC_UNKNOWN = 0x2bf
BYPASS = 0x3ff
class ATF15xxDevice:
idcode = None # int
fuse_count = None # int
data_width = None # dict(range/tuple,range)
@classmethod
def word_size(cls, svf_row):
for svf_rows, svf_cols in cls.data_width.items():
if svf_row in svf_rows:
return len(svf_cols)
assert False
@staticmethod
def jed_to_svf_coords(jed_index):
raise NotImplementedError
@classmethod
def jed_to_svf(cls, jed_bits):
svf_bits = {}
for jed_index, jed_bit in enumerate(jed_bits):
svf_index = cls.jed_to_svf_coords(jed_index)
if svf_index is None: continue
svf_row, svf_col = svf_index
if svf_row not in svf_bits:
svf_bits[svf_row] = bitarray(cls.word_size(svf_row))
svf_bits[svf_row].setall(1)
svf_bits[svf_row][svf_col] = jed_bit
return svf_bits
@staticmethod
def svf_to_jed_coords(svf_row, svf_col):
raise NotImplementedError
@classmethod
def svf_to_jed(cls, svf_bits):
jed_bits = bitarray(cls.fuse_count)
jed_bits.setall(0)
for svf_row, svf_word in svf_bits.items():
for svf_col, svf_bit in enumerate(svf_word):
jed_index = cls.svf_to_jed_coords(svf_row, svf_col)
if jed_index is None: continue
jed_bits[jed_index] = svf_bit
return jed_bits
class ATF1502ASDevice(ATF15xxDevice):
idcode = 0x0150203f
fuse_count = 16808
data_width = {
range( 0, 108): range(86),
range(128, 229): range(86),
(256,): range(32),
(512,): range(4),
(768,): range(16),
}
@staticmethod
def jed_to_svf_coords(jed_index):
if jed_index in range( 0, 7680):
return 12 + (jed_index - 0) % 96, 79 - (jed_index - 0) // 96
if jed_index in range( 7680, 15360):
return 128 + (jed_index - 7680) % 96, 79 - (jed_index - 7680) // 96
if jed_index in range(15360, 16320):
return 0 + (jed_index - 15360) // 80, 79 - (jed_index - 15360) % 80
if jed_index in range(16320, 16720):
return 224 + (jed_index - 16320) % 5, 79 - (jed_index - 16320) // 5
if jed_index in range(16720, 16750):
return 224 + (jed_index - 16320) % 5, 85 - (jed_index - 16320) // 5 + 80
if jed_index in range(16750, 16782):
return 256, 31 - (jed_index - 16750)
if jed_index in range(16782, 16786):
return 512, 3 - (jed_index - 16782)
if jed_index in range(16786, 16802):
return 768, 15 - (jed_index - 16786)
if jed_index in range(16802, 16808):
return # reserved
assert False
@staticmethod
def svf_to_jed_coords(svf_row, svf_col):
if svf_row in range( 0, 12):
if svf_col in range(0, 80):
return 15360 + (svf_row - 0) * 80 + (79 - svf_col)
else:
return # always 1
if svf_row in range( 12, 108):
if svf_col in range(0, 80):
return 0 + (svf_row - 12) + (79 - svf_col) * 96
else:
return # always 1
if svf_row in range(128, 224):
if svf_col in range(0, 80):
return 7680 + (svf_row - 128) + (79 - svf_col) * 96
else:
return # always 1
if svf_row in range(224, 229):
if svf_col in range(0, 80):
return 16320 + (svf_row - 224) + (79 - svf_col) * 5
else:
return 16720 + (svf_row - 224) + (85 - svf_col) * 5
if svf_row == 256:
return 16750 + (31 - svf_col)
if svf_row == 512:
return 16782 + ( 3 - svf_col)
if svf_row == 768:
return 16786 + (15 - svf_col)
assert False
class ATF1504ASDevice(ATF15xxDevice):
idcode = 0x0150403f
fuse_count = 34192
data_width = {
range( 0, 108): range(166),
range(128, 233): range(166),
(256,): range(32),
(512,): range(4),
(768,): range(16),
}
@staticmethod
def jed_to_svf_coords(jed_index):
if jed_index in range( 0, 15360):
return 12 + (jed_index - 0) % 96, 165 - (jed_index - 0) // 96
if jed_index in range(15360, 30720):
return 128 + (jed_index - 15360) % 96, 165 - (jed_index - 15360) // 96
if jed_index in range(30720, 32640):
return 0 + (jed_index - 30720) // 160, 165 - (jed_index - 30720) % 160
if jed_index in range(32640, 34134):
return 224 + (jed_index - 32640) % 9, 165 - (jed_index - 32640) // 9
if jed_index in range(34134, 34166):
return 256, 31 - (jed_index - 34134)
if jed_index in range(34166, 34170):
return 512, 3 - (jed_index - 34166)
if jed_index in range(34170, 34186):
return 768, 15 - (jed_index - 34170)
if jed_index in range(34186, 34192):
return # reserved
assert False
@staticmethod
def svf_to_jed_coords(svf_row, svf_col):
if svf_row in range( 0, 12):
if svf_col in range(6, 166):
return 30720 + (svf_row - 0) * 160 + (165 - svf_col)
else:
return # always 1
if svf_row in range( 12, 108):
if svf_col in range(6, 166):
return 0 + (svf_row - 12) + (165 - svf_col) * 96
else:
return # always 1
if svf_row in range(128, 224):
if svf_col in range(6, 166):
return 15360 + (svf_row - 128) + (165 - svf_col) * 96
else:
return # always 1
if svf_row in range(224, 233):
if svf_col in range(0, 166):
return 32640 + (svf_row - 224) + (165 - svf_col) * 9
else:
return # always 1
if svf_row == 256:
return 34134 + (31 - svf_col)
if svf_row == 512:
return 34166 + ( 3 - svf_col)
if svf_row == 768:
return 34170 + (15 - svf_col)
assert False
class ATF1508ASDevice(ATF15xxDevice):
idcode = 0x0150803f
fuse_count = 74136
data_width = {
range( 0, 108): range(326),
range(128, 251): range(326),
(256,): range(32),
(512,): range(4),
(768,): range(16),
}
@staticmethod
def jed_to_svf_coords(jed_index):
if jed_index in range( 0, 30720):
return 12 + (jed_index - 0) % 96, 325 - (jed_index - 0) // 96
if jed_index in range(30720, 61440):
return 128 + (jed_index - 30720) % 96, 325 - (jed_index - 30720) // 96
if jed_index in range(61440, 65280):
return 0 + (jed_index - 61440) // 320, 325 - (jed_index - 61440) % 320
if jed_index in range(65280, 74082):
return 224 + (jed_index - 65280) % 27, 325 - (jed_index - 65280) // 27
if jed_index in range(74082, 74114):
return 256, 31 - (jed_index - 74082)
if jed_index in range(74114, 74118):
return 512, 3 - (jed_index - 74114)
if jed_index in range(74118, 74134):
return 768, 15 - (jed_index - 74118)
if jed_index in range(74134, 74136):
return # reserved
assert False
@staticmethod
def svf_to_jed_coords(svf_row, svf_col):
if svf_row in range( 0, 12):
if svf_col in range(6, 326):
return 61440 + (svf_row - 0) * 320 + (325 - svf_col)
else:
return # always 1
if svf_row in range( 12, 108):
if svf_col in range(6, 326):
return 0 + (svf_row - 12) + (325 - svf_col) * 96
else:
return # always 1
if svf_row in range(128, 224):
if svf_col in range(6, 326):
return 30720 + (svf_row - 128) + (325 - svf_col) * 96
else:
return # always 1
if svf_row in range(224, 251):
if svf_col in range(0, 326):
return 65280 + (svf_row - 224) + (325 - svf_col) * 27
else:
return # always 1
if svf_row == 256:
return 74082 + (31 - svf_col)
if svf_row == 512:
return 74114 + ( 3 - svf_col)
if svf_row == 768:
return 74118 + (15 - svf_col)
assert False
if __name__ == '__main__':
with open('atf1502as_svf2jed.csv', 'w') as f:
f.write('SVF ROW,SVF COL,JED\n')
for svf_rows, svf_cols in ATF1502ASDevice.data_width.items():
for svf_row in svf_rows:
for svf_col in svf_cols:
jed_index = ATF1502ASDevice.svf_to_jed_coords(svf_row, svf_col)
if jed_index is None: jed_index = 0x7fff
f.write('{},{},{}\n'.format(svf_row, svf_col, jed_index))
with open('atf1502as_jed2svf.csv', 'w') as f:
f.write('JED,SVF ROW,SVF COL\n')
for jed_index in range(ATF1502ASDevice.fuse_count):
svf_index = ATF1502ASDevice.jed_to_svf_coords(jed_index)
if svf_index is None: continue
f.write('{},{},{}\n'.format(jed_index, *svf_index))
with open('atf1504as_svf2jed.csv', 'w') as f:
f.write('SVF ROW,SVF COL,JED\n')
for svf_rows, svf_cols in ATF1504ASDevice.data_width.items():
for svf_row in svf_rows:
for svf_col in svf_cols:
jed_index = ATF1504ASDevice.svf_to_jed_coords(svf_row, svf_col)
if jed_index is None: jed_index = 0xffff
f.write('{},{},{}\n'.format(svf_row, svf_col, jed_index))
with open('atf1504as_jed2svf.csv', 'w') as f:
f.write('JED,SVF ROW,SVF COL\n')
for jed_index in range(ATF1504ASDevice.fuse_count):
svf_index = ATF1504ASDevice.jed_to_svf_coords(jed_index)
if svf_index is None: continue
f.write('{},{},{}\n'.format(jed_index, *svf_index))
with open('atf1508as_svf2jed.csv', 'w') as f:
f.write('SVF ROW,SVF COL,JED\n')
for svf_rows, svf_cols in ATF1508ASDevice.data_width.items():
for svf_row in svf_rows:
for svf_col in svf_cols:
jed_index = ATF1508ASDevice.svf_to_jed_coords(svf_row, svf_col)
if jed_index is None: jed_index = 0x1ffff
f.write('{},{},{}\n'.format(svf_row, svf_col, jed_index))
with open('atf1508as_jed2svf.csv', 'w') as f:
f.write('JED,SVF ROW,SVF COL\n')
for jed_index in range(ATF1508ASDevice.fuse_count):
svf_index = ATF1508ASDevice.jed_to_svf_coords(jed_index)
if svf_index is None: continue
f.write('{},{},{}\n'.format(jed_index, *svf_index))