CompileDES  3.13
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.
Code-generator for target C.
virtual void LineFeed(int lines=1)
LineFeed (convenience support for derived classes)
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
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)
virtual void IndentDec()
Indentation (convenience support for derived classes)
Abstract address; see also Absstract_Addresses.
Abstract expression; see also Absstract_Addresses.
Execution semantics in terms of code primitives.
bool mBitAddressArithmetic
code option: compute bit and word address on target
std::string mStateUpdateHook
code option: state change hook
virtual void DoGenerateDeclarations(void)
cut-and-paste template for code snippet assembly
virtual void DoGenerateResetCode(void)
cut-and-paste template for code snippet assembly
virtual void LiteralAppend(void)
Cosmetic: append literally from configuration.
virtual void Comment(const std::string &text)
Target comments (see EmbeddedcCodeGenerator for consistent reimplementation pattern)
std::map< std::string, bitarray_rec > mBitarrays
Record of all declared bit-arrays.
virtual void DoReadTargetConfiguration(TokenReader &rTr)
re-implement token i/o for extra configuration
std::string mIntegerType
target data type for integer
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
bool mArrayForBitmasks
code option: use const array to represent bit-masks
virtual void DoCompile(void)
virtual hook to extend compiled data
virtual void LiteralPrepend(void)
Cosmetic: prepend literally from configuration data.
std::string mPrefix
universal prefix (pseudo name space)
std::string mEventExecutionHook
code option: event exec hook
Implementation of code primitives by generic C-code.
Definition: cgp_embeddedc.h:71
void DoCompile(void)
add my preferences to DoCompile
void DoGenerate(void)
virtual hook for generate
virtual bool HasIntarray(void)
default int-array: not supported
virtual void DoWriteTargetConfiguration(TokenWriter &rTw) const
File i/o.
virtual void Comment(const std::string &text)
Target comments (see EmbeddedcCodeGenerator for consistent reimplementation pattern)
EmbeddedcCodeGenerator(void)
Constructor.
virtual void DoReadTargetConfiguration(TokenReader &rTr)
File i/o.
virtual AA IntarrayAccess(const AA &address, int index)
default int-array: not supported
virtual void Clear(void)
Clear all data.
virtual void DecrementTimers(void)
re-implemented/additional code blocks
virtual std::string TargetAddress(const AA &address)
abstract address conversion
virtual ~EmbeddedcCodeGenerator(void)
Explicit destructor.
virtual AX TargetExpression(const AA &address)
abstract address conversion
void InsertExecHooks(void)
Helper to insert target code for execution hooks.
virtual void IntarrayDeclare(const AA &address, int offset, int len)
default int-array: not supported