CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Duff's device
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
shimpossible



Joined: 27 Aug 2018
Posts: 6

View user's profile Send private message

Duff's device
PostPosted: Tue Sep 11, 2018 8:01 pm     Reply with quote

There is this handy loop unrolling trick call a Duff's device
https://en.wikipedia.org/wiki/Duff%27s_device

It seems the CCS compiler doesn't support this. I get the error
"Error#51 A numeric expression must appear here." on the 2nd case
As far as I can tell its because the case statement is inside the do/while braces. All the case statements are constants so the error doesn't make sense.

Does the compiler just not support the nested case statements?
Ttelmah



Joined: 11 Mar 2010
Posts: 19495

View user's profile Send private message

PostPosted: Wed Sep 12, 2018 12:33 am     Reply with quote

No. CCS supports this fine.
Your problem I think is the variable declaration. Remember a 'short' in CCS C, is an int1, and you can't construct pointers to an int1.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Sep 12, 2018 6:35 pm     Reply with quote

Ttelmah, I converted it to CCS and it didn't compile.

I got these errors:
Quote:

*** Error 51 "PCH_test.c" Line 14(5,9): A numeric expression must appear here
*** Error 51 "PCH_test.c" Line 15(5,9): A numeric expression must appear here
*** Error 51 "PCH_test.c" Line 16(5,9): A numeric expression must appear here
*** Error 51 "PCH_test.c" Line 17(5,9): A numeric expression must appear here
*** Error 51 "PCH_test.c" Line 18(5,9): A numeric expression must appear here
*** Error 51 "PCH_test.c" Line 19(5,9): A numeric expression must appear here
*** Error 51 "PCH_test.c" Line 20(5,9): A numeric expression must appear here
7 Errors, 0 Warnings.
Build Failed.


Test program:
Code:

#include <18F46K22.h>
#fuses INTRC_IO, NOWDT
#use delay(clock=4M)

 
void send(int8 *to, int8 *from, int8 count)
{
int8 n;

n = (count + 7) / 8;

switch (count % 8) {
    case 0: do { *to = *from++;
    case 7:      *to = *from++;
    case 6:      *to = *from++;
    case 5:      *to = *from++;
    case 4:      *to = *from++;
    case 3:      *to = *from++;
    case 2:      *to = *from++;
    case 1:      *to = *from++;
            } while (--n > 0);
    }
}

//=========================================
void main()
{

while(TRUE);
}


Ttelmah



Joined: 11 Mar 2010
Posts: 19495

View user's profile Send private message

PostPosted: Fri Sep 14, 2018 1:30 am     Reply with quote

Yes. It is spotting that you are meeting the opening bracket only in the first case, so complains from there. You can though just use the unwrapped version:
Code:

#include <18F46K22.h>
#fuses INTRC_IO, NOWDT
#use delay(clock=4M)

void send(int8 *to, int8 *from, int8 count)
{
    int8 n;

    n = (count + 7) / 8;
    switch (count % 8) {
        case 0: *to = *from++;
        case 7: *to = *from++;
        case 6: *to = *from++;
        case 5: *to = *from++;
        case 4: *to = *from++;
        case 3: *to = *from++;
        case 2: *to = *from++;
        case 1: *to = *from++;
    }
    while (--n > 0) {
        *to = *from++;
        *to = *from++;
        *to = *from++;
        *to = *from++;
        *to = *from++;
        *to = *from++;
        *to = *from++;
        *to = *from++;
    }
}

