From f10f9246dd82063d1f9d29fab880047d7cc38393 Mon Sep 17 00:00:00 2001 From: Pradeep2004 <78598837+Pradeep2004@users.noreply.github.com> Date: Fri, 30 Apr 2021 17:45:16 +0200 Subject: [PATCH 01/11] Create Readme Debugging Murax SoC without JTAG adapter --- Readme | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 Readme diff --git a/Readme b/Readme new file mode 100644 index 0000000..4fa5265 --- /dev/null +++ b/Readme @@ -0,0 +1,74 @@ +1. INTRODUCTION + +The traditional way of debugging an SoC which is programmed inside a FPGA was by using a JTAG Adapter which comes with an FTDI Chip. In recent times, modern FPGA’s come with an integrated FTDI chip which makes debugging easy with only a USB cable. + +In this document, I am going to guide you through the steps in an experiment which I conducted along with my supervisor to debug an SoC named MURAX without using an external JTAG adapter on ARTY A7 FPGA. + +2. Generation of Bscane2 within Murax SoC in Linux + +The BSCANE2 allows access between the internal FPGA logic and the JTAG Boundary Scan logic controller. This allows for communication between the internal running design and the dedicated JTAG pins of the FPGA. + +2.1 Steps to create Bscane2 + +• After cloning all the files from https://github.com/SpinalHDL/VexRiscv, go to this path : src/main/scala/vexriscv/demo and find the Murax.scala file. + +• Comment out these lines to remove the toplevel jtag I/O pins: + Line 165, Line 395 to 397, Line 410 to 403 + +• In the Murax.scala file, delete line number 253 and add the following lines : + val jtagCtrl = JtagTapInstructionCtrl() + val tap = jtagCtrl.fromXilinxBscane2(userId = 2) + jtagCtrl <> plugin.io.bus.fromJtagInstructionCtrl(ClockDomain(tap.TCK)) + +• Add the following import statement at the beginning in Murax.scala : +import spinal.lib.com.jtag.JtagTapInstructionCtrl + +• Then to generate the SoC with a demo program already in ram, run: +sbt "runMain vexriscv.demo.MuraxWithRamInit" + +• A verilog file will be generated with the name Murax.v and four .bin files will be generated inside VexRiscv folder which can be used to program the FPGA. Inside the Murax.v file, we can see that the Bscane2 ports will be instantiated, confirming that the Bscane2 has been created within the Murax SoC to debug it. +  +3. Programming Arty A7 FPGA + +There are many applications to program a FPGA. I am using Xilinx Vivado 2020 Application to program the FPGA. + +3.1 Steps involved to program the FPGA + +• Create a new project and choose the board which are using and choose the constraint file. + +• As, I mentioned in the previous section a verilog file and four .bin files will be generated in the Vexriscv folder. Copy these files and paste them inside your vivado project in this path : project_name.srcs\sources_1\imports\Downloads + +• Create a toplevel file by instantiating Murax I/O ports in it to blink the LED’s on the FPGA. (Note : The program to blink the LED’s is already present in Murax.v file). The toplevel file and constraint file, if required can be found here : https://github.com/SpinalHDL/VexRiscv/tree/master/scripts/Murax/arty_a7 , but make sure all the jtag ports of Murax are commented or deleted in the toplevel file. + +• Next, click Generate Bitstream and program the FPGA with the bit file. You can see the LED’s blink and Murax SoC has been programmed into the FPGA. + +4. Debugging via OpenOCD GDB in Linux + +• In a new terminal in Linux, after cloning and setting up openocd with the steps provided in this link : https://github.com/SpinalHDL/openocd_riscv , run the below command to establish a openocd connection with Jtag of FPGA. +• To run openocd : +Use the below command : +src/openocd -c "set CPU0_YAML ..VexRiscv/cpu0.yaml" -f tcl/interface/usb_connect.cfg -f tcl/interface/soc_init.cfg + +• You basically have to provide 2 files. +usb_connect.cfg => interface configuration +soc_init.cfg => take over the control of the CPU + +• For usb_connect.cfg +you can take it from https://github.com/SpinalHDL/SaxonSoc/blob/dev-0.3/bsp/digilent/ArtyA7SmpLinux/openocd/usb_connect.cfg (without modifications i would say) + + +• For soc_init.cfg +https://github.com/SpinalHDL/SaxonSoc/blob/dev-0.3/bsp/digilent/ArtyA7SmpLinux/openocd/soc_init.cfg +You can take it but you need to : set cpu_count to 1 and remove Line 22 to 35. + +• Then, after openocd is running, in new terminal, follow the below commands in VexriscvSocSoftware folder ( https://github.com/SpinalHDL/VexRiscvSocSoftware ). + +• Go to the path VexRiscvSocSoftware/projects/murax/demo/build and then give the below commands : + + riscv64-unknown-elf-gdb demo.elf + target remote localhost:3333 + monitor reset halt + load + continue + +• After giving the monitor reset halt command you can see that the LED’s stop blinking and when the continue command is given the LED’s start continuing from the point where they stopped. From ff2b7c64a493764745b700ef23f7087ce1e5530d Mon Sep 17 00:00:00 2001 From: Pradeep2004 <78598837+Pradeep2004@users.noreply.github.com> Date: Fri, 30 Apr 2021 17:46:16 +0200 Subject: [PATCH 02/11] Debugging Murax SoC without JTAG Adapter --- Readme | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Readme b/Readme index 4fa5265..08fc96b 100644 --- a/Readme +++ b/Readme @@ -51,7 +51,7 @@ src/openocd -c "set CPU0_YAML ..VexRiscv/cpu0.yaml" -f tcl/interface/usb_connect • You basically have to provide 2 files. usb_connect.cfg => interface configuration -soc_init.cfg => take over the control of the CPU +soc_init.cfg => take over the control of the CPU. • For usb_connect.cfg you can take it from https://github.com/SpinalHDL/SaxonSoc/blob/dev-0.3/bsp/digilent/ArtyA7SmpLinux/openocd/usb_connect.cfg (without modifications i would say) From d15f358b44fe11e405e91f0846f109d61156fcc7 Mon Sep 17 00:00:00 2001 From: Pradeep2004 <78598837+Pradeep2004@users.noreply.github.com> Date: Fri, 30 Apr 2021 22:35:41 +0200 Subject: [PATCH 03/11] Update Readme --- Readme | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Readme b/Readme index 08fc96b..b4b223a 100644 --- a/Readme +++ b/Readme @@ -12,8 +12,14 @@ The BSCANE2 allows access between the internal FPGA logic and the JTAG Boundary • After cloning all the files from https://github.com/SpinalHDL/VexRiscv, go to this path : src/main/scala/vexriscv/demo and find the Murax.scala file. -• Comment out these lines to remove the toplevel jtag I/O pins: - Line 165, Line 395 to 397, Line 410 to 403 +• Comment out the following lines to remove the toplevel jtag I/O pins in Murax.scala file + val jtag = slave(Jtag()) + val jtagClkBuffer = SB_GB() + jtagClkBuffer.USER_SIGNAL_TO_GLOBAL_BUFFER <> io.jtag_tck + jtagClkBuffer.GLOBAL_BUFFER_OUTPUT <> murax.io.jtag.tck + murax.io.jtag.tdi <> io.jtag_tdi + murax.io.jtag.tdo <> io.jtag_tdo + murax.io.jtag.tms <> io.jtag_tms • In the Murax.scala file, delete line number 253 and add the following lines : val jtagCtrl = JtagTapInstructionCtrl() From 334df7010cfdc6359155e1658addb5ce0c9e1da9 Mon Sep 17 00:00:00 2001 From: Pradeep2004 <78598837+Pradeep2004@users.noreply.github.com> Date: Fri, 30 Apr 2021 22:37:26 +0200 Subject: [PATCH 04/11] debugging Murax SoC without Jtag Adapter --- Readme | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Readme b/Readme index b4b223a..6ebb306 100644 --- a/Readme +++ b/Readme @@ -67,7 +67,7 @@ you can take it from https://github.com/SpinalHDL/SaxonSoc/blob/dev-0.3/bsp/digi https://github.com/SpinalHDL/SaxonSoc/blob/dev-0.3/bsp/digilent/ArtyA7SmpLinux/openocd/soc_init.cfg You can take it but you need to : set cpu_count to 1 and remove Line 22 to 35. -• Then, after openocd is running, in new terminal, follow the below commands in VexriscvSocSoftware folder ( https://github.com/SpinalHDL/VexRiscvSocSoftware ). +• Then, after openocd is running, in new terminal, follow the below commands in VexriscvSocSoftware folder ( https://github.com/SpinalHDL/VexRiscvSocSoftware ) • Go to the path VexRiscvSocSoftware/projects/murax/demo/build and then give the below commands : From fb8694aa8d722670403f6eebe392c147c4eedec2 Mon Sep 17 00:00:00 2001 From: Pradeep2004 <78598837+Pradeep2004@users.noreply.github.com> Date: Fri, 30 Apr 2021 22:43:37 +0200 Subject: [PATCH 05/11] Create nativeJtag --- doc/nativeJtag | 1 + 1 file changed, 1 insertion(+) create mode 100644 doc/nativeJtag diff --git a/doc/nativeJtag b/doc/nativeJtag new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/doc/nativeJtag @@ -0,0 +1 @@ + From d72e9fad3f41995fa54ba2677df8b7181fa4ddaa Mon Sep 17 00:00:00 2001 From: Pradeep2004 <78598837+Pradeep2004@users.noreply.github.com> Date: Fri, 30 Apr 2021 22:44:22 +0200 Subject: [PATCH 06/11] Delete nativeJtag --- doc/nativeJtag | 1 - 1 file changed, 1 deletion(-) delete mode 100644 doc/nativeJtag diff --git a/doc/nativeJtag b/doc/nativeJtag deleted file mode 100644 index 8b13789..0000000 --- a/doc/nativeJtag +++ /dev/null @@ -1 +0,0 @@ - From d4ab5e971b99a7919701b31f887e4b8e76e77f15 Mon Sep 17 00:00:00 2001 From: Pradeep2004 <78598837+Pradeep2004@users.noreply.github.com> Date: Fri, 30 Apr 2021 22:55:18 +0200 Subject: [PATCH 07/11] Debugging Murax SoC without using Jtag Adapter --- doc/nativeJtag/Readme | 1 + 1 file changed, 1 insertion(+) create mode 100644 doc/nativeJtag/Readme diff --git a/doc/nativeJtag/Readme b/doc/nativeJtag/Readme new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/doc/nativeJtag/Readme @@ -0,0 +1 @@ + From 6ca917b5cc5d2fd594253ea1497d8c08ee5e0490 Mon Sep 17 00:00:00 2001 From: Pradeep2004 <78598837+Pradeep2004@users.noreply.github.com> Date: Fri, 30 Apr 2021 22:56:47 +0200 Subject: [PATCH 08/11] Debugging Murax SoC without using Jtag Adapter --- doc/nativeJtag/Readme | 79 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/doc/nativeJtag/Readme b/doc/nativeJtag/Readme index 8b13789..6ebb306 100644 --- a/doc/nativeJtag/Readme +++ b/doc/nativeJtag/Readme @@ -1 +1,80 @@ +1. INTRODUCTION +The traditional way of debugging an SoC which is programmed inside a FPGA was by using a JTAG Adapter which comes with an FTDI Chip. In recent times, modern FPGA’s come with an integrated FTDI chip which makes debugging easy with only a USB cable. + +In this document, I am going to guide you through the steps in an experiment which I conducted along with my supervisor to debug an SoC named MURAX without using an external JTAG adapter on ARTY A7 FPGA. + +2. Generation of Bscane2 within Murax SoC in Linux + +The BSCANE2 allows access between the internal FPGA logic and the JTAG Boundary Scan logic controller. This allows for communication between the internal running design and the dedicated JTAG pins of the FPGA. + +2.1 Steps to create Bscane2 + +• After cloning all the files from https://github.com/SpinalHDL/VexRiscv, go to this path : src/main/scala/vexriscv/demo and find the Murax.scala file. + +• Comment out the following lines to remove the toplevel jtag I/O pins in Murax.scala file + val jtag = slave(Jtag()) + val jtagClkBuffer = SB_GB() + jtagClkBuffer.USER_SIGNAL_TO_GLOBAL_BUFFER <> io.jtag_tck + jtagClkBuffer.GLOBAL_BUFFER_OUTPUT <> murax.io.jtag.tck + murax.io.jtag.tdi <> io.jtag_tdi + murax.io.jtag.tdo <> io.jtag_tdo + murax.io.jtag.tms <> io.jtag_tms + +• In the Murax.scala file, delete line number 253 and add the following lines : + val jtagCtrl = JtagTapInstructionCtrl() + val tap = jtagCtrl.fromXilinxBscane2(userId = 2) + jtagCtrl <> plugin.io.bus.fromJtagInstructionCtrl(ClockDomain(tap.TCK)) + +• Add the following import statement at the beginning in Murax.scala : +import spinal.lib.com.jtag.JtagTapInstructionCtrl + +• Then to generate the SoC with a demo program already in ram, run: +sbt "runMain vexriscv.demo.MuraxWithRamInit" + +• A verilog file will be generated with the name Murax.v and four .bin files will be generated inside VexRiscv folder which can be used to program the FPGA. Inside the Murax.v file, we can see that the Bscane2 ports will be instantiated, confirming that the Bscane2 has been created within the Murax SoC to debug it. +  +3. Programming Arty A7 FPGA + +There are many applications to program a FPGA. I am using Xilinx Vivado 2020 Application to program the FPGA. + +3.1 Steps involved to program the FPGA + +• Create a new project and choose the board which are using and choose the constraint file. + +• As, I mentioned in the previous section a verilog file and four .bin files will be generated in the Vexriscv folder. Copy these files and paste them inside your vivado project in this path : project_name.srcs\sources_1\imports\Downloads + +• Create a toplevel file by instantiating Murax I/O ports in it to blink the LED’s on the FPGA. (Note : The program to blink the LED’s is already present in Murax.v file). The toplevel file and constraint file, if required can be found here : https://github.com/SpinalHDL/VexRiscv/tree/master/scripts/Murax/arty_a7 , but make sure all the jtag ports of Murax are commented or deleted in the toplevel file. + +• Next, click Generate Bitstream and program the FPGA with the bit file. You can see the LED’s blink and Murax SoC has been programmed into the FPGA. + +4. Debugging via OpenOCD GDB in Linux + +• In a new terminal in Linux, after cloning and setting up openocd with the steps provided in this link : https://github.com/SpinalHDL/openocd_riscv , run the below command to establish a openocd connection with Jtag of FPGA. +• To run openocd : +Use the below command : +src/openocd -c "set CPU0_YAML ..VexRiscv/cpu0.yaml" -f tcl/interface/usb_connect.cfg -f tcl/interface/soc_init.cfg + +• You basically have to provide 2 files. +usb_connect.cfg => interface configuration +soc_init.cfg => take over the control of the CPU. + +• For usb_connect.cfg +you can take it from https://github.com/SpinalHDL/SaxonSoc/blob/dev-0.3/bsp/digilent/ArtyA7SmpLinux/openocd/usb_connect.cfg (without modifications i would say) + + +• For soc_init.cfg +https://github.com/SpinalHDL/SaxonSoc/blob/dev-0.3/bsp/digilent/ArtyA7SmpLinux/openocd/soc_init.cfg +You can take it but you need to : set cpu_count to 1 and remove Line 22 to 35. + +• Then, after openocd is running, in new terminal, follow the below commands in VexriscvSocSoftware folder ( https://github.com/SpinalHDL/VexRiscvSocSoftware ) + +• Go to the path VexRiscvSocSoftware/projects/murax/demo/build and then give the below commands : + + riscv64-unknown-elf-gdb demo.elf + target remote localhost:3333 + monitor reset halt + load + continue + +• After giving the monitor reset halt command you can see that the LED’s stop blinking and when the continue command is given the LED’s start continuing from the point where they stopped. From 2a5bf9e993ba0c7089ae41c240589cd2c939d7e2 Mon Sep 17 00:00:00 2001 From: Pradeep2004 <78598837+Pradeep2004@users.noreply.github.com> Date: Fri, 30 Apr 2021 22:57:59 +0200 Subject: [PATCH 09/11] Delete Readme --- Readme | 80 ---------------------------------------------------------- 1 file changed, 80 deletions(-) delete mode 100644 Readme diff --git a/Readme b/Readme deleted file mode 100644 index 6ebb306..0000000 --- a/Readme +++ /dev/null @@ -1,80 +0,0 @@ -1. INTRODUCTION - -The traditional way of debugging an SoC which is programmed inside a FPGA was by using a JTAG Adapter which comes with an FTDI Chip. In recent times, modern FPGA’s come with an integrated FTDI chip which makes debugging easy with only a USB cable. - -In this document, I am going to guide you through the steps in an experiment which I conducted along with my supervisor to debug an SoC named MURAX without using an external JTAG adapter on ARTY A7 FPGA. - -2. Generation of Bscane2 within Murax SoC in Linux - -The BSCANE2 allows access between the internal FPGA logic and the JTAG Boundary Scan logic controller. This allows for communication between the internal running design and the dedicated JTAG pins of the FPGA. - -2.1 Steps to create Bscane2 - -• After cloning all the files from https://github.com/SpinalHDL/VexRiscv, go to this path : src/main/scala/vexriscv/demo and find the Murax.scala file. - -• Comment out the following lines to remove the toplevel jtag I/O pins in Murax.scala file - val jtag = slave(Jtag()) - val jtagClkBuffer = SB_GB() - jtagClkBuffer.USER_SIGNAL_TO_GLOBAL_BUFFER <> io.jtag_tck - jtagClkBuffer.GLOBAL_BUFFER_OUTPUT <> murax.io.jtag.tck - murax.io.jtag.tdi <> io.jtag_tdi - murax.io.jtag.tdo <> io.jtag_tdo - murax.io.jtag.tms <> io.jtag_tms - -• In the Murax.scala file, delete line number 253 and add the following lines : - val jtagCtrl = JtagTapInstructionCtrl() - val tap = jtagCtrl.fromXilinxBscane2(userId = 2) - jtagCtrl <> plugin.io.bus.fromJtagInstructionCtrl(ClockDomain(tap.TCK)) - -• Add the following import statement at the beginning in Murax.scala : -import spinal.lib.com.jtag.JtagTapInstructionCtrl - -• Then to generate the SoC with a demo program already in ram, run: -sbt "runMain vexriscv.demo.MuraxWithRamInit" - -• A verilog file will be generated with the name Murax.v and four .bin files will be generated inside VexRiscv folder which can be used to program the FPGA. Inside the Murax.v file, we can see that the Bscane2 ports will be instantiated, confirming that the Bscane2 has been created within the Murax SoC to debug it. -  -3. Programming Arty A7 FPGA - -There are many applications to program a FPGA. I am using Xilinx Vivado 2020 Application to program the FPGA. - -3.1 Steps involved to program the FPGA - -• Create a new project and choose the board which are using and choose the constraint file. - -• As, I mentioned in the previous section a verilog file and four .bin files will be generated in the Vexriscv folder. Copy these files and paste them inside your vivado project in this path : project_name.srcs\sources_1\imports\Downloads - -• Create a toplevel file by instantiating Murax I/O ports in it to blink the LED’s on the FPGA. (Note : The program to blink the LED’s is already present in Murax.v file). The toplevel file and constraint file, if required can be found here : https://github.com/SpinalHDL/VexRiscv/tree/master/scripts/Murax/arty_a7 , but make sure all the jtag ports of Murax are commented or deleted in the toplevel file. - -• Next, click Generate Bitstream and program the FPGA with the bit file. You can see the LED’s blink and Murax SoC has been programmed into the FPGA. - -4. Debugging via OpenOCD GDB in Linux - -• In a new terminal in Linux, after cloning and setting up openocd with the steps provided in this link : https://github.com/SpinalHDL/openocd_riscv , run the below command to establish a openocd connection with Jtag of FPGA. -• To run openocd : -Use the below command : -src/openocd -c "set CPU0_YAML ..VexRiscv/cpu0.yaml" -f tcl/interface/usb_connect.cfg -f tcl/interface/soc_init.cfg - -• You basically have to provide 2 files. -usb_connect.cfg => interface configuration -soc_init.cfg => take over the control of the CPU. - -• For usb_connect.cfg -you can take it from https://github.com/SpinalHDL/SaxonSoc/blob/dev-0.3/bsp/digilent/ArtyA7SmpLinux/openocd/usb_connect.cfg (without modifications i would say) - - -• For soc_init.cfg -https://github.com/SpinalHDL/SaxonSoc/blob/dev-0.3/bsp/digilent/ArtyA7SmpLinux/openocd/soc_init.cfg -You can take it but you need to : set cpu_count to 1 and remove Line 22 to 35. - -• Then, after openocd is running, in new terminal, follow the below commands in VexriscvSocSoftware folder ( https://github.com/SpinalHDL/VexRiscvSocSoftware ) - -• Go to the path VexRiscvSocSoftware/projects/murax/demo/build and then give the below commands : - - riscv64-unknown-elf-gdb demo.elf - target remote localhost:3333 - monitor reset halt - load - continue - -• After giving the monitor reset halt command you can see that the LED’s stop blinking and when the continue command is given the LED’s start continuing from the point where they stopped. From d194867b19ff9758cca4d99e8535244c27bf3719 Mon Sep 17 00:00:00 2001 From: Pradeep2004 <78598837+Pradeep2004@users.noreply.github.com> Date: Fri, 30 Apr 2021 23:14:50 +0200 Subject: [PATCH 10/11] Create usb_connect.cfg --- doc/nativeJtag/usb_connect.cfg | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 doc/nativeJtag/usb_connect.cfg diff --git a/doc/nativeJtag/usb_connect.cfg b/doc/nativeJtag/usb_connect.cfg new file mode 100644 index 0000000..09b75df --- /dev/null +++ b/doc/nativeJtag/usb_connect.cfg @@ -0,0 +1,32 @@ +if [info exists env(SPINAL_SIM)] { + set SPINAL_SIM $::env(SPINAL_SIM) +} else { + set SPINAL_SIM no +} + + + +if {$SPINAL_SIM == "yes"} { + interface jtag_tcp + set _CHIPNAME fpga_spinal + set TAP_NAME $_CHIPNAME.bridge + set _CPUTAPID 0x10001fff + jtag newtap $_CHIPNAME bridge -expected-id $_CPUTAPID -irlen 4 -ircapture 0x1 -irmask 0xF + reset_config none + adapter_khz 50000 +} else { + interface ftdi + ftdi_device_desc "Digilent USB Device" + ftdi_vid_pid 0x0403 0x6010 + ftdi_channel 0 + ftdi_layout_init 0x00e8 0x60eb + ftdi_tdo_sample_edge falling + + reset_config none + adapter_khz 50000 + + source [find cpld/xilinx-xc7.cfg] + source [find cpld/jtagspi.cfg] + + set TAP_NAME xc7.tap +} From 1470069dbd664ba711e2768bb714aac6430b81df Mon Sep 17 00:00:00 2001 From: Pradeep2004 <78598837+Pradeep2004@users.noreply.github.com> Date: Fri, 30 Apr 2021 23:15:58 +0200 Subject: [PATCH 11/11] Create soc_init.cfg --- doc/nativeJtag/soc_init.cfg | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 doc/nativeJtag/soc_init.cfg diff --git a/doc/nativeJtag/soc_init.cfg b/doc/nativeJtag/soc_init.cfg new file mode 100644 index 0000000..92d67cf --- /dev/null +++ b/doc/nativeJtag/soc_init.cfg @@ -0,0 +1,20 @@ +set cpu_count 1 + + +for {set i 0} {$i < $cpu_count} {incr i} { + target create saxon.cpu$i vexriscv -endian little -chain-position $TAP_NAME -coreid $i -dbgbase [expr $i*0x1000+0x10B80000] + vexriscv readWaitCycles 40 + vexriscv cpuConfigFile $CPU0_YAML + if {$SPINAL_SIM != "yes"} { + vexriscv jtagMapping 3 3 0 1 2 2 + } +} + +for {set i 0} {$i < $cpu_count} {incr i} { + targets saxon.cpu$i + poll_period 50 + init + soft_reset_halt +} + +puts " done"