build/xilinx/programmer: add multi jtag devices support to VivadoProgrammer
[litex.git] / litex / build / xilinx / programmer.py
1 import os
2 import sys
3 import subprocess
4
5 from litex.build.generic_programmer import GenericProgrammer
6 from litex.build.xilinx import common
7
8
9 class XC3SProg(GenericProgrammer):
10 needs_bitreverse = False
11
12 def __init__(self, cable, flash_proxy_basename=None):
13 GenericProgrammer.__init__(self, flash_proxy_basename)
14 self.cable = cable
15
16 def load_bitstream(self, bitstream_file):
17 subprocess.call(["xc3sprog", "-v", "-c", self.cable, bitstream_file])
18
19 def flash(self, address, data_file):
20 flash_proxy = self.find_flash_proxy()
21 subprocess.call(["xc3sprog", "-v", "-c", self.cable, "-I"+flash_proxy, "{}:w:0x{:x}:BIN".format(data_file, address)])
22
23
24
25 class FpgaProg(GenericProgrammer):
26 needs_bitreverse = False
27
28 def __init__(self, flash_proxy_basename=None):
29 GenericProgrammer.__init__(self, flash_proxy_basename)
30
31 def load_bitstream(self, bitstream_file):
32 subprocess.call(["fpgaprog", "-v", "-f", bitstream_file])
33
34 def flash(self, address, data_file):
35 if address != 0:
36 raise ValueError("fpga prog needs a main bitstream at address 0")
37 flash_proxy = self.find_flash_proxy()
38 subprocess.call(["fpgaprog", "-v", "-sa", "-r", "-b", flash_proxy,
39 "-f", data_file])
40
41
42 def _run_impact(cmds):
43 with subprocess.Popen("impact -batch", stdin=subprocess.PIPE, shell=True) as process:
44 process.stdin.write(cmds.encode("ASCII"))
45 process.communicate()
46 return process.returncode
47
48
49 def _create_xsvf(bitstream_file, xsvf_file):
50 assert os.path.exists(bitstream_file), bitstream_file
51 assert not os.path.exists(xsvf_file), xsvf_file
52 assert 0 == _run_impact("""
53 setPreference -pref KeepSVF:True
54 setMode -bs
55 setCable -port xsvf -file {xsvf}
56 addDevice -p 1 -file {bitstream}
57 program -p 1
58 quit
59 """.format(bitstream=bitstream_file, xsvf=xsvf_file))
60
61
62 class iMPACT(GenericProgrammer):
63 needs_bitreverse = False
64
65 def load_bitstream(self, bitstream_file):
66 cmds = """setMode -bs
67 setCable -p auto
68 addDevice -p 1 -file {bitstream}
69 program -p 1
70 quit
71 """.format(bitstream=bitstream_file)
72 _run_impact(cmds)
73
74
75 def _run_vivado(path, ver, cmds):
76 if sys.platform == "win32" or sys.platform == "cygwin":
77 vivado_cmd = "vivado -mode tcl"
78 else:
79 settings = common.settings(path, ver)
80 vivado_cmd = "bash -c \"source " + settings + "&& vivado -mode tcl\""
81 with subprocess.Popen(vivado_cmd, stdin=subprocess.PIPE, shell=True) as process:
82 process.stdin.write(cmds.encode("ASCII"))
83 process.communicate()
84
85
86 class VivadoProgrammer(GenericProgrammer):
87 needs_bitreverse = False
88 def __init__(self, vivado_path="/opt/Xilinx/Vivado", vivado_ver=None,
89 flash_part="n25q256-3.3v-spi-x1_x2_x4"):
90 GenericProgrammer.__init__(self)
91 self.vivado_path = vivado_path
92 self.vivado_ver = vivado_ver
93 self.flash_part = flash_part
94
95 def load_bitstream(self, bitstream_file, target="", device=0):
96 cmds = """open_hw
97 connect_hw_server
98 open_hw_target {target}
99
100 set_property PROBES.FILE {{}} [lindex [get_hw_devices] {{{device}}}]
101 set_property PROGRAM.FILE {{{bitstream}}} [lindex [get_hw_devices] {{{device}}}]
102
103 program_hw_devices [lindex [get_hw_devices] {{{device}}}]
104 refresh_hw_device [lindex [get_hw_devices] {{{device}}}]
105
106 quit
107 """.format(target=target, bitstream=bitstream_file, device=device)
108 _run_vivado(self.vivado_path, self.vivado_ver, cmds)
109
110 # XXX works to flash bitstream, adapt it to flash bios
111 def flash(self, address, data_file, device=0):
112 cmds = """open_hw
113 connect_hw_server
114 open_hw_target
115 create_hw_cfgmem -hw_device [lindex [get_hw_devices] {{{device}}}] -mem_dev [lindex [get_cfgmem_parts {{{flash_part}}}] 0]
116
117 set_property PROGRAM.BLANK_CHECK 0 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices] {{{device}}} ]]
118 set_property PROGRAM.ERASE 1 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices] {{{device}}} ]]
119 set_property PROGRAM.CFG_PROGRAM 1 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices] {{{device}}} ]]
120 set_property PROGRAM.VERIFY 1 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices] {{{device}}} ]]
121 refresh_hw_device [lindex [get_hw_devices] {{{device}}}]
122
123 set_property PROGRAM.ADDRESS_RANGE {{use_file}} [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices] {{{device}}} ]]
124 set_property PROGRAM.FILES [list "{data}" ] [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices] {{{device}}}]]
125 set_property PROGRAM.UNUSED_PIN_TERMINATION {{pull-none}} [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices] {{{device}}} ]]
126 set_property PROGRAM.BLANK_CHECK 0 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices] {{{device}}} ]]
127 set_property PROGRAM.ERASE 1 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices] {{{device}}} ]]
128 set_property PROGRAM.CFG_PROGRAM 1 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices] {{{device}}} ]]
129 set_property PROGRAM.VERIFY 1 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices] {{{device}}} ]]
130
131 startgroup
132 if {{![string equal [get_property PROGRAM.HW_CFGMEM_TYPE [lindex [get_hw_devices] {{{device}}}]] [get_property MEM_TYPE [get_property CFGMEM_PART [get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices] {{{device}}} ]]]]] }} {{ create_hw_bitstream -hw_device [lindex [get_hw_devices] {{{device}}}] [get_property PROGRAM.HW_CFGMEM_BITFILE [ lindex [get_hw_devices] {{{device}}}]]; program_hw_devices [lindex [get_hw_devices] {{{device}}}]; }};
133 program_hw_cfgmem -hw_cfgmem [get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices] {{{device}}} ]]
134 endgroup
135
136 quit
137 """.format(data=data_file, flash_part=self.flash_part, device=device)
138 _run_vivado(self.vivado_path, self.vivado_ver, cmds)