CompileDES  3.12
Executable-Code Generation from Synchronised libFAUDES Automata
cgp_embeddedc.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_embeddedc.h"
12 
13 
14 /*
15 ******************************************************************
16 ******************************************************************
17 ******************************************************************
18 
19 EmbeddedcCodeGenerator implementation
20 
21 ******************************************************************
22 ******************************************************************
23 ******************************************************************
24 */
25 
26 // Register derived class
28 
29 
30 // EmbeddedcCodeGenerator(void)
32  FD_DCG("EmbeddedcCodeGenerator(" << this << ")::EmbeddedcCodeGenerator()");
33 }
34 
35 
36 // EmbeddedcCodeGenerator(void)
38  FD_DCG("EmbeddedcCodeGenerator(" << this << ")::~EmbeddedcCodeGenerator()");
39 }
40 
41 // clear
43  FD_DCG("EmbeddedcCodeGenerator::Clear()");
44  // call base
46  // my flavor of defaults
47  mPrefix="fcg_";
48  mWordType="unsigned char";
49  mWordSize=8;
50  mIntegerType="int";
51  mIntegerSize=16;
52 }
53 
54 //DoReadTargetConfiguration(rTr)
56  FD_DCG("EmbeddedcCodeGenerator::DoReadTargetConfiguration()");
57  // base
59 }
60 
61 //DoWriteTargetConfiguration(rTw)
63  FD_DCG("EmbeddedcCodeGenerator::DoWriteTargetConfiguration()");
64  // base
66 }
67 
68 // DoCompile()
70  // call base
72  // my preferences
74  FCG_VERB1("EmbeddedcCodeGenerator::Compile(): prefer compiled bitmasks over bit-address maths");
75  mBitAddressArithmetic = false;
76  }
77 }
78 
79 
80 // DoGenerate()
82  FD_DCG("EmbeddedcCodeGenerator(" << this << ")::DoGenerate()");
83  // cut and paste from base
84  mBitarrays.clear();
85  // say hello
86  Comment("************************************************");
87  Comment("CodeGenerator: Target Embedded C ");
88  Comment("************************************************");
89  LineFeed(1);
90  Comment(std::string("CompileDES ") + VersionString());
91  Comment(std::string("Configuration: ") + Name());
92  LineFeed(2+1);
93  // base class snippets
96  // cyclic function
97  LineFeed(2);
98  Output() << "void " << mPrefix << "cyclic(void) { ";
99  LineFeed();
102  Output() << "}; /* end function " << mPrefix << "cyclic() */";
103  LineFeed();
104  LineFeed(2+1);
105  // extra: provide timer decrement interface to host application
106  DecrementTimers();
107  // snippets
108  LiteralAppend();
109  Comment("************************************************");
110  Comment("CodeGenerator: Generated Code Ends Here ");
111  Comment("************************************************");
112 }
113 
114 
115 
116 // code blocks: organise time decrement as function to be periodically
117 // invoked by the host application
119  // timer update function
120  if(TimersBegin()!=TimersEnd()) {
121  Comment("************************************************");
122  Comment("* update timer states *");
123  Comment("************************************************");
124  LineFeed(2);
125  Output() << "void " << mPrefix <<"timerdec(int dec) { ";
126  LineFeed();
127  IndentInc();
128  TimerIterator tit= TimersBegin();
129  for(;tit!=TimersEnd();++tit) {
130  Output() << "if( " << TargetAddress(AA("timer_" + tit->second.mAddress + "_run")) << " ) "
131  << TargetAddress(AA("timer_" + tit->second.mAddress + "_cnt")) << " -= dec;";
132  LineFeed();
133  }
134  IndentDec();
135  Output() << "};";
136  LineFeed();
137  LineFeed(1+2);
138  }
139 }
140 
141 // generate code
143  if((mEventExecutionHook!="") || (mStateUpdateHook!="")) {
144  Comment("call hooks");
145  if(mEventExecutionHook!="") {
146  std::string hook = mEventExecutionHook + "(" + TargetExpression(AA("exec_event")) + ");";
147  Output() << hook;
148  LineFeed(1);
149  }
150  if(mStateUpdateHook!="") {
151  std::string hook = mStateUpdateHook + "(" + TargetAddress(AA("parallel_state")) + ");";
152  Output() << hook;
153  LineFeed(1);
154  }
155  LineFeed(1);
156  }
157 }
158 
159 // generate code
160 void EmbeddedcCodeGenerator::Comment(const std::string& text) {
161  // write comment
162  if(!mMuteComments) {
163  Output() << "/* " << text << " */";
164  LineFeed();
165  }
166  // call base to record muted comments
168 }
169 
170 // address transformation
171 std::string EmbeddedcCodeGenerator::TargetAddress(const AA& address) {
172  // should so some mangeling to replace non-ascii / funny characters
173  std::string res=mPrefix+address;
174  return res;
175 }
176 
177 // address transformation
179  return AX(TargetAddress(address));
180 }
181 
182 // generate code: integer
183 void EmbeddedcCodeGenerator::IntegerDeclare(const AA& address){
184  Output() << "static " << mIntegerType << " " << TargetAddress(address) << ";";
185  LineFeed();
186 }
187 
188 // generate code: integer
189 void EmbeddedcCodeGenerator::IntegerDeclare(const AA& address, int val){
190  Output() << "static " << mIntegerType << " " << TargetAddress(address) << "=" << val << ";";
191  LineFeed();
192 }
193 
194 // generate code: integer
195 void EmbeddedcCodeGenerator::IntegerAssign(const AA& address, int val){
196  Output() << TargetAddress(address) << " = " << IntegerConstant(val) << ";";
197  LineFeed();
198 }
199 
200 // generate code: integer
201 void EmbeddedcCodeGenerator::IntegerAssign(const AA& address, const AX& expression){
202  Output() << TargetAddress(address) << " = " << expression << ";";
203  LineFeed();
204 }
205 
206 // generate code: integer
207 void EmbeddedcCodeGenerator::IntegerIncrement(const AA& address, int val) {
208  if(val==1)
209  Output() << TargetAddress(address) << "++;";
210  else if(val==-1)
211  Output() << TargetAddress(address) << "--;";
212  else if(val!=0)
213  Output() << TargetAddress(address) << " += " << IntegerConstant(val) << ";";
214  if(val!=0)
215  LineFeed();
216 }
217 
218 // integer maths
219 EmbeddedcCodeGenerator::AX EmbeddedcCodeGenerator::IntegerQuotient(const AX& expression, int val) {
220  return AX(expression + " / " + IntegerConstant(val));
221 }
222 
223 // integer maths
224 EmbeddedcCodeGenerator::AX EmbeddedcCodeGenerator::IntegerRemainder(const AX& expression, int val) {
225  return AX(expression + " % " + IntegerConstant(val));
226 }
227 
228 // integer maths
229 CodePrimitives::AX EmbeddedcCodeGenerator::IntegerBitmask(const AX& expression) {
230  return AX("(" + WordConstant(1) + " << " + expression + ")" );
231 }
232 
233 // integer compare
234 CodePrimitives::AX EmbeddedcCodeGenerator::IntegerIsEq(const AA& address, int val) {
235  return AX(TargetAddress(address) + " == " + IntegerConstant(val));
236 }
237 
238 // integer compare
239 CodePrimitives::AX EmbeddedcCodeGenerator::IntegerIsEq(const AA& address, const AX& expression) {
240  return AX(TargetAddress(address) + " == " + expression);
241 }
242 
243 // integer compare
244 CodePrimitives::AX EmbeddedcCodeGenerator::IntegerIsNotEq(const AA& address, const AX& expression) {
245  return AX(TargetAddress(address) + " != " + expression);
246 }
247 
248 // integer compare
249 CodePrimitives::AX EmbeddedcCodeGenerator::IntegerIsNotEq(const AA& address, int val) {
250  return AX(TargetAddress(address) + " != " + IntegerConstant(val));
251 }
252 
253 // integer compare
254 CodePrimitives::AX EmbeddedcCodeGenerator::IntegerIsGreater(const AA& address, int val) {
255  return AX(TargetAddress(address) + " > " + IntegerConstant(val));
256 }
257 
258 // integer compare
259 CodePrimitives::AX EmbeddedcCodeGenerator::IntegerIsLess(const AA& address, int val) {
260  return AX(TargetAddress(address) + " < " + IntegerConstant(val));
261 }
262 
263 // integer maths
264 bool EmbeddedcCodeGenerator::HasIntmaths(void) {
265  return true;
266 }
267 
268 // generate code: integer
269 CodePrimitives::AX EmbeddedcCodeGenerator::IntegerConstant(int val) {
270  AX res(ToStringInteger(val));
271  if(mIntegerType == "char") return res;
272  if(mIntegerType == "int8_t") return res;
273  if(mIntegerType == "int") return res;
274  if(mIntegerType == "int16_t") return res;
275  if(mIntegerType == "long") return AX(res + "L");
276  if(mIntegerType == "int32_t") return AX(res + "L");
277  if(mIntegerType == "long long") return AX(res + "LL");
278  FCG_ERR("EmbeddedcCodeGenerator: unsupported integer data type [" << mIntegerType << "]");
279  return res;
280 }
281 
282 // generate code: word
283 void EmbeddedcCodeGenerator::WordDeclare(const AA& address){
284  Output() << "static " << mWordType << " " << TargetAddress(address) << ";";
285  LineFeed();
286 }
287 
288 // generate code: word
289 void EmbeddedcCodeGenerator::WordDeclare(const AA& address, word_t val){
290  Output() << "static " << mWordType << " " << TargetAddress(address) << "=" << val << ";";
291  LineFeed();
292 }
293 
294 // generate code: word
295 void EmbeddedcCodeGenerator::WordAssign(const AA& address, word_t val){
296  Output() << TargetAddress(address) << " = " << WordConstant(val) << ";";
297  LineFeed();
298 }
299 
300 // generate code: word
301 void EmbeddedcCodeGenerator::WordAssign(const AA& address, const AX& expression){
302  Output() << TargetAddress(address) << " = " << expression << ";";
303  LineFeed();
304 }
305 
306 // generate code: word
307 void EmbeddedcCodeGenerator::WordOr(const AA& address, word_t val) {
308  Output() << TargetAddress(address) << " |= " << WordConstant(val) << ";";
309  LineFeed();
310 }
311 
312 // generate code: word
313 void EmbeddedcCodeGenerator::WordOr(const AA& address, const AX& expression) {
314  Output() << TargetAddress(address) << " |= " << expression << ";";
315  LineFeed();
316 }
317 
318 // generate code: word
319 void EmbeddedcCodeGenerator::WordOr(const AA& address, const AA& op1, const AA& op2) {
320  Output() << TargetAddress(address) << " = " << TargetExpression(op1) << " | " << TargetExpression(op2) << ";";
321  LineFeed();
322 }
323 
324 // generate code: word
325 void EmbeddedcCodeGenerator::WordOr(const AA& address, const AA& op1, word_t op2) {
326  Output() << TargetAddress(address) << " = " << TargetExpression(op1) << " | " << WordConstant(op2) << ";";
327  LineFeed();
328 }
329 
330 // generate code: word
331 void EmbeddedcCodeGenerator::WordAnd(const AA& address, word_t val) {
332  Output() << TargetAddress(address) << " &= " << WordConstant(val) << ";";
333  LineFeed();
334 }
335 
336 // generate code: word
337 void EmbeddedcCodeGenerator::WordAnd(const AA& address, const AX& expression) {
338  Output() << TargetAddress(address) << " &= " << expression << ";";
339  LineFeed();
340 }
341 
342 // generate code: word
343 void EmbeddedcCodeGenerator::WordAnd(const AA& address, const AA& op1, const AA& op2) {
344  Output() << TargetAddress(address) << " = " << TargetExpression(op1) << " & " << TargetExpression(op2) << ";";
345  LineFeed();
346 }
347 
348 // generate code: word
349 void EmbeddedcCodeGenerator::WordAnd(const AA& address, const AA& op1, word_t op2) {
350  Output() << TargetAddress(address) << " = " << TargetExpression(op1) << " & " << WordConstant(op2) << ";";
351  LineFeed();
352 }
353 
354 // generate code: word
355 void EmbeddedcCodeGenerator::WordNand(const AA& address, const AX& expression) {
356  Output() << TargetAddress(address) << " &= ~(" << expression << ");";
357  LineFeed();
358 }
359 
360 // generate code: word
361 CodePrimitives::AX EmbeddedcCodeGenerator::WordIsBitSet(const AA& address, int idx) {
362  return AX("( " + TargetAddress(address) + " & " + WordConstant(0x01<<idx) + " ) != 0");
363 }
364 
365 // generate code: word
366 CodePrimitives::AX EmbeddedcCodeGenerator::WordIsBitClr(const AA& address, int idx) {
367  return AX("( " + TargetAddress(address) + " & " + WordConstant(0x01<<idx) + " ) == 0");
368 }
369 
370 // generate code: word
371 CodePrimitives::AX EmbeddedcCodeGenerator::WordIsMaskSet(const AA& address, word_t mask) {
372  return AX("( " + TargetAddress(address) + " & " + WordConstant(mask) + " ) != 0");
373 }
374 
375 // generate code: conditionals
376 CodePrimitives::AX EmbeddedcCodeGenerator::WordIsEq(const AA& address, word_t val) {
377  return AX(TargetAddress(address) + " == " + WordConstant(val));
378 }
379 
380 // generate code: conditionals
381 CodePrimitives::AX EmbeddedcCodeGenerator::WordIsNotEq(const AA& address, word_t val) {
382  return AX(TargetAddress(address) + " != " + WordConstant(val));
383 }
384 
385 // generate code: word
386 EmbeddedcCodeGenerator::AX EmbeddedcCodeGenerator::WordConstant(word_t val) {
387  AX res;
388  std::stringstream sstr;
389  sstr << "0x" << std::setbase(16) << std::setfill('0');
390  // special case: zero
391  if(val==0) sstr << std::setw(2);
392  // special case: char
393  if(mWordType == "unsigned char") { sstr << std::setw(2); val &=0xff; }
394  // do stream
395  if(mWordType == "unsigned char") sstr << val;
396  else if(mWordType == "uint8_t") sstr << ((uint8_t) val) << "U";
397  else if(mWordType == "unsigned short") sstr << ((unsigned short) val) << "U";
398  else if(mWordType == "unsigned int") sstr << ((unsigned int) val) << "U";
399  else if(mWordType == "uint16_t") sstr << ((uint16_t) val) << "U";
400  else if(mWordType == "unsigned long") sstr << ((unsigned long) val) << "UL";
401  else if(mWordType == "uint32_t") sstr << ((uint32_t) val) << "UL";
402  else if(mWordType == "unsigned long long") sstr << ((unsigned long long) val) << "ULL";
403  else FCG_ERR("EmbeddedcCodeGenerator: unsupported word data type [" << mWordType <<"]");
404  sstr >> res;
405  return res;
406 }
407 
408 // generate code: string constant
409 EmbeddedcCodeGenerator::AX EmbeddedcCodeGenerator::StringConstant(const std::string& val) {
410  AX res;
411  res.append(1,'\"');
412  for(std::size_t i=0; i<val.length(); ++i) {
413  char c=val.at(i);
414  // terminate
415  if(c==0) break;
416  // quote double quote
417  if(c=='"') { res.append("\\\""); continue; }
418  // quote back slash
419  if(c=='\\') { res.append("\\\\"); continue; }
420  // printable ascii
421  if((c>=0x20) && (c<0x7f)) { res.append(1,c); continue; };
422  // error on other (alternative: use octal encoding to support utf8)
423  FCG_ERR("EmbeddedcCodeGenerator: non-printable ascii or other encoding unsupported [" << val <<"]");
424  }
425  res.append(1,'\"');
426  return res;
427 }
428 
429 // const-int array (Embedded C only helper)
430 EmbeddedcCodeGenerator::AX EmbeddedcCodeGenerator::IntarrayConstant(int offset, const std::vector<int>& val) {
431  std::stringstream strstr;
432  int newline=20;
433  if(val.size()+offset<25) newline=25;
434  strstr << "{ " ;
435  size_t vit=0;
436  while(true) {
437  if(vit==val.size()+offset) break;
438  if(vit< (size_t) offset)
439  strstr << IntegerConstant(0);
440  else
441  strstr << IntegerConstant(val[vit-offset]);
442  ++vit;
443  if(vit==val.size()+offset) break;
444  strstr << ", ";
445  newline--;
446  if(newline==0) {
447  strstr << std::endl << " ";
448  newline=20;
449  }
450  }
451  strstr << " }";
452  return AX(strstr.str());
453 }
454 
455 // const-int-array
456 void EmbeddedcCodeGenerator::CintarrayDeclare(const AA& address, int offset, const std::vector<int>& val) {
457  if(val.size()==0) {
458  FCG_ERR("EmbeddedcCodeGenerator::Cintarray(): ignoring empty const vector");
459  return;
460  }
461  if(val.size()>= (1ULL << (mIntegerSize-1))) {
462  FCG_ERR("EmbeddedcCodeGenerator::Cintarray(): const vector exceeds addres range");
463  return;
464  }
465  const std::vector<int> *pval=&val;
466  if(offset>0) {
467  std::vector<int> oval(val.size()+offset,0);
468  for(size_t i=0; i<val.size(); ++i)
469  oval[offset+i]=val[i];
470  pval=&oval;
471  }
472  Output() << "const " << mIntegerType << " " << TargetAddress(address) << "[] = ";
473  LineFeed();
474  IndentInc();
475  Output() << IntarrayConstant(offset,val) << ";";
476  LineFeed();
477  IndentDec();
478 }
479 
480 // int array access by const
481 EmbeddedcCodeGenerator::AA EmbeddedcCodeGenerator::CintarrayAccess(const AA& address, int index) {
482  return AA(address + "[" + ToStringInteger(index) + "]");
483 };
484 
485 // int array access by expression
486 EmbeddedcCodeGenerator::AA EmbeddedcCodeGenerator::CintarrayAccess(const AA& address, const AA& indexaddr){
487  return AA(address + "[" + TargetAddress(indexaddr) + "]");
488 };
489 
490 // tell parent class about this feature
491 bool EmbeddedcCodeGenerator::HasCintarray(void) {
492  return true;
493 };
494 
495 
496 // const-word array (Embedded C only helper)
497 EmbeddedcCodeGenerator::AX EmbeddedcCodeGenerator::WordarrayConstant(int offset, const std::vector<word_t>& val) {
498  std::stringstream strstr;
499  int newline=20;
500  if(val.size()+offset<25) newline=25;
501  strstr << "{ " ;
502  size_t vit=0;
503  while(true) {
504  if(vit==val.size()+offset) break;
505  if(vit < (size_t) offset)
506  strstr << WordConstant(0);
507  else
508  strstr << WordConstant(val[vit-offset]);
509  ++vit;
510  if(vit==val.size()+offset) break;
511  strstr << ", ";
512  newline--;
513  if(newline==0) {
514  strstr << std::endl << " ";
515  newline=20;
516  }
517  }
518  strstr << " }";
519  return AX(strstr.str());
520 }
521 
522 // const-word-array
523 void EmbeddedcCodeGenerator::CwordarrayDeclare(const AA& address, int offset, const std::vector<word_t>& val) {
524  if(val.size()==0) {
525  FCG_ERR("EmbeddedcCodeGenerator::Cwordarray(): ignoring empty const vector");
526  return;
527  }
528  if(val.size()>= (1ULL << (mIntegerSize-1))) {
529  FCG_ERR("EmbeddedcCodeGenerator::Cwordarray(): const vector exceeds addres range");
530  return;
531  }
532  Output() << "const " << mWordType << " " << TargetAddress(address) << "[] = ";
533  IndentInc();
534  Output() << WordarrayConstant(offset,val) << ";";
535  LineFeed();
536  IndentDec();
537 }
538 
539 // word-array access by const
540 EmbeddedcCodeGenerator::AA EmbeddedcCodeGenerator::CwordarrayAccess(const AA& address, int index) {
541  return AA(address + "[" + ToStringInteger(index) + "]");
542 };
543 
544 // word array access by expression
545 EmbeddedcCodeGenerator::AA EmbeddedcCodeGenerator::CwordarrayAccess(const AA& address, const AA& indexaddr){
546  return AA(address + "[" + TargetAddress(indexaddr) + "]");
547 };
548 
549 // tell parent class about this feature
550 bool EmbeddedcCodeGenerator::HasCwordarray(void) {
551  return true;
552 };
553 
554 // int-array
555 void EmbeddedcCodeGenerator::IntarrayDeclare(const AA& address, int offset, const std::vector<int>& val) {
556  if(val.size()==0) {
557  FCG_ERR("EmbeddedcCodeGenerator::Intarray(): ignoring empty const vector");
558  return;
559  }
560  if(val.size()>= (1ULL << (mIntegerSize-1))) {
561  FCG_ERR("EmbeddedcCodeGenerator::Intarray(): vector exceeds address range");
562  return;
563  }
564  Output() << mIntegerType << " " << TargetAddress(address) << "[] = ";
565  IndentInc();
566  Output() << IntarrayConstant(offset,val) << ";";
567  LineFeed();
568  IndentDec();
569 }
570 
571 // int-array
572 void EmbeddedcCodeGenerator::IntarrayDeclare(const AA& address, int offset, int len) {
573  if(len==0) {
574  FCG_ERR("EmbeddedcCodeGenerator::Intarray(): ignoring empty const vector");
575  return;
576  }
577  if(len+offset>= (1LL << (mIntegerSize-1))) {
578  FCG_ERR("EmbeddedcCodeGenerator::Intarray(): const vector exceeds address range");
579  return;
580  }
581  Output() << mIntegerType << " " << TargetAddress(address) << "[" << IntegerConstant(len+offset) << "];";
582  LineFeed();
583 }
584 
585 // int-array access by const
587  return AA(address + "[" + ToStringInteger(index) + "]");
588 };
589 
590 // int array access by expression
592  return AA(address + "[" + TargetAddress(indexaddr) + "]");
593 };
594 
595 // tell parent class about this feature
597  return true;
598 };
599 
600 // word-array
601 void EmbeddedcCodeGenerator::WordarrayDeclare(const AA& address, int offset, const std::vector<word_t>& val) {
602  if(val.size()==0) {
603  FCG_ERR("EmbeddedcCodeGenerator::Wordarray(): ignoring empty const vector");
604  return;
605  }
606  if(val.size()+offset >= (1ULL << (mIntegerSize-1))) {
607  FCG_ERR("EmbeddedcCodeGenerator::Wordarray(): const vector exceeds addres range");
608  return;
609  }
610  Output() << mWordType << " " << TargetAddress(address) << "[] = ";
611  IndentInc();
612  Output() << WordarrayConstant(offset,val) << ";";
613  LineFeed();
614  IndentDec();
615 }
616 
617 // word-array
618 void EmbeddedcCodeGenerator::WordarrayDeclare(const AA& address, int offset, int len) {
619  if(len==0) {
620  FCG_ERR("EmbeddedcCodeGenerator::Wordarray(): ignoring empty const vector");
621  return;
622  }
623  if(len+offset>= (1LL << (mIntegerSize-1))) {
624  FCG_ERR("EmbeddedcCodeGenerator::Wordarray(): const vector exceeds addres range");
625  return;
626  }
627  Output() << mWordType << " " << TargetAddress(address) << "[" << IntegerConstant(len+offset) << "];";
628  LineFeed();
629 }
630 
631 // word-array access by const
632 EmbeddedcCodeGenerator::AA EmbeddedcCodeGenerator::WordarrayAccess(const AA& address, int index) {
633  return AA(address + "[" + ToStringInteger(index) + "]");
634 };
635 
636 // word array access by expression
637 EmbeddedcCodeGenerator::AA EmbeddedcCodeGenerator::WordarrayAccess(const AA& address, const AA& indexaddr){
638  return AA(address + "[" + TargetAddress(indexaddr) + "]");
639 };
640 
641 // tell parent class about this feature
642 bool EmbeddedcCodeGenerator::HasWordarray(void) {
643  return true;
644 };
645 
646 // literal const-string array (Embedded C only helper)
647 EmbeddedcCodeGenerator::AX EmbeddedcCodeGenerator::StrarrayConstant(int offset, const std::vector<std::string>& val) {
648  std::stringstream strstr;
649  int newline;
650  if(val.size()+offset <4) {
651  newline=4;
652  strstr << "{ ";
653  } else {
654  newline=1;
655  strstr << "{" << std::endl;
656  }
657  size_t vit=0;
658  while(true) {
659  if(vit==val.size()+offset) break;
660  if(vit < (size_t)offset)
661  strstr << StringConstant("");
662  else
663  strstr << StringConstant(val[vit-offset]);
664  ++vit;
665  if(vit==val.size()+offset) break;
666  strstr << ", ";
667  newline--;
668  if(newline==0) {
669  strstr << std::endl;
670  newline=1;
671  }
672  }
673  strstr << " }";
674  return AX(strstr.str());
675 }
676 
677 // const string array
678 void EmbeddedcCodeGenerator::CstrarrayDeclare(const AA& address, int offset, const std::vector<std::string>& val) {
679  if(val.size()==0) {
680  FCG_ERR("EmbeddedcCodeGenerator::Cstrarrayy(): ignoring empty string array");
681  return;
682  }
683  if(val.size()+offset >= (1ULL << (mIntegerSize-1))) {
684  FCG_ERR("EmbeddedcCodeGenerator::Cstrarray(): string array exceeds address range");
685  return;
686  }
687  Output() << "const char* const" << " " << TargetAddress(address) << "[] = ";
688  IndentInc();
689  Output() << StrarrayConstant(offset,val) << ";";
690  LineFeed();
691  IndentDec();
692 };
693 
694 // const string array
695 EmbeddedcCodeGenerator::AA EmbeddedcCodeGenerator::CstrarrayAccess(const AA& address, int index) {
696  return AA(address + "[" + ToStringInteger(index) + "]");
697 };
698 
699 // const string array
700 EmbeddedcCodeGenerator::AA EmbeddedcCodeGenerator::CstrarrayAccess(const AA& address, const AA& indexaddr){
701  return AA(address + "[" + TargetAddress(indexaddr) + "]");
702 };
703 
704 // tell parent about this feature
705 bool EmbeddedcCodeGenerator::HasCstrarray(void) {
706  return true;
707 };
708 
709 
710 // generate code: conditionals
711 void EmbeddedcCodeGenerator::IfTrue(const AX& expression) {
712  Output() << "if( " << expression << " ) {";
713  LineFeed();
714  IndentInc();
715 }
716 
717 // generate code: conditionals
718 void EmbeddedcCodeGenerator::IfFalse(const AX& expression) {
719  Output() << "if( ! ( " << expression << " ) ) {";
720  LineFeed();
721  IndentInc();
722 }
723 
724 // generate code: conditionals
725 void EmbeddedcCodeGenerator::IfWord(const AX& expression) {
726  Output() << "if( " << expression << " ) {";
727  LineFeed();
728  IndentInc();
729 }
730 
731 // generate code: conditionals
732 void EmbeddedcCodeGenerator::IfElse(void) {
733  IndentDec();
734  Output() << "} else {";
735  LineFeed();
736  IndentInc();
737 }
738 
739 // generate code: conditionals
740 void EmbeddedcCodeGenerator::IfElseIfTrue(const AX& expression) {
741  IndentDec();
742  Output() << "} else if( " << expression << " ) {";
743  LineFeed();
744  IndentInc();
745 }
746 
747 // generate code: conditionals
748 void EmbeddedcCodeGenerator::IfEnd(void) {
749  IndentDec();
750  Output() << "};";
751  LineFeed();
752 }
753 
754 // switch control
755 void EmbeddedcCodeGenerator::SwitchBegin(const AA& address){
756  Output() << "switch(" << TargetAddress(address) << ") {";
757  LineFeed();
758 }
759 
760 // switch control
761 void EmbeddedcCodeGenerator::SwitchCase(const AA& address, int val){
762  (void) address;
763  Output() << "case " << IntegerConstant(val) << ":";
764  LineFeed();
765  IndentInc();
766 }
767 
768 // switch control
769 void EmbeddedcCodeGenerator::SwitchCases(const AA& address, int from, int to){
770  // simplify to singleton
771  if(from==to) {
772  SwitchCase(address, from);
773  return;
774  }
775  // do range (quiet for empty)
776  for(int val=from; val<=to; ++val) {
777  Output() << "case " << IntegerConstant(val) << ":";
778  LineFeed();
779  }
780  IndentInc();
781 }
782 
783 // switch control
784 void EmbeddedcCodeGenerator::SwitchCases(const AA& address, const std::set< int >& vals){
785  (void) address;
786  // do set (quiet for empty)
787  std::set< int >::const_iterator vit=vals.begin();
788  for(; vit!=vals.end(); ++ vit) {
789  Output() << "case " << IntegerConstant(*vit) << ":";
790  LineFeed();
791  }
792  IndentInc();
793 }
794 
795 // switch control
796 void EmbeddedcCodeGenerator::SwitchBreak(void){
797  Output() << "break;";
798  LineFeed();
799  IndentDec();
800 }
801 
802 // switch control
803 void EmbeddedcCodeGenerator::SwitchEnd(void){
804  Output() << "default:";
805  LineFeed();
806  IndentInc();
807  Output() << "break;";
808  LineFeed();
809  IndentDec();
810  Output() << "};";
811  LineFeed();
812 }
813 
814 // switch control
815 bool EmbeddedcCodeGenerator::HasMultiCase(void) {
816  return true;
817 }
818 
819 // loops
820 void EmbeddedcCodeGenerator::LoopBegin(void) {
821  Output() << "while(1) {";
822  LineFeed();
823  IndentInc();
824 }
825 
826 // loops
827 void EmbeddedcCodeGenerator::LoopBreak(const AX& expression) {
828  Output() << "if( " << expression << " ) break;";
829  LineFeed();
830 }
831 
832 
833 // loops
834 void EmbeddedcCodeGenerator::LoopEnd(void) {
835  IndentDec();
836  Output() << "};";
837  LineFeed();
838 }
839 
840 void EmbeddedcCodeGenerator::FunctionReturn(void) {
841  Output() << "return;";
842  LineFeed();
843 }
844 
845 
846 // timer
847 void EmbeddedcCodeGenerator::TimerDeclare(const AA& address, const std::string& litval) {
848  // read/check ftu time format
849  char* next;
850  const char* first = litval.c_str();
851  strtol(first,&next,10);
852  bool err=false;
853  if(*next!='f') err=true;
854  if(!err) if(*(++next)!='t') err=true;
855  if(!err) if(*(++next)!='u') err=true;
856  if(!err) if(*(++next)!=0) err=true;
857  if(err) {
858  FCG_ERR("EmbeddedcCodeGenerator: missmatched time literal "+ litval);
859  }
860  Output() << "static int " << TargetAddress(AA("timer_"+address+"_cnt")) << ";";
861  LineFeed();
862  Output() << "static char " << TargetAddress(AA("timer_"+address+"_run")) << ";";
863  LineFeed();
864 }
865 void EmbeddedcCodeGenerator::TimerStart(const AA& address) {
866  Output() << TargetAddress(AA("timer_"+address+"_run")) << " = 1;";
867  LineFeed();
868 }
869 void EmbeddedcCodeGenerator::TimerStop(const AA& address) {
870  Output() << TargetAddress(AA("timer_"+address+"_run")) << " = 0;";
871  LineFeed();
872 }
873 void EmbeddedcCodeGenerator::TimerReset(const AA& address, const std::string& litval) {
874  int val=(int) strtol(litval.c_str(),NULL,10);
875  Output() << TargetAddress(AA("timer_"+address+"_cnt")) << " = " << IntegerConstant(val) << ";";
876  LineFeed();
877 }
878 CodePrimitives::AX EmbeddedcCodeGenerator::TimerIsElapsed(const AA& address) {
879  return AX(TargetAddress(AA("timer_"+address+"_run")) + " && (" + TargetAddress(AA("timer_"+address+"_cnt")) + " <= 0)");
880 }
881 
882 
883 // output actions
884 void EmbeddedcCodeGenerator::RunActionSet(const std::string& address) {
885  Output() << address << " = 1;" ;
886  LineFeed();
887 }
888 void EmbeddedcCodeGenerator::RunActionClr(const std::string& address) {
889  Output() << address << " = 0;" ;
890  LineFeed();
891 }
892 void EmbeddedcCodeGenerator::RunActionExe(const AX& expression) {
893  Output() << expression << ";";
894  LineFeed();
895 }
896 
897 
898 
#define FAUDES_REGISTERCODEGENERATOR(ftype, ctype)
Class registration macro.
void InsertExecHooks(void)
Helper to insert target code for execution hooks.
virtual void DoGenerateCyclicCode(void)
cut-and-paste template for code snippet assembly
Abstract expression; see also Absstract_Addresses.
virtual std::ostream & Output(void)
Output stream.
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
int mWordSize
compressed boolean capacity of target type word
virtual void DoWriteTargetConfiguration(TokenWriter &rTw) const
File i/o.
EmbeddedcCodeGenerator(void)
Constructor.
virtual void LineFeed(int lines=1)
LineFeed (convenience support for derived classes)
Implementation of code primitives by generic C-code.
Definition: cgp_embeddedc.h:71
virtual std::string TargetAddress(const AA &address)
abstract address conversion
virtual void DecrementTimers(void)
re-implemented/additional code blocks
void DoGenerate(void)
virtual hook for generate
virtual void Clear(void)
Clear all data.
std::map< std::string, TimerConfiguration >::iterator TimerIterator
Access to timer records by iterator.
virtual void IndentInc()
Indentation (convenience support for derived classes)
bool mArrayForBitmasks
code option: use const array to represent bit-masks
std::string mStateUpdateHook
code option: state change hook
virtual void DoGenerateDeclarations(void)
cut-and-paste template for code snippet assembly
void DoCompile(void)
add my preferences to DoCompile
virtual void DoReadTargetConfiguration(TokenReader &rTr)
re-implement token i/o for extra configuration
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 void DoCompile(void)
virtual hook to extend compiled data
virtual void LiteralAppend(void)
Cosmetic: append literally from configuration.
virtual void DoReadTargetConfiguration(TokenReader &rTr)
File i/o.
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
std::string mWordType
target data type for word
virtual AA IntarrayAccess(const AA &address, int index)
default int-array: not supported
virtual void Clear(void)
Clear all data.
virtual void DoWriteTargetConfiguration(TokenWriter &rTw) const
re-implement token i/o for extra configuration
unsigned long word_t
Code-generator internal data type of target words.
virtual bool HasIntarray(void)
default int-array: not supported
std::string mEventExecutionHook
code option: event exec hook
Abstract address; see also Absstract_Addresses.
virtual AX TargetExpression(const AA &address)
abstract address conversion
std::string mPrefix
universal prefix (pseudo name space)
virtual void IntarrayDeclare(const AA &address, int offset, int len)
default int-array: not supported
virtual void IndentDec()
Indentation (convenience support for derived classes)
TimerIterator TimersBegin()
Access to timer records by iterator.
Code-generator for target C.
std::map< std::string, bitarray_rec > mBitarrays
Record of all declared bit-arrays.
virtual ~EmbeddedcCodeGenerator(void)
Explicit destructor.
virtual void LiteralPrepend(void)
Cosmetic: prepend literally from configuration data.
bool mMuteComments
mute comments
bool mBitAddressArithmetic
code option: compute bit and word address on target
virtual void Comment(const std::string &text)
Target comments (see EmbeddedcCodeGenerator for consistent reimplementation pattern) ...
Execution semantics in terms of code primitives.
TimerIterator TimersEnd()
Access to timer records by iterator.