CompileDES  3.12
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.
virtual void CintarrayDeclare(const AA &address, int offset, const std::vector< int > &val)
generate code: conditionals
virtual void CwordarrayDeclare(const AA &address, int offset, const std::vector< word_t > &val)
generate code: conditionals
virtual void DoGenerateCyclicCode(void)
cut-and-paste template for code snippet assembly
Idx Size(void) const
Number of generators.
virtual AX IntarrayConstant(const std::vector< int > &val)
generate code: conditionals
virtual void IfElseIfTrue(const AX &expression)
generate code: conditionals
virtual void SwitchCase(const AA &address, int val)
generate code: conditionals
virtual void FunctionReturn(void)
generate code: conditionals
virtual void DeclareImportPhysicalIo(void)
generate code: conditionals
virtual void LoopBegin(void)
generate code: conditionals
virtual void DeclareStatus(void)
Declare "status".
virtual AA CwordarrayAccess(const AA &address, int index)
generate code: conditionals
Abstract expression; see also Absstract_Addresses.
LineIterator LinesEnd()
Access to line records by iterator.
virtual AX IntegerRemainder(const AX &expression, int val)
generate code: conditionals
virtual void DeclareRecentEvent(void)
Declare "recent_event".
virtual void LiteralCyclic(void)
generate code: conditionals
virtual bool HasCstrarray(void)
generate code: conditionals
virtual void IfWord(const AX &expression)
generate code: conditionals
virtual bool HasMultiCase(void)
generate code: conditionals
virtual std::ostream & Output(void)
Output stream.
virtual void TimerStop(const AA &address)
generate code: conditionals
virtual void Comment(const std::string &text)
Target comments (see EmbeddedcCodeGenerator for consistent reimplementation pattern) ...
virtual void DoGenerateResetCode(void)
cut-and-paste template for code snippet assembly
virtual AA CintarrayAccess(const AA &address, int index)
generate code: conditionals
Code-generator for target IEC 61131-3 ST.
virtual AX WordIsBitSet(const AA &address, int idx)
generate code: conditionals
Implementation of primitives by IEC 61131 ST.
int mWordSize
compressed boolean capacity of target type word
virtual void IfElse(void)
generate code: conditionals
virtual void LineFeed(int lines=1)
LineFeed (convenience support for derived classes)
virtual void BooleanDeclare(const AA &address)
generate code: conditionals
virtual std::string TargetAddress(const AA &address)
abstract address conversion
virtual AA WordarrayAccess(const AA &address, int index)
generate code: conditionals
virtual bool HasCwordarray(void)
generate code: conditionals
virtual AX StringConstant(const std::string &val)
generate code: conditionals
std::string mLiteralCyclic
option: extra cyclic code
virtual void DoGenerateLookups(void)
code generation hook (lookup functions)
virtual void IfTrue(const AX &expression)
generate code: conditionals
virtual AX IntegerConstant(int val)
generate code: conditionals
virtual void IfEnd(void)
generate code: conditionals
virtual void WordAnd(const AA &address, word_t val)
generate code: conditionals
virtual AX IntegerQuotient(const AX &expression, int val)
generate code: conditionals
virtual AA IntarrayAccess(const AA &address, int index)
generate code: conditionals
virtual void DeclareSmallCarray(void)
Declare bit-mask loop-ups.
virtual void RunActionExe(const AX &expression)
generate code: conditionals
virtual AX StrarrayConstant(const std::vector< std::string > &val)
generate code: conditionals
virtual void DeclareAux(void)
Declare variables local to the provided snippets, e.g. helpers for bit-mask computation.
virtual void DeclareLargeCarray(void)
Declare compiled transition relations.
virtual void WordDeclare(const AA &address)
generate code: conditionals
virtual void DeclareImportSymbolicIo(void)
generate code: conditionals
virtual void WordarrayDeclare(const AA &address, int offset, int len)
generate code: conditionals
virtual void DeclareReset(void)
Declare "reset".
virtual void SwitchBreak(void)
generate code: conditionals
Iec61131stCodeGenerator(void)
Constructor.
virtual void DeclareTimers(void)
generate code: conditionals
virtual bool HasIntmaths(void)
generate code: conditionals
std::map< std::string, TimerConfiguration >::iterator TimerIterator
Access to timer records by iterator.
bool mArrayForState
code option: use int arrays to represent that overall state
virtual AX IntegerIsGreater(const AA &address, int val)
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 IndentInc()
Indentation (convenience support for derived classes)
bool mArrayForBitmasks
code option: use const array to represent bit-masks
virtual void ResetState(void)
generate code: conditionals
std::string mStateUpdateHook
code option: state change hook
virtual void WordNand(const AA &address, const AX &expression)
generate code: conditionals
virtual void ResetState(void)
Reset state.
virtual AX WordarrayConstant(const std::vector< word_t > &val)
generate code: conditionals
virtual void InsertExecHooks(void)
generate code: conditionals
virtual void WordAssign(const AA &address, word_t val)
generate code: conditionals
virtual void IntegerAssign(const AA &address, int val)
generate code: conditionals
virtual void VariableDeclare(const std::string &laddr, const std::string &ltype)
generate code: conditionals
virtual void DoReadTargetConfiguration(TokenReader &rTr)
re-implement token i/o for extra configuration
virtual void RunActionClr(const std::string &address)
generate code: conditionals
virtual void IntarrayDeclare(const AA &address, int offset, int len)
generate code: conditionals
static std::string VersionString(void)
Version (refers to macro COMPILEDES_VERSION, defined in cgp_codegenerator.h)
std::string mIntegerType
target data type for integer
virtual AX BooleanIsEq(const AA &op1, const AA &op2)
generate code: conditionals
virtual void DoCompile(void)
virtual hook to extend compiled data
virtual void DeclareStateNameLookup(void)
Declare symbolic name lookup tables.
virtual void LiteralAppend(void)
Cosmetic: append literally from configuration.
virtual void DeclareParallelState(void)
Declare "parallel_state".
virtual void WordOr(const AA &address, word_t val)
generate code: conditionals
virtual void BooleanAssign(const AA &address, int val)
generate code: conditionals
virtual const std::string & Name(void) const
Get objects&#39;s name (reimplementing base faudes::Type)
int mIntegerSize
compressed boolean capacity of target type integer
virtual AX WordConstant(word_t val)
generate code: conditionals
std::map< std::string, ActionAddress >::iterator ActionAddressIterator
Access to action record by iterator.
virtual AX WordIsMaskSet(const AA &address, word_t mask)
generate code: conditionals
virtual void DoGenerateFunction(void)
code generation hook (function block)
std::string mWordType
target data type for word
virtual void LoopBreak(const AX &expression)
generate code: conditionals
virtual void DeclareLoopState(void)
Declare loop state, i.e. line levels, loop flag.
bool mEventNameLookup
code option: event name lookup
std::string mIecDeclarePhysical
option: formal declaration of io lines
virtual void DeclarePendingEvents(void)
Declare "pending_events" and "enabled_events".
virtual void SwitchBegin(const AA &address)
generate code: conditionals
virtual void DeclareTimers(void)
Use target implementation to declare timers, typically "timer_run_*" and "timer_cnt_*".
virtual void Clear(void)
Clear all data.
virtual int CountImportSymbolicIo(void)
generate code: conditionals
virtual void DoWriteTargetConfiguration(TokenWriter &rTw) const
re-implement token i/o for extra configuration
virtual AX WordIsBitClr(const AA &address, int idx)
generate code: conditionals
unsigned long word_t
Code-generator internal data type of target words.
ActionAddressIterator ActionAddressesBegin()
Access to action addresses by iterator.
virtual AX WordIsEq(const AA &address, word_t val)
generate code: conditionals
virtual AX BooleanIsNotEq(const AA &op1, const AA &op2)
generate code: conditionals
virtual void DeclareEventNameLookup(void)
Declare symbolic name lookup tables.
virtual AX TimerIsElapsed(const AA &address)
generate code: conditionals
virtual void RunActionSet(const std::string &address)
generate code: conditionals
virtual void Clear(void)
Clear all data.
virtual ~Iec61131stCodeGenerator(void)
Explicit destructor.
std::string mEventExecutionHook
code option: event exec hook
Abstract address; see also Absstract_Addresses.
virtual bool HasCintarray(void)
generate code: conditionals
virtual int CountImportPhysicalIo(void)
generate code: conditionals
virtual AX IntegerIsEq(const AA &address, int val)
generate code: conditionals
virtual bool HasWordarray(void)
generate code: conditionals
bool mStateNameLookup
code option: state name lookup
virtual AX IntegerIsNotEq(const AA &address, int val)
generate code: conditionals
virtual AX TimeConstant(int val)
generate code: conditionals
ActionAddressIterator ActionAddressesEnd()
Access to action addresses by iterator.
std::string mPrefix
universal prefix (pseudo name space)
virtual AX IntegerBitmask(const AX &expression)
generate code: conditionals
virtual void IndentDec()
Indentation (convenience support for derived classes)
virtual void CstrarrayDeclare(const AA &address, int offset, const std::vector< std::string > &val)
generate code: conditionals
virtual void TimerStart(const AA &address)
generate code: conditionals
virtual void IntegerIncrement(const AA &address, int val)
generate code: conditionals
virtual void DeclareSystime(void)
generate code: conditionals
std::map< std::string, LineAddress >::iterator LineIterator
Access to line records by iterator.
virtual void SwitchEnd(void)
generate code: conditionals
TimerIterator TimersBegin()
Access to timer records by iterator.
bool mHasIecTimeOperators
option: overloaded operators for time maths
virtual void UpdateSystime(void)
generate code: conditionals
virtual void DoReadTargetConfiguration(TokenReader &rTr)
File i/o.
virtual void DecrementTimers(void)
code snippet
std::map< std::string, bitarray_rec > mBitarrays
Record of all declared bit-arrays.
virtual bool HasIntarray(void)
generate code: conditionals
void DoCompile(void)
add my preferences to DoCompile
virtual void TimerReset(const AA &address, const std::string &val)
generate code: conditionals
LineIterator LinesBegin()
Access to line records by iterator.
virtual void IntegerDeclare(const AA &address)
generate code: conditionals
virtual void Comment(const std::string &text)
generate code: conditionals
virtual void LiteralPrepend(void)
Cosmetic: prepend literally from configuration data.
virtual AX WordIsNotEq(const AA &address, word_t val)
generate code: conditionals
virtual void IfFalse(const AX &expression)
generate code: conditionals
virtual void DoWriteTargetConfiguration(TokenWriter &rTw) const
File i/o.
bool mMuteComments
mute comments
virtual void LoopEnd(void)
generate code: conditionals
virtual void SwitchCases(const AA &address, int from, int to)
generate code: conditionals
virtual AA CstrarrayAccess(const AA &address, int index)
generate code: conditionals
bool mBitAddressArithmetic
code option: compute bit and word address on target
std::vector< bool > mHasStateNames
record per generator whether there is a lookup table
virtual AX TargetExpression(const AA &address)
abstract address conversion
virtual AX IntegerIsLess(const AA &address, int val)
generate code: conditionals
Execution semantics in terms of code primitives.
TimerIterator TimersEnd()
Access to timer records by iterator.