title: Programming multiple devices parallelly using Vivado
body: <p>We have a setup where two Xilinx FPGA devices are individually connected to a computer. We use Vivado Tcl Console to program the FPGAs in our automation environment. I am able to successfully program the two devices one after the other. However, I am trying to reduce the programming time by launching two vivado instances in parallel and program each device simultaneously. While doing so, I get errors like below:</p>
  <pre><code>Targets(s) &quot;, jsn-JTAG-SMT2-XXXXXXXXjsn-JTAG-HS3-XXXXXXXX&quot; may be locked by another hw_server.
  
  Error Message: ERROR: [Common 17-39] 'get_hw_targets' failed due to earlier errors.
  </code></pre>
  <p>Here is my python script that launches hw_server and cs_server on different ports and programs FPGAs parallely.</p>
  <pre><code>def program(hw_server_cmd, cs_server_cmd, cmd):
      cs_server_process = subprocess.Popen(cs_server_cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, encoding='utf8')
      cs_server_process.wait()
      print(&quot;cs_server started&quot;)
  
      hw_server_process = subprocess.Popen(hw_server_cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, encoding='utf8')
      hw_server_process.wait()
      print(&quot;hw_server started&quot;)
      p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, encoding='utf8')        
      p.wait()
      stdout, stderr = p.communicate()
      p.wait()
      hw_server_process.kill()
      cs_server_process.kill()
      print('Command [{}] return value: {}'.format(cmd, p.returncode))
      print('stdout for cmd [{}]: {}'.format(cmd, stdout))
      print('stderr for cmd [{}]: {}'.format(cmd, stderr))
  
  
  if __name__ == '__main__':
      cs_server_cmd_1 = r&quot;C:\Xilinx\Vivado\2020.1\bin\cs_server.bat -d -stcp::3041&quot;
      hw_server_cmd_1 = r&quot;C:\Xilinx\Vivado\2020.1\bin\hw_server.bat -d -stcp::3121&quot;
      cmd_1 = r'C:\Xilinx\Vivado\2020.1\bin\vivado.bat -mode tcl -source ProgFPGA_1.tcl'
  
      cs_server_cmd_2 = r&quot;C:\Xilinx\Vivado\2020.1\bin\cs_server.bat -d -stcp::3042&quot;
      hw_server_cmd_2 = r&quot;C:\Xilinx\Vivado\2020.1\bin\hw_server.bat -d -stcp::3122&quot;
      cmd_2 = r'C:\Xilinx\Vivado\2020.1\bin\vivado.bat -mode tcl -source ProgFPGA_2.tcl'
  
      fpga_prog_threads = {}    
      fpga_prog_threads[0] = threading.Thread(name=f'Programming FPGA on Platform 1', target=program, args=[hw_server_cmd_1, cs_server_cmd_1,  cmd_1])
      fpga_prog_threads[1] = threading.Thread(name=f'Programming FPGA on Platform 2', target=program, args=[hw_server_cmd_2, cs_server_cmd_2, cmd_2])
      for t in fpga_prog_threads.values():
          t.start()
          #t.join()
  
      join_all_threads(list(fpga_prog_threads.values()), 3600)
  </code></pre>
  <p>Here is one of the tcl script I used. The other file also contains same set of commands but different port numbers and Serial number.</p>
  <pre><code>    open_hw_manager
      connect_hw_server -url 127.0.0.1:3121 -cs_url 127.0.0.1:3041 -allow_non_jtag
      current_hw_server 127.0.0.1:3121
  
      current_hw_target [get_hw_targets */xilinx_tcf/Digilent/XXXXXXXXXX]
      open_hw_target
  
      current_hw_device [lindex [get_hw_devices] 0]
      refresh_hw_device -update_hw_probes false [lindex [get_hw_devices] 0]
      
      set_property PROBES.FILE {} [lindex [get_hw_devices] 0]
      set_property FULL_PROBES.FILE {} [lindex [get_hw_devices] 0]
      set_property PROGRAM.FILE {C:/temp/bitfile2.bit} [lindex [get_hw_devices] 0]
      program_hw_devices [lindex [get_hw_devices] 0]
      refresh_hw_device [lindex [get_hw_devices] 0]    
      exit
  </code></pre>
  <p>Could someone point out what I am doing wrong here that is stopping me from programming the devices simultaneously?</p>
  <p>P.S: Initially we used Xilinx ISE. I tried to program the devices simultaneously using impact.exe. In that case one FPGA or the other always returned error message like &quot;Pin did not go HIGH&quot;.</p>