Shop OBEX P1 Docs P2 Docs Learn Events
How does fcache work? — Parallax Forums

How does fcache work?

SRLMSRLM Posts: 5,045
edited 2013-01-25 16:40 in Propeller 1
Exactly what the title says. I think I've run into a bug when using fcache and cmm together, and I'm trying to hunt it down. Basically, the bug only exists when both the -fcache and -mcmm flags are defined. I've run into this several times before, and IIRC it's always with loops. I've ignored it before by manually unrolling the loop, but I'm peeved enough now to try and hunt it down.

So, I would like to try and come up with a small program that reproduces the possible bug, but I don't know on what criteria a loop in CMM is put into fcache. Where can I find that sort of thing out?


ps: On my current code, this is the snippet that is causing problems:
while(format[stringIndex] >= '0' and format[stringIndex] <= '9'){
	paddingBuffer[paddingIndex++] = format[stringIndex];
//	printf("+%c+", format[stringIndex]);				
	stringIndex++;
}

It should end up coping one char array to another. It seems to loop the correct amount of times, but it doesn't seem to copy the bytes correctly. I say "seem" because it's really difficult to diagnose: adding certain printf statements (both inside and outside the loop) "fixes" the problem, and it doesn't hang.

pps: the optimization level doesn't seem to matter: I used the pragma option, and it changed the amount it was wrong by, but no the wrongness.

Comments

  • Christof Eb.Christof Eb. Posts: 1,201
    edited 2013-01-23 03:37
    Hi,
    - I am looking forward to an answer of one of the cracks...
    Meanwhile I can recomment to have a look at the pasm compiler output. There you can see, if a part of a routine is in the fcache. The part of the code will be first loaded into cog ram and then be executed.
    As far as I know:
    A loop can be fcached, if it fits into the cache and if it has no function calls in it. If you use a function like printf(), the loop cannot be in the cache.
    My experience with fcache and lmm and cmm was so far, that it worked.
    Good Luck, Christof
  • ersmithersmith Posts: 6,054
    edited 2013-01-23 12:56
    SRLM wrote: »
    So, I would like to try and come up with a small program that reproduces the possible bug, but I don't know on what criteria a loop in CMM is put into fcache. Where can I find that sort of thing out?
    There's some documentation in gcc.pdf, and some in the Memory.html file in propgcc/docs, but I don't think there's any one place that pulls together all the information about fcache. That's an unfortunate oversight :-(.

    The rules for what goes into fcache are:

    (1) Fcache is only active if compiling with -mfcache (which is implied by -O2 and above, and by -Os in LMM mode). -mno-fcache always disables it.
    (2) A loop cannot go into fcache if it is bigger than the fcache size (512 bytes in LMM mode, 256 in other modes).
    (3) A loop cannot go into fcache if it contains any branches, including subroutine calls, outside of itself. There is a special provision for recursive functions: see below.
    (4) If a loop does contain recursive calls (only) then the compiler checks to see if the entire function can be placed into fcache. The rules for this are pretty much the same as for an individual loop: the function has to be small enough, and cannot contain any calls or branches outside of itself.
    (5) If a function is marked as __attribute__((fcache)) then the compiler will try to put the whole function into fcache, following the rules in (4). This is true even if the function is not recursive.

    I'd certainly be interested to see if you can figure out what's going on with your bug. My guess off-hand is that the assembler is probably translating one of the CMM mode instructions incorrectly inside the FCACHE region. It's supposed to automatically convert compressed instructions into normal ones, but something may be going wrong there.

    Thanks,
    Eric
  • SRLMSRLM Posts: 5,045
    edited 2013-01-24 22:00
    Hi Eric, maybe you can help with this (or anybody else who is interested, for that matter). I haven't been able to isolate the looping problem, but I have found another interesting problem:
    Using -mno-fcache freezes the program
    This seems to happen in CMM mode with -Os and -O0, and it happens in LMM mode in -Os but not -O0.

    I've attached the offending program. You should be able to run it on any Propeller board with 64kB EEPROM. Download with:
    propeller-load -r -t460800 main.elf
    

    A successful start is
    Configuration Utility!
    
    --------------------------
    
    Current unit number:   73
    Current board version: 0xB2
    Current RTC clock is: 200-0-0 at 0:0:0
    
    --------------------------
    
    Please enter the unit number or * to keep current number, then <enter>:
    

    An unsuccessful run freezes after the "!" mark in the welcome message.

    I have noticed this problem (namely that -O0 in CMM mode freezes programs), but I've never been able to be relatively sure that it was a problem with the compiler and not my code. I'm fairly confident in this code, however, so I've posted it here.
  • ersmithersmith Posts: 6,054
    edited 2013-01-25 05:02
    I don't see the attachment... did you forget it, or am I missing something obvious?

    In CMM mode "-Os" and "-Os -mno-fcache" should be completely identical (fcache code cannot be compressed, so asking for size optimization in CMM also turns off fcache). Also, "-O0" and "-O0 -mno-fcache" should be identical in all cases, since fcache is only enabled when optimization is.

    Or perhaps I'm not understanding:
    Using -mno-fcache freezes the program
    This seems to happen in CMM mode with -Os and -O0, and it happens in LMM mode in -Os but not -O0.

    The only one of these cases where -mno-fcache should have any affect on the compiler is LMM -Os.

    Eric
  • SRLMSRLM Posts: 5,045
    edited 2013-01-25 09:49
    ersmith wrote: »
    I don't see the attachment... did you forget it, or am I missing something obvious?

    My fault. It should be attached to post #4 now.
  • ersmithersmith Posts: 6,054
    edited 2013-01-25 12:52
    I think the problem may be in the i2c class. There are some waitcnt(CNT + halfCycle) calls in there, where halfCycle is 60. 60 cycles is only 15 instructions; in CMM mode, I think it's very possible that the expansion of the waitcnt function itself may take longer than that, particularly if optimization is turned off. This would cause the waitcnt to wait until CNT rolled over, something like 54 seconds. When I changed the value of halfCycle to 600 (ridiculously high, of course, but certain to be long enough) the hang went away for me.

    Eric
  • SRLMSRLM Posts: 5,045
    edited 2013-01-25 16:40
    Ah, good call. I forgot about that minimum count. Thank you for not getting too mad at me :)
Sign In or Register to comment.