Forum Discussion
Altera TSE driver and example program for lwIP (1.3.2)
After many many requests and complaints about lack of support and/or documentation for support of lwIP for the Altera TSE, I have developed a drop-in TSE driver and example program and made this available to the NIOS II community. This was done for NIOS II 8.1 SP0.01. I don't expect difficulty with version 9.x.
This is for the latest version of lwIP (the latest is as of this post) for a minimal program and HTTP server based on the http server in the lwIP contrib folder. The lwIP TSE driver uses the altera_avalon_tse driver and SGDMA as-is. There is a complete (as in 41-step) set of instructions on creating the project and example program. More information and the link to the driver is available here: http://lwip.wikia.com/wiki/available_device_drivers#lwip_1.3.2 Please direct any questions, changes for NIOS II 9.1, or comments to this thread. 12-16-2010 update: This example works with NIOS Version 10.0 with some tweaks to the procedure to create the project. Also, a lwIP 1.4 release candidate has been out for a while and it drops into this example (in place of 1.3) without changes. Bill257 Replies
- Altera_Forum
Honored Contributor
I'm not sure what to tell you. You have the hardware and 2 examples that should work (lwIP and Interniche). lwIP doesn't work. Only you can tell if Interniche does or doesn't work. If it does work, then we know to look for a difference in the interface on this board to the TSE driver. If Interniche doesn't work, there is no point looking at lwIP since it won't work either. They use the same TSE/SGDMA driver code and I know the lwIP specific code is good - others have confirmed this (plus, I use a derivative of it in shipping products).
Bill - Altera_Forum
Honored Contributor
And what about MAC Address?
Do I must to enter CORRECT MAC address or enough to enter MAC address,which is different from other MAC addresses in my subnet? - Altera_Forum
Honored Contributor
You can use the one that the dev kit will use when running e.g. the Interniche examples. If it doesn't come with a MAC address, you will have to use a temporary one but be sure to stay behind a router or directly connected to a PC. I use a real test MAC address from our block of addresses that I know is not in use locally.
Bill - Altera_Forum
Honored Contributor
Bill!
Could you give some hints how to improve throughput in lwIP-based solution? The main task of my application is transmitting constant rate bitstream (ADC data) to remote computer. Expected payload is about 100 Mbit/sec, so, to have some margin, I’d like to achieve 150 Mbit/sec UDP throughput. For experimenting I use lwIP_Example you kindly posted here + I added routine for generating UDP traffic (see udp_test.c attached; udp_test_init() is called just after IP address is assigned by DHCP, udp_test() is called repeatedly from lwIP loop in main()). I measure throughput by ‘bm’ utility from Altera's “Nios II Ethernet Acceleration Design Example”. On the moment I I have 55 MBit/sec. What improvements can be made from software side? 1) Switching from –O0 to –O3 improved bitrate from 11.5M to 55M (almost 5 times). What about other compiler options? 2) I see that lwIP code contains provisions for linking several packets into a chain. Can I benefit from this feature and how to use it? 3) What are the most performance critical parts of lwIP that can be disabled? 4) I have point-to-point link and can assume that receiver has known in advance IP and MAC. Is it possible to save on routing? 5) Any other ideas? Thank you in advance, Igor - Altera_Forum
Honored Contributor
5) to have higher udp bandwidth, you can also generate the UDP packets in hardware, as shown in this example: http://www.nioswiki.com/exampledesigns/nios2udpoffloadexample
- Altera_Forum
Honored Contributor
Igor,
This question comes up a lot on the lwIP forums. Unfortunately it often is responded to with "lwIP is lightwieght and performance is secondary", and IMO the performance part of lwIP is neglected. It could perform *way* better. However, I spent months optimizing lwIP, Altera drivers and my code to get the performance we require for the 100MHz NIOS II we're running. Without my effort our product line for this would have been canned. Out of the box performance is poor with the Altera hardware and lwIP. I will try to order this in the order of importance:- Optimize -O3 as you saw helps a lot. As difficult as it is, I debug this way. For better debugging and not a huge hit in performance, use -O1.
- Use the inline IP header checksum in lwIP (I contributed this by the way). It helps a lot.
- Do the UDP/TCP checksum in Verilog/VHDL (in hardware). If you can't, use assembly code for inet_chksum. If you can't, use the optimized (option 3) C inet_chksum. Or, simply disable UDP checksum in LWIPOPTS.h. UDP tends to drop packets, not change bytes in packets. Running with UDP checksumming disabled will not be an issue normally.
- Replace SMEMCPY with an efficient inline memory copy.
- Do the following code/data relocations:
- Put inet_chksum in onchip RAM (if you use it)
- Put ethernetif in onchip RAM
- Put ethernetif->lwipRxPbuf in onchip RAM
- Put tse in onchip RAM
- Put tse_mac_device in onchip RAM
- Use separate memory pools and put PBUF_POOL in onchip RAM
- Put netif_list and netif_default in onchip RAM
- Put pbuf_header in onchip RAM
- Put lwip_stats in onchip RAM
- Put arp_table in onchip RAM
- Put find_entry in onchip RAM
- Put etharp_send_ip in onchip RAM
- Put etharp_find_addr in onchip RAM
- Put etharp_output in onchip RAM
- Put etharp_query in onchip RAM
- Use udp_sendto_if to send UDP packets.
- Replace memcpy with a more efficient memcpy than Altera's.
- Remove the memory copy for unaligned transfers in lwip_tse_mac.c.
- Use chained SGDMA transfers.
- Don't wait for a packet to be sent - use pbuf reference counts and delete the previously sent pbuf on the next pbuf send. This removes the wait for completion of each packet sent.
- Rewrite/refactor the SGDMA driver - it's very inefficient.
- Rewrite/refactor the TSE driver - it's very inefficient.
- Altera_Forum
Honored Contributor
For the inet checksum there has to be a significant gain in defining a custom instruction that adds the two 16-bit halves of a 32 bit word together, then adds that 17 bit result to a 32 bit result.
A second version that includes a 'rotate by 8 bits' for misaligned data would also help. These would speed up a C/asm version without adding the full complexity of a full VHDL version. - Altera_Forum
Honored Contributor
Yes, true dsl - we also did a custom opcode for htonl and ntohl.
- Altera_Forum
Honored Contributor
I've a custom opcode that uses the 'B' register number to select between:
- 32 bit byte reverse - 16 bit byte reverse - 32 bit bit reverse - 16 bit bit reverse - 8 bit bit reverse It should be possible to make the supported transformations configurable in the sopc builder - to save fpga real estate, but we aren't that short of gates. I also did G.711 a-law <=> u-law in combinatorial logic, but they take about 12ns :-( - Altera_Forum
Honored Contributor
Bill!
I have tried options 2 and 3 only by now and really amazed! After I upgraded lwIP_Example with lwIP-1.4.0rc1 (LWIP_INLINE_IP_CHKSUM defined) the benchmark improved from 55M to 95M. And after I also disabled UDP checksum I got 310M!!! Daixiwen! Very interesting link! I didn't think about moving main data stream away from Nios internals before, but will surely try it now. Many thanks to all for hints and suggestions! Igor