- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The alt_dcache_flush function from the hal may not correctly flush all dirty data in the cache. Consider the case where I want to flush the contents of a video buffer that is larger than the data cache.
const alt_u32 VideoRamSize = 38400; BYTE videoRam[VideoRamSize]; alt_dcache_flush(videoRam, sizeof(videoRam)); The current hal implementation uses the flushda instruction. If the data cache size is 8k the function limits the address range that may be flushed to the first 8k of the videoRam buffer (comment: "This is the most we would ever need to flush"). If the buffer was modified beyond this range and these addresses are cached they will not be flushed. This results in a screen full of garbled pixels. I changed the hal function to use the flushd instruction as in earlier versions. Then everything works as expected. One can also comment out: len = NIOS2_DCACHE_SIZE; now flushda also works but this leads to more iterations in the for loop. Could someone explain how flushd really works? In alt_dcache_flush(void *start, alt_u32 length) flushd is passed an address and in alt_dcache_flush_all an index starting at 0. Is there a way to invalidate an address range in the cache even if it is never modified by the processor? In my case some component other than the processor continuously writes data to a memory buffer. A program running on the NIOSII reads this data for further processing. So the data is never dirty from the processor's point of view. I would like to force the processor to invalidate any cached addresses from this buffer before starting a read-out cycle. If I read the documentation correctly the flushd instruction won't work and I have to use the IORD_32DIRECT macro. Are there any recommendations what cache line size to use depending on the data cache size and application type?Link Copied
4 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi orsino,
> alt_dcache_flush(videoRam, sizeof(videoRam)); > > The current hal implementation uses the flushda instruction. If the data cache > size is 8k the function limits the address range that may be flushed to the first 8k > of the videoRam buffer (comment: "This is the most we would ever need to flush"). Sounds like a bug. Based on the documentation, flushda does recognize the tag, so alt_dcache_flush() should (must) flush the entire effective address range. > I changed the hal function to use the flushd instruction as in earlier versions. Then > everything works as expected. This makes sense ... since flushd ignores the tag, the address range (span, whatever) would be limited to the size of the dcache. > Could someone explain how flushd really works? flushd ignores the tag, flushes the line if dirty, then invalidates. The key phrase being: "ignores the tag". When you use flushd, you may end up flushing data that is not actually in the effective address range of your buffer (only the line indexes are the same). This is actually a cool feature when your I/O buffers are larger than your cache -- you save time by (more or less) flushing cache lines, rather than entire effective address ranges. flushda is new ... so my experience is with it is limited. However the docs do suggest that the tags are _not_ ignored -- when using flushda, you need to check the entire effective address range. (That's why it sounds like a bug to me). Perhaps the HAL gurus could comment on this. > Is there a way to invalidate an address range in the cache even if it is > never modified by the processor? This always bothered me. The flushd documentation states, "if the line is dirty, flushd writes the line back to memory and invalidates the line". But it doesn't state what happens if the line is _not_ dirty -- I've always assumed that the line is invalidated in either case ... but I really don't know for sure. Regards, --Scott- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This does look like a bug in alt_dcache_flush(). I'll get it fixed. The fix should be to# ifdef out the code that limits len when flushda exists. Here's what what a fixed version looks like:
void alt_dcache_flush (void* start, alt_u32 len) {# if NIOS2_DCACHE_SIZE > 0 char* i; char* end; # ifndef NIOS2_FLUSHDA_SUPPORTED /* * This is the most we would ever need to flush. */ if (len > NIOS2_DCACHE_SIZE) { len = NIOS2_DCACHE_SIZE; }# endif /* NIOS2_FLUSHDA_SUPPORTED */ end = ((char*) start) + len; for (i = start; i < end; i+= NIOS2_DCACHE_LINE_SIZE) { ALT_FLUSH_DATA(i); } /* * For an unaligned flush request, we've got one more line left. * Note that this is dependent on NIOS2_DCACHE_LINE_SIZE to be a * multiple of 2 (which it always is). */ if (((alt_u32) start) & (NIOS2_DCACHE_LINE_SIZE - 1)) { ALT_FLUSH_DATA(i); } # endif /* NIOS2_DCACHE_SIZE > 0 */ } As for the behavior of the flushd instruction when the line is not dirty, it is invalidated.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi All,
> > I would like to force the processor to invalidate any cached addresses from this > > buffer before starting a read-out cycle. > > I've always assumed that the line is invalidated in either case ... but I really don't > > know for sure. > As for the behavior of the flushd instruction when the line is not dirty, it is invalidated. And there you have it ... thanks James! ... ya gotta love this forum :-) So you can call flushd to invalidate ... regardless of the dirty state. If your buffer is larger than the cache, you'll do best just calling alt_dcache_flush_all() ... and save the extra iterations. Regards, --Scott- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi all,
In my system, I have gotten 6 buffers for splash screens, video and OSD. pOSDFrameBufferLA = (unsigned short*)alt_uncached_malloc(DUAL_VIEW_FRAME_SIZE*2 + 128); The expression above will allocate a OSD buffer which will never be cached. Nios have 4GB address space, but we can use only 2G. Because the higher 2GB is mapped to the lower 2GB. The only difference between higher 2GB and lower 2GB is that the higher 2GB will always bypass the cache. FYI http://forum.niosforum.com/work2/style_emoticons/<#EMO_DIR#>/biggrin.gif David
Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page