diff options
author | Tim Newsome <tim@sifive.com> | 2021-05-07 11:49:42 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-05-07 11:49:42 -0700 |
commit | c9f43c1652c1d8abf85f3466f41ffd5ec4d911d6 (patch) | |
tree | 21306f7c8d15ad937e2e234d564e81a0e43efa86 /debug/rbb_daisychain.py | |
parent | 1b05661baa79f03830f5ddefa999dc7aaf7b1ce1 (diff) | |
download | riscv-tests-c9f43c1652c1d8abf85f3466f41ffd5ec4d911d6.zip riscv-tests-c9f43c1652c1d8abf85f3466f41ffd5ec4d911d6.tar.gz riscv-tests-c9f43c1652c1d8abf85f3466f41ffd5ec4d911d6.tar.bz2 |
Test daisy chained homogeneous spike instances. (#334)
* Test debugging multiple spikes in a daisy chain.
* Hugely speed up rbb_daisychain.
Now 2 dual-hart spikes are less than 4x slower than a single dual-hart
spike.
* WIP
* Test daisy chained homogeneous spike instances.
For OpenOCD, this means we're checking that we can talk to multiple
TAPs. Next up is heterogeneous testing.
* Enable Sv48Test.
Didn't mean to disable it with this commit.
* Test authentication again.
Another change I hadn't meant to push...
Diffstat (limited to 'debug/rbb_daisychain.py')
-rwxr-xr-x | debug/rbb_daisychain.py | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/debug/rbb_daisychain.py b/debug/rbb_daisychain.py new file mode 100755 index 0000000..b7c21e6 --- /dev/null +++ b/debug/rbb_daisychain.py @@ -0,0 +1,111 @@ +#!/usr/bin/python3 + +import argparse +import sys +import socket + +# https://github.com/ntfreak/openocd/blob/master/doc/manual/jtag/drivers/remote_bitbang.txt + +class Tap: + def __init__(self, port): + self.port = port + self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.socket.connect(("localhost", port)) + + def execute(self, commands): + sent = self.socket.send(commands) + assert len(commands) == sent + read_count = 0 + for command in commands: + if command == ord('R'): + read_count += 1 + result = b"" + while len(result) < read_count: + result += self.socket.recv(read_count - len(result)) + assert len(result) == read_count + return result + +class Chain: + def __init__(self, debug=False): + self.debug = debug + self.taps = [] + + def append(self, tap): + self.taps.append(tap) + + def execute(self, commands): + values = [] + for i, tap in enumerate(self.taps): + tmp_commands = [] + for command in commands: + if i > 0 and ord('0') <= command <= ord('7'): + # Replace TDI with the value from the previous TAP. + v = values.pop(0) + command &= 0xfe + if v == ord('1'): + command |= 1 + + if i < len(self.taps) - 1: + if command != ord('R'): + tmp_commands.append(command) + if ord('0') <= command <= ord('7'): + # Read TDO before every scan. + tmp_commands.append(ord('R')) + else: + tmp_commands.append(command) + assert len(values) == 0 + values = list(tap.execute(bytes(tmp_commands))) + if self.debug: + sys.stdout.write(" %d %r -> %r\n" % (i, bytes(tmp_commands), + bytes(values))) + return bytes(values) + +def main(): + parser = argparse.ArgumentParser( + description='Combine multiple remote_bitbang processes into a ' + 'single scan-chain.') + parser.add_argument("listen_port", type=int, + help="port to listen on") + parser.add_argument("tap_port", nargs="+", type=int, + help="port of a remote_bitbang TAP to connect to") + parser.add_argument("--debug", action='store_true', + help="Print out debug messages.") + args = parser.parse_args() + + server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + server.bind(("localhost", args.listen_port)) + server.listen(1) + + chain = Chain(args.debug) + for port in args.tap_port: + chain.append(Tap(port)) + + sys.stdout.write("Listening on port %d.\n" % server.getsockname()[1]) + sys.stdout.flush() + + while True: + (client, _) = server.accept() + + while True: + try: + commands = client.recv(4096) + except (ConnectionResetError, OSError): + sys.stdout.write("Client disconnected due to exception.\n") + break + + if len(commands) == 0: + sys.stdout.write("Client disconnected.\n") + break + + if args.debug: + sys.stdout.write("%r\n" % commands) + result = chain.execute(commands) + if args.debug: + sys.stdout.write(" -> %r\n" % result) + client.send(result) + + client.close() + sys.stdout.flush() + +if __name__ == '__main__': + sys.exit(main()) |