03-27-2013 10:44 AM
@dan_u wrote:
Are you sure about that? I would hope a polymorphic VI would work more like a conditional disable structure. It loads all instances into memory when opening the VI, but for the compilation only the active code (the instance used) must be compileable.
In a perfect world...
Well, I definitely cannot claim I am sure about it, but this link certainly explains that you cannot have broken polymorphic sub VIs. Though this link does explains the broken sub VI due to incompatible connector pane, but I feel its related to OPs concern.
03-27-2013 12:01 PM
Shane,
I've put together an example that demonstrates exactly what you are seeing. The polymorphic VI I have built has one instance that flashes the
FPGA LED of a CompactRIO using a static IO node from the project explorer and another instance that flashes the RT LED of CompactRIO using the RT Leds.vi.
As the RT Leds.vi cannot exist on an FPGA target, we see the broken run arrow when we place the polymorphic VI under an FPGA target, even with the FPGA instance is selected. ANY broken polymorph instance will break the run arrow when the polymorph is placed on a block diagram. The figure below shows my example with a broken top level FPGA VI (containing the polymorph), an executable FPGA instance of that polymorph and the offending broken (non-executable) RT instance of that polymorph.
Now, the way we work around this is use conditional diagram disable structures to disable pieces of code that aren't executable on certain target types. See the image below for how our VIs look once this has been added. Notice now that the FPGA top level VI no longer has a broken run arrow (even though the RT instace of the polymorph is missing a VI that has been disabled).
Note that you must also add a default case for the conditional disable structures which has no code in it. I've attached my project saved for LV 2011 (in case you are on an earlier version) for you to take a look at if you have any questions. I think this should clear up any confusion, best of luck!
03-27-2013 12:23 PM
OK, thanks for the answer but I still maintain this doesn't need to be.
I mean, the Polymorphic VI isn't broken per se.
Does this affect Classes in the same way that we need to pepper our classes with conditional disable structures just to use them across device boundaries?
Ugh, I fear I already know the answer.
Shane.
03-27-2013 04:23 PM
Nick-C wrote:
Now, the way we work around this is use conditional diagram disable structures to disable pieces of code that aren't executable on certain target types.
Therefore you don't even need the polymorphic VI, which is an advantage in terms of keeping code synchronized.
03-27-2013 04:40 PM
GregS makes a good point, so long as the inputs for each instance are the same data type. Remember that polymorphs can adapt to data types (for example to have an algorithm that runs on RT with a double data type or on FPGA with fixed point) 🙂
03-28-2013 02:21 AM
@GregSands wrote:
Nick-C wrote:
Now, the way we work around this is use conditional diagram disable structures to disable pieces of code that aren't executable on certain target types.
Therefore you don't even need the polymorphic VI, which is an advantage in terms of keeping code synchronized.
Well no, I still need the poly VI. The poly VI is a encoder and decoder for a set of commands, it's not just for a single operation. It's my communications API to the FPGA module in essence. I only want to decode on the FPGA (After communication) whereas I need to both encode and decode on the host side. I solved my problem by simply splitting the poly VI into a decode and encode Poly VI.
Shane.
03-28-2013 05:03 AM
This behaviour stills trikes me an unneccessary.
It lies with the fact that a POLY Vi is deemed broken if ANY of its members are not executable. Back in the days of no projects and no RT or FPGA contexts this might have been OK but I don't see why this blurred line between IDE and compiler should prevent me from using code like I have outlined.
I think, personally, that a polymorphic VI should NOT be broken if certain elements of its instances are broken as long as those instances are not being used. Poly VIs are typed at compile time, not at run-time like classes so this should be OK for the compiler. Instead, showing a warning triangle on the Poly VI icon should highlight that some of the isntances are not compatible with the context in which it is being used.
Going even further I think there are more elegant solutions to this device-boundary problem which could be addressed. Some way to define which parts of a POLY VI (OR more importantly, a Class) are deemed for which target would be a huge aid. Something which I feel would greatly help the evolution of LVOOP within the entire LabVIEW environment.
Shane.
03-28-2013 05:29 AM
Another note.
There's no option to set "Remove unused Polymorphic instances" when creating a build spec for FPGA so I presume this is automatically done (anything else would be crazy). In other words, default behaviour here is that unused instances are NOT compiled and shouldn't return a compiler error.
03-28-2013 10:53 AM
Hi Shane,
After talking with Nick I did some research into this. As was already demonstrated, a poly VI is considered broken if any of its members are not executable. The poly VI itself breaks, which is expected behavior for how that functionality is currently written. If you feel strongly that it should be executable with broken poly instances as long as they are not in use, please make an idea exchange post for it. I would kudos it.
The use case you have is one of the main use cases for the conditional disable structure, having the same code base run in multiple contexts with context specific VIs.
Just to make sure I understand correctly, you have developed a poly VI which you intend to use on both FPGA and RT, but you never intend to actually call the FPGA instance on RT and vice versa (which is why it is an annoyance to add conditional disable structures to the two instances)? If you do not intend to use the VIs in multiple contexts, is it possible to take them out of the poly VI? If you do intend to use them in both contexts, you will need conditional disable structures anyway.
If you have specific functions you are calling that are context specific (such as Nick's example of the FPGA LED and the RT LED), you can wrap those functions in a conditional structure and another subVI, which will reduce the number of conditional structures you need in your code, but the expected method for doing this is to use conditional disable structures.
Regarding your question about dynamic dispatch, I ran a few tests and found that the same thing is true. If any of the override VIs are broken (even if they are not being explicitly called anywhere), the main VI will be broken with the error text: "One or more of the set of VIs which this dynamic dispatch subVI or property item may call are broken. Each LabVIEW class may own a VI with the same name as a VI owned by the parent of the class or older ancestor. The dynamic dispatch subVI or property item will call one of these VIs, chosen when the subVI or property item actually executes. If any of the VIs are broken, then this subVI or property item also is broken."
This seems to be because dynamic dispatch gives you the flexibility of calling any of the override VIs at runtime, so it needs to be guaranteed that all possible VIs are executable. This is different that poly VIs (which can not dynamically change at runtime), so I don't see any other way for this to work other than breaking the run arrow.
I will let Nick answer your question regarding build specs for FPGA.
Regards,
Jeff Peacock
Product Support Engineer | LabVIEW R&D | National Instruments
03-28-2013 12:06 PM - edited 03-28-2013 12:08 PM
Thanks Jeff for the detailed answer.
I would indeed love if a Poly VI would only break if a USED instance of the VI is broken.
My use case is as follows. I have many parameters which I need to send from Host (PC) to RT and FPGA. I format these into a U64 for transfer and unpack them at the other end. I need to be able to pack and unpack on the Host side (PC) and possible also unpack on the RT. On the FPGA I only need to unpack. All of the unpack VIs are executable on FPGA, RT and PC. The packing VIs are executable only on the PC. I thus use my Poly VI as a hardware API between the different layers of my architecture. If I need to do some vertical communication, I just take the Poly VI and presto, I have everything I need in order to ensure the communication is parsed properly. This is why I'd love them all in the SAME VI. I suppose I'll just add the conditional disable structures to get this going erven if it fills me with an icky feeling.
I don't know how but I feel having a more elegant solution to this would be pretty cool and enable much easier transitioning between different hardware bases.
With Dynamic dispatch, the decisions as to which version is called is a run-time decision so this I can fully understand. I don't think the "Run even if some are broken" is ever going to work here. But Dynamic dispatch isn't compatible with FPGA anyway......
Shane.