PLCgen improvement plan
Development of PLCgen (see #397 (closed)) has progressed to the point that all main features are present and running. Issue #676 (closed) is tracking progress for making the program available for everybody.
That however does not mean development of the program ends with closing #676 (closed). There are a still many things left to do in the code generator. The main change of this issue compared to #397 (closed) is that instead of constantly building new functionality, the focus here is more at consolidating and improving the program to a mature tool.
Phase 1: Priority 1 (deadline: September 2024)
RWS wants to do lab tests with PLCgen in October 2024. The following list is the ESCET-related improvements that need to be made. For now, the target is S7-300 only. This list is also tracked in epic &3.
Click to expand detailed list of issues
Bug fixing / testing
-
Create a PLCgen test set of smaller models, that cover all supported language features and options, as well as all relevant aspects of the generator (#798 (closed)). -
Execute the test set in the lab. Fix any issues that are found. Make any architectural changes necessary to fix the issues. (#798 (closed)) -
'Test' the documentation. (#798 (closed)) -
Fix bugs that were found while testing: -
!920 (merged) Make "timer" a reserved word in PLCgen -
#770 (closed) Expression/type related improvements/fixes. -
#818 (closed) PLCgen crashes on nested tuples. (!876 (merged)) -
#847 (closed) Problems with EXPT
. -
#847 (closed) Problems with parameters of function calls. -
#847 (closed) MIN
andMAX
on non-int
issues. -
#848 (closed) Problems with "DB"
. -
#848 (closed) Problems with semicolons. -
#849 (closed) Documentation does not list the right steps (for TIA Portal v15). -
#850 (closed) Problems with timers (this bug has priority). -
#852 (closed) Documentation has a timer example model with a syntax error. -
#854 (closed) Allow having a type extension to a prefix function name (e.g., SEL_...
). -
#857 (closed) PLCgen crashes on models with switch expressions. -
#858 (closed) CIF to CIF transformation to transform 'switch' expressions to 'if' expressions doesn't handled nested 'switch' expressions. -
#859 (closed) PLCgen should disallow 'switch' expressions on tuples/arrays. -
#860 (closed) PLCgen test model "empty" does not execute on S7-300 -
#862 (closed) PLCgen test model "timers" does not compile -
#863 (closed) PLCgen test model "tuples" does not compile -
#868 (closed) Boolean algebraic variables don't update in PLC-code -
#876 (closed) Drop power and exponentiation support in PLCgen. -
#877 (closed) PLCgen test model "constants" does not compile -
#884 (closed) PLCgen: I/O table entry address size is always checked against target's max integer size -
#890 (closed) PLCgen test model "io" does not compile -
#901 (closed) PLCgen: S7 has additional naming constraints / #921 (closed) PLCgen test mode "names" does not compile -
#912 (closed) PLCgen: Error when compiling code for large model -
#923 (closed) PLCgen: generate edge selection variables based on absolute names of automata -
#934 (closed) PLCgen: use smallest integer representation possible for ranged integer and enum-typed variables/constants. -
#935 (closed) PLCgen: split generated MAIN
over multiple functions to prevent too large code -
#945 (closed) Rework PLCgen name generator -
#965 (closed) PLCgen: using bound from controller properties annotation's bounded response could lead to killed loops -
#967 (closed) PLCgen crashes on invalid I/O table files -
#968 (closed) PLCgen test models "op_and_bind_prio_num" do not comply with expected results -
#969 (closed) PLCgen: constants with enum values get unsupported values if enums are eliminated to constants -
#980 (closed) PLCgen test model "sync_events_funcs" does not compile -
#984 (closed) PLCgen: location pointers have names ending in '.' -
#986 (closed) PLCgen: event functions should not directly write to input variable -
#987 (closed) PLCgen s7 documentation: small improvements for steps in TIA Portal
-
Controller checker
-
In the generated PLC code, use two 'while' loops, one for uncontrollable events and one for controllable events. (#628 (closed)) -
Adapt other tools to be compatible with using two 'while' loops for uncontrollable/controllable events. (#628 (closed)) -> Superseded by #970 (closed) (see below) -
In the controller checker, compute 'while' loop bounds, separately for uncontrollable events and controllable events. Add as an annotation to the CIF model. (#621) -
Use 'while' loop bounds in generated PLC code. (#816 (closed)) -
Add non-blocking under control check to the controller checker tool. (#410) -
CIF controller properties checker for bounded response has performance issues. (#911) -> Done, for as far as it was planned for this phase. -
Document and use a consistent transition execution order for CIF tools that use it. (#970 (closed)) -> Done, for as far as it was planned for this phase.
Documentation/traceability
-
Support @doc annotations on all CIF elements that have a name or can have a name. (#593 (closed)) -
Make @doc a non-experimental feature. (#869 (closed)) -
Generate documentation in the generated PLC code for @doc annotations, similar to how the CIF code generator does it. (#814 (closed)) -
Add more comments to the generated PLCgen, for input reading, state initialization/updating, and output writing, similar to how already done for transition code. (#815 (closed)/!902 (merged)) -
Document the general structure of the PLC code in the PLC code (first read inputs, then perform transitions, then write outputs). (#805 (closed)/!878 (merged)) -
Document in the code generator why we read inputs at the start and write outputs at the end. (#831 (closed)) -
Preserve names of state/event exclusion invariants, to ensure they end up in the generated code. (#830 (closed)) -
Allow to customize name of variables connected to an I/O address. (#897 (closed))
Versions
-
Generate comments with application name, version, and date/time of generation in PLC code. (#805 (closed)) -
Allow users to supply additional information to be incorporated in the header of the generated code. (#805 (closed))
Phase 2: Priority 2 (deadline: December 2024)
RWS wants to do tests with PLCgen for a real-world object. The object would be closed for the tests. The tests will likely be done in January 2025. The following ESCET-related changes are planned to be finished before then:
Bugs
-
PLCgen crashes on nested arrays (#1017 (closed)) -
PLCgen crashes on compatible enum values being used in assignments (#1018 (closed)) -
Exceeded maximum number of blocks in PLC-code for CPU (#1031 (closed)) -
Failure of the test op_bind_and_prio_numX
for S7-400 (#1034 (closed)) -
PLCgen TwinCAT self-certification: generated solution files are not valid (#1035 (closed)) -
PLCgen TwinCAT self-certification: build error on SEL_DINT
/SEL_LREAL
(#1036 (closed), #1041 (closed)) -
PLCgen TwinCAT self-certification: division by zero exception (#1037 (closed)) -
PLCgen TwinCAT self-certification: VAR_TEMP
not supported in functions (#1038 (closed)) -
PLCgen TwinCAT self-certification: variables from MAIN
not recognized inFUNCTION
(#1039 (closed)) -
PLCgen TwinCAT self-certification: Cannot compare type BOOL
with typeDINT
(#1040 (closed)) -
PLCgen: Insufficient work memory (#1043 (closed)) -
PLCgen: I/O table CSV file 4-cell line confusingly requires only 4 cell-lines (#1044 (closed)) -
PLCgen self-certification test set: the results of the division are not compared correctly, for op_bind_and_prio_num2
andop_bind_and_prio_num3
(#1052 (closed)) -
PLCGen: Separate functions for reading input and writing output (#1055 (closed)) -
PLCgen self-certification test set: the results of the tests: channels
,expr_binary
,expr_stdlib
andtuples
are not compared correctly (#1057 (closed)) -
PLCgen: test names_s7
fails for S7-1200 (#1061 (closed)) -
PLCgen: ambiguities in IO test (#1062 (closed), #1068 (closed)) -
PLCgen self-certification test set: proposal for improvement of the test timers
(#1076 (closed)) -
PLCgen TwinCAT self-certification: unexpected results for channels.cif test (#1082 (closed))
Simulation
-
Execution mode for CIF simulator (#1045 (closed), #970 (closed)) -
Simulator SVG input mappings that assign input variables (#778 (closed), #227 (closed)) -
Rename CIF simulator environment events option to non-urgent events option (#1063 (closed))
Controller checks
-
Improve feedback in case controller checks don't hold (part of #892) -
Improve performance of controller checks (part of #892)
Readability / traceability / small diffs
-
PLCgen: (too?) many lines of model overview in generated code (#1022 (closed)) -
PLCgen: 'current location of automaton' text in model overview is confusing (#1023 (closed)) -
Support constants natively in PLCgen, rather than by inlining their values, to improve readability. (!905 (merged)) -
Generate edge selection variables based on absolute names of automata (#923 (closed)) -
Use the names of enumeration literals rather than their indices. (#934 (closed)) -
Don't generate 'magic numbers' in the generated PLC code, as they hurt readability. (#774 (closed)) -
Use less numbers in the generated PLC code in general, as they hurt readability. See discussion at #679 (comment 2857456). -
Improve the names in the generated PLC code. - Use as much as possible (absolute) CIF names and structure, to be able to relate PLC code back to the CIF model.
- For extra generated names (like derived variables for times, but also temporary variables) use prefixes/postfixes, to place them in different ‘namespaces’, such that they don’t conflict with each other, and prevents having to rename the CIF names.
-
Check that changes (mostly) cause only local changes in the generated code. Address the biggest issues. See discussion at #679 (comment 2857439).
Migration/validation
-
Include self-certification tests as integration tests. (#1014) -
PLCgen self-certification test set: make it easier to compare TIA Portal output against expected test output. (#1033 (closed)) -
Test PLCgen for TwinCAT, using the test set of small test models from #798 (closed), using the lab setup. Report any issues. (#1020) -
Test PLCgen for S7-400/1200/1500, using the test set of small test models from #798 (closed), using the lab setup. Report any issues. (#1019) -
Make the old PLC code generator deprecated, making the new PLC code generator the recommended PLC code generator. Do mark the untested targets as experimental (all but S7 and TwinCAT). -
Have a PLC expert do some checks. For instance, to check that there are no blocking issues remaining (not a full re-evaluation, but only checking the points from previous CGI report, and not for safety PLCs). Address any issues that arise. RWS takes the lead here. No ESCET issue is created unless something comes up in the evaluation. -
Ask a maintenance engineer whether the generated PLC code is traceable/understandable enough. Address any issues that arise. RWS takes the lead here. No ESCET issue is created unless something comes up in the evaluation. See also #679 (comment 2854113). -
PLCgen: structure event functions in a hierarchy in TIA Portal (#1059)
-
-
Declare annotations a stable CIF language feature (used e.g. for @doc
annotations). (#869 (closed))
Other
-
Multi-level synthesis (#318) -
Expanding PLC Code Generator with reading/writing to the internal tags for S7 target types (#979 (closed)) -
Document loopsKilled
variable (#1013 (closed)) -
SBE course 1st version (#742 (closed))
(Other) things to do
From here on, all other things that could be improved in PLCgen are listed. Not all may actually be picked up. Some are duplicates of the new lists of above. It should be considered a wishlist.
Preparation
-
Copy remaining relevant points of #397 (closed) to here. -
Integrate TODO
items currently sprinkled throughout the code. (#397 (closed), point 26) -
Add list of possible improvements from the report published by CGI for as far as they relate to the PLC code generator. -
Finish and close #676 (closed) -
Finish and close #397 (closed) with respect to all points that have not been copied to this issue.
Bugs
-
PLCgen Siemens target: location variables get assigned non-existing values. (#675 (closed)) (#397 (closed) point 31) -
Proper code generation for the Siemens target wrt timers can arguably also be seen as a high priority improvement/fix. See also the 'Targets' section below (#679). (!912 (merged)) -
Protect the PLC from getting negative TON end-values. (!912 (merged)) -
cifplcgen
is missing from the scriptable tools overview in the CIF documentation. (!731 (merged)) -
Issues found during testing of generated S7 PLC code (thanks to @jverbakel): -
State variables need a memory address when they are in a global table, or they can be stored in a DB file. (Fixed, they got moved to a DB file in the mean time.) -
Double underscore sequences in an identifier are not allowed (Gets fixed in !806 (merged)). -
firstRun
variable does not exist. Comment: Also check its initialization value. -
preset_timer_t
variable does not exist. -
timer
is a reserved word (it's a function block type in S7). (!920 (merged)) -
Fights between local variable name, global variable name, and eg types can be resolved by prefixing local variables with#
and adding"
around global variables. (rejected, as not supported by all PLC vendors) -
PLC timers use TIME
type, while CIF uses real numbers to express duration. Conversion is needed with a cast from a number toTIME
, eg bytimer0.PT := DINT_TO_TIME(LREAL_TO_DINT(#preset_timer_t * 1000));
. CIF does not prescribe a unit fortime
, but generally we use 'seconds' as unit, and the PLCgen docs describe this already as well. (!912 (merged)) -
SEL
function expects boolean values to select, other types must be denoted by appending a type, e.g.SEL_LREAL
. (#854 (closed))
-
Conceptual cleanliness
-
Reconsider how a function block call should be created. Currently, the code that produces calls to the timer function block may have too much knowledge about PLC target information. See !683 (comment 1320599), !688 (comment 1349579) and !770 (comment 1700315). -
!785 (merged) tried and failed in the current setup of variables and functions. However, as noted in !785 (comment 1704688) the problem could be that variables and functions are much closer related than they are usually in other languages. The direction therefore could potentially be to merge these concept in the core data (possibly with interfaces), and then variables, functions, function blocks, POUs, and programs all collapse to the same basic idea. -
Reconsider the model classes for functions, function blocks, function calls, variables, etc. See !785 (comment 1704170). (#770 (closed))
-
-
ExprGenerator
has a bunch of// S7-400 and S7-300 only support <<OPERATOR>> on the same types.
It ensures these restrictions without regard to the actually used target. Other comments seems to point at similar considerations, check all line comment in that file. (Remarks deleted in !1151 (merged)) -
Variable tables have confusing names. Method addTimerVariable
is used to add non-timer variables. Reconsider it all. See also !697 (comment 1392717). Fixed in !770 (merged). -
As suggested at !770 (comment 1658164), cleaning up variable access with respect to getting the name or getting the stored value of the variable is useful. Fixed in !785 (merged). -
Drop writing to derivatives in the expression generator and the underlying CifDataProvider
, as CIF doesn't support that (in !1093 (merged)). -
Drop the special case of keeping constants generated from "Constants created by Convert enumerations are not inlined." See also !905 (comment 2405184) -
State variables that get copied for reading their values during update should not have a copy for each different event. -
The PlcFuncOperation
field should move fromPlcSemanticFuncDescription
toPlcBasicFuncDescription
as it is needed more often. This will drop thePlcSemanticFuncDescription
. Done in #877 (closed), !956 (merged) -
Re-organizing initialisation of funcdescriptions seems like a good idea too. Too many parameters in the constructors currently. -
Re-organize the main driver code in the target, such that various generators only exchange data through the main driver (instead of through invisible back-doors directly between different generators). See #993
Industrial usage
A Dutch report (PDF) was written by CGI for RWS about PLC code generation in synthesis-based engineering (SBE) context.
Many conclusions are about the design process, rather than about implementation issues in the generator itself. Here, only the latter are considered.
The identified points have been given a brief English description. The V
and A
references relate to points in the report.
The V
references are safety related, while the A
references are more general considerations from system development.
-
Ensure suitably short PLC cycle execution times ( V-3
). (see #621 for event loop bound calculation, #816 (closed) for using them in PLCgen) -
Avoid using the WHILE
statement (V-4
). -
Add suitable comment lines to the code what it is doing ( V-6
), egread inputs
ortry to perform event E
. (#782 (closed) adds comments to the code) -
Add more details to input and output code about what is read or written. (#815 (closed)) -
Add more details to initialization of state variables, and updates of continuous variables. (#815 (closed)) -
Extend the code generator to include safety PLCs ( V-1
,A-7
). -
Avoid set
/reset
function blocks (V-7
). -
Include the used versions of the input models, synthesis software, and code generator in the generated code ( V-10
). (#805 (closed) allows inserting a text-file at the top of the code) -
Allow function blocks to be included from a model ( A-2
). -
Allow having user-parameters to tune/configure system behavior without falling back to changing the models ( A-3
). -
Enable relating between modeling information and the generated code ( A-4
,A-13
). #587 (closed) was a first step in this direction, but is obsolete now. #593 (closed) is working on the underlying foundation to enable@doc
annotations, and #814 (closed) is about using@doc
in PLCgen.-
A-4
specifically addresses the need to relate generated guard tests for a requirement, while -
A-13
addresses the reverse need (which requirements are addressed in this code?) -
See what else is need to ensure traceability.
-
-
Ensure that small changes in the models don't lead to large changes in the generated code ( A-5
).
Improve user-experience (UX)
-
Add PLC input/output annotations for linking sensors/actuators to CIF variables. (#1049) -
Add @plc:input
annotation. -
Add @plc:output
annotation. -
Allow them without arguments, to just mark them and have them be considered for code generation. See also #679 (comment 2534561). -
Allow customizing addresses, etc, like in the I/O table file.
-
-
Add doc
annotations for attaching documentation links to elements in the CIF specification. #593 (closed) #814 (closed) (old: #587 (closed) (#397 (closed) point 28)) -
Add user-defined internal functions (#397 (closed) point 18). -
Add continuous variables (#397 (closed) point 6, #630 (closed) implements it ) -
Prechecker "continuous variable as timer" sometimes emits strange error reports, see #681 (closed) (!798 (merged)) (!819 (merged)) -
Allow using algebraic variables (#956 (closed)), continuous variables and locations as outputs, not just discrete variables. -
Generate code/type dependencies file (#994 (closed))
Pre-checking
-
Consider generalizing the 'continuous variables as timers' check and move it to common.cif.precheckers
. (#397 (closed) point 31) -
Implement non-blocking under control checking, described in Reijnen 202, needed by plcgen, may possibly be done independently (#397 (closed) point 25, #410). -
Disallow list[0]
completely (!879 (merged) fixes this).
Testing
-
Reduce test duplication. (#781 (closed)) -
Test the validation performed by InputOutputGenerator
for I/O table files. -
Ensure all cif2plc
tests and/or tests from the test set of #798 (closed) are added to theplcgen
integration test set. -
Test that all options have the desired effect on the generated code, for all targets. -
Perform testing for what function notation forms are supported by what target, and update the target classes to match that. (is part of #798 (closed) for S7-300) -
Perform extensive testing of the new PLC code generator, on real PLCs, for the various targets. (is part of #798 (closed) for S7-300)
Options
-
Check which options are really useful. Maybe some could be removed and just decided by the target instead. (See #679 (comment 1657463) for the argumentation that why it is considered done.) -
Add "auto" to the convert-enums option to let the target decide. (!764 (merged)) -
Check and handle other options that lack an auto
value. (See #679 (comment 1657458) for the argumentation why it is considered done.) -
Enum conversion should handle three output forms: Enumeration values, constants, and numbers. -
Consider renaming options, but only if we agree that is a good idea. See #679 (comment 1392038). -
Consider a different name for convert-enums
, such asconvert-locations
, to improve clarity in what it does? -
Consider a different name for simplify-values
to avoid confusion withconvert-enums
functionality?
-
-
Replace the PlcFormalFuncInvokeArgOption
,PlcFormalFuncInvokeFuncOption
options by 'supported function invocation notations'. (!688 (merged)) -
Remove the PlcFormalFuncInvokeArgOption
,PlcFormalFuncInvokeFuncOption
options. (!697 (merged)) -
Add the PlcMaxIterOption
options. (!697 (merged)) -
Output file option is not always for creating a file.
Code improvements
-
Consider generating names in code more carefully so there is a system in place. See also !664 (comment 1262087). -
Consider adding an analysis+rewrite step to improve generated PLC statement models (from #397 (closed) point 8, and several other sub-points so it covers all available expressions). -
Consider improving algebraic variable handling beyond replacing them with their definitions (#397 (closed) points 21/22). Perhaps with the analysis framework? (#1056) -
Implement constant declarations and usage in the PLC (from #397 (closed) point 3). -
Code still has some root[Cif]Provider
names, they should be renamed toscopeCifProvider
. (#397 (closed) point 31) (!751 (merged)) -
Currently there is a requirement "The continuous variable is only assigned in a single-variable assignment, not in multi-assingments.". This seems an unnecessary limitation. (#97 point 31) -
Reduce restrictions for precondition check on continuous variables: -
Checker currently requires 'Continuous variables, if explicitly initialized, must have an initial value that is zero or larger, and this must be statically decidable.' We may want to reconsider this. See also !700 (comment 1477524). -
Checker currently requires continuous variables to be assigned only in single-variable assignments, while the implementation does support multi-assignments already. See also !700 (comment 1477527). -
Checker currently requires continuous variables to be initialized to, assigned, or compared to, a non-negative value. Not all of these restrictions may be needed. See also !700 (comment 1517084). -
Remove app.framework
paths from the writers. See #666.
-
Event transitions code improvements
-
In event transition code magic numbers are used to point at automata and edges. It should likely use CIF automata and CIF location names instead. (#397 (closed) point 29) (#774 (closed) discusses names and number triplets like 12_34_456
(automaton, location, edge) ) -
Event transition code could use more comments what is being done to guide the reviewer. For example -
mention the automaton that owns the edges being checked. (#782 (closed) adds comments to the code) -
Some empty lines eg between different events could be useful too. (#397 (closed) point 29) -
other improvements if needed/useful.
-
-
Use better names or add comments to make it easier to find the connection between guard checking code and update code of the same edge. (#397 (closed) point 29) (#782 (closed) adds comments to the code)
Performance
-
Add sequencing of event transition processing (Reijnen 2020, #397 (closed) point 23): -
Collect querying of state data in guards and state updates. [See issue #595 ] -
Construct a graph as input for the algorithm.
-
Targets
-
Add a timer type-name ( IEC_Timer
for S7). -
Allow for a function name suffix ( .TON
) with a function-block instance. (!785 (merged) ) -
Consider integrating Writer
classes more withTarget
classes (#397 (closed) point 27) -
Targets could perhaps also use a fresh look at their code (#397 (closed) point 27). -
S7
(!770 (merged), !785 (merged)) -
ABB
-
PlcOpen XML
-
TwinCAT
-
IEC 61131-3
-
-
Siemens target currently banishes all forms of array, but as PLCgen relies less on functions, the reason for that in cifplc (".. because S7 doesn't support functions returning arrays and doesn't support arrays of arrays.") seems to leave room for improvement. -
Try to add links to public PLC system documentation for reference for the targets (see !770 (comment 1657881) ) -
PLCopen XML
-> https://reference.opcfoundation.org/nodesets/87 -
IEC 61131-3
-> No public access, Wikipedia has a short description https://en.wikipedia.org/wiki/IEC_61131-3, likely other targets are useful too. -
TwinCAT
-> https://infosys.beckhoff.com/english.php?content=../content/1033/tc3_plc_intro/2529458827.html&id= -
ABB
-
Siemens S7-300
-
Siemens S7-400
-
Siemens S7-1200
-
Siemens S7-1500
-
-
Improve output for targets: -
Newer TIA Portal versions support 'enums' (#851)
-
Other
-
Improve naming in the generated code, and add documentation that explains the generated code. (#774 (closed)) (#782 (closed) adds comments to the code) -
CIF assumes that both input and output variables are part of the state. This is debatable as often these variables are only pass-through copies of the read input data or created output data. (#397 (closed) "other considerations" at the bottom) -
Since all code and data lives in the main program, there isn't any need to make a copy of the inputs to a state variable. It can simply always use the input variable itself instead.- (As noted in #679 (comment 1656095), using the input variable itself may at some point interfere with input changes due to actions from the asynchronously running safety PLC.)
-
Another form of this improvement can be not use a state variable for storing read input. That value is valid only for the duration of the cycle, and could be a temporary variable instead.
-
-
As noted in !619 (merged) (comment 1159022) the chosen approach of performing event transitions by first deciding complete feasibility of an event before even considering performing it means that guard checking code of an edge and the update code that the edge may perform are not close to each other in the source code. This complicates code review. (#397 (closed) "other considerations" at the bottom) -
#628 (closed) should be decided at some point. (#397 (closed) "other considerations" at the bottom) -
See what else to do to address the recommendations from the report that CGI wrote for RWS about PLC code generation: ROK-IA.SBE.RAP01_v1.0.pdf -
PLCgen: custom function calls (generic approach) (#1060)
Migration
-
Does it support all tool options, properly. (#397 (closed) point 32) -
Does it have all the features of the current/old PLC code generator? Is it a full replacement? (#397 (closed) point 32) -
Is there any documentation, are there test, etc, from the current/old PLC code generator that have not yet been migrated. (#397 (closed) point 32) -
Deprecate cif2plc
. -
Get rid of cif2plc
,cif to plc
,cif_to_plc
, etc in PLCgen.