pcdshub / pytmc

Generate EPICS IOCs and records from TwinCAT projects - along with many TwinCAT project tools
https://pcdshub.github.io/pytmc/
Other
10 stars 11 forks source link

Nested Struct Arrays do not become PVs #271

Closed ZLLentz closed 3 years ago

ZLLentz commented 3 years ago

Fell down a rabbit hole today tracking this down- I'm not 100% sure but here's what I think is going on.

Each of our PLCs has a pragma'd instance of FB_Arbiter, which contains a pragma'd instance of FB_BeamParamAssertionPool, which contain a pragma'd array of ST_BP_ArbInternal, which inherits from ST_BeamParams, which contains a pragma'd array of ST_PMPS_Attenuator, which has a couple pragma'd fields.

Since every level is pragma'd you expect the PVs to be made e.g. the following PV should exist: PLC:LFE:MOTION:ARB:AP:Entry:001:AuxAtt:01:Att_RBV

Where the first index (001) is the array of beam parameters, and the second index (01) is the array of attenuation structs that make up the attenuation request associated with the beam parameter request. I think we've followed all the documented pytmc rules, and other PVs like PLC:LFE:MOTION:ARB:AP:Entry:001:ID_RBV do exist.

But in reality, the entire AuxAtt section defined in ST_BeamParams is dropped- the only references you can find in the wild to the AuxAtt PVs are outside of the FB_Arbiter array.

Therefore I think there's a bug (or feature) where pytmc doesn't make any PVs out of nested arrays.

I'm not sure if this specifically will be needed or not (there are probably workarounds, such as pragma-ing an array of primitives instead of an array of structs) to get a single waveform, but we do plan on adding attenuation/aperture information to the pmps diagnostic at some point.

klauer commented 3 years ago

I tried to find the cause of the specific one you mentioned here, and traced the master branch's issue back to ST_PMPS_Attenuator_IO lacking pragmas. ~(If you have a version with pragmas, I'd like to take a look at that and re-evaluate!)~. This is what lfe-motion shows in its .tmc for that data type:

    <DataType>
      <Name GUID="{7E016B85-166E-4B4F-AAC4-ECA8DDD44F13}">ST_PMPS_Attenuator_IO</Name>
      <BitSize>64</BitSize>
      <SubItem>
        <Name>nTran</Name>
        <Type GUID="{18071995-0000-0000-0000-00000000000D}">REAL</Type>
        <BitSize>32</BitSize>
        <BitOffs>0</BitOffs>
      </SubItem>
      <SubItem>
        <Name>xAttOK</Name>
        <Type GUID="{18071995-0000-0000-0000-000000000005}">UINT</Type>
        <BitSize>16</BitSize>
        <BitOffs>32</BitOffs>
      </SubItem>
      <Hides>
        <Hide GUID="{76269EAC-36F0-4513-B811-3725FD02409A}"/>
        <Hide GUID="{E96BEA56-6301-4A6A-BF6A-F08340C87594}"/>
        <Hide GUID="{FE32F9A9-7E7A-413D-8D77-0C99C34D8CD9}"/>
        <Hide GUID="{D01709AA-9B4A-464A-B4D1-4BF476CFE7DE}"/>
        <Hide GUID="{D6F0EA12-B425-4603-9C4B-B4FD442416C3}"/>
        <Hide GUID="{0FF3CAED-DFFA-453E-8BDC-2F6EE7142B14}"/>
        <Hide GUID="{AC42932A-79BD-4670-8CF2-1DDEA2EE41C7}"/>
        <Hide GUID="{EE241488-3DC7-4C48-A9D8-BB32379587BC}"/>
        <Hide GUID="{EE241488-3DC7-4C48-A9D8-BB32379587BC}"/>
      </Hides>
    </DataType>
    <DataType>
      <Name Namespace="PMPS">ST_PMPS_Attenuator</Name>
      <BitSize>64</BitSize>
      <ExtendsType GUID="{7E016B85-166E-4B4F-AAC4-ECA8DDD44F13}">ST_PMPS_Attenuator_IO</ExtendsType>
    </DataType>

... clearly no pragmas there. The confusing part is that it looks like there should be in ST_PMPS_Attenuator - except they're commented out - perhaps just as a hint to look at the base type?

TYPE ST_PMPS_Attenuator EXTENDS ST_PMPS_Attenuator_IO :
STRUCT
    (*
        {attribute 'pytmc' := 'pv: Att
            io: i
            field: EGU %
        '}
        nTran : UINT;
        {attribute 'pytmc' := 'pv: OK
            io: i
        '}
        xAttOK : UINT; // true = no errors and attenuator is stable
        *)
END_STRUCT

Adding in a pragma manually to the .tmc in lfe-motion with a whimsical pv: FOOBAR (for easy grepping, really), yields:

 FloatRecordPackage(tcname='GVL.fbArbiter.fbBPAssertionPool.epicsDataPool[20].astAttenuators[16].nTran', pvname='PLC:LFE:MOTION:ARB:AP:Entry:020:AuxAtt:016:FOOBAR'),

So I think that's the core of the issue...

klauer commented 3 years ago

I think the pytmc debug gui is broken for chains that are missing a pragma. To determine the above, I had poked around with pytmc summary --debug, which is the expert (i.e., probably only me at this point) way of doing things.

I think the GUI working would have helped in this case, so let me review what's going on there.

klauer commented 3 years ago

Correction: the pytmc debug GUI isn't broken, it's just not user-friendly by any stretch (maybe even user-hostile? :shrug:).

To see the fact that nTran and such are missing pragmas:

  1. Run pytmc debug --allow-no-pragma plc-lfe-motion/plc-lfe-motion.tsproj
  2. Wait about a minute or two (it's reaaaally slow because it's doing the outer product of many symbols)
  3. Select Chains w/o records
  4. Type in epicsDataPool in the filter or something similar, and scroll down to the variable in question
  5. Note that the pv row is empty for nTran, leading to pytmc ignoring it
image
ZLLentz commented 3 years ago

The confusing part is that it looks like there should be in ST_PMPS_Attenuator - except they're commented out - perhaps just as a hint to look at the base type?

Oof, that got me good. I especially got baited because these old PVs were generated once upon a time:

$ pvgrep AuxAtt
ioc-SDSPLC      PLC:SDSPLC:RequestedBP:AuxAtt:001:Att_RBV, "longin"
ioc-SDSPLC      PLC:SDSPLC:RequestedBP:AuxAtt:002:Att_RBV, "longin"
ioc-SDSPLC      PLC:SDSPLC:RequestedBP:AuxAtt:003:Att_RBV, "longin"
ioc-SDSPLC      PLC:SDSPLC:RequestedBP:AuxAtt:004:Att_RBV, "longin"
ioc-SDSPLC      PLC:SDSPLC:RequestedBP:AuxAtt:005:Att_RBV, "longin"
ioc-SDSPLC      PLC:SDSPLC:RequestedBP:AuxAtt:006:Att_RBV, "longin"

Turns out these were part of an in-progress PR dev build in the pmps library but were commented out prior to merging

Sorry for the wild goose chase

klauer commented 3 years ago

No problem, @ZLLentz - I think we still need better tooling around "why isn't this PV generated?!". I'm just not sure what form that should take. Any suggestions are welcome!