Forum Discussion
Altera_Forum
Honored Contributor
21 years agoNIOS SDRAM performance
I have measured the speed of memcpy's of NIOS2. I use optimized code consisting of four consecutive READs and four consecutive write accesses. Code snippet:
while (i--) {
d0 = __builtin_ldwio(pfrom);
d1 = __builtin_ldwio(pfrom+1);
d2 = __builtin_ldwio(pfrom+2);
d3 = __builtin_ldwio(pfrom+3);
pfrom+=4;
__builtin_stwio(pto, d0);
__builtin_stwio(pto+1, d1);
__builtin_stwio(pto+2, d2);
__builtin_stwio(pto+3, d3);
pto+=4;
} Compiling this with -O3 will yields quite optimal code with four reads to different regs and for writes: movhi r7, %hiadj(1048576) # pfrom
addi r7, r7, %lo(1048576) # pfrom
movhi r6, %hiadj(1052672) # pto
addi r6, r6, %lo(1052672) # pto
movi r8, 15 # i
.L25:
ldwio r3, 0(r7) # d0, * pfrom
ldwio r4, 4(r7) # d1
ldwio r5, 8(r7) # d2
ldwio r9, 12(r7) # d3
addi r7, r7, 16 # pfrom, pfrom
stwio r3, 0(r6) # d0, * pto
stwio r4, 4(r6) # d1
stwio r5, 8(r6) # d2
stwio r9, 12(r6) # d3
addi r8, r8, -1 # i, i
cmpnei r3, r8, -1 # i
addi r6, r6, 16 # pto, pto
bne r3, zero, .L25 The transfer rates seemed too slow, so I did further investigations. It turns out that NIOS2 has a very poor SDRAM read performance because it does not perform consecutive SDRAM read accesses (but it does for write accesses). Here's a link to an oscilloscope image of a READ access: oscilloscope: sdram read (http://dziegel.free.fr/nios2/sdram_read.jpg) However, write access seems to be fine: oscilloscope: sdram write (http://dziegel.free.fr/nios2/sdram_write.jpg) Note: As you can see in the oscilloscope images, the accesses to not cross a SDRAM row (no RAS cycle between reads). Tests were performed on a NIOS 1C20 Development Kit, Project: NIOS2 full_featured. So my questions are: - What are the reasons for the slow read performance? IMHO, the read requests could be executed in the same speed than the write requests. - Will this behaviour be changed / fixed? Thank you, Dirk19 Replies
- Altera_Forum
Honored Contributor
Dirk,
Thanks for the good info. I was planning on writing the exact code you did for moving/copying SDRAM and I just assumed it would have good performance due to back to back reads. Looking at the datasheet a read should take the number of clocks you have set for CAS latency in most situations. (certainly back to back reads on the same row) I count about 12 clocks in your trace! Since SDRAM is so popular for NIOS/SOPC systems this would be an excellent place to focus efforts to increase performance. It would be nice if someone from Altera could at least comment on this topic. If Altera has no plans to improve this I would be willing to fund the improvements if anyone knows how to modify/replace the SDRAM controller. (assuming its legal to modify the SDRAM controller) Anyone know of a better SDRAM controller that is SOPC builder ready? Ken - Altera_Forum
Honored Contributor
Ken and Altera,
I guess it's not the SDRAM controller's fault, this comes from NIOS http://forum.niosforum.com/work2/style_emoticons/<#EMO_DIR#>/sad.gif . A copy using DMA does not show this behaviour, I see consecutive reads (sorry no oscilloscope image at hand). Maybe the NIOS data master implementation is suboptimal... I'd really be interested in the technical reason for these delays ;-) Dirk - Altera_Forum
Honored Contributor
Dirk,
I've definitely found the dma to be the ultimate data mover as well. While this is ok for some things, you can't for instance dma directly into registers when you need to manipulate data. I guess a work around would be to dma small work packets into a small onchip ram. Sorta like a manual cache. Unless LDW on onchip ram has the same problem as it does when reading SDRAM. Have you looked into the LD and ST to and from onchip? Ken - Altera_Forum
Honored Contributor
Ken,
I didn't look at LD and ST to onchip mem - I need memcpy performance by processor in my app - I often copy small amounts of data ~20 bytes, so the setup of a DMA ist not neglectible any more compared to the copy duration. And the SDRAM is accessed by custom components, so I really need the data in RAM (cache bypass!). What it also worries me is that this behaviour may affect performance in general, since all consecutive data reads (if you work on array or so) are affected. I'd really like to see the NIOS data master fixed http://forum.niosforum.com/work2/style_emoticons/<#EMO_DIR#>/biggrin.gif ... Dirk - Altera_Forum
Honored Contributor
Hi Dirk,
What you're seeing is the result of the Nios data master not being 'latency aware' (the instruction master is, and this allows relatively speedy instruction fetch even with a cache miss). Both master ports on the DMA controller are, and that is why Ken sees the performance he does. In a nutshell, Nios II was really designed to be as simple (small/fast) as possible and deliver best performance when things are cached. However, you raise a valid point with respect to more complex systems that have custom logic or other processors sharing memory -- as such things cannot be cached. I'll have a chat with our CPU expert to see what the penalty for adding latency awareness to the data master would be. In the mean time I have to second the opinions above for either using DMA (which sounds like something you don't want to do), or dedicating a small on-chip RAM(s) to your high-speed buffers. The onchip memories can also be dual-ported, further enhancing performance. PS: Latency aware means that an Avalon master accepts the 'readdatavalid' signal, rather than merely the 'waitrequest' signal as all masters must do. - Altera_Forum
Honored Contributor
Hello Jesse,
the main reason why we (me and my colleagues) have chosen a FPGA based solution is that we needed some custom peripherals that can share memory with a CPU http://forum.niosforum.com/work2/style_emoticons/<#EMO_DIR#>/wink.gif . Additionally, small portions of the shared data has to be copied around in memory, that's what I need memcpy performance for. And, my total shared mem is ~2MB in size, so on-chip RAM won't do http://forum.niosforum.com/work2/style_emoticons/<#EMO_DIR#>/biggrin.gif Technically, where do these 12 cycles come from? I'd expect to see 2 or 3 cycles between reads, not 12. But I see your argument (size/speed tradeoff), this is reasonable. For my application, I'd like a wizard option to choose between a small or fast data master, just as for the NIOS2 core. Dirk - Altera_Forum
Honored Contributor
Jesse,
Any progress in your talks with your CPU Expert? This is really important stuff. 2-3 cycles expected vs. 12 cycles is death for many applications. (including mine) And the biggest/scariest problem is that this info has to come out only after monumental efforts by people like Dirk. Chapter 16 "Nios II Core Implementation Details" states that the /f core is designed to "Minimize the instructions-per-cycle execution efficiency" and for "performance-critical applications ... with large amounts of code and or/data..." Then in the Instruction Execution Performance for the Nios II /f Core Table, LOAD has >1 as the number of cycles. Anyway, "large amounts of code and or/data" means SDRAM these days, and although 12 cycles is technically covered by >1, the enormous penalty for SDRAM access should at least be spelled out. What other issues like this remain un documented? We're designing real products with real money and deserve to have this information provided. We can handle the truth we just need to know what it is. Of course there is also the fact that if you want to compete (or want us customers to compete) with the NiosII processor we'll need to do much better than 12 cycles per read. Sorry if this comes across as harsh. I have all the respect and appreciation for Altera and the Nios/SOPC group and wish you all and your products the greatest possible success. And I look forward to the day when I ship a Nios based product that kicks butt. Ken - Altera_Forum
Honored Contributor
Hi all,
Regarding what Jesse said, I might be wrong but as far as I know whenever you have an Avalon master device you intend to use with Altera SDRAM controller, that respective master HAS to use the 'readdatavalid' signal. The 'waitrequest' is only used by the SDRAM controller to hold new requests from the master if there is no more room in the pipeline. In order to optimize the SDRAM access you have to be able to fill the SDRAM pipeline with requests, this means you will have to request data in advance (whether this means 'dumb', DMA-like approaches, or 'smart' techniques like cache or instruction/branch prediction). When you do random data reads, optimizing SDRAM access will require help from a operation-dedicated cache controller (which can 'predict' where your next reads will be) or a very big cache. Even if you are not changing the row address, having holes in the pipeline will cause poor performance. Now, probably an Altera guru can explain this a bit more accurately, but this is how I would explain Dirk's findings: The 12 clock cycles for a read comes from the fact that the data cache doesn't request/store words of data from the SDRAM in advance. The cache simply waits for the CPU to request a word, encounters a miss, passes it to the SDRAM controller, gets it back and passes it to the CPU. So we have probably 3 clock cycles until the request hits the Avalon bus, then we have 3 cycles till it hits the SDRAM chip, 3-4 clocks into the SDRAM (read+CAS delay), +1 clock back to the Avalon bus, +1 clock at least to the CPU, +1 clock next cached instruction, VOILA. Add 3-4 more clocks if you need to change the SDRAM row, depending of clock speed. while all this, the cpu simply waits, doing nothing else. Now it would be nice if we can fill up the pipeline so we can eliminate the wasted clocks. This can't be done unless the cache controller burst-reads some words in advance (with the added penalty if you end up not using them in the future). It also means that if you do random reads a lot you will get far worse performance, as you will get a burst-read for each access, when you need in fact only one word here and there. These issues are not Altera specific, they will happen in other systems using processors like ARM or x86 variations. The only thing different is that these will usually run the SDRAM at 133MHz or above, so the impact on performance is not so visible. With a Cyclone device, these speeds are hard to achieve. One thing Altera can do is to add burst type access to the SDRAM controller, add burst read capability on the data cache and let the user enable/disable these in SOPC Builder. This way, one user can try both approaches and decide which one fits his/her application best. Now, I have the feeling I'm forgetting something.... Oh yes, why are the writes on Dirk's example taking only one cycle each? http://forum.niosforum.com/work2/style_emoticons/<#EMO_DIR#>/rolleyes.gif Most reasonable explanation is that's because of the write-back capability in the cache. The cache controller simply stores all the requests and then commits them to the SDRAM at once, DMA-style http://forum.niosforum.com/work2/style_emoticons/<#EMO_DIR#>/wink.gif What would be interesting to see here (and we can't see on the timing graphs) is how many cycles have passed between CPU initiating the first write and the time the SDRAM gets the actual write command at the pins. Hopefully you will get more interesting details from Altera. Regards, C - Altera_Forum
Honored Contributor
Clancy,
Interesting theory but I've seen evidence to the contrary. Jesse seems to know the problem and the fact that the dma engine doesn't exhibit it pretty much proves the cpu core needn't either. 12 clocks on a 50MHz bus is 240ns. No competitive processor is going to take that long to do carefully hand coded back to back consecutive reads from PC100 SDRAM. RAS + CAS for this part should be something like 30-50ns for initial access then 1 clock per additional accesses in the same column. Like I've written before, I've seen the dma master read 480 32 bit words out of an onchip fifo and put them into SDRAM in about 485 clocks. This is writing, (and reading!) but no way is 12 clocks per read what we should expect. An interesting trace would be dma SDRAM to onchip. This would show us what Dirk's traces should look like. Ken - Altera_Forum
Honored Contributor
Clancy,
[list][*]I'm not doing random reads. My tests were performing a memcpy, these are consecutive reads. So no RAS cycle except if bank/row needs to be changed. [*]I use stwio/ldwio instructions. These are cache-bypass instructions, so the data cache must not have a performance impact. There cannot be some cycle penalty "until a rquest hits the Avalon bus". [*]There are almost no cycle penalties (I guess one or two) to get requests out to the SDRAM. You can see consecutive SDRAM writes, so all cycles necessary to get a request from NIOS to SDRAM are "hidden" in the time the SDRAM controller needs to select bank/row and initiate the write (the SDRAM controller has a pipleine that can store a few requests) [*]If a request is passed to the SDRAM, it needs one cycle to crank out the response, at least if no bank/row needs to be changed. Just put the new address on the bus, and set the control signals (RAS, CAS, CS, WE) to READ. [*]The next instruction (no matter whether it is cached or not) is already in the pipeline (which is stalled until the response arrives), so no cycle penalty to get the next instruction (at least if NIOS does not FLUSH it's pipeline, but IMO there should be no reason for it). [/list] Additionally, we are in contact with Altera support since more than 3 months about this issue (through our support here in Germany) and they still did not tell us an officical statement about the reasion / planned fix for this... http://forum.niosforum.com/work2/style_emoticons/<#EMO_DIR#>/sad.gif Dirk