CompileDES  3.13
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 
19 Iec611311stGenerator 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  mLiteralCyclic="";
56 }
57 
58 //DoReadTargetConfiguration(rTr)
60  FD_DCG("Iec61131stCodeGenerator::DoReadTargetConfiguration()");
61  // base
63  // iec option
64  Token token;
65  if(rTr.ExistsBegin("IecDeclarePhysical")) {
66  rTr.ReadBegin("IecDeclarePhysical",token);
67  mIecDeclarePhysical= token.AttributeStringValue("val");
68  rTr.ReadEnd("IecDeclarePhysical");
69  }
70  // iec option
71  if(rTr.ExistsBegin("IncludeCyclic"))
72  rTr.ReadVerbatim("IncludeCyclic",mLiteralCyclic);
73  if(rTr.ExistsBegin("IecTimeOperators")) {
74  rTr.ReadBegin("IecTimeOperators",token);
75  mHasIecTimeOperators= token.AttributeIntegerValue("val");
76  rTr.ReadEnd("IecTimeOperators");
77  }
78 }
79 
80 //DoWriteTargetConfiguration(rTw)
82  FD_DCG("Iec61131stCodeGenerator::DoWriteTargetConfiguration()");
83  // base
85  // code option
86  Token token;
87  token.SetEmpty("IecDeclarePhysical");
88  token.InsAttributeString("val",mIecDeclarePhysical);
89  rTw.Write(token);
90  // code option
91  if(mLiteralCyclic.size()>0)
92  rTw.WriteVerbatim("IncludeCyclic",mLiteralCyclic);
93  token.SetEmpty("IecTimeOperators");
94  token.InsAttributeBoolean("val",mHasIecTimeOperators);
95  rTw.Write(token);
96 }
97 
98 
99 
100 /*
101 ******************************************************************
102 ******************************************************************
103 ******************************************************************
104 
105 Iec611311stGenerator implementation --- code organisation
106 
107 ******************************************************************
108 ******************************************************************
109 ******************************************************************
110 */
111 
112 // DoCompile()
114  // call base
116  // my preferences
118  FCG_VERB1("Iec61131stCodeGenerator::Compile(): prefer compiled bitmasks over bit-address maths");
119  mBitAddressArithmetic = false;
120  }
121  // set array for state for returnvalue
123  FCG_VERB1("Iec61131stCodeGenerator::Compile(): using array for state as return value datatype");
124  mArrayForState = true;
125  }
126 }
127 
128 
129 // DoGenerate()
131  // cut and paste from base
132  mBitarrays.clear();
133  // doit: say hello
134  Comment("************************************************");
135  Comment("CodeGenerator: Target IEC 61131 Structured Text ");
136  Comment("************************************************");
137  LineFeed(1);
138  Comment(std::string("CompileDES ") + VersionString());
139  Comment(std::string("Configuration: ") + Name());
140  LineFeed(2+1);
141  // snippets
142  LiteralPrepend();
143  // doit: function block to host cyclic code
145  // doit: functions to host lookup tables
147  // snippets
148  LiteralAppend();
149  Comment("************************************************");
150  Comment("CodeGenerator: Generated Code Ends Here ");
151  Comment("************************************************");
152 }
153 
154 
155 
156 // code blocks: cyclic function block
158  Comment("************************************************");
159  Comment("* function block to host cyclic code *");
160  Comment("************************************************");
161  LineFeed(2);
162  Output() << "FUNCTION_BLOCK " << mPrefix <<"cyclic_fb";
163  LineFeed(2);
164  Output() << "VAR_INPUT";
165  LineFeed(2);
166  DeclareReset();
167  Output() << "END_VAR";
168  LineFeed(2);
169  Output() << "VAR_OUTPUT";
170  LineFeed(2);
171  DeclareStatus();
175  Output() << "END_VAR";
176  LineFeed(2);
177  Output() << "VAR";
178  LineFeed(2);
183  DeclareTimers();
184  DeclareAux();
187  DeclareSystime();
188  Output() << "END_VAR";
189  LineFeed(2);
190  if(CountImportSymbolicIo()>0) {
191  Output() << "VAR_EXTERNAL";
192  LineFeed(2);
194  Output() << "END_VAR";
195  LineFeed(2);
196  }
197  if(CountImportPhysicalIo()>0) {
199  LineFeed(2);
201  Output() << "END_VAR";
202  LineFeed(2);
203  }
204  LiteralCyclic();
206  DecrementTimers();
208  LineFeed(1+2);
209  Comment("************************************************");
210  Comment("* end of cyclic function block *");
211  LineFeed(1);
212  Output() << "END_FUNCTION_BLOCK";
213  LineFeed();
214  LineFeed(2+1);
215 }
216 
217 
218 // code blocks: function to host lookup tables
220  if(mEventNameLookup) {
221  Comment("************************************************");
222  Comment("* function to host the event name loopup table *");
223  Comment("************************************************");
224  LineFeed(2);
225  Output() << "FUNCTION " << mPrefix <<"event_lookup_f" << " : STRING";
226  LineFeed(2);
227  Output() << "VAR_INPUT";
228  LineFeed();
229  Output() << "IDX : " << mIntegerType <<";";
230  LineFeed();
231  Output() << "END_VAR";
232  LineFeed(2);
233  Output() << "VAR CONSTANT";
234  LineFeed();
236  Output() << "END_VAR";
237  LineFeed(2);
238  Output() << mPrefix <<"event_lookup_f" << " := " << mPrefix << "event_lookup[IDX]" << ";";
239  LineFeed(2);
240  Output() << "END_FUNCTION";
241  LineFeed();
242  LineFeed(2+1);
243  }
244  if(mStateNameLookup) {
245  Comment("************************************************");
246  Comment("* function to host state name loopup tables *");
247  Comment("************************************************");
248  LineFeed(2);
249  Output() << "FUNCTION " << mPrefix <<"state_lookup_f" << " : STRING";
250  LineFeed(2);
251  Output() << "VAR_INPUT";
252  LineFeed();
253  Output() << "GID : " << mIntegerType <<";";
254  LineFeed();
255  Output() << "IDX : " << mIntegerType <<";";
256  LineFeed();
257  Output() << "END_VAR";
258  LineFeed(2);
259  Output() << "VAR CONSTANT";
260  LineFeed();
262  Output() << "END_VAR";
263  LineFeed(2);
264  Output() << mPrefix << "state_lookup_f:='';";
265  LineFeed();
266  Output() << "CASE GID OF";
267  LineFeed();
268  for(size_t gid=0; gid<Size(); ++gid) {
269  if(mHasStateNames[gid])
270  Output() << ToStringInteger(gid) << ": "
271  << mPrefix <<"state_lookup_f" << " := " << mPrefix << "state_lookup_" << ToStringInteger(gid) << "[IDX]" << ";";
272  LineFeed();
273  }
274  Output() << "END_CASE;";
275  LineFeed();
276  Output() << "IF LEN(" << mPrefix << "state_lookup_f) = 0 THEN";
277  LineFeed();
278  Output() << " " << mPrefix <<"state_lookup_f" << " := CONCAT('s'," << mIntegerType << "_TO_STRING(IDX))" << ";";
279  LineFeed();
280  Output() << "END_IF;";
281  LineFeed(2);
282  Output() << "END_FUNCTION";
283  LineFeed();
284  LineFeed(2+1);
285  }
286 }
287 
288 
289 // extend base reset by iec timers
291  FD_DCG("Iec61131stCodeGenerator(" << this << ")::StateReset()");
292  // call base
294  // have iec extras
295  UpdateSystime();
296 }
297 
298 
299 
300 // code blocks: extend base timer declaration
302  // call base
304  // extend
305  if(TimersBegin()!=TimersEnd()) {
306  Comment("elapsed time since last invokation");
307  VariableDeclare(TargetAddress(AA("time_elapsed")),"TIME");
308  LineFeed();
309  }
310 }
311 
312 
313 // code blocks: import interface variables
315  // bail out on unconfigured
316  if(mIecDeclarePhysical=="") return 0;
317  // figure count
318  int iocnt=0;
319  LineIterator lit=LinesBegin();
320  for(;lit!=LinesEnd();++lit) {
321  std::string lineaddr= lit->second.mAddress;
322  if(lineaddr.size()<1) continue; // paranoia
323  if(lineaddr.at(0)=='%') iocnt++;
324  }
326  for(;ait!=ActionAddressesEnd();++ait) {
327  if(!ait->second.mSetClr) continue;
328  std::string actaddr= ait->second.mAddress;
329  if(actaddr.size()<1) continue; // paranoia
330  if(actaddr.at(0)=='%') ++iocnt;
331  }
332  return iocnt;
333 }
334 
335 
337  Comment("import physical i/o addresses");
338  LineIterator lit=LinesBegin();
339  for(;lit!=LinesEnd();++lit) {
340  std::string lineaddr= lit->second.mAddress;
341  if(lineaddr.size()<1) continue; // paranoia
342  if(lineaddr.at(0)=='%') {
343  Output() << "AT " << lineaddr << " : BOOL;";
344  LineFeed();
345  }
346  }
348  for(;ait!=ActionAddressesEnd();++ait) {
349  if(!ait->second.mSetClr) continue;
350  std::string actaddr= ait->second.mAddress;
351  if(actaddr.size()<1) continue; // paranoia
352  if(actaddr.at(0)=='%') {
353  Output() << "AT " << actaddr << " : BOOL;";
354  LineFeed();
355  }
356  }
357  LineFeed(1);
358 }
359 
360 // code blocks: import interface variables
362  // figure count
363  int iocnt=0;
364  LineIterator lit=LinesBegin();
365  for(;lit!=LinesEnd();++lit) {
366  std::string lineaddr= lit->second.mAddress;
367  if(lineaddr.size()<1) continue; // paranoia
368  if(lineaddr.at(0)!='%') iocnt++;
369  }
371  for(;ait!=ActionAddressesEnd();++ait) {
372  if(!ait->second.mSetClr) continue;
373  std::string actaddr= ait->second.mAddress;
374  if(actaddr.size()<1) continue; // paranoia
375  if(actaddr.at(0)!='%') ++iocnt;
376  }
377  return iocnt;
378 }
379 
381  Comment("import i/o variables and addresses");
382  LineIterator lit=LinesBegin();
383  for(;lit!=LinesEnd();++lit) {
384  std::string lineaddr= lit->second.mAddress;
385  if(lineaddr.size()<1) continue; // paranoia
386  if(lineaddr.at(0)!='%') {
387  VariableDeclare(lineaddr,"BOOL");
388  LineFeed();
389  }
390  }
392  for(;ait!=ActionAddressesEnd();++ait) {
393  if(!ait->second.mSetClr) continue;
394  std::string actaddr= ait->second.mAddress;
395  if(actaddr.size()<1) continue; // paranoia
396  if(actaddr.at(0)!='%') {
397  VariableDeclare(actaddr,"BOOL");
398  LineFeed();
399  }
400  }
401  LineFeed(1);
402 }
403 
404 
405 // code blocks: literal prepend from configuration
407  if(mLiteralCyclic.size()==0) return;
408  Comment("************************************************");
409  Comment("* extra cyclic code from configuration *");
410  LineFeed();
411  Output() << mLiteralCyclic;
412  LineFeed(2);
413  Comment("* end of extra code from configuration *");
414  Comment("************************************************");
415  LineFeed(1+1);
416 }
417 
418 // generate code
420  if((mEventExecutionHook!="") || (mStateUpdateHook!=""))
421  Comment("call hooks");
422  if(mEventExecutionHook!="") {
423  std::string hook = mEventExecutionHook + "(" + TargetExpression(AA("exec_event")) + ");";
424  Output() << hook;
425  LineFeed(1);
426  }
427  if(mStateUpdateHook!="") {
428  std::string hook = mStateUpdateHook + "(" + TargetAddress(AA("parallel_state")) + ");";
429  Output() << hook;
430  LineFeed(1);
431  }
432  LineFeed(1);
433 }
434 
435 
436 // code blocks: organise time decrement as inline code snippet
438  if(TimersBegin()==TimersEnd()) return;
439  // timer update function
440  Comment("************************************************");
441  Comment("* update timer states *");
442  LineFeed(2);
443  Output() << "IF " << TargetAddress(AA("time_elapsed")) << " > " << TimeConstant(0) << " THEN";
444  LineFeed();
445  IndentInc();
446  TimerIterator tit= TimersBegin();
447  for(;tit!=TimersEnd();++tit) {
448  AA cnt("timer_" + tit->second.mAddress + "_cnt");
449  AA run("timer_" + tit->second.mAddress + "_run");
450  Output() << "IF " << TargetAddress(AA(run)) << " THEN";
451  IndentInc();
452  LineFeed();
453  Output() << "IF " << TargetAddress(cnt) << " > " << TargetAddress(AA("time_elapsed")) << " THEN";
454  IndentInc();
455  LineFeed();
457  Output() << TargetAddress(cnt) << " := " << TargetAddress(cnt) << " - " << TargetAddress(AA("time_elapsed")) << ";";
458  } else {
459  Output() << TargetAddress(cnt) << " := SUB_TIME(" << TargetAddress(cnt) << ", " << TargetAddress(AA("time_elapsed")) << ");";
460  }
461  IndentDec();
462  LineFeed();
463  Output() << "ELSE";
464  LineFeed();
465  IndentInc();
466  Output() << TargetAddress(cnt) << " := TIME#0s;";
467  IndentDec();
468  LineFeed();
469  Output() << "END_IF;";
470  IndentDec();
471  LineFeed();
472  Output() << "END_IF;";
473  LineFeed();
474  }
475  IndentDec();
476  Output() << "END_IF;";
477  LineFeed();
478  LineFeed(1+2);
479 
480 }
481 
482 // code blocks: mimique systime by iec timer
484  if(TimersBegin()==TimersEnd()) return;
485  Comment("iec timer to simulate system time");
486  VariableDeclare(TargetAddress(AA("systime_ton")),"TON");
487  VariableDeclare(TargetAddress(AA("systime_recent")),"TIME");
488  VariableDeclare(TargetAddress(AA("systime_now")),"TIME");
489  LineFeed();
490 }
491 
492 // code blocks: mimique systime by iec timer
494  if(TimersBegin()==TimersEnd()) return;
495  Comment("do reset/track systime");
496  Output() << "IF " << mPrefix << "exec_event = -1 " << " THEN" << std::endl;
497  Output() << " " << mPrefix << "systime_ton(IN:=false);" << std::endl;
498  Output() << " " << mPrefix << "systime_recent := TIME#0ms;" << std::endl;
499  Output() << "END_IF;" << std::endl;
500  Output() << mPrefix << "systime_ton(IN:=true, PT:=TIME#2h, ET=>" << mPrefix << "systime_now);" << std::endl;
502  Output() << mPrefix << "time_elapsed := " << mPrefix << "systime_now - " << mPrefix << "systime_recent;" << std::endl;
503  } else {
504  Output() << mPrefix << "time_elapsed := SUB_TIME(" << mPrefix << "systime_now," << mPrefix << "systime_recent);" << std::endl;
505  }
506  Output() << "IF " << mPrefix << "systime_now < TIME#1h THEN" << std::endl;
507  Output() << " " << mPrefix << "systime_recent := " << mPrefix << "systime_now;" << std::endl;
508  Output() << "ELSE" << std::endl;
509  Output() << " " << mPrefix << "systime_ton(IN:=false, PT:=TIME#2h);" << std::endl;
510  Output() << " " << mPrefix << "systime_ton(IN:=true, PT:=TIME#2h);" << std::endl;
511  Output() << " " << mPrefix << "systime_recent := TIME#0ms;" << std::endl;
512  Output() << "END_IF;" << std::endl;
513  LineFeed(1);
514 }
515 
516 
517 
518 /*
519 ******************************************************************
520 ******************************************************************
521 ******************************************************************
522 
523 Iec611311stGenerator implementation --- code primitives
524 
525 ******************************************************************
526 ******************************************************************
527 ******************************************************************
528 */
529 
530 
531 // generate code
532 void Iec61131stCodeGenerator::Comment(const std::string& text) {
533  // write comment
534  if(!mMuteComments) {
535  Output() << "(* " << text << " *)";
536  LineFeed();
537  }
538  // call base to record muted comments
540 }
541 
542 // declaration template
543 void Iec61131stCodeGenerator::VariableDeclare(const std::string& laddr, const std::string& ltype) {
544  if((ltype != mIntegerType) && (ltype != mWordType) && (ltype != "BOOL") && (ltype != "STRING") && (ltype != "TIME") && (ltype != "TON"))
545  FCG_ERR("Iec61131stCodeGenerator::VariableDeclare(): unsupported type [" << ltype << "]");
546  Output() << laddr << " : " << ltype << ";";
547  LineFeed();
548 }
549 
550 void Iec61131stCodeGenerator::VariableDeclare(const std::string& laddr, const std::string& ltype, const std::string& lval) {
551  if((ltype != mIntegerType) && (ltype != mWordType) && (ltype != "BOOL") && (ltype != "STRING") && (ltype != "TIME"))
552  FCG_ERR("Iec61131stCodeGenerator::VariableDeclare(): unsupported type [" << ltype << "]");
553  Output() << laddr << " : " << ltype << " := " << lval << ";";
554  LineFeed();
555 }
556 
557 // address transformation
558 std::string Iec61131stCodeGenerator::TargetAddress(const AA& address) {
559  std::string res;
560  // cosmetic: use uppercase plain names for input/output variables
561  if(address=="reset") res="RESET";
562  if(address=="status") res="STATUS";
563  if(mEventNameLookup) {
564  if(address=="recent_event") res="RECENT_EVENT";
565  if(address.find("pending_events")==0)
566  if(address!="pending_events_t")
567  res="PENDING_EVENTS"+address.substr(14);
568  if(address.find("enabled_events")==0)
569  if(address!="enabled_events_t")
570  res="ENABLED_EVENTS"+address.substr(14);
571  }
572  if(mStateNameLookup) {
573  if(address.find("parallel_state")==0)
574  if(address!="parallel_state_t")
575  res="PARALLEL_STATE"+address.substr(14);
576  }
577  // base case
578  if(res=="") res=mPrefix+address;
579  return res;
580 }
581 
582 // address transformation
584  return AX(TargetAddress(address));
585 }
586 
587 // generate code: integer
590 }
591 
592 // generate code: integer
593 void Iec61131stCodeGenerator::IntegerDeclare(const AA& address, int val){
595 }
596 
597 // generate code: integer
598 void Iec61131stCodeGenerator::IntegerAssign(const AA& address, int val){
599  Output() << TargetAddress(address) << " := " << IntegerConstant(val) << ";";
600  LineFeed();
601 }
602 
603 // generate code: integer
604 void Iec61131stCodeGenerator::IntegerAssign(const AA& address, const AX& expression){
605  Output() << TargetAddress(address) << " := " << expression << ";";
606  LineFeed();
607 }
608 
609 // generate code: integer
610 void Iec61131stCodeGenerator::IntegerIncrement(const AA& address, int val) {
611  if(val>0)
612  Output() << TargetAddress(address) << " := " << TargetAddress(address) << " + " << IntegerConstant(val) << ";";
613  else if(val<0)
614  Output() << TargetAddress(address) << " := " << TargetAddress(address) << " - " << IntegerConstant(-val) << ";";
615  if(val!=0)
616  LineFeed();
617 }
618 
619 // integer maths
621  return AX(expression + " / " + IntegerConstant(val));
622 }
623 
624 // integer maths
626  return AX(expression + " MOD " + IntegerConstant(val));
627 }
628 
629 // integer maths
631  return AX("SHL( IN:=" + WordConstant(1) + " , N:=" + expression + " )" );
632 }
633 
634 // integer maths
636  return true;
637 }
638 
639 // generate code: integer
641  std::string res(ToStringInteger(val));
642  if(mIntegerType == "INT") return AX(res);
643  if(mIntegerType == "DINT") return AX("DINT#" + res);
644  if(mIntegerType == "LINT") return AX("LINT#" + res);
645  FCG_ERR("Iec61131stCodeGenerator: unsupported integer data type");
646  return AX(res);
647 }
648 
649 // generate code: conditionals
651  return AX(TargetAddress(address) + " = " + IntegerConstant(val));
652 }
653 
654 // generate code: conditionals
655 CodePrimitives::AX Iec61131stCodeGenerator::IntegerIsEq(const AA& address, const AX& expression) {
656  return AX(TargetAddress(address) + " = " + expression);
657 }
658 
659 // generate code: conditionals
661  return AX(TargetAddress(address) + " <> " + IntegerConstant(val));
662 }
663 
664 // generate code: conditionals
666  return AX(TargetAddress(address) + " != " + expression);
667 }
668 
669 // generate code: conditionals
671  return AX(TargetAddress(address) + " > " + IntegerConstant(val));
672 }
673 
674 // generate code: conditionals
676  return AX(TargetAddress(address) + " < " + IntegerConstant(val));
677 }
678 
679 
680 
681 // generate code: word
684 }
685 
686 // generate code: word
689 }
690 
691 // generate code: word
693  Output() << TargetAddress(address) << " := " << WordConstant(val) << ";";
694  LineFeed();
695 }
696 
697 // generate code: word
698 void Iec61131stCodeGenerator::WordAssign(const AA& address, const AX& expression){
699  Output() << TargetAddress(address) << " := " << expression << ";";
700  LineFeed();
701 }
702 
703 
704 // generate code: word
705 void Iec61131stCodeGenerator::WordOr(const AA& address, word_t val) {
706  Output() << TargetAddress(address) << " := " << TargetExpression(address) << " OR " << WordConstant(val) << ";";
707  LineFeed();
708 }
709 
710 // generate code: word
711 void Iec61131stCodeGenerator::WordOr(const AA& address, const AX& expression) {
712  Output() << TargetAddress(address) << " := " << TargetExpression(address) << " OR " << expression << ";";
713  LineFeed();
714 }
715 
716 // generate code: word
717 void Iec61131stCodeGenerator::WordOr(const AA& address, const AA& op1, const AA& op2) {
718  Output() << TargetAddress(address) << " := " << TargetExpression(op1) << " OR " << TargetExpression(op2) << ";";
719  LineFeed();
720 }
721 
722 // generate code: word
723 void Iec61131stCodeGenerator::WordOr(const AA& address, const AA& op1, word_t op2) {
724  Output() << TargetAddress(address) << " := " << TargetExpression(op1) << " OR " << WordConstant(op2) << ";";
725  LineFeed();
726 }
727 
728 // generate code: word
729 void Iec61131stCodeGenerator::WordAnd(const AA& address, word_t val) {
730  Output() << TargetAddress(address) << " := " << TargetAddress(address) << " AND " << WordConstant(val) << ";";
731  LineFeed();
732 }
733 
734 // generate code: word
735 void Iec61131stCodeGenerator::WordAnd(const AA& address, const AX& expression) {
736  Output() << TargetAddress(address) << " := " << TargetAddress(address) << " AND " << expression << ";";
737  LineFeed();
738 }
739 
740 // generate code: word
741 void Iec61131stCodeGenerator::WordAnd(const AA& address, const AA& op1, const AA& op2) {
742  Output() << TargetAddress(address) << " := " << TargetAddress(op1) << " AND " << TargetAddress(op2) << ";";
743  LineFeed();
744 }
745 
746 // generate code: word
747 void Iec61131stCodeGenerator::WordAnd(const AA& address, const AA& op1, word_t op2) {
748  Output() << TargetAddress(address) << " := " << TargetExpression(op1) << " AND " << WordConstant(op2) << ";";
749  LineFeed();
750 }
751 
752 // generate code: word
753 void Iec61131stCodeGenerator::WordNand(const AA& address, const AX& expression) {
754  Output() << TargetAddress(address) << " := " << TargetAddress(address) << " AND (NOT " << expression << " );";
755  LineFeed();
756 }
757 
758 // generate code: conditionals
760  return AX("( " + TargetAddress(address) + " AND " + WordConstant(0x01<<idx) + " ) <> " + WordConstant(0));
761 }
762 
763 // generate code: conditionals
765  return AX("( " + TargetAddress(address) + " AND " + WordConstant(0x01<<idx) + " ) == " + WordConstant(0));
766 }
767 
770  return AX("( " + TargetAddress(address) + " AND " + WordConstant(mask) + " ) <> " + WordConstant(0));
771 }
772 
773 // generate code: conditionals
775  return AX(TargetAddress(address) + " = " + WordConstant(val));
776 }
777 
778 // generate code: conditionals
780  return AX("NOT ( " + TargetAddress(address) + " = " + WordConstant(val) + " )");
781 }
782 
783 // generate code: word
785  // have neet zero
786  if(val==0) return AX( mWordType + "#0");
787  // construct typed hex representation
788  std::stringstream sstr;
789  sstr << mWordType << "#16#" << std::setbase(16) << std::setfill('0');
790  if(mWordType == "BYTE") sstr << std::setw(2) << (val & 0xff);
791  else if(mWordType == "WORD") sstr << std::setw(4) << (val & 0xffff);
792  else if(mWordType == "DWORD") sstr << std::setw(8) << (val & 0xffffffff);
793  else if(mWordType == "LWORD") sstr << std::setw(16) << (val & 0xffffffffffffffff);
794  else FCG_ERR("Iec61131stCodeGenerator: unsupported word data type");
795  AX res(sstr.str());
796  return res;
797 }
798 
799 
800 // generate code: bool
802  VariableDeclare(TargetAddress(address),"BOOL");
803 }
804 
805 // generate code: bool
806 void Iec61131stCodeGenerator::BooleanDeclare(const AA& address, int val){
807  std::string valstr;
808  if(val) valstr="true"; else valstr="false";
809  VariableDeclare(TargetAddress(address),"BOOL",valstr);
810 }
811 
812 // generate code: bool
813 void Iec61131stCodeGenerator::BooleanAssign(const AA& address, int val){
814  std::string valstr;
815  if(val) valstr="true"; else valstr="false";
816  Output() << TargetAddress(address) << " := " << valstr << ";";
817  LineFeed();
818 }
819 
820 // generate code: bool
821 void Iec61131stCodeGenerator::BooleanAssign(const AA& address, const AX& expression){
822  Output() << TargetAddress(address) << " := " << expression << ";";
823  LineFeed();
824 }
825 
826 // generate code: bool
828  return AX(TargetAddress(op1) + " <> " + TargetAddress(op2));
829 }
830 
831 // generate code: bool
833  return AX(TargetAddress(op1) + " = " + TargetAddress(op2));
834 }
835 
836 
837 // const-int array (local iec only helper)
839  std::stringstream strstr;
840  int newline=20;
841  if(val.size()<25) newline=25;
842  strstr << "[ " ;
843  size_t vit=0;
844  while(true) {
845  if(vit==val.size()) break;
846  strstr << IntegerConstant(val[vit]);
847  ++vit;
848  if(vit==val.size()) break;
849  strstr << ", ";
850  newline--;
851  if(newline==0) {
852  strstr << std::endl << " ";
853  newline=20;
854  }
855  }
856  strstr << " ]";
857  return AX(strstr.str());
858 }
859 
860 // const-int-array
861 void Iec61131stCodeGenerator::CintarrayDeclare(const AA& address, int offset, const std::vector<int>& val) {
862  if(val.size()==0) {
863  FCG_ERR("Iec61131stCodeGenerator::Cintarray(): ignoring empty const vector");
864  return;
865  }
866  if(val.size()+offset >= (1ULL << (mIntegerSize-1))) {
867  FCG_ERR("Iec61131stCodeGenerator::Cwordarray(): const vector exceeds address range");
868  return;
869  }
870  // declare with initialiser
871  Output() << TargetAddress(address) << " : ARRAY[" << offset << ".." << val.size()+offset-1 << "] OF " << mIntegerType << " := ";
872  LineFeed();
873  IndentInc();
874  Output() << IntarrayConstant(val) << ";";
875  LineFeed();
876  IndentDec();
877 }
878 
879 
880 // int array access by const
882  return AA(address + "[" + ToStringInteger(index) + "]");
883 };
884 
885 // int array access by expression
887  return AA(address + "[" + TargetAddress(indexaddr) + "]");
888 };
889 
890 // tell parent class about this feature
892  return true;
893 };
894 
895 
896 // const-word array
898  std::stringstream strstr;
899  int newline=8;
900  if(val.size()<11) newline=15;
901  strstr << "[ " ;
902  size_t vit=0;
903  while(true) {
904  if(vit==val.size()) break;
905  strstr << WordConstant(val[vit]);
906  ++vit;
907  if(vit==val.size()) break;
908  strstr << ", ";
909  newline--;
910  if(newline==0) {
911  strstr << std::endl << " ";
912  newline=8;
913  }
914  }
915  strstr << " ]";
916  return AX(strstr.str());
917 }
918 
919 // const-word-array
920 void Iec61131stCodeGenerator::CwordarrayDeclare(const AA& address, int offset, const std::vector<word_t>& val) {
921  if(val.size()==0) {
922  FCG_ERR("Iec61131stCodeGenerator::Cwordarray(): ignoring empty const vector");
923  return;
924  }
925  if(val.size()+offset >= (1ULL << (mIntegerSize-1))) {
926  FCG_ERR("Iec61131stCodeGenerator::Cwordarray(): const vector exceeds addres range");
927  return;
928  }
929  // declare with initialiser
930  Output() << TargetAddress(address) << " : ARRAY[" << offset << ".." << val.size()+offset-1 << "] OF " << mWordType << " := ";
931  LineFeed();
932  IndentInc();
933  Output() << WordarrayConstant(val) << ";";
934  LineFeed();
935  IndentDec();
936 }
937 
938 
939 // word-array access by const
941  return AA(address + "[" + ToStringInteger(index) + "]");
942 };
943 
944 // word array access by expression
946  return AA(address + "[" + TargetAddress(indexaddr) + "]");
947 };
948 
949 // tell parent class about this feature
951  return true;
952 };
953 
954 // generate code: string constant
956  AX res;
957  res.append(1,'\'');
958  for(std::size_t i=0; i<val.length(); ++i) {
959  char c=val.at(i);
960  // terminate
961  if(c==0) break;
962  // quote quote
963  if(c=='\'') { res.append("$'"); continue; }
964  // quote dollar
965  if(c=='$') { res.append("$$"); continue; }
966  // printable ascii
967  if((c>=0x20) && (c<0x7f)) { res.append(1,c); continue; };
968  // error on other (alternative: use octal encoding to support utf8)
969  FCG_ERR("EmbeddedcCodeGenerator: non-printable ascii or other encoding unsupported [" << val <<"]");
970  }
971  res.append(1,'\'');
972  return res;
973 }
974 
975 // literal const-string array
977  std::stringstream strstr;
978  int newline;
979  if(val.size()<4) {
980  newline=4;
981  strstr << "[ ";
982  } else {
983  newline=1;
984  strstr << "[ " << std::endl;
985  }
986  size_t vit=0;
987  while(true) {
988  if(vit==val.size()) break;
989  strstr << StringConstant(val[vit]);
990  ++vit;
991  if(vit==val.size()) break;
992  strstr << ", ";
993  newline--;
994  if(newline==0) {
995  strstr << std::endl;
996  newline=1;
997  }
998  }
999  strstr << " ]";
1000  return AX(strstr.str());
1001 }
1002 
1003 
1004 // const-string-array
1005 void Iec61131stCodeGenerator::CstrarrayDeclare(const AA& address, int offset, const std::vector<std::string>& val) {
1006  if(val.size()==0) {
1007  FCG_ERR("Iec61131stCodeGenerator::Cstrarray(): ignoring empty const vector");
1008  return;
1009  }
1010  if(val.size()+offset>= (1ULL << (mIntegerSize-1))) {
1011  FCG_ERR("Iec61131stCodeGenerator::Cstrarray(): const vector exceeds addres range");
1012  return;
1013  }
1014  // figure string size
1015  size_t len=0;
1016  for(size_t i=0; i<val.size(); ++i)
1017  if(val[i].size()>len) len=val[i].size();
1018  // declare with initialiser
1019  Output() << TargetAddress(address) << " : ARRAY[" << offset << ".." << val.size()+offset-1 << "] OF STRING[" << ToStringInteger(len) <<"] := ";
1020  LineFeed();
1021  IndentInc();
1022  Output() << StrarrayConstant(val) << ";";
1023  LineFeed();
1024  IndentDec();
1025 }
1026 
1027 
1028 // string-array access by const
1030  return AA(address + "[" + ToStringInteger(index) + "]");
1031 };
1032 
1033 // string array access by expression
1035  return AA(address + "[" + TargetAddress(indexaddr) + "]");
1036 };
1037 
1038 // tell parent class about this feature
1040  return true;
1041 };
1042 
1043 // int-array
1044 void Iec61131stCodeGenerator::IntarrayDeclare(const AA& address, int offset, const std::vector<int>& val) {
1045  if(val.size()==0) {
1046  FCG_ERR("Iec61131stCodeGenerator::Intarray(): ignoring empty const vector");
1047  return;
1048  }
1049  if(val.size()+offset >= (1ULL << (mIntegerSize-1))) {
1050  FCG_ERR("Iec61131stCodeGenerator::Intarray(): const vector exceeds addres range");
1051  return;
1052  }
1053  // declare with initialiser
1054  Output() << TargetAddress(address) << " : ARRAY[" << offset << ".." << val.size()+offset-1 << "] OF " << mIntegerType << " := ";
1055  LineFeed();
1056  IndentInc();
1057  Output() << IntarrayConstant(val) << ";";
1058  LineFeed();
1059  IndentDec();
1060 }
1061 
1062 
1063 // int-array
1064 void Iec61131stCodeGenerator::IntarrayDeclare(const AA& address, int offset, int len) {
1065  if(len==0) {
1066  FCG_ERR("Iec61131stCodeGenerator::Intarray(): ignoring empty const vector");
1067  return;
1068  }
1069  if(len+offset >= (1LL << (mIntegerSize-1))) {
1070  FCG_ERR("Iec61131stCodeGenerator::Intarray(): const vector exceeds addres range");
1071  return;
1072  }
1073  Output() << TargetAddress(address) << " : ARRAY[" << offset << ".." << len+offset-1 << "] OF " << mIntegerType << ";";
1074  LineFeed();
1075 }
1076 
1077 // word-array access by const
1079  return AA(address + "[" + ToStringInteger(index) + "]");
1080 };
1081 
1082 // word array access by expression
1084  return AA(address + "[" + TargetAddress(indexaddr) + "]");
1085 };
1086 
1087 // tell parent class about this feature
1089  return true;
1090 };
1091 
1092 
1093 // word-array
1094 void Iec61131stCodeGenerator::WordarrayDeclare(const AA& address, int offset, const std::vector<word_t>& val) {
1095  if(val.size()==0) {
1096  FCG_ERR("Iec61131stCodeGenerator::Wordarray(): ignoring empty const vector");
1097  return;
1098  }
1099  if(val.size()+offset >= (1ULL << (mIntegerSize-1))) {
1100  FCG_ERR("Iec61131stCodeGenerator::Wordarray(): const vector exceeds addres range");
1101  return;
1102  }
1103  // declare with initialiser
1104  Output() << TargetAddress(address) << " : ARRAY[" << offset << ".." << val.size()+offset-1 << "] OF " << mWordType << " := ";
1105  LineFeed();
1106  IndentInc();
1107  Output() << WordarrayConstant(val) << ";";
1108  LineFeed();
1109  IndentDec();
1110 }
1111 
1112 
1113 // word-array
1114 void Iec61131stCodeGenerator::WordarrayDeclare(const AA& address, int offset, int len) {
1115  if(len==0) {
1116  FCG_ERR("Iec61131stCodeGenerator::Wordarray(): ignoring empty const vector");
1117  return;
1118  }
1119  if(len>= (1LL << (mIntegerSize-1))) {
1120  FCG_ERR("Iec61131stCodeGenerator::Wordarray(): const vector exceeds addres range");
1121  return;
1122  }
1123  Output() << TargetAddress(address) << " : ARRAY[" << offset << ".." << len+offset-1 << "] OF " << mWordType << ";";
1124  LineFeed();
1125 }
1126 
1127 // word-array access by const
1129  return AA(address + "[" + ToStringInteger(index) + "]");
1130 };
1131 
1132 // word array access by expression
1134  return AA(address + "[" + TargetAddress(indexaddr) + "]");
1135 };
1136 
1137 // tell parent class about this feature
1139  return true;
1140 };
1141 
1142 
1143 
1144 // event set
1145 /*
1146 void Iec61131stCodeGenerator::EventSetDeclareImport(const AA& address) {
1147  // same as declare
1148  EventSetDeclare(address);
1149 }
1150 */
1151 
1152 // generate code: conditionals
1153 void Iec61131stCodeGenerator::IfTrue(const AX& expression) {
1154  Output() << "IF " << expression << " THEN";
1155  LineFeed();
1156  IndentInc();
1157 }
1158 
1159 // generate code: conditionals
1160 void Iec61131stCodeGenerator::IfFalse(const AX& expression) {
1161  Output() << "IF NOT " << expression << " THEN";
1162  LineFeed();
1163  IndentInc();
1164 }
1165 
1166 // generate code: conditionals
1167 void Iec61131stCodeGenerator::IfWord(const AX& expression) {
1168  Output() << "IF ( " << expression << " ) <> " << WordConstant(0) << " THEN";
1169  LineFeed();
1170  IndentInc();
1171 }
1172 
1173 // generate code: conditionals
1175  IndentDec();
1176  Output() << "ELSE";
1177  LineFeed();
1178  IndentInc();
1179 }
1180 
1181 // generate code: conditionals
1183  IndentDec();
1184  Output() << "ELSIF " << expression << " THEN";
1185  LineFeed();
1186  IndentInc();
1187 }
1188 
1189 // generate code: conditionals
1191  IndentDec();
1192  Output() << "END_IF;";
1193  LineFeed();
1194 }
1195 
1196 // switch control
1198  Output() << "CASE " << TargetAddress(address) << " OF";
1199  LineFeed();
1200 }
1201 
1202 // switch control
1203 void Iec61131stCodeGenerator::SwitchCase(const AA& address, int val){
1204  (void) address;
1205  Output() << IntegerConstant(val) << ":";
1206  LineFeed();
1207  IndentInc();
1208 }
1209 
1210 // switch control
1211 void Iec61131stCodeGenerator::SwitchCases(const AA& address, int from, int to){
1212  // bail out on empty
1213  if(from>to) {
1214  FCG_VERB0("CodeGenerator: WARNING: inconsistent empty range of switch-cases");
1215  IndentInc();
1216  return;
1217  }
1218  // simplify to singleton
1219  if(from==to) {
1220  SwitchCase(address, from);
1221  return;
1222  }
1223  // do range
1224  Output() << IntegerConstant(from) << " .. " << IntegerConstant(to) << ":";
1225  LineFeed();
1226  IndentInc();
1227 }
1228 
1229 // switch control
1230 void Iec61131stCodeGenerator::SwitchCases(const AA& address, const std::set< int >& vals){
1231  // bail out on empty
1232  if(vals.empty()) {
1233  FCG_VERB0("CodeGenerator: WARNING: inconsistent empty range of switch-cases");
1234  IndentInc();
1235  return;
1236  }
1237  // simplify to range
1238  int from=*vals.begin();
1239  int to= *(--vals.end());
1240  if(to+1-from== (int) vals.size()) {
1241  SwitchCases(address,from,to);
1242  return;
1243  }
1244  // do set
1245  std::set< int >::const_iterator vit=vals.begin();
1246  for(; vit!=vals.end(); ++ vit) {
1247  if(vit!=vals.begin()) Output() << ", ";
1248  Output() << IntegerConstant(*vit);
1249  }
1250  Output() << ":";
1251  LineFeed();
1252  IndentInc();
1253 }
1254 
1255 // switch control
1257  IndentDec();
1258 }
1259 
1260 // switch control
1262  Output() << "END_CASE;";
1263  LineFeed();
1264 }
1265 
1266 // switch control
1268  return true;
1269 }
1270 
1271 // loops
1273  Output() << "WHILE true DO";
1274  LineFeed();
1275  IndentInc();
1276 }
1277 
1278 // loops
1279 void Iec61131stCodeGenerator::LoopBreak(const AX& expression) {
1280  Output() << "IF " << expression << " THEN EXIT; END_IF;";
1281  LineFeed();
1282 }
1283 
1284 // loops
1286  IndentDec();
1287  Output() << "END_WHILE;";
1288  LineFeed();
1289 }
1290 
1291 // loops
1293  Output() << "RETURN;";
1294  LineFeed();
1295 }
1296 
1297 // timer
1298 void Iec61131stCodeGenerator::TimerDeclare(const AA& address, const std::string &val) {
1299  // todo: type check time literal
1300  (void) val;
1301  VariableDeclare(TargetAddress(AA("timer_"+address+"_cnt")),"TIME");
1302  VariableDeclare(TargetAddress(AA("timer_"+address+"_run")),"BOOL");
1303 }
1305  Output() << TargetAddress(AA("timer_"+address+"_run")) << " := true;";
1306  LineFeed();
1307 }
1309  Output() << TargetAddress(AA("timer_"+address+"_run")) << " := false;";
1310  LineFeed();
1311 }
1312 void Iec61131stCodeGenerator::TimerReset(const AA& address, const std::string& litval) {
1313  Output() << TargetAddress(AA("timer_"+address+"_cnt")) << " := " << litval << ";";
1314  LineFeed();
1315 }
1316 
1318  return AX(TargetAddress(AA("timer_"+address+"_run")) + " AND (" +
1319  TargetAddress(AA("timer_"+address+"_cnt")) + " <= " + TimeConstant(0) + ")");
1320 }
1321 
1323  std::string res("TIME#" + ToStringInteger(val) + "ms");
1324  return AX(res);
1325 }
1326 
1327 
1328 // output actions
1329 void Iec61131stCodeGenerator::RunActionSet(const std::string& address) {
1330  Output() << address << " := true;" ;
1331  LineFeed();
1332 }
1333 void Iec61131stCodeGenerator::RunActionClr(const std::string& address) {
1334  Output() << address << " := false;" ;
1335  LineFeed();
1336 }
1338  Output() << expression << ";";
1339  LineFeed();
1340 }
1341 
1342 Iec61131stCodeGenerator::IECVariableType Iec61131stCodeGenerator::CurrentVariableType(void) {
1343  return mCurrentVariableType;
1344 }
1345 
1346 void Iec61131stCodeGenerator::CurrentVariableType(const IECVariableType & type) {
1347  mCurrentVariableType = type;
1348 }
1349 
1350 
#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)
LineIterator LinesEnd()
Access to line records by iterator.
std::map< std::string, LineAddress >::iterator LineIterator
Access to line records 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.
std::map< std::string, TimerConfiguration >::iterator TimerIterator
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
virtual std::ostream & Output(void)
Output stream.
static std::string VersionString(void)
Version (refers to macro COMPILEDES_VERSION, defined in cgp_codegenerator.h)
virtual const std::string & Name(void) const
Get objects's name (reimplementing base faudes::Type)
Idx Size(void) const
Number of generators.
virtual void IndentDec()
Indentation (convenience support for derived classes)
ActionAddressIterator ActionAddressesEnd()
Access to action addresses by iterator.
std::map< std::string, ActionAddress >::iterator ActionAddressIterator
Access to action record 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
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