tools/litex_server: fix comms import
[litex.git] / litex / tools / litex_server.py
1 #!/usr/bin/env python3
2
3 import argparse
4
5 import sys
6 import socket
7 import time
8 import threading
9
10 from litex.tools.remote.etherbone import EtherbonePacket, EtherboneRecord, EtherboneWrites
11 from litex.tools.remote.etherbone import EtherboneIPC
12
13
14 class RemoteServer(EtherboneIPC):
15 def __init__(self, comm, bind_ip, bind_port=1234):
16 self.comm = comm
17 self.bind_ip = bind_ip
18 self.bind_port = bind_port
19 self.lock = False
20
21 def open(self):
22 if hasattr(self, "socket"):
23 return
24 socket_flags = 0
25 if hasattr(socket, "SO_REUSEADDR"):
26 socket_flags = socket_flags | socket.SO_REUSEADDR
27 if hasattr(socket, "SO_REUSEPORT"):
28 socket_flags = socket_flags | socket.SO_REUSEPORT
29 self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
30 self.socket.setsockopt(socket.SOL_SOCKET, socket_flags, 1)
31 self.socket.bind((self.bind_ip, self.bind_port))
32 print("tcp port: {:d}".format(self.bind_port))
33 self.socket.listen(1)
34 self.comm.open()
35
36 def close(self):
37 self.comm.close()
38 if not hasattr(self, "socket"):
39 return
40 self.socket.close()
41 del self.socket
42
43 def _serve_thread(self):
44 while True:
45 client_socket, addr = self.socket.accept()
46 print("Connected with " + addr[0] + ":" + str(addr[1]))
47 try:
48 while True:
49 try:
50 packet = self.receive_packet(client_socket)
51 if packet == 0:
52 break
53 except:
54 break
55 packet = EtherbonePacket(packet)
56 packet.decode()
57
58 record = packet.records.pop()
59
60 # wait for lock
61 while self.lock:
62 time.sleep(0.01)
63
64 # set lock
65 self.lock = True
66
67 # handle writes:
68 if record.writes != None:
69 self.comm.write(record.writes.base_addr, record.writes.get_datas())
70
71 # handle reads
72 if record.reads != None:
73 reads = []
74 for addr in record.reads.get_addrs():
75 reads.append(self.comm.read(addr))
76
77 record = EtherboneRecord()
78 record.writes = EtherboneWrites(datas=reads)
79 record.wcount = len(record.writes)
80
81 packet = EtherbonePacket()
82 packet.records = [record]
83 packet.encode()
84 self.send_packet(client_socket, packet)
85
86 # release lock
87 self.lock = False
88
89 finally:
90 print("Disconnect")
91 client_socket.close()
92
93 def start(self, nthreads):
94 for i in range(nthreads):
95 self.serve_thread = threading.Thread(target=self._serve_thread)
96 self.serve_thread.setDaemon(True)
97 self.serve_thread.start()
98
99
100 def main():
101 print("LiteX remote server")
102 parser = argparse.ArgumentParser()
103 # Common arguments
104 parser.add_argument("--bind-ip", default="localhost",
105 help="Host bind address")
106 parser.add_argument("--bind-port", default=1234,
107 help="Host bind port")
108
109 # UART arguments
110 parser.add_argument("--uart", action="store_true",
111 help="Select UART interface")
112 parser.add_argument("--uart-port", default=None,
113 help="Set UART port")
114 parser.add_argument("--uart-baudrate", default=115200,
115 help="Set UART baudrate")
116
117 # UDP arguments
118 parser.add_argument("--udp", action="store_true",
119 help="Select UDP interface")
120 parser.add_argument("--udp-ip", default="192.168.1.50",
121 help="Set UDP remote IP address")
122 parser.add_argument("--udp-port", default=1234,
123 help="Set UDP remote port")
124
125 # PCIe arguments
126 parser.add_argument("--pcie", action="store_true",
127 help="Select PCIe interface")
128 parser.add_argument("--pcie-bar", default=None,
129 help="Set PCIe BAR")
130
131 # USB arguments
132 parser.add_argument("--usb", action="store_true",
133 help="Select USB interface")
134 parser.add_argument("--usb-vid", default=None,
135 help="Set USB vendor ID")
136 parser.add_argument("--usb-pid", default=None,
137 help="Set USB product ID")
138 parser.add_argument("--usb-max-retries", default=10,
139 help="Number of times to try reconnecting to USB")
140 args = parser.parse_args()
141
142
143 if args.uart:
144 from litex.tools.remote.comm_uart import CommUART
145 if args.uart_port is None:
146 print("Need to specify --uart-port, exiting.")
147 exit()
148 uart_port = args.uart_port
149 uart_baudrate = int(float(args.uart_baudrate))
150 print("[CommUART] port: {} / baudrate: {} / ".format(uart_port, uart_baudrate), end="")
151 comm = CommUART(uart_port, uart_baudrate)
152 elif args.udp:
153 from litex.tools.remote.comm_udp import CommUDP
154 udp_ip = args.udp_ip
155 udp_port = int(args.udp_port)
156 print("[CommUDP] ip: {} / port: {} / ".format(udp_ip, udp_port), end="")
157 comm = CommUDP(udp_ip, udp_port)
158 elif args.pcie:
159 from litex.tools.remote.comm_pcie import CommPCIe
160 pcie_bar = args.pcie_bar
161 if args.pcie_bar is None:
162 print("Need to speficy --pcie-bar, exiting.")
163 exit()
164 print("[CommPCIe] bar: {} / ".format(args.pcie_bar), end="")
165 comm = CommPCIe(args.pcie_bar)
166 elif args.usb:
167 from litex.tools.remote.comm_usb import CommUSB
168 if args.usb_pid is None and args.usb_vid is None:
169 print("Need to speficy --usb-vid or --usb-pid, exiting.")
170 exit()
171 print("[CommUSB] vid: {} / pid: {} / ".format(args.usb_vid, args.usb_pid), end="")
172 pid = args.usb_pid
173 if pid is not None:
174 pid = int(pid, base=0)
175 vid = args.usb_vid
176 if vid is not None:
177 vid = int(vid, base=0)
178 comm = CommUSB(vid=vid, pid=pid, max_retries=args.usb_max_retries)
179 else:
180 parser.print_help()
181 exit()
182
183 server = RemoteServer(comm, args.bind_ip, int(args.bind_port))
184 server.open()
185 server.start(4)
186 try:
187 import time
188 while True: time.sleep(100)
189 except KeyboardInterrupt:
190 pass
191
192 if __name__ == "__main__":
193 main()