//=========================================
void main()
{
   int8 dest;
   int8 source[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
   
   send(&dest, source, 16);
   while(TRUE);
}

Does what it is meant to.
Ttelmah



Joined: 11 Mar 2010
Posts: 19495

View user's profile Send private message

PostPosted: Fri Sep 14, 2018 9:14 am     Reply with quote

Though breaking a rule (avoid goto if possible...), this compiles and gives more efficient code:
Code:

send(int8 *to, int8 *from, int8 count)
{
        int8 n=(count+7)/8;
        switch(count%8){
        case 0:     
do_label:  *to = *from++;
        case 7:               
           *to = *from++;
        case 6:               
           *to = *from++;
        case 5:               
           *to = *from++;
        case 4:               
           *to = *from++;
        case 3:               
           *to = *from++;
        case 2:               
           *to = *from++;
        case 1:               
           *to = *from++;
           if (--n>0)
              goto do_label;
        }
}


Probably the best that can be generated. Smile
shimpossible



Joined: 27 Aug 2018
Posts: 6

View user's profile Send private message

PostPosted: Sat Sep 15, 2018 4:51 am     Reply with quote

Its not breaking the rule, since you can't avoid it.

It seems CCS is not ANSI compliant with respect to switch statements. oh well, at least there are work arounds
temtronic



Joined: 01 Jul 2010
Posts: 9221
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sat Sep 15, 2018 5:04 am     Reply with quote

rules were made to be broken Very Happy

using goto is fine by me, afterall it IS in the PIC instructin set. Smile

and ...
CCS was never ever 100% ANSI compliant, Don't think any compiler or language is or can be.
Ttelmah



Joined: 11 Mar 2010
Posts: 19495

View user's profile Send private message

PostPosted: Sat Sep 15, 2018 12:30 pm     Reply with quote

You will find quite a few other threads online with people having problems compiling this with other compilers. CCS is not alone in not permitting this.
It works under the key that switch components may contain any statement (correct). However it is failing here because the do itself contains only some cases, with the opening and closing brackets of the do statement not guaranteed to be met in all code paths. Now whether this is allowed is indeterminate, so it is probably fair to not allow it.
The goto is a sensible solution to this, and since it does not go outside a function (this is where goto becomes dangerous, since it can then leave the stack unbalanced), should be fine. Very Happy
jeremiah



Joined: 20 Jul 2010
Posts: 1345

View user's profile Send private message

PostPosted: Sat Sep 15, 2018 9:19 pm     Reply with quote

shimpossible wrote:
Its not breaking the rule, since you can't avoid it.

It seems CCS is not ANSI compliant with respect to switch statements. oh well, at least there are work arounds


You are correct. This is part of ANSI C but not supported by the CCS compiler at this time. In fact, when I implemented protothreads for CCS, I was unable to use the duff's based version and had to use something more similar to the gcc extension version (which CCS does support). This doesn't help with loop unrolling, but just extra info.

You might try tossing an email to CCS support and see if they would be willing to add it. It has definite uses.
Ttelmah



Joined: 11 Mar 2010
Posts: 19495

View user's profile Send private message

PostPosted: Sun Sep 16, 2018 12:26 am     Reply with quote

It's actually a very questionable 'is it legal' thing.... That you can have the switch containing a 'do' like this is explicitly 'legal'. However the issue is if you arrive with a starting value that could result in you not getting to 'case 0', is not. In this case you would get to the 'while' without ever meeting the 'do'. Duff's original comment on this was 'it works' (which it did on the PDP C), but whether is is (or should be) 'allowed' is questionable!. If your compiler's parser actually verifies that the do/while components must always be matched, it'll fail.
As it stands this makes it 'not guaranteed' to be legal. but legal in most C's....
The 'while' treatment is not an explicit part of ANSI C compliance. The 'do' treatment though is. Now which is actually causing the compiler to complain is questionable here. So whether the handling is ANSI compliant would take a lot of checking to verify.... Sad
If I remember Duff did do a version that put the 'do' outside case 0 to deal with this explicitly, because he foresaw that compilers might not like this. Might be worth seeing if this is around somewhere and whether this compiles with the CCS compiler?. If it does it'll throw light on what is failing.
Ttelmah



Joined: 11 Mar 2010
Posts: 19495

View user's profile Send private message

PostPosted: Sun Sep 16, 2018 1:49 pm     Reply with quote

Yes, I found the version he published when making some comments about this. It translates as:
Code:

void send(int8 *to, int8 *from, int8 count)
{
   int8 n, r;

   n = (count + 7) / 8;
   r=count % 8;
   if (r==0)
      do {
   switch (r) {
         case 0:      *to = *from++;
         case 7:      *to = *from++;
         case 6:      *to = *from++;
         case 5:      *to = *from++;
         case 4:      *to = *from++;
         case 3:      *to = *from++;
         case 2:      *to = *from++;
         case 1:      *to = *from++;
      }
   } while (--n > 0);
}

This compiles correctly.

This shows that the fault with CCS here is that it is not accepting the 'do{' inside the switch, which is required behaviour in ANSI...
jeremiah



Joined: 20 Jul 2010
Posts: 1345

View user's profile Send private message

PostPosted: Fri Sep 28, 2018 12:41 pm     Reply with quote

EDIT: I know you already addressed this Ttelmah, just adding some additional info.

Ttelmah wrote:
It's actually a very questionable 'is it legal' thing....


It's definitely legal in both C and C++. The language subcommittees reviewed it and decided it was legal.

It wasn't intentional, but once they saw it didn't violate any of the rules of the standard they left it legal.

Here's an old interview with the creator of Duff's Device:
https://www.lysator.liu.se/c/duffs-device.html

They are referring to the original version where the do is after CASE 0. Remember that cases do not provide scope in C or C++ so they cannot forbid partial scopes between cases. A switch statement's scope starts before the cases and ends after the cases, but inbetween is all the same scope, so CASE0 and CASE1 share the same scope.
Ttelmah



Joined: 11 Mar 2010
Posts: 19495

View user's profile Send private message

PostPosted: Fri Sep 28, 2018 1:39 pm     Reply with quote

Not quite.
The question that was initially raised was whether it was legal to have the do statement start in a switch like this. They decided this was legal.
However it was also observed that because of the way it can operate, it is possible to reach the terminating condition without having met the initial condition. It should not happen with legitimate count values, but could. They observed that a compiler that implemented a test for this could refuse the code, and it was legitimate for it to do so.....

This then was why I had to prove 'which part' was making CCS fail. It _is_ the part that should be legal.....
Darren Rook



Joined: 06 Sep 2003
Posts: 287
Location: Milwaukee, WI

View user's profile Send private message Send e-mail

PostPosted: Mon Jul 13, 2020 9:13 am     Reply with quote

FYI - this has been fixed by CCS a few months ago and is legal now.
_________________
I came, I saw, I compiled.
Ttelmah



Joined: 11 Mar 2010
Posts: 19495

View user's profile Send private message

PostPosted: Mon Jul 13, 2020 9:33 am     Reply with quote

Thanks for the update Darren. Smile
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group