CompileDES 3.14
Executable-Code Generation from Synchronised libFAUDES Automata
cgp_iec61131st.cpp
Go to the documentation of this file.
1
3/*
4 FAU Discrete Event Systems Library (libFAUDES)
5
6 Copyright (C) 2010, 2016 Thomas Moor
7
8*/
9
10// my includes
11#include "cgp_iec61131st.h"
12
13
14/*
15******************************************************************
16******************************************************************
17******************************************************************
18
19Iec611311stGenerator implementation --- class maintenance
20
21******************************************************************
22******************************************************************
23******************************************************************
24*/
25
26
27// Register derived class
29
30
31// Iec61131stCodeGenerator(void)
33 FD_DCG("Iec61131stCodeGenerator(" << this << ")::Iec61131stCodeGenerator()");
34}
35
36
37// Iec61131stCodeGenerator(void)
39 FD_DCG("Iec61131stCodeGenerator(" << this << ")::~Iec61131stCodeGenerator()");
40}
41
42
43// clear
45 FD_DCG("Iec61131stCodeGenerator::Clear()");
46 // call base
48 // my flavor of defaults
49 mPrefix="fcg_";
50 mWordType="BYTE";
51 mWordSize=8;
52 mIntegerType="INT";
53 mIntegerSize=16;
54 mIecDeclarePhysical="VAR_EXTERNAL";
55 mIecDeclareSymbolic="VAR_EXTERNAL";
57}
58
59//DoReadTargetConfiguration(rTr)
61 FD_DCG("Iec61131stCodeGenerator::DoReadTargetConfiguration()");
62 // base
64 Token token;
65 // iec option
66 if(rTr.ExistsBegin("IecDeclarePhysical")) {
67 rTr.ReadBegin("IecDeclarePhysical",token);
68 mIecDeclarePhysical= token.AttributeStringValue("val");
69 rTr.ReadEnd("IecDeclarePhysical");
70 }
71 // iec option
72 if(rTr.ExistsBegin("IecDeclareSymbolic")) {
73 rTr.ReadBegin("IecDeclareSymbolic",token);
74 mIecDeclareSymbolic= token.AttributeStringValue("val");
75 rTr.ReadEnd("IecDeclareSymbolic");
76 }
77 // iec option
78 if(rTr.ExistsBegin("IncludeCyclic"))
79 rTr.ReadVerbatim("IncludeCyclic",mLiteralCyclic);
80 if(rTr.ExistsBegin("IecTimeOperators")) {
81 rTr.ReadBegin("IecTimeOperators",token);
82 mHasIecTimeOperators= token.AttributeIntegerValue("val");
83 rTr.ReadEnd("IecTimeOperators");
84 }
85}
86
87//DoWriteTargetConfiguration(rTw)
89 FD_DCG("Iec61131stCodeGenerator::DoWriteTargetConfiguration()");
90 // base
92 Token token;
93 // code option
94 token.SetEmpty("IecDeclarePhysical");
95 token.InsAttributeString("val",mIecDeclarePhysical);
96 rTw.Write(token);
97 // code option
98 token.SetEmpty("IecDeclareSymbolic");
99 token.InsAttributeString("val",mIecDeclareSymbolic);
100 rTw.Write(token);
101 // code option
102 if(mLiteralCyclic.size()>0)
103 rTw.WriteVerbatim("IncludeCyclic",mLiteralCyclic);
104 token.SetEmpty("IecTimeOperators");
105 token.InsAttributeBoolean("val",mHasIecTimeOperators);
106 rTw.Write(token);
107}
108
109
110
111/*
112******************************************************************
113******************************************************************
114******************************************************************
115
116Iec611311stGenerator implementation --- code organisation
117
118******************************************************************
119******************************************************************
120******************************************************************
121*/
122
123// DoCompile()
125 // call base
127 // my preferences
129 FCG_VERB1("Iec61131stCodeGenerator::Compile(): prefer compiled bitmasks over bit-address maths");
130 mBitAddressArithmetic = false;
131 }
132 // set array for state for returnvalue
134 FCG_VERB1("Iec61131stCodeGenerator::Compile(): using array for state as return value datatype");
135 mArrayForState = true;
136 }
137}
138
139
140// DoGenerate()
142 // cut and paste from base
143 mBitarrays.clear();
144 // doit: say hello
145 Comment("************************************************");
146 Comment("CodeGenerator: Target IEC 61131 Structured Text ");
147 Comment("************************************************");
148 LineFeed(1);
149 Comment(std::string("CompileDES ") + VersionString());
150 Comment(std::string("Configuration: ") + Name());
151 LineFeed(2+1);
152 // snippets
154 // doit: function block to host cyclic code
156 // doit: functions to host lookup tables
158 // snippets
160 Comment("************************************************");
161 Comment("CodeGenerator: Generated Code Ends Here ");
162 Comment("************************************************");
163}
164
165
166
167// code blocks: cyclic function block
169 Comment("************************************************");
170 Comment("* function block to host cyclic code *");
171 Comment("************************************************");
172 LineFeed(2);
173 Output() << "FUNCTION_BLOCK " << mPrefix <<"cyclic_fb";
174 LineFeed(2);
175 Output() << "VAR_INPUT";
176 LineFeed(2);
177 DeclareReset();
178 Output() << "END_VAR";
179 LineFeed(2);
180 Output() << "VAR_OUTPUT";
181 LineFeed(2);
186 Output() << "END_VAR";
187 LineFeed(2);
188 Output() << "VAR";
189 LineFeed(2);
195 DeclareAux();
199 Output() << "END_VAR";
200 LineFeed(2);
201 if(CountImportSymbolicIo()>0) {
203 LineFeed(2);
205 Output() << "END_VAR";
206 LineFeed(2);
207 }
208 if(CountImportPhysicalIo()>0) {
210 LineFeed(2);
212 Output() << "END_VAR";
213 LineFeed(2);
214 }
219 LineFeed(1+2);
220 Comment("************************************************");
221 Comment("* end of cyclic function block *");
222 LineFeed(1);
223 Output() << "END_FUNCTION_BLOCK";
224 LineFeed();
225 LineFeed(2+1);
226}
227
228
229// code blocks: function to host lookup tables
231 if(mEventNameLookup) {
232 Comment("************************************************");
233 Comment("* function to host the event name loopup table *");
234 Comment("************************************************");
235 LineFeed(2);
236 Output() << "FUNCTION " << mPrefix <<"event_lookup_f" << " : STRING";
237 LineFeed(2);
238 Output() << "VAR_INPUT";
239 LineFeed();
240 Output() << "IDX : " << mIntegerType <<";";
241 LineFeed();
242 Output() << "END_VAR";
243 LineFeed(2);
244 Output() << "VAR CONSTANT";
245 LineFeed();
247 Output() << "END_VAR";
248 LineFeed(2);
249 Output() << mPrefix <<"event_lookup_f" << " := " << mPrefix << "event_lookup[IDX]" << ";";
250 LineFeed(2);
251 Output() << "END_FUNCTION";
252 LineFeed();
253 LineFeed(2+1);
254 }
255 if(mStateNameLookup) {
256 Comment("************************************************");
257 Comment("* function to host state name loopup tables *");
258 Comment("************************************************");
259 LineFeed(2);
260 Output() << "FUNCTION " << mPrefix <<"state_lookup_f" << " : STRING";
261 LineFeed(2);
262 Output() << "VAR_INPUT";
263 LineFeed();
264 Output() << "GID : " << mIntegerType <<";";
265 LineFeed();
266 Output() << "IDX : " << mIntegerType <<";";
267 LineFeed();
268 Output() << "END_VAR";
269 LineFeed(2);
270 Output() << "VAR CONSTANT";
271 LineFeed();
273 Output() << "END_VAR";
274 LineFeed(2);
275 Output() << mPrefix << "state_lookup_f:='';";
276 LineFeed();
277 Output() << "CASE GID OF";
278 LineFeed();
279 for(size_t gid=0; gid<Size(); ++gid) {
280 if(mHasStateNames[gid])
281 Output() << ToStringInteger(gid) << ": "
282 << mPrefix <<"state_lookup_f" << " := " << mPrefix << "state_lookup_" << ToStringInteger(gid) << "[IDX]" << ";";
283 LineFeed();
284 }
285 Output() << "END_CASE;";
286 LineFeed();
287 Output() << "IF LEN(" << mPrefix << "state_lookup_f) = 0 THEN";
288 LineFeed();
289 Output() << " " << mPrefix <<"state_lookup_f" << " := CONCAT('s'," << mIntegerType << "_TO_STRING(IDX))" << ";";
290 LineFeed();
291 Output() << "END_IF;";
292 LineFeed(2);
293 Output() << "END_FUNCTION";
294 LineFeed();
295 LineFeed(2+1);
296 }
297}
298
299
300// extend base reset by iec timers
302 FD_DCG("Iec61131stCodeGenerator(" << this << ")::StateReset()");
303 // call base
305 // have iec extras
307}
308
309
310
311// code blocks: extend base timer declaration
313 // call base
315 // extend
316 if(TimersBegin()!=TimersEnd()) {
317 Comment("elapsed time since last invokation");
318 VariableDeclare(TargetAddress(AA("time_elapsed")),"TIME");
319 LineFeed();
320 }
321}
322
323
324// code blocks: import interface variables
326 // bail out on unconfigured
327 if(mIecDeclarePhysical=="") return 0;
328 // figure count
329 int iocnt=0;
331 for(;lit!=LinesEnd();++lit) {
332 std::string lineaddr= lit->second.mAddress;
333 if(lineaddr.size()<1) continue; // paranoia
334 if(lineaddr.at(0)=='%') iocnt++;
335 }
337 for(;ait!=ActionAddressesEnd();++ait) {
338 if(!ait->second.mSetClr) continue;
339 std::string actaddr= ait->second.mAddress;
340 if(actaddr.size()<1) continue; // paranoia
341 if(actaddr.at(0)=='%') ++iocnt;
342 }
343 return iocnt;
344}
345
346
348 Comment("import physical i/o addresses");
350 for(;lit!=LinesEnd();++lit) {
351 std::string lineaddr= lit->second.mAddress;
352 if(lineaddr.size()<1) continue; // paranoia
353 if(lineaddr.at(0)=='%') {
354 Output() << "AT " << lineaddr << " : BOOL;";
355 LineFeed();
356 }
357 }
359 for(;ait!=ActionAddressesEnd();++ait) {
360 if(!ait->second.mSetClr) continue;
361 std::string actaddr= ait->second.mAddress;
362 if(actaddr.size()<1) continue; // paranoia
363 if(actaddr.at(0)=='%') {
364 Output() << "AT " << actaddr << " : BOOL;";
365 LineFeed();
366 }
367 }
368 LineFeed(1);
369}
370
371// code blocks: import interface variables
373 // bail out on unconfigured
374 if(mIecDeclareSymbolic=="") return 0;
375 // figure count
376 int iocnt=0;
378 for(;lit!=LinesEnd();++lit) {
379 std::string lineaddr= lit->second.mAddress;
380 if(lineaddr.size()<1) continue; // paranoia
381 if(lineaddr.at(0)!='%') iocnt++;
382 }
384 for(;ait!=ActionAddressesEnd();++ait) {
385 if(!ait->second.mSetClr) continue;
386 std::string actaddr= ait->second.mAddress;
387 if(actaddr.size()<1) continue; // paranoia
388 if(actaddr.at(0)!='%') ++iocnt;
389 }
390 return iocnt;
391}
392
394 Comment("import i/o variables");
396 for(;lit!=LinesEnd();++lit) {
397 std::string lineaddr= lit->second.mAddress;
398 if(lineaddr.size()<1) continue; // paranoia
399 if(lineaddr.at(0)!='%') {
400 VariableDeclare(lineaddr,"BOOL");
401 LineFeed();
402 }
403 }
405 for(;ait!=ActionAddressesEnd();++ait) {
406 if(!ait->second.mSetClr) continue;
407 std::string actaddr= ait->second.mAddress;
408 if(actaddr.size()<1) continue; // paranoia
409 if(actaddr.at(0)!='%') {
410 VariableDeclare(actaddr,"BOOL");
411 LineFeed();
412 }
413 }
414 LineFeed(1);
415}
416
417
418// code blocks: literal prepend from configuration
420 if(mLiteralCyclic.size()==0) return;
421 Comment("************************************************");
422 Comment("* extra cyclic code from configuration *");
423 LineFeed();
425 LineFeed(2);
426 Comment("* end of extra code from configuration *");
427 Comment("************************************************");
428 LineFeed(1+1);
429}
430
431// generate code
433 if((mEventExecutionHook!="") || (mStateUpdateHook!=""))
434 Comment("call hooks");
435 if(mEventExecutionHook!="") {
436 std::string hook = mEventExecutionHook + "(" + TargetExpression(AA("exec_event")) + ");";
437 Output() << hook;
438 LineFeed(1);
439 }
440 if(mStateUpdateHook!="") {
441 std::string hook = mStateUpdateHook + "(" + TargetAddress(AA("parallel_state")) + ");";
442 Output() << hook;
443 LineFeed(1);
444 }
445 LineFeed(1);
446}
447
448
449// code blocks: organise time decrement as inline code snippet
451 if(TimersBegin()==TimersEnd()) return;
452 // timer update function
453 Comment("************************************************");
454 Comment("* update timer states *");
455 LineFeed(2);
456 Output() << "IF " << TargetAddress(AA("time_elapsed")) << " > " << TimeConstant(0) << " THEN";
457 LineFeed();
458 IndentInc();
460 for(;tit!=TimersEnd();++tit) {
461 AA cnt("timer_" + tit->second.mAddress + "_cnt");
462 AA run("timer_" + tit->second.mAddress + "_run");
463 Output() << "IF " << TargetAddress(AA(run)) << " THEN";
464 IndentInc();
465 LineFeed();
466 Output() << "IF " << TargetAddress(cnt) << " > " << TargetAddress(AA("time_elapsed")) << " THEN";
467 IndentInc();
468 LineFeed();
470 Output() << TargetAddress(cnt) << " := " << TargetAddress(cnt) << " - " << TargetAddress(AA("time_elapsed")) << ";";
471 } else {
472 Output() << TargetAddress(cnt) << " := SUB_TIME(" << TargetAddress(cnt) << ", " << TargetAddress(AA("time_elapsed")) << ");";
473 }
474 IndentDec();
475 LineFeed();
476 Output() << "ELSE";
477 LineFeed();
478 IndentInc();
479 Output() << TargetAddress(cnt) << " := TIME#0s;";
480 IndentDec();
481 LineFeed();
482 Output() << "END_IF;";
483 IndentDec();
484 LineFeed();
485 Output() << "END_IF;";
486 LineFeed();
487 }
488 IndentDec();
489 Output() << "END_IF;";
490 LineFeed();
491 LineFeed(1+2);
492
493}
494
495// code blocks: mimique systime by iec timer
497 if(TimersBegin()==TimersEnd()) return;
498 Comment("iec timer to simulate system time");
499 VariableDeclare(TargetAddress(AA("systime_ton")),"TON");
500 VariableDeclare(TargetAddress(AA("systime_recent")),"TIME");
501 VariableDeclare(TargetAddress(AA("systime_now")),"TIME");
502 LineFeed();
503}
504
505// code blocks: mimique systime by iec timer
507 if(TimersBegin()==TimersEnd()) return;
508 Comment("do reset/track systime");
509 Output() << "IF " << mPrefix << "exec_event = -1 " << " THEN" << std::endl;
510 Output() << " " << mPrefix << "systime_ton(IN:=false);" << std::endl;
511 Output() << " " << mPrefix << "systime_recent := TIME#0ms;" << std::endl;
512 Output() << "END_IF;" << std::endl;
513 Output() << mPrefix << "systime_ton(IN:=true, PT:=TIME#2h, ET=>" << mPrefix << "systime_now);" << std::endl;
515 Output() << mPrefix << "time_elapsed := " << mPrefix << "systime_now - " << mPrefix << "systime_recent;" << std::endl;
516 } else {
517 Output() << mPrefix << "time_elapsed := SUB_TIME(" << mPrefix << "systime_now," << mPrefix << "systime_recent);" << std::endl;
518 }
519 Output() << "IF " << mPrefix << "systime_now < TIME#1h THEN" << std::endl;
520 Output() << " " << mPrefix << "systime_recent := " << mPrefix << "systime_now;" << std::endl;
521 Output() << "ELSE" << std::endl;
522 Output() << " " << mPrefix << "systime_ton(IN:=false, PT:=TIME#2h);" << std::endl;
523 Output() << " " << mPrefix << "systime_ton(IN:=true, PT:=TIME#2h);" << std::endl;
524 Output() << " " << mPrefix << "systime_recent := TIME#0ms;" << std::endl;
525 Output() << "END_IF;" << std::endl;
526 LineFeed(1);
527}
528
529
530
531/*
532******************************************************************
533******************************************************************
534******************************************************************
535
536Iec611311stGenerator implementation --- code primitives
537
538******************************************************************
539******************************************************************
540******************************************************************
541*/
542
543
544// generate code
545void Iec61131stCodeGenerator::Comment(const std::string& text) {
546 // write comment
547 if(!mMuteComments) {
548 Output() << "(* " << text << " *)";
549 LineFeed();
550 }
551 // call base to record muted comments
553}
554
555// declaration template
556void Iec61131stCodeGenerator::VariableDeclare(const std::string& laddr, const std::string& ltype) {
557 if((ltype != mIntegerType) && (ltype != mWordType) && (ltype != "BOOL") && (ltype != "STRING") && (ltype != "TIME") && (ltype != "TON"))
558 FCG_ERR("Iec61131stCodeGenerator::VariableDeclare(): unsupported type [" << ltype << "]");
559 Output() << laddr << " : " << ltype << ";";
560 LineFeed();
561}
562
563void Iec61131stCodeGenerator::VariableDeclare(const std::string& laddr, const std::string& ltype, const std::string& lval) {
564 if((ltype != mIntegerType) && (ltype != mWordType) && (ltype != "BOOL") && (ltype != "STRING") && (ltype != "TIME"))
565 FCG_ERR("Iec61131stCodeGenerator::VariableDeclare(): unsupported type [" << ltype << "]");
566 Output() << laddr << " : " << ltype << " := " << lval << ";";
567 LineFeed();
568}
569
570// address transformation
571std::string Iec61131stCodeGenerator::TargetAddress(const AA& address) {
572 std::string res;
573 // cosmetic: use uppercase plain names for input/output variables
574 if(address=="reset") res="RESET";
575 if(address=="status") res="STATUS";
576 if(mEventNameLookup) {
577 if(address=="recent_event") res="RECENT_EVENT";
578 if(address.find("pending_events")==0)
579 if(address!="pending_events_t")
580 res="PENDING_EVENTS"+address.substr(14);
581 if(address.find("enabled_events")==0)
582 if(address!="enabled_events_t")
583 res="ENABLED_EVENTS"+address.substr(14);
584 }
585 if(mStateNameLookup) {
586 if(address.find("parallel_state")==0)
587 if(address!="parallel_state_t")
588 res="PARALLEL_STATE"+address.substr(14);
589 }
590 // base case
591 if(res=="") res=mPrefix+address;
592 return res;
593}
594
595// address transformation
599
600// generate code: integer
604
605// generate code: integer
609
610// generate code: integer
611void Iec61131stCodeGenerator::IntegerAssign(const AA& address, int val){
612 Output() << TargetAddress(address) << " := " << IntegerConstant(val) << ";";
613 LineFeed();
614}
615
616// generate code: integer
617void Iec61131stCodeGenerator::IntegerAssign(const AA& address, const AX& expression){
618 Output() << TargetAddress(address) << " := " << expression << ";";
619 LineFeed();
620}
621
622// generate code: integer
623void Iec61131stCodeGenerator::IntegerIncrement(const AA& address, int val) {
624 if(val>0)
625 Output() << TargetAddress(address) << " := " << TargetAddress(address) << " + " << IntegerConstant(val) << ";";
626 else if(val<0)
627 Output() << TargetAddress(address) << " := " << TargetAddress(address) << " - " << IntegerConstant(-val) << ";";
628 if(val!=0)
629 LineFeed();
630}
631
632// integer maths
634 return AX(expression + " / " + IntegerConstant(val));
635}
636
637// integer maths
639 return AX(expression + " MOD " + IntegerConstant(val));
640}
641
642// integer maths
644 return AX("SHL( IN:=" + WordConstant(1) + " , N:=" + expression + " )" );
645}
646
647// integer maths
649 return true;
650}
651
652// generate code: integer
654 std::string res(ToStringInteger(val));
655 if(mIntegerType == "INT") return AX(res);
656 if(mIntegerType == "DINT") return AX("DINT#" + res);
657 if(mIntegerType == "LINT") return AX("LINT#" + res);
658 FCG_ERR("Iec61131stCodeGenerator: unsupported integer data type");
659 return AX(res);
660}
661
662// generate code: conditionals
664 return AX(TargetAddress(address) + " = " + IntegerConstant(val));
665}
666
667// generate code: conditionals
669 return AX(TargetAddress(address) + " = " + expression);
670}
671
672// generate code: conditionals
674 return AX(TargetAddress(address) + " <> " + IntegerConstant(val));
675}
676
677// generate code: conditionals
679 return AX(TargetAddress(address) + " != " + expression);
680}
681
682// generate code: conditionals
684 return AX(TargetAddress(address) + " > " + IntegerConstant(val));
685}
686
687// generate code: conditionals
689 return AX(TargetAddress(address) + " < " + IntegerConstant(val));
690}
691
692
693
694// generate code: word
698
699// generate code: word
703
704// generate code: word
706 Output() << TargetAddress(address) << " := " << WordConstant(val) << ";";
707 LineFeed();
708}
709
710// generate code: word
711void Iec61131stCodeGenerator::WordAssign(const AA& address, const AX& expression){
712 Output() << TargetAddress(address) << " := " << expression << ";";
713 LineFeed();
714}
715
716
717// generate code: word
718void Iec61131stCodeGenerator::WordOr(const AA& address, word_t val) {
719 Output() << TargetAddress(address) << " := " << TargetExpression(address) << " OR " << WordConstant(val) << ";";
720 LineFeed();
721}
722
723// generate code: word
724void Iec61131stCodeGenerator::WordOr(const AA& address, const AX& expression) {
725 Output() << TargetAddress(address) << " := " << TargetExpression(address) << " OR " << expression << ";";
726 LineFeed();
727}
728
729// generate code: word
730void Iec61131stCodeGenerator::WordOr(const AA& address, const AA& op1, const AA& op2) {
731 Output() << TargetAddress(address) << " := " << TargetExpression(op1) << " OR " << TargetExpression(op2) << ";";
732 LineFeed();
733}
734
735// generate code: word
736void Iec61131stCodeGenerator::WordOr(const AA& address, const AA& op1, word_t op2) {
737 Output() << TargetAddress(address) << " := " << TargetExpression(op1) << " OR " << WordConstant(op2) << ";";
738 LineFeed();
739}
740
741// generate code: word
742void Iec61131stCodeGenerator::WordAnd(const AA& address, word_t val) {
743 Output() << TargetAddress(address) << " := " << TargetAddress(address) << " AND " << WordConstant(val) << ";";
744 LineFeed();
745}
746
747// generate code: word
748void Iec61131stCodeGenerator::WordAnd(const AA& address, const AX& expression) {
749 Output() << TargetAddress(address) << " := " << TargetAddress(address) << " AND " << expression << ";";
750 LineFeed();
751}
752
753// generate code: word
754void Iec61131stCodeGenerator::WordAnd(const AA& address, const AA& op1, const AA& op2) {
755 Output() << TargetAddress(address) << " := " << TargetAddress(op1) << " AND " << TargetAddress(op2) << ";";
756 LineFeed();
757}
758
759// generate code: word
760void Iec61131stCodeGenerator::WordAnd(const AA& address, const AA& op1, word_t op2) {
761 Output() << TargetAddress(address) << " := " << TargetExpression(op1) << " AND " << WordConstant(op2) << ";";
762 LineFeed();
763}
764
765// generate code: word
766void Iec61131stCodeGenerator::WordNand(const AA& address, const AX& expression) {
767 Output() << TargetAddress(address) << " := " << TargetAddress(address) << " AND (NOT " << expression << " );";
768 LineFeed();
769}
770
771// generate code: conditionals
773 return AX("( " + TargetAddress(address) + " AND " + WordConstant(0x01<<idx) + " ) <> " + WordConstant(0));
774}
775
776// generate code: conditionals
778 return AX("( " + TargetAddress(address) + " AND " + WordConstant(0x01<<idx) + " ) == " + WordConstant(0));
779}
780
783 return AX("( " + TargetAddress(address) + " AND " + WordConstant(mask) + " ) <> " + WordConstant(0));
784}
785
786// generate code: conditionals
788 return AX(TargetAddress(address) + " = " + WordConstant(val));
789}
790
791// generate code: conditionals
793 return AX("NOT ( " + TargetAddress(address) + " = " + WordConstant(val) + " )");
794}
795
796// generate code: word
798 // have neet zero
799 if(val==0) return AX( mWordType + "#0");
800 // construct typed hex representation
801 std::stringstream sstr;
802 sstr << mWordType << "#16#" << std::setbase(16) << std::setfill('0');
803 if(mWordType == "BYTE") sstr << std::setw(2) << (val & 0xff);
804 else if(mWordType == "WORD") sstr << std::setw(4) << (val & 0xffff);
805 else if(mWordType == "DWORD") sstr << std::setw(8) << (val & 0xffffffff);
806 else if(mWordType == "LWORD") sstr << std::setw(16) << (val & 0xffffffffffffffff);
807 else FCG_ERR("Iec61131stCodeGenerator: unsupported word data type");
808 AX res(sstr.str());
809 return res;
810}
811
812
813// generate code: bool
815 VariableDeclare(TargetAddress(address),"BOOL");
816}
817
818// generate code: bool
819void Iec61131stCodeGenerator::BooleanDeclare(const AA& address, int val){
820 std::string valstr;
821 if(val) valstr="true"; else valstr="false";
822 VariableDeclare(TargetAddress(address),"BOOL",valstr);
823}
824
825// generate code: bool
826void Iec61131stCodeGenerator::BooleanAssign(const AA& address, int val){
827 std::string valstr;
828 if(val) valstr="true"; else valstr="false";
829 Output() << TargetAddress(address) << " := " << valstr << ";";
830 LineFeed();
831}
832
833// generate code: bool
834void Iec61131stCodeGenerator::BooleanAssign(const AA& address, const AX& expression){
835 Output() << TargetAddress(address) << " := " << expression << ";";
836 LineFeed();
837}
838
839// generate code: bool
841 return AX(TargetAddress(op1) + " <> " + TargetAddress(op2));
842}
843
844// generate code: bool
846 return AX(TargetAddress(op1) + " = " + TargetAddress(op2));
847}
848
849
850// const-int array (local iec only helper)
852 std::stringstream strstr;
853 int newline=20;
854 if(val.size()<25) newline=25;
855 strstr << "[ " ;
856 size_t vit=0;
857 while(true) {
858 if(vit==val.size()) break;
859 strstr << IntegerConstant(val[vit]);
860 ++vit;
861 if(vit==val.size()) break;
862 strstr << ", ";
863 newline--;
864 if(newline==0) {
865 strstr << std::endl << " ";
866 newline=20;
867 }
868 }
869 strstr << " ]";
870 return AX(strstr.str());
871}
872
873// const-int-array
874void Iec61131stCodeGenerator::CintarrayDeclare(const AA& address, int offset, const std::vector<int>& val) {
875 if(val.size()==0) {
876 FCG_ERR("Iec61131stCodeGenerator::Cintarray(): ignoring empty const vector");
877 return;
878 }
879 if(val.size()+offset >= (1ULL << (mIntegerSize-1))) {
880 FCG_ERR("Iec61131stCodeGenerator::Cwordarray(): const vector exceeds address range");
881 return;
882 }
883 // declare with initialiser
884 Output() << TargetAddress(address) << " : ARRAY[" << offset << ".." << val.size()+offset-1 << "] OF " << mIntegerType << " := ";
885 LineFeed();
886 IndentInc();
887 Output() << IntarrayConstant(val) << ";";
888 LineFeed();
889 IndentDec();
890}
891
892
893// int array access by const
895 return AA(address + "[" + ToStringInteger(index) + "]");
896};
897
898// int array access by expression
900 return AA(address + "[" + TargetAddress(indexaddr) + "]");
901};
902
903// tell parent class about this feature
905 return true;
906};
907
908
909// const-word array
911 std::stringstream strstr;
912 int newline=8;
913 if(val.size()<11) newline=15;
914 strstr << "[ " ;
915 size_t vit=0;
916 while(true) {
917 if(vit==val.size()) break;
918 strstr << WordConstant(val[vit]);
919 ++vit;
920 if(vit==val.size()) break;
921 strstr << ", ";
922 newline--;
923 if(newline==0) {
924 strstr << std::endl << " ";
925 newline=8;
926 }
927 }
928 strstr << " ]";
929 return AX(strstr.str());
930}
931
932// const-word-array
933void Iec61131stCodeGenerator::CwordarrayDeclare(const AA& address, int offset, const std::vector<word_t>& val) {
934 if(val.size()==0) {
935 FCG_ERR("Iec61131stCodeGenerator::Cwordarray(): ignoring empty const vector");
936 return;
937 }
938 if(val.size()+offset >= (1ULL << (mIntegerSize-1))) {
939 FCG_ERR("Iec61131stCodeGenerator::Cwordarray(): const vector exceeds addres range");
940 return;
941 }
942 // declare with initialiser
943 Output() << TargetAddress(address) << " : ARRAY[" << offset << ".." << val.size()+offset-1 << "] OF " << mWordType << " := ";
944 LineFeed();
945 IndentInc();
946 Output() << WordarrayConstant(val) << ";";
947 LineFeed();
948 IndentDec();
949}
950
951
952// word-array access by const
954 return AA(address + "[" + ToStringInteger(index) + "]");
955};
956
957// word array access by expression
959 return AA(address + "[" + TargetAddress(indexaddr) + "]");
960};
961
962// tell parent class about this feature
964 return true;
965};
966
967// generate code: string constant
969 AX res;
970 res.append(1,'\'');
971 for(std::size_t i=0; i<val.length(); ++i) {
972 char c=val.at(i);
973 // terminate
974 if(c==0) break;
975 // quote quote
976 if(c=='\'') { res.append("$'"); continue; }
977 // quote dollar
978 if(c=='$') { res.append("$$"); continue; }
979 // printable ascii
980 if((c>=0x20) && (c<0x7f)) { res.append(1,c); continue; };
981 // error on other (alternative: use octal encoding to support utf8)
982 FCG_ERR("EmbeddedcCodeGenerator: non-printable ascii or other encoding unsupported [" << val <<"]");
983 }
984 res.append(1,'\'');
985 return res;
986}
987
988// literal const-string array
990 std::stringstream strstr;
991 int newline;
992 if(val.size()<4) {
993 newline=4;
994 strstr << "[ ";
995 } else {
996 newline=1;
997 strstr << "[ " << std::endl;
998 }
999 size_t vit=0;
1000 while(true) {
1001 if(vit==val.size()) break;
1002 strstr << StringConstant(val[vit]);
1003 ++vit;
1004 if(vit==val.size()) break;
1005 strstr << ", ";
1006 newline--;
1007 if(newline==0) {
1008 strstr << std::endl;
1009 newline=1;
1010 }
1011 }
1012 strstr << " ]";
1013 return AX(strstr.str());
1014}
1015
1016
1017// const-string-array
1018void Iec61131stCodeGenerator::CstrarrayDeclare(const AA& address, int offset, const std::vector<std::string>& val) {
1019 if(val.size()==0) {
1020 FCG_ERR("Iec61131stCodeGenerator::Cstrarray(): ignoring empty const vector");
1021 return;
1022 }
1023 if(val.size()+offset>= (1ULL << (mIntegerSize-1))) {
1024 FCG_ERR("Iec61131stCodeGenerator::Cstrarray(): const vector exceeds addres range");
1025 return;
1026 }
1027 // figure string size
1028 size_t len=0;
1029 for(size_t i=0; i<val.size(); ++i)
1030 if(val[i].size()>len) len=val[i].size();
1031 // declare with initialiser
1032 Output() << TargetAddress(address) << " : ARRAY[" << offset << ".." << val.size()+offset-1 << "] OF STRING[" << ToStringInteger(len) <<"] := ";
1033 LineFeed();
1034 IndentInc();
1035 Output() << StrarrayConstant(val) << ";";
1036 LineFeed();
1037 IndentDec();
1038}
1039
1040
1041// string-array access by const
1043 return AA(address + "[" + ToStringInteger(index) + "]");
1044};
1045
1046// string array access by expression
1048 return AA(address + "[" + TargetAddress(indexaddr) + "]");
1049};
1050
1051// tell parent class about this feature
1053 return true;
1054};
1055
1056// int-array
1057void Iec61131stCodeGenerator::IntarrayDeclare(const AA& address, int offset, const std::vector<int>& val) {
1058 if(val.size()==0) {
1059 FCG_ERR("Iec61131stCodeGenerator::Intarray(): ignoring empty const vector");
1060 return;
1061 }
1062 if(val.size()+offset >= (1ULL << (mIntegerSize-1))) {
1063 FCG_ERR("Iec61131stCodeGenerator::Intarray(): const vector exceeds addres range");
1064 return;
1065 }
1066 // declare with initialiser
1067 Output() << TargetAddress(address) << " : ARRAY[" << offset << ".." << val.size()+offset-1 << "] OF " << mIntegerType << " := ";
1068 LineFeed();
1069 IndentInc();
1070 Output() << IntarrayConstant(val) << ";";
1071 LineFeed();
1072 IndentDec();
1073}
1074
1075
1076// int-array
1077void Iec61131stCodeGenerator::IntarrayDeclare(const AA& address, int offset, int len) {
1078 if(len==0) {
1079 FCG_ERR("Iec61131stCodeGenerator::Intarray(): ignoring empty const vector");
1080 return;
1081 }
1082 if(len+offset >= (1LL << (mIntegerSize-1))) {
1083 FCG_ERR("Iec61131stCodeGenerator::Intarray(): const vector exceeds addres range");
1084 return;
1085 }
1086 Output() << TargetAddress(address) << " : ARRAY[" << offset << ".." << len+offset-1 << "] OF " << mIntegerType << ";";
1087 LineFeed();
1088}
1089
1090// word-array access by const
1092 return AA(address + "[" + ToStringInteger(index) + "]");
1093};
1094
1095// word array access by expression
1097 return AA(address + "[" + TargetAddress(indexaddr) + "]");
1098};
1099
1100// tell parent class about this feature
1102 return true;
1103};
1104
1105
1106// word-array
1107void Iec61131stCodeGenerator::WordarrayDeclare(const AA& address, int offset, const std::vector<word_t>& val) {
1108 if(val.size()==0) {
1109 FCG_ERR("Iec61131stCodeGenerator::Wordarray(): ignoring empty const vector");
1110 return;
1111 }
1112 if(val.size()+offset >= (1ULL << (mIntegerSize-1))) {
1113 FCG_ERR("Iec61131stCodeGenerator::Wordarray(): const vector exceeds addres range");
1114 return;
1115 }
1116 // declare with initialiser
1117 Output() << TargetAddress(address) << " : ARRAY[" << offset << ".." << val.size()+offset-1 << "] OF " << mWordType << " := ";
1118 LineFeed();
1119 IndentInc();
1120 Output() << WordarrayConstant(val) << ";";
1121 LineFeed();
1122 IndentDec();
1123}
1124
1125
1126// word-array
1127void Iec61131stCodeGenerator::WordarrayDeclare(const AA& address, int offset, int len) {
1128 if(len==0) {
1129 FCG_ERR("Iec61131stCodeGenerator::Wordarray(): ignoring empty const vector");
1130 return;
1131 }
1132 if(len>= (1LL << (mIntegerSize-1))) {
1133 FCG_ERR("Iec61131stCodeGenerator::Wordarray(): const vector exceeds addres range");
1134 return;
1135 }
1136 Output() << TargetAddress(address) << " : ARRAY[" << offset << ".." << len+offset-1 << "] OF " << mWordType << ";";
1137 LineFeed();
1138}
1139
1140// word-array access by const
1142 return AA(address + "[" + ToStringInteger(index) + "]");
1143};
1144
1145// word array access by expression
1147 return AA(address + "[" + TargetAddress(indexaddr) + "]");
1148};
1149
1150// tell parent class about this feature
1152 return true;
1153};
1154
1155
1156
1157// event set
1158/*
1159void Iec61131stCodeGenerator::EventSetDeclareImport(const AA& address) {
1160 // same as declare
1161 EventSetDeclare(address);
1162}
1163*/
1164
1165// generate code: conditionals
1166void Iec61131stCodeGenerator::IfTrue(const AX& expression) {
1167 Output() << "IF " << expression << " THEN";
1168 LineFeed();
1169 IndentInc();
1170}
1171
1172// generate code: conditionals
1173void Iec61131stCodeGenerator::IfFalse(const AX& expression) {
1174 Output() << "IF NOT " << expression << " THEN";
1175 LineFeed();
1176 IndentInc();
1177}
1178
1179// generate code: conditionals
1180void Iec61131stCodeGenerator::IfWord(const AX& expression) {
1181 Output() << "IF ( " << expression << " ) <> " << WordConstant(0) << " THEN";
1182 LineFeed();
1183 IndentInc();
1184}
1185
1186// generate code: conditionals
1188 IndentDec();
1189 Output() << "ELSE";
1190 LineFeed();
1191 IndentInc();
1192}
1193
1194// generate code: conditionals
1196 IndentDec();
1197 Output() << "ELSIF " << expression << " THEN";
1198 LineFeed();
1199 IndentInc();
1200}
1201
1202// generate code: conditionals
1204 IndentDec();
1205 Output() << "END_IF;";
1206 LineFeed();
1207}
1208
1209// switch control
1211 Output() << "CASE " << TargetAddress(address) << " OF";
1212 LineFeed();
1213}
1214
1215// switch control
1216void Iec61131stCodeGenerator::SwitchCase(const AA& address, int val){
1217 (void) address;
1218 Output() << IntegerConstant(val) << ":";
1219 LineFeed();
1220 IndentInc();
1221}
1222
1223// switch control
1224void Iec61131stCodeGenerator::SwitchCases(const AA& address, int from, int to){
1225 // bail out on empty
1226 if(from>to) {
1227 FCG_VERB0("CodeGenerator: WARNING: inconsistent empty range of switch-cases");
1228 IndentInc();
1229 return;
1230 }
1231 // simplify to singleton
1232 if(from==to) {
1233 SwitchCase(address, from);
1234 return;
1235 }
1236 // do range
1237 Output() << IntegerConstant(from) << " .. " << IntegerConstant(to) << ":";
1238 LineFeed();
1239 IndentInc();
1240}
1241
1242// switch control
1243void Iec61131stCodeGenerator::SwitchCases(const AA& address, const std::set< int >& vals){
1244 // bail out on empty
1245 if(vals.empty()) {
1246 FCG_VERB0("CodeGenerator: WARNING: inconsistent empty range of switch-cases");
1247 IndentInc();
1248 return;
1249 }
1250 // simplify to range
1251 int from=*vals.begin();
1252 int to= *(--vals.end());
1253 if(to+1-from== (int) vals.size()) {
1254 SwitchCases(address,from,to);
1255 return;
1256 }
1257 // do set
1258 std::set< int >::const_iterator vit=vals.begin();
1259 for(; vit!=vals.end(); ++ vit) {
1260 if(vit!=vals.begin()) Output() << ", ";
1261 Output() << IntegerConstant(*vit);
1262 }
1263 Output() << ":";
1264 LineFeed();
1265 IndentInc();
1266}
1267
1268// switch control
1272
1273// switch control
1275 Output() << "END_CASE;";
1276 LineFeed();
1277}
1278
1279// switch control
1281 return true;
1282}
1283
1284// loops
1286 Output() << "WHILE true DO";
1287 LineFeed();
1288 IndentInc();
1289}
1290
1291// loops
1293 Output() << "IF " << expression << " THEN EXIT; END_IF;";
1294 LineFeed();
1295}
1296
1297// loops
1299 IndentDec();
1300 Output() << "END_WHILE;";
1301 LineFeed();
1302}
1303
1304// loops
1306 Output() << "RETURN;";
1307 LineFeed();
1308}
1309
1310// timer
1311void Iec61131stCodeGenerator::TimerDeclare(const AA& address, const std::string &val) {
1312 // todo: type check time literal
1313 (void) val;
1314 VariableDeclare(TargetAddress(AA("timer_"+address+"_cnt")),"TIME");
1315 VariableDeclare(TargetAddress(AA("timer_"+address+"_run")),"BOOL");
1316}
1318 Output() << TargetAddress(AA("timer_"+address+"_run")) << " := true;";
1319 LineFeed();
1320}
1322 Output() << TargetAddress(AA("timer_"+address+"_run")) << " := false;";
1323 LineFeed();
1324}
1325void Iec61131stCodeGenerator::TimerReset(const AA& address, const std::string& litval) {
1326 Output() << TargetAddress(AA("timer_"+address+"_cnt")) << " := " << litval << ";";
1327 LineFeed();
1328}
1329
1331 return AX(TargetAddress(AA("timer_"+address+"_run")) + " AND (" +
1332 TargetAddress(AA("timer_"+address+"_cnt")) + " <= " + TimeConstant(0) + ")");
1333}
1334
1336 std::string res("TIME#" + ToStringInteger(val) + "ms");
1337 return AX(res);
1338}
1339
1340
1341// output actions
1342void Iec61131stCodeGenerator::RunActionSet(const std::string& address) {
1343 Output() << address << " := true;" ;
1344 LineFeed();
1345}
1346void Iec61131stCodeGenerator::RunActionClr(const std::string& address) {
1347 Output() << address << " := false;" ;
1348 LineFeed();
1349}
1351 Output() << expression << ";";
1352 LineFeed();
1353}
1354
1355Iec61131stCodeGenerator::IECVariableType Iec61131stCodeGenerator::CurrentVariableType(void) {
1356 return mCurrentVariableType;
1357}
1358
1359void Iec61131stCodeGenerator::CurrentVariableType(const IECVariableType & type) {
1360 mCurrentVariableType = type;
1361}
1362
1363
#define FAUDES_REGISTERCODEGENERATOR(ftype, ctype)
Class registration macro.
Code-generator for target IEC 61131-3 ST.
virtual void LineFeed(int lines=1)
LineFeed (convenience support for derived classes)
virtual const std::string & Name(void) const
Get objects's name (reimplementing base faudes::Type)
LineIterator LinesEnd()
Access to line records by iterator.
std::map< std::string, ActionAddress >::iterator ActionAddressIterator
Access to action record by iterator.
TimerIterator TimersBegin()
Access to timer records by iterator.
virtual void IndentInc()
Indentation (convenience support for derived classes)
TimerIterator TimersEnd()
Access to timer records by iterator.
int mWordSize
compressed boolean capacity of target type word
bool mMuteComments
mute comments
LineIterator LinesBegin()
Access to line records by iterator.
int mIntegerSize
compressed boolean capacity of target type integer
std::map< std::string, TimerConfiguration >::iterator TimerIterator
Access to timer records by iterator.
virtual std::ostream & Output(void)
Output stream.
std::map< std::string, LineAddress >::iterator LineIterator
Access to line records by iterator.
static std::string VersionString(void)
Version (refers to macro COMPILEDES_VERSION, defined in cgp_codegenerator.h)
Idx Size(void) const
Number of generators.
virtual void IndentDec()
Indentation (convenience support for derived classes)
ActionAddressIterator ActionAddressesEnd()
Access to action addresses by iterator.
ActionAddressIterator ActionAddressesBegin()
Access to action addresses by iterator.
unsigned long word_t
Code-generator internal data type of target words.
Abstract address; see also Absstract_Addresses.
Abstract expression; see also Absstract_Addresses.
Execution semantics in terms of code primitives.
virtual void DeclareTimers(void)
Use target implementation to declare timers, typically "timer_run_*" and "timer_cnt_*".
bool mBitAddressArithmetic
code option: compute bit and word address on target
std::string mStateUpdateHook
code option: state change hook
virtual void DeclareSmallCarray(void)
Declare bit-mask loop-ups.
virtual void DoGenerateResetCode(void)
cut-and-paste template for code snippet assembly
bool mArrayForState
code option: use int arrays to represent that overall state
virtual void DeclareReset(void)
Declare "reset".
virtual void LiteralAppend(void)
Cosmetic: append literally from configuration.
virtual void DeclareStatus(void)
Declare "status".
virtual void DeclareRecentEvent(void)
Declare "recent_event".
virtual void Comment(const std::string &text)
Target comments (see EmbeddedcCodeGenerator for consistent reimplementation pattern)
virtual void DeclareAux(void)
Declare variables local to the provided snippets, e.g. helpers for bit-mask computation.
bool mEventNameLookup
code option: event name lookup
virtual void DeclareEventNameLookup(void)
Declare symbolic name lookup tables.
std::map< std::string, bitarray_rec > mBitarrays
Record of all declared bit-arrays.
bool mStateNameLookup
code option: state name lookup
virtual void DoReadTargetConfiguration(TokenReader &rTr)
re-implement token i/o for extra configuration
virtual void DeclareParallelState(void)
Declare "parallel_state".
std::string mIntegerType
target data type for integer
virtual void DeclareLoopState(void)
Declare loop state, i.e. line levels, loop flag.
virtual void DoGenerateCyclicCode(void)
cut-and-paste template for code snippet assembly
virtual void Clear(void)
Clear all data.
std::string mWordType
target data type for word
virtual void DoWriteTargetConfiguration(TokenWriter &rTw) const
re-implement token i/o for extra configuration
virtual void DeclareLargeCarray(void)
Declare compiled transition relations.
virtual void ResetState(void)
Reset state.
bool mArrayForBitmasks
code option: use const array to represent bit-masks
virtual void DeclareStateNameLookup(void)
Declare symbolic name lookup tables.
virtual void DoCompile(void)
virtual hook to extend compiled data
virtual void LiteralPrepend(void)
Cosmetic: prepend literally from configuration data.
std::vector< bool > mHasStateNames
record per generator whether there is a lookup table
virtual void DeclarePendingEvents(void)
Declare "pending_events" and "enabled_events".
std::string mPrefix
universal prefix (pseudo name space)
std::string mEventExecutionHook
code option: event exec hook
Implementation of primitives by IEC 61131 ST.
virtual void WordNand(const AA &address, const AX &expression)
generate code: conditionals
virtual AX IntegerIsEq(const AA &address, int val)
generate code: conditionals
virtual void DoReadTargetConfiguration(TokenReader &rTr)
File i/o.
virtual void RunActionSet(const std::string &address)
generate code: conditionals
virtual void IfElseIfTrue(const AX &expression)
generate code: conditionals
virtual void DoWriteTargetConfiguration(TokenWriter &rTw) const
File i/o.
virtual AX IntegerIsLess(const AA &address, int val)
generate code: conditionals
virtual void DeclareImportPhysicalIo(void)
generate code: conditionals
virtual void UpdateSystime(void)
generate code: conditionals
virtual AX BooleanIsNotEq(const AA &op1, const AA &op2)
generate code: conditionals
virtual void CintarrayDeclare(const AA &address, int offset, const std::vector< int > &val)
generate code: conditionals
virtual void IfFalse(const AX &expression)
generate code: conditionals
virtual bool HasCintarray(void)
generate code: conditionals
virtual void WordDeclare(const AA &address)
generate code: conditionals
virtual bool HasWordarray(void)
generate code: conditionals
virtual void IfTrue(const AX &expression)
generate code: conditionals
virtual void BooleanDeclare(const AA &address)
generate code: conditionals
virtual ~Iec61131stCodeGenerator(void)
Explicit destructor.
virtual AX BooleanIsEq(const AA &op1, const AA &op2)
generate code: conditionals
virtual void BooleanAssign(const AA &address, int val)
generate code: conditionals
virtual void IfWord(const AX &expression)
generate code: conditionals
virtual AX WordIsEq(const AA &address, word_t val)
generate code: conditionals
virtual void InsertExecHooks(void)
generate code: conditionals
virtual void TimerDeclare(const AA &address, const std::string &val)
generate code: conditionals
void DoGenerate(void)
code generation hook (overall)
virtual void Clear(void)
Clear all data.
virtual void SwitchEnd(void)
generate code: conditionals
virtual void LoopEnd(void)
generate code: conditionals
virtual AX WordarrayConstant(const std::vector< word_t > &val)
generate code: conditionals
virtual AX StrarrayConstant(const std::vector< std::string > &val)
generate code: conditionals
virtual void TimerStart(const AA &address)
generate code: conditionals
virtual void WordAssign(const AA &address, word_t val)
generate code: conditionals
virtual AA CstrarrayAccess(const AA &address, int index)
generate code: conditionals
virtual void DeclareSystime(void)
generate code: conditionals
virtual AX WordIsNotEq(const AA &address, word_t val)
generate code: conditionals
virtual void WordarrayDeclare(const AA &address, int offset, int len)
generate code: conditionals
virtual AX StringConstant(const std::string &val)
generate code: conditionals
virtual void Comment(const std::string &text)
generate code: conditionals
virtual void TimerReset(const AA &address, const std::string &val)
generate code: conditionals
virtual AX IntegerConstant(int val)
generate code: conditionals
virtual void DecrementTimers(void)
code snippet
virtual AX IntegerRemainder(const AX &expression, int val)
generate code: conditionals
std::string mLiteralCyclic
option: extra cyclic code
virtual void IfEnd(void)
generate code: conditionals
virtual bool HasIntarray(void)
generate code: conditionals
virtual AA CintarrayAccess(const AA &address, int index)
generate code: conditionals
void DoCompile(void)
add my preferences to DoCompile
virtual void DeclareImportSymbolicIo(void)
generate code: conditionals
virtual AX IntarrayConstant(const std::vector< int > &val)
generate code: conditionals
virtual AX WordIsMaskSet(const AA &address, word_t mask)
generate code: conditionals
virtual std::string TargetAddress(const AA &address)
abstract address conversion
virtual bool HasCwordarray(void)
generate code: conditionals
virtual int CountImportPhysicalIo(void)
generate code: conditionals
virtual AX IntegerIsGreater(const AA &address, int val)
generate code: conditionals
virtual void RunActionClr(const std::string &address)
generate code: conditionals
virtual AX TimeConstant(int val)
generate code: conditionals
virtual AX WordIsBitSet(const AA &address, int idx)
generate code: conditionals
virtual bool HasIntmaths(void)
generate code: conditionals
virtual AA WordarrayAccess(const AA &address, int index)
generate code: conditionals
virtual void DoGenerateLookups(void)
code generation hook (lookup functions)
virtual AX TimerIsElapsed(const AA &address)
generate code: conditionals
virtual void LoopBegin(void)
generate code: conditionals
virtual void WordOr(const AA &address, word_t val)
generate code: conditionals
virtual void ResetState(void)
generate code: conditionals
virtual void SwitchBegin(const AA &address)
generate code: conditionals
virtual void RunActionExe(const AX &expression)
generate code: conditionals
virtual void CstrarrayDeclare(const AA &address, int offset, const std::vector< std::string > &val)
generate code: conditionals
virtual AX WordIsBitClr(const AA &address, int idx)
generate code: conditionals
virtual void LoopBreak(const AX &expression)
generate code: conditionals
virtual void SwitchBreak(void)
generate code: conditionals
virtual AA IntarrayAccess(const AA &address, int index)
generate code: conditionals
virtual AX IntegerIsNotEq(const AA &address, int val)
generate code: conditionals
virtual void IntegerAssign(const AA &address, int val)
generate code: conditionals
virtual void IfElse(void)
generate code: conditionals
virtual void WordAnd(const AA &address, word_t val)
generate code: conditionals
virtual void IntegerDeclare(const AA &address)
generate code: conditionals
virtual void SwitchCases(const AA &address, int from, int to)
generate code: conditionals
virtual void DeclareTimers(void)
generate code: conditionals
bool mHasIecTimeOperators
option: overloaded operators for time maths
virtual void VariableDeclare(const std::string &laddr, const std::string &ltype)
generate code: conditionals
virtual AX IntegerBitmask(const AX &expression)
generate code: conditionals
virtual void IntegerIncrement(const AA &address, int val)
generate code: conditionals
Iec61131stCodeGenerator(void)
Constructor.
virtual bool HasMultiCase(void)
generate code: conditionals
std::string mIecDeclareSymbolic
option: formal declaration of io variables
virtual void CwordarrayDeclare(const AA &address, int offset, const std::vector< word_t > &val)
generate code: conditionals
virtual AX WordConstant(word_t val)
generate code: conditionals
virtual bool HasCstrarray(void)
generate code: conditionals
virtual AA CwordarrayAccess(const AA &address, int index)
generate code: conditionals
virtual void IntarrayDeclare(const AA &address, int offset, int len)
generate code: conditionals
virtual void SwitchCase(const AA &address, int val)
generate code: conditionals
virtual void DoGenerateFunction(void)
code generation hook (function block)
virtual void TimerStop(const AA &address)
generate code: conditionals
virtual int CountImportSymbolicIo(void)
generate code: conditionals
virtual void FunctionReturn(void)
generate code: conditionals
virtual AX TargetExpression(const AA &address)
abstract address conversion
std::string mIecDeclarePhysical
option: formal declaration of io lines
virtual AX IntegerQuotient(const AX &expression, int val)
generate code: conditionals
virtual void LiteralCyclic(void)
generate code: conditionals