![]() |
JACK WHITHAM | ||
![]() |
![]() |
||
![]() |
Home -> Using VL2 |
| |||||||||||
|
The data contains the following things:User: vluser --- BEGIN VIRTUAL LAB AUTHORISATION DATA --- eNqlllmPo7oSx9/7U/TbjBSdZocQaaQLgbAFQtgCKNKInbCYPQQ+/aF75j7chyMd3bGEhV EUZuCNuQ99dGu3dmayymrcERWSKU/xpK89b/H9T6U2b9KbH+lFd/Sqt/x6ofP977phn/Ey 1gzB/Bl0bUp0ZbWTNsFc823G8CwR/I9kZ/Gqat5vkJgjrZJhB4sz2rz6nPEfJp/5/C6L/f fVZF/TjAMPIRDR9L05cfQfQxlZ+2rawJP/4Go08d2w== --- END VIRTUAL LAB AUTHORISATION DATA ---
Twisted is probably the least intuitive component of VL2, because it allows asynchronous programming, where methods typically return Deferred objects instead of results. In the words of the Twisted manual,
A twisted.internet.defer.Deferred is a promise that a function will at some point have a result.However, you do not need to understand much about Twisted in order to use VL2. Unless you use advanced features, your programs will look like typical synchronous code. Twisted becomes incredibly useful when you are writing GUI code or servers that use VL2 as a backend.
The Conch package also requires the pycrypto module.
The easiest way to use VL2 is to write a program in Python. You can also connect to VL2 using any SSH client; by entering vlab protocol commands, you can control the service directly. Equally, you can use your favourite programming language to implement an interface for the protocol. But the Python approach is easiest because the hard work has been done for you.
The first program is a skeleton that simply connects to the VL2 service. This forms the basis for all of the subsequent programs, which "fill in" detail on line 12:
Line by line, the functions of this program are as follows.1 import vlab 2 from twisted.internet import reactor, defer 3 4 @defer.inlineCallbacks 5 def Run(): 6 print 'Connecting to the board' 7 auth = vlab.loadAuthorisation("vluser.key") 8 vlf = vlab.VlabClientFactory(auth) 9 reactor.connectTCP(auth.relay_server_name, 22, vlf) 10 vl = yield vlf.getChannel() 11 yield vl.connect("s3esk") 12 13 vl.disconnect() 14 reactor.stop() 15 16 if ( __name__ == "__main__" ): 17 reactor.addSystemEventTrigger('after', 'startup', Run) 18 reactor.run()
The second program does two things: (1) connect to VL2, then (2) program a bit file onto an FPGA. If you are new to FPGAs, see a general introduction and a Xilinx product page for information specific to Xilinx FPGAs, currently the only type of FPGA device supported by VL2.
In this program, the new features are as follows:1 import vlab 2 from twisted.internet import reactor, defer 3 4 @defer.inlineCallbacks 5 def Run(): 6 print 'Loading bit file' 7 bits = file('test.bit', 'rb').read() 8 9 print 'Connecting to the board' 10 auth = vlab.loadAuthorisation("vluser.key") 11 vlf = vlab.VlabClientFactory(auth) 12 reactor.connectTCP(auth.relay_server_name, 22, vlf) 13 vl = yield vlf.getChannel() 14 yield vl.connect("s3esk") 15 16 print 'Sending bit file' 17 bid = yield vl.sendBitfile(bits) 18 print 'Bid is', bid 19 yield vl.programFPGA(0, bid) 20 print 'Done' 21 22 vl.disconnect() 23 reactor.stop() 24 25 if ( __name__ == "__main__" ): 26 reactor.addSystemEventTrigger('after', 'startup', Run) 27 reactor.run()
An exception would be raised at this point if the bit file is not valid, or if it has been generated for a different type of FPGA.
The third program connects to a UART after programming. A UART is a hardware device that sends and receives data over a serial line. The serial protocol is RS232, always with 8 bits, one stop bit, and no parity. The baud rate is selectable.
Almost all computers can use RS232, and any FPGA design can use RS232 with the addition of a small UART of its own. We could have implemented an ad-hoc protocol for communication between the FPGA design and the virtual lab, but that would be silly when a perfectly adequate serial protocol has been in use for decades. The virtual lab UART is not a high bandwidth connection. RS232 is not fast. But it is perfectly adequate for debugging designs.
In this program, the notable new feature is the use of vlab.VlabUARTProtocol() to create a Twisted Protocol object, which is passed to openUART. The Protocol represents the UART. You can give any Twisted Protocol to openUART. For some applications it may be best to write your own. But vlab.VlabUARTProtocol() already has the ability to wait for N bytes to be received, as in data = yield uart.read(N). You can use the read and write methods to control your FPGA design from Python.1 import vlab 2 from twisted.internet import reactor, defer 3 4 MESSAGE = 'Hello World' 5 6 @defer.inlineCallbacks 7 def Run(): 8 print 'Connecting to board and programming FPGA' 9 bits = file("test.bit", 'rb').read() 10 auth = vlab.loadAuthorisation("vluser.key") 11 vlf = vlab.VlabClientFactory(auth) 12 reactor.connectTCP(auth.relay_server_name, 22, vlf) 13 vl = yield vlf.getChannel() 14 yield vl.connect("s3esk") 15 bid = yield vl.sendBitfile(bits) 16 yield vl.programFPGA(0, bid) 17 18 print 'Opening UART' 19 uart = vlab.VlabUARTProtocol() 20 yield vl.openUART(0, uart) 21 22 print 'Sending a message' 23 uart.write(MESSAGE) 24 25 print 'Waiting for reply' 26 data = yield uart.read(len(MESSAGE)) 27 28 print 'Reply is:', repr(data) 29 30 vl.disconnect() 31 reactor.stop() 32 33 if ( __name__ == "__main__" ): 34 reactor.addSystemEventTrigger('after', 'startup', Run) 35 reactor.run()
Sometimes you want to interact with the design on the FPGA. One way to do that is to implement a complete application, like the EMS client, which provides whatever features you actually need for whatever it is you are doing. Of course there is no "one size fits all" solution. But many FPGA designs include CPUs, and CPUs tend to run interactive programs.
For these, you might want to interact with the FPGA design via a UART. The following example program connects to a StrongARM-based embedded system named CATS. It toggles a relay to operate the reset switch, and then opens an interactive terminal session. Once the terminal session is running, any output from CATS is echoed to the screen. Any keys pressed by the user are sent to CATS. This is not an FPGA system, hence no bit file is sent. If it was, the FPGA programming step would precede openUART as usual.
1 import vlab 2 from twisted.internet import reactor, defer 3 from vlab import terminal 4 5 @defer.inlineCallbacks 6 def Run(): 7 print 'Connecting to CATS board' 8 auth = vlab.loadAuthorisation("vluser.key") 9 vlf = vlab.VlabClientFactory(auth) 10 reactor.connectTCP(auth.relay_server_name, 22, vlf) 11 vl = yield vlf.getChannel() 12 yield vl.connect("cats") 13 yield vl.setUART(0, 115200) 14 15 print 'Pressing reset switch' 16 yield vl.setRelay(1, 1) 17 yield vl.setRelay(1, 0) 18 yield vl.setRelay(1, 1) 19 20 print 'Opening UART' 21 uart = terminal.DumbTerminal() 22 terminal.setTransport(uart) 23 yield vl.openUART(0, uart) 24 25 if ( __name__ == "__main__" ): 26 reactor.addSystemEventTrigger('after', 'startup', Run) 27 reactor.run() 28
DumbTerminal is a Python class. It can be extended to implement
more advanced features such as an escape character to exit the program
(by extending the write() method).
Your virtual lab relay server might be behind a firewall, preventing
connections from the Internet. For example, at York, the virtual
lab server is only reachable within the Computer Science Department.
In this situation, you can use a SOCKS proxy to forward connections.
VlabClientFactory objects are created slightly differently:
The EMS client is a complete virtual lab program
with a GUI.
Using SOCKS to get around firewalls
In the example, the SOCKS server is socksserver.example.com and
the port is 1080. The virtual lab client connects to the SOCKS
server and tells it to forward the connection to the virtual
lab relay server. The most common usage of this feature is probably
in conjunction with the "-D" option of an SSH client.
vlf = vlab.VlabClientFactory(auth_data=auth,
socks_connect_address=auth.relay_server_name,
socks_connect_port=22)
reactor.connectTCP('socksserver.example.com', 1080, vlf)
vl = yield vlf.getChannel()
A Complete Program
Copyright (C) Jack Whitham 1997-2011