System Console is a tool included in Quartus Prime that allows you to debug FPGAs via JTAG. Since you can hit registers and check values in real time from the command line, it is useful for debugging on an actual machine. Regarding how to use it, there is a Very easy-to-understand article on Macnica's page, so I will leave it to you. This article will show you how to work with the System Console from a Python program.
OS: CentOS7 (I think it works on other OS) Intel FPGA Tools: 20.1 Python: 3.6
Change the system_console_path
part of the third line of the code below to suit your environment.
import subprocess
system_console_path = '/eda/intel/20.2/quartus/sopc_builder/bin/system-console'
class altera_system_console:
def __init__(self):
sc_path = [system_console_path, '--cli', '--disable_readline']
self.console = subprocess.Popen(sc_path, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
self.cmd_count = 1
self.read_output()
def __del__(self):
self.console.terminate()
def read_output(self, print_flag=True):
if self.cmd_count == 0:
print('cmd_count is zero')
return ''
txt = ''
while True:
r = self.console.stdout.read(1)
if r == b'%':
self.console.stdout.read(1)
if print_flag:
print(txt)
break
txt += r.decode("utf8")
self.cmd_count -= 1
return txt
def cmd(self, cmd_string, print_flag=True):
self.console.stdin.write(bytes(cmd_string + '\n', 'utf-8'))
self.console.stdin.flush()
self.cmd_count += 1
return self.read_output(print_flag)
def write(self, addr, data, bits=32, print_flag=True):
if not bits in [8, 16, 32]:
print('bits is an invalid value')
return self.cmd('master_write_{} $master_path 0x{:x} 0x{:x}'.format(bits, addr, data), print_flag=print_flag)
def read(self, addr, length, bits=32, print_flag=True):
if not bits in [8, 16, 32]:
print('bits is an invalid value')
self.cmd('master_read_{} $master_path 0x{:x} 0x{:x}'.format(bits, addr, length), print_flag=print_flag)
c = altera_system_console()
This time, we'll use Python's interactive mode. Save the above code as system_console.py
and execute the following command to switch to interactive mode with system_console.py
executed to the end.
python3 -i system_console.py
If all goes well, you will see the output of the System Console.
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
Welcome to Intel's FPGA System Console
This Tcl console provides access to the hardware modules instantiated in your
FPGA. You can use System Console for all of the following purposes:
* To start, stop, or step a Nios II processor
* To read or write Avalon Memory-Mapped (Avalon-MM) slaves using special
masters
* To sample the SOPC system clock as well as system reset signal
* To run JTAG loopback tests to analyze board noise problems
* To shift arbitrary instruction register and data register values to
instantiated system level debug (SLD) nodes
In addition, the directory <QuartusII Dir>/sopc_builder/system_console/scripts
contains Tcl files that provide miscellaneous utilities and examples of how to
access the functionality provided. You can include those macros in your
scripts by issuing Tcl source commands.
--------------------------------------------------------------------------------
>>>
From this state, you can enter commands for System Console by entering c.cmd ('commands you want to enter for System Console')
.
For example, you can connect to the service (see Macnica's page (https://www.macnica.co.jp/business/semiconductor/articles/intel/134097/)) as follows. The right side of > >>
is the command you are typing, and below that is the output of the System Console.
>>> _ = c.cmd('get_service_paths master')
{/devices/10AX115H(1|2|3|4|4E3)|..@1#1-9/(link)/JTAG/(110:132 v1 #0)/phy_0/master} {/devices/10AX115H(1|2|3|4|4E3)|..@1#1-9/(link)/JTAG/(70:34 v3 #0)/nios2_0} {/devices/5M(1270ZF324|2210Z)|EPM2210@2#1-9/(link)/JTAG/(110:130 v3 #0)/jtagmem_0}
>>> _ = c.cmd('set mpath [lindex [get_service_paths master] 1]')
/devices/10AX115H(1|2|3|4|4E3)|..@1#1-9/(link)/JTAG/(70:34 v3 #0)/nios2_0
>>> _ = c.cmd('claim_service master $mpath ""')
/channels/local/(lib)/master_1
>>> _ = c.cmd('set master_path [claim_service master $mpath ""]')
/channels/local/(lib)/master_2
You can also read and write to the address in the same way.
>>> _ = c.cmd('master_read_32 $master_path 0x40000000 1')
0x22222222
>>> _ = c.cmd('master_write_32 $master_path 0x40000000 0x11111111')
>>> _ = c.cmd('master_read_32 $master_path 0x40000000 1')
0x11111111
You can also read and write to the address as shown below by adding the write
and read
methods to the altera_system_console
class.
>>> _ = c.write(0x40000004, 0x33333333)
>>> _ = c.read(0x40000000, 0x2)
0x11111111 0x33333333
>>> for i in range(10):
... _ = c.write(0x40000000 | i * 4, i, print_flag=False)
...
>>> _ = c.read(0x40000000, 0xA)
0x00000000 0x00000001 0x00000002 0x00000003 0x00000004 0x00000005 0x00000006 0x00000007 0x00000008 0x00000009
I think the following are some of the good things about debugging via Python. --Fixed work (connection to service, etc.) required when starting System Console can be described in the Python program in advance. --A series of processing required for debugging can be made into a function or a class. --You can easily write data mechanically using a for statement, or change the processing depending on the output result with an if statement. Also, in combination with the VS Code function, in VS Code, if you press Shift + Enter with the code selected, you can enter the code into the console in interactive mode, and while writing the debug command, it It is very convenient because you can check in real time in interactive mode.
Recommended Posts