Shop OBEX P1 Docs P2 Docs Learn Events
how to optimize const (sub-) expressions? — Parallax Forums

how to optimize const (sub-) expressions?

ManAtWorkManAtWork Posts: 2,176
edited 2020-05-29 09:34 in Propeller 2
When I pass parameters to pasm functions I often need scaling factors that are composed out of multiple sub-factors. For example
#define adcLsbPerV (65536.0 / 3.3) // ADC resolution LSBs per volt
#define sensorGain 0.1		   // current sensor output 100mV/A

void SetNomCurr (float df, float qf)
{
  ctrl.currNomD= df * (adcLsbPerV * sensorGain);
}
I thought (whishful thinking) the compiler would recognize that the expression in the brackets is constant and can be pre-calculated at compile time. But it generates all code literally, instead, producing one division and two multiplications. Since floating point operations are expensive I'd like to avoid that and try to get one multiplication, only. Of course, I could do the pre-calculation myself and write
  ctrl.currNomD= df * 1985.939393;
But that looks ugly and is not very maintenance friendly. If I took a different sensor I had to search and replace every occurance of the constant. I also tried
  const float f = adcLsbPerV * sensorGain;
  ctrl.currNomD= df * f;
But that still produces runtime code for one float div and two muls. If I use "static const" I get strange compiler errors pointing at random different locations in my code the have compiled without errors, before. I remember there is a "constexp" qualifier in C++. In Spin1 there also was "const()" to tell the compiler that a (sub-) expression can be calculated at compile time. Is there a trick I can use in Fastspin C?

Comments

  • I'll have to look at this, it sounds like a bug in fastspin. The optimizer normally does fold constant expressions, but I guess something may be broken for floating point expressions.
  • Many thanks, Eric. I promise I'll send you some donation, again. I'm still in the evaluation and learn phase and have to try out many things. As soon as there is light visible at the end of the tunnel and I can be sure that I can complete the project and come up with a working product I have some money left over...
  • I tried a workaround and defined all constant factors in a Spin file. (Float constants have worked well in the Propeller tool for P1, I remember)
    '' Config.spin2
    '' constants and definitions for Speedcube3 servo controller
    
    CON
      adcLsbPerV = 65536.0 / 3.3	' ADC resolution LSBs per volt
      adcVperLsb = 3.3 / 65536.0	' inverse
      pwmVperLsb = 1.0 / 65536.0	' PWM resolution volt per LSB (multiply with DC bus voltage)
      sensorGain = 0.1 * 6.8/10.1	' current sensor output 100mV/A, resistor divider 3k3:6k8
      adcAperLsb = adcVPerLsb / sensorGain
      currLoopGain = adcAperLsb / pwmVperLsb ' scaling factor for current PID coefficients
    
    PUB start ' dummy function, compiler doesn't like empty objects
      repeat
    
    But when I use this as an object in C I get a weird error message "Unable to handle member currloopgain" when I try to do this:
    static struct __using("Config.spin2") cfg;
    ...
      float f= cfg.currloopgain / (float)(ctrl.dcVolt);
    
  • @ManAtWork: There's a bug in handling floating point constants from Spin files in C (as you've discovered). This will be fixed in 4.2.0.

    Thanks for your support!
Sign In or Register to comment.