CompileDES  3.09
Executable-Code Generation from Synchronised libFAUDES Automata
cgp_codeprimitives.cpp
Go to the documentation of this file.
1 
3 /*
4 
5  FAU Discrete Event Systems Library (libFAUDES)
6 
7  Copyright (C) 2010, 2016, 2017, Thomas Moor
8 
9 */
10 
11 // my includes
12 #include "cgp_codeprimitives.h"
13 #include <cctype>
14 
15 /*e
16 ******************************************************************
17 ******************************************************************
18 ******************************************************************
19 
20 CodePrimitives implementation --- maintaine class
21 
22 ******************************************************************
23 ******************************************************************
24 ******************************************************************
25 */
26 
27 
28 // CodePrimitives(void)
30  FD_DCG("CodePrimitives(" << this << ")::CodePrimitives()");
31 }
32 
33 // CodePrimitives(void)
35  FD_DCG("CodePrimitives(" << this << ")::~CodePrimitives()");
36 }
37 
38 
39 // Clear()
41  FD_DCG("CodePrimitives(" << this << ")::Clear()");
42  // call base
44  // clear my configuration parameters
45  mPrefix="faudes_";
46  mWordType="word_type";
47  mWordSize=8;
48  mIntegerType="int_type";
49  mIntegerSize=8;
50  mArrayForTransitions=HasCintarray();
52  mArrayForBitmasks=HasCwordarray();
53  mBitAddressArithmetic= HasIntmaths() && !mArrayForBitmasks;
54  mArrayForBitarray= HasWordarray();
56  mArrayForState=false;
58  mLoopPendingInputs=false;
59  mLoopEnabledOutputs=false;
61  mEventNameLookup=false;
62  mStateNameLookup=false;
65  mLiteralPrepend="";
66  mLiteralAppend="";
67 }
68 
69 
70 //DoReadTargetConfiguration(rTr)
72  FD_DCG("CodePrimitives::DoReadTargetConfiguration()");
73  Token token;
74  // call base
76  // prefix
77  if(rTr.ExistsBegin("Prefix")) {
78  rTr.ReadBegin("Prefix",token);
79  mPrefix=token.AttributeStringValue("val");
80  if(mPrefix!="") {
81  if(*mPrefix.rbegin()!='_') mPrefix=mPrefix+"_";
82  }
83  rTr.ReadEnd("Prefix");
84  }
85  // integral target type
86  if(rTr.ExistsBegin("WordType")) {
87  rTr.ReadBegin("WordType",token);
88  mWordType=token.AttributeStringValue("val");
89  rTr.ReadEnd("WordType");
90  }
91  // wordsize
92  if(rTr.ExistsBegin("WordSize")) {
93  rTr.ReadBegin("WordSize",token);
94  mWordSize=token.AttributeIntegerValue("val");
95  rTr.ReadEnd("WordSize");
96  }
97  // unsigned integral type
98  if(rTr.ExistsBegin("IntegerType")) {
99  rTr.ReadBegin("IntegerType",token);
100  mIntegerType=token.AttributeStringValue("val");
101  rTr.ReadEnd("IntegerType");
102  }
103  // intsize
104  if(rTr.ExistsBegin("IntegerSize")) {
105  rTr.ReadBegin("IntegerSize",token);
106  mIntegerSize=token.AttributeIntegerValue("val");
107  rTr.ReadEnd("IntegerSize");
108  }
109  // code option
110  if(rTr.ExistsBegin("ArrayForTransitions")) {
111  rTr.ReadBegin("ArrayForTransitions",token);
112  mArrayForTransitions= token.AttributeIntegerValue("val");
113  rTr.ReadEnd("ArrayForTransitions");
114  }
115  // code option
116  if(rTr.ExistsBegin("MaintainStateIndices")) {
117  rTr.ReadBegin("MaintainStateIndices",token);
118  mMaintainStateIndices= token.AttributeIntegerValue("val");
119  rTr.ReadEnd("MaintainStateindices");
120  }
121  // code option
122  if(rTr.ExistsBegin("ArrayForBitmasks")) {
123  rTr.ReadBegin("ArrayForBitmasks",token);
124  mArrayForBitmasks= token.AttributeIntegerValue("val");
125  rTr.ReadEnd("ArrayForBitmasks");
126  }
127  // code option
128  if(rTr.ExistsBegin("ArrayForBitarray")) {
129  rTr.ReadBegin("ArrayForBitarray",token);
130  mArrayForBitarray= token.AttributeIntegerValue("val");
131  rTr.ReadEnd("ArrayForBitarray");
132  }
133  // code option
134  if(rTr.ExistsBegin("BitAddressArithmetic")) {
135  rTr.ReadBegin("BitAddressArithmetic",token);
136  mBitAddressArithmetic= token.AttributeIntegerValue("val");
137  rTr.ReadEnd("BitAddressArithmetic");
138  }
139  // code option
140  if(rTr.ExistsBegin("BisectionForBitfind")) {
141  rTr.ReadBegin("BisectionForBitfind",token);
142  mBisectionForBitfind= token.AttributeIntegerValue("val");
143  rTr.ReadEnd("BisectionForBitfind");
144  }
145  // code option
146  if(rTr.ExistsBegin("ArrayForState")) {
147  rTr.ReadBegin("ArrayForState",token);
148  mArrayForState= token.AttributeIntegerValue("val");
149  rTr.ReadEnd("ArrayForState");
150  }
151  // code option
152  if(rTr.ExistsBegin("EventsetsForPerformance")) {
153  rTr.ReadBegin("EventsetsForPerformance",token);
154  mEventsetsForPerformance= token.AttributeIntegerValue("val");
155  rTr.ReadEnd("EventsetsForPerformance");
156  }
157  // code option
158  if(rTr.ExistsBegin("LoopPendingInputs")) {
159  rTr.ReadBegin("LoopPendingInputs",token);
160  mLoopPendingInputs= token.AttributeIntegerValue("val");
161  rTr.ReadEnd("LoopPendingInputs");
162  }
163  // code option
164  if(rTr.ExistsBegin("LoopEnabledOutputs")) {
165  rTr.ReadBegin("LoopEnabledOutputs",token);
166  mLoopEnabledOutputs= token.AttributeIntegerValue("val");
167  rTr.ReadEnd("LoopEnabledOutputs");
168  }
169  // code option
170  if(rTr.ExistsBegin("StrictEventSynchronisation")) {
171  rTr.ReadBegin("StrictEventSynchronisation",token);
172  mStrictEventSynchronisation= token.AttributeIntegerValue("val");
173  rTr.ReadEnd("StrictEventSynchronisation");
174  }
175  // code option
176  if(rTr.ExistsBegin("EventNameLookup")) {
177  rTr.ReadBegin("EventNameLookup",token);
178  mEventNameLookup= token.AttributeIntegerValue("val");
179  rTr.ReadEnd("EventNameLookup");
180  }
181  // code option
182  if(rTr.ExistsBegin("StateNameLookup")) {
183  rTr.ReadBegin("StateNameLookup",token);
184  mStateNameLookup= token.AttributeIntegerValue("val");
185  rTr.ReadEnd("StateNameLookup");
186  }
187  // code option
188  if(rTr.ExistsBegin("EventExecutionHook")) {
189  rTr.ReadBegin("EventExecutionHook",token);
190  mEventExecutionHook= token.AttributeStringValue("val");
191  rTr.ReadEnd("EventExecutionHook");
192  }
193  // code option
194  if(rTr.ExistsBegin("StateUpdateHook")) {
195  rTr.ReadBegin("StateUpdateHook",token);
196  mStateUpdateHook= token.AttributeStringValue("val");
197  rTr.ReadEnd("StateUpdateHook");
198  }
199  // literal
200  if(rTr.ExistsBegin("IncludeBefore"))
201  rTr.ReadVerbatim("IncludeBefore",mLiteralPrepend);
202  // literal
203  if(rTr.ExistsBegin("IncludeAfter"))
204  rTr.ReadVerbatim("IncludeAfter",mLiteralAppend);
205  FD_DCG("CodePrimitives::DoReadTargetConfiguration(): done");
206 }
207 
208 
209 
210 //DoWriteTargetConfiguration(rTr,rLabel)
211 void CodePrimitives::DoWriteTargetConfiguration(TokenWriter& rTw) const {
212  // call base
214  // write my configuration parameters
215  Token token;
216  // prefix
217  token.SetEmpty("Prefix");
218  token.InsAttributeString("val",mPrefix);
219  rTw.Write(token);
220  // word type
221  token.SetEmpty("WordType");
222  token.InsAttributeString("val",mWordType);
223  rTw.Write(token);
224  // wordsize
225  token.SetEmpty("WordSize");
226  token.InsAttributeInteger("val",mWordSize);
227  rTw.Write(token);
228  // integer type
229  token.SetEmpty("IntegerType");
230  token.InsAttributeString("val",mIntegerType);
231  rTw.Write(token);
232  // integersize
233  token.SetEmpty("IntegerSize");
234  token.InsAttributeInteger("val",mIntegerSize);
235  rTw.Write(token);
236  // code option
237  token.SetEmpty("ArrayForTransitions");
238  token.InsAttributeBoolean("val",mArrayForTransitions);
239  rTw.Write(token);
240  // code option
241  token.SetEmpty("MaintainStateIndices");
242  token.InsAttributeBoolean("val",mMaintainStateIndices);
243  rTw.Write(token);
244  // code option
245  token.SetEmpty("ArrayForBitmasks");
246  token.InsAttributeBoolean("val",mArrayForBitmasks);
247  // code option
248  token.SetEmpty("ArrayForBitarray");
249  token.InsAttributeBoolean("val",mArrayForBitarray);
250  rTw.Write(token);
251  // code option
252  token.SetEmpty("BitAddressArithmetic");
253  token.InsAttributeBoolean("val",mBitAddressArithmetic);
254  rTw.Write(token);
255  // code option
256  token.SetEmpty("BisectionForBitfind");
257  token.InsAttributeBoolean("val",mBisectionForBitfind);
258  rTw.Write(token);
259  // code option
260  token.SetEmpty("ArrayForState");
261  token.InsAttributeBoolean("val",mArrayForState);
262  rTw.Write(token);
263  // code option
264  token.SetEmpty("EventsetsForPerformance");
265  token.InsAttributeBoolean("val",mEventsetsForPerformance);
266  rTw.Write(token);
267  // code option
268  token.SetEmpty("LoopPendingInputs");
269  token.InsAttributeBoolean("val",mLoopPendingInputs);
270  rTw.Write(token);
271  // code option
272  token.SetEmpty("LoopEnabledOutputs");
273  token.InsAttributeBoolean("val",mLoopEnabledOutputs);
274  rTw.Write(token);
275  // code option
276  token.SetEmpty("StrictEventSynchronisation");
277  token.InsAttributeBoolean("val",mStrictEventSynchronisation);
278  rTw.Write(token);
279  // code option
280  token.SetEmpty("EventNameLookup");
281  token.InsAttributeBoolean("val",mEventNameLookup);
282  rTw.Write(token);
283  // code option
284  token.SetEmpty("StateNameLookup");
285  token.InsAttributeBoolean("val",mStateNameLookup);
286  // code option
287  token.SetEmpty("EventExecutionHook");
288  token.InsAttributeString("val",mEventExecutionHook);
289  rTw.Write(token);
290  // code option
291  token.SetEmpty("StateUpdateHook");
292  token.InsAttributeString("val",mStateUpdateHook);
293  rTw.Write(token);
294  // preamble/main
295  if(mLiteralPrepend.size()>0)
296  rTw.WriteVerbatim("IncludeBefore",mLiteralPrepend);
297  if(mLiteralAppend.size()>0)
298  rTw.WriteVerbatim("IncludeAfter",mLiteralAppend);
299 }
300 
301 // DoCompile()
303  // care about states first
304  if(mStateNameLookup && !HasCstrarray()) {
305  FCG_VERB1("CodePrimitives::Compile(): cannot generate lookup tables for the specified platforms");
306  mStateNameLookup=false;
307  }
309  FCG_VERB1("CodePrimitives::Compile(): state name lookup implies to maintain state indices as provided");
311  }
312  if((!mStateUpdateHook.empty()) && (!mMaintainStateIndices)) {
313  FCG_VERB1("CodePrimitives::Compile(): state update hook implies to maintain state indices as provided");
315  }
316  // check whether all generators have consecutive state indicees
317  for(size_t git=0; git<Size(); ++git) {
318  if(At(git).MaxStateIndex()!=At(git).States().Size()) {
320  FCG_VERB0("CodeGenerator::Generator(): generator [" << At(git).Name() << "] " <<
321  "has non-consecutive state indicees --- this will introduce an inefficient sparse lookup table");
322  }
323  if(!mMaintainStateIndices) {
324  FCG_VERB0("CodeGenerator::Generator(): generator [" << At(git).Name() << "] " <<
325  "has non-consecutive state indicees --- applying MinStateIndex()");
326  mGenerators[git].MinStateIndex();
327  }
328  }
329  }
330  // call base, incl transitionvector setup
332  // fix transition vector to use faudes indices
334  for(size_t git=0; git<Size(); ++git) {
335  std::vector<int>& transvect = mTransitionVector[git];
336  std::map<int,Idx>& faudesidx = mStateFaudesIndex[git];
337  for(size_t vit=0; vit< transvect.size(); ++vit) {
338  int ev = transvect[vit];
339  if(ev==0) continue;
340  int x2 = transvect[++vit];
341  transvect[vit]=faudesidx[x2];
342  }
343  }
344  }
345  // test conformance
346  FD_DCG("CodePrimitives(" << this << ")::DoCompile()");
347  // check and fix configuration
348  if(mArrayForTransitions && !HasCintarray()) {
349  FCG_VERB1("CodePrimitives::Compile(): cannot generate compiled arrays for the specified target");
350  mArrayForTransitions=false;
351  }
352  if(mArrayForBitmasks && !HasCwordarray()) {
353  FCG_VERB1("CodePrimitives::Compile(): cannot generate compiled bit-masks for the specified target");
354  mArrayForBitmasks=false;
355  }
356  if(mArrayForBitmasks && (mWordSize>8))
357  FCG_VERB1("CodePrimitives::Compile(): compiled bitmasks not recommended for word-size #" << mWordSize);
358  if(mArrayForBitmasks && (mWordSize>16)) {
359  FCG_VERB1("CodePrimitives::Compile(): reject compiled bitmasks for word-size #" << mWordSize);
360  mArrayForBitmasks = false;
361  }
362  if(mBitAddressArithmetic && !HasIntmaths()) {
363  FCG_VERB1("CodePrimitives::Compile(): bit address-maths not available for the specified target");
364  mBitAddressArithmetic=false;
365  }
367  FCG_VERB1("CodePrimitives::Compile(): reject option eventsets-for-performance for specified target");
368  mEventsetsForPerformance = false;
369  }
370  /*
371  if(mLoopEnabledOutputs && !mEventsetsForPerformance) {
372  FCG_VERB1("CodePrimitives::Compile(): option loop-enabled-outputs suggests eventsets-for-performance");
373  }
374  */
376  FCG_VERB1("CodePrimitives::Compile(): option loop-enabled-outputs implies loop-enabled-inputs");
377  }
378  if(mLoopEnabledOutputs) {
379  if(mLastOutputEvent+1+mInternalEvents.Size() != mUsedEvents.Size()) {
380  FCG_ERR("CodePrimitives::Compile(): option loop-enabled-outputs requires high priority for output events");
381  }
382  }
383  if(mEventNameLookup && !HasCstrarray()) {
384  FCG_VERB1("CodePrimitives::Compile(): cannot generate lookup tables for the specified platform");
385  mEventNameLookup=false;
386  }
387  if((!mStateUpdateHook.empty()) && (!HasIntarray())) {
388  FCG_VERB1("CodePrimitives::Compile(): cannot implement state-update hook for the specified platform");
389  mStateUpdateHook="";
390  }
391  if((!mStateUpdateHook.empty()) && (!mArrayForState)) {
392  FCG_VERB1("CodePrimitives::Compile(): state-update hook implies array representation of overall state");
393  mArrayForState=true;
394  }
395 }
396 
397 /*
398 ******************************************************************
399 ******************************************************************
400 ******************************************************************
401 
402 CodePrimitives implementation: internal data organisation
403 
404 ******************************************************************
405 ******************************************************************
406 ******************************************************************
407 */
408 
409 
410 // mangle an arbitrary string to a valid target symbol
411 std::string CodePrimitives::TargetSymbol(const std::string& str) {
412  // could have a static lookup here ... avoid doublets aso .. use synthetic symbols
413  std::string res;
414  std::string::const_iterator sit=str.begin();
415  for(;sit!=str.end();++sit){
416  if(std::isalpha(*sit)) { res.push_back(*sit); continue; };
417  if(std::isdigit(*sit) && res.size()>0) { res.push_back(*sit); continue; }
418  if(res.size()>0) res.push_back('_');
419  }
420  return res;
421 }
422 
423 
424 // effective target state index
425 int CodePrimitives::StateTargetIdx(size_t git, Idx idx) {
426  // if we compile with transition array, use the pointer to entry as target index
428  return CodeGenerator::StateTargetIdx(git,idx);
429  }
430  // else default to original index, which is consecutive starting with 1
431  return idx;
432 }
433 
434 // retrieve faudes state idx
435 Idx CodePrimitives::StateFaudesIdx(size_t git, int idx) {
436  // if we compile with transition array, target idx refers to the transitions vector
438  return CodeGenerator::StateFaudesIdx(git,idx);
439  }
440  // else default to original index, which is consecutive starting with 1
441  return idx;
442 }
443 
444 
445 
446 /*
447 ******************************************************************
448 ******************************************************************
449 ******************************************************************
450 
451 CodePrimitives implementation --- generate code blocks
452 
453 ******************************************************************
454 ******************************************************************
455 ******************************************************************
456 */
457 
458 
459 // code blocks: literal prepend from configuration
461  if(mLiteralPrepend.size()==0) return;
462  Comment("************************************************");
463  Comment("* prepend code snippet from configuration *");
464  LineFeed(2);
465  Output() << mLiteralPrepend;
466  LineFeed(2+2);
467 }
468 
469 
470 // code blocks: variables (global)
472  Comment("status (0x00 <> waiting, 0x01<>executing, 0x02<>err)");
473  WordDeclare(AA("status"));
474  LineFeed(1);
475 }
476 
477 // code blocks: variables (global)
479  Comment("external reset");
480  BooleanDeclare(AA("reset"), false);
481  LineFeed(1);
482 }
483 
484 // code blocks: variables (global)
486  Comment("recent event (0<>none)");
487  IntegerDeclare(AA("recent_event"));
488  LineFeed(1);
489 }
490 
491 
492 // code blocks: variables (opt global)
494  Comment("parallel state");
495  if(mArrayForState) {
496  IntarrayDeclare(AA("parallel_state"),Size());
497  } else {
498  for(Idx gid=0; gid< Size(); gid++)
499  IntegerDeclare(AA("parallel_state").Sub(gid));
500  }
501  LineFeed(1);
502 }
503 
504 // code blocks: variables (opt global)
506  // std event sets
507  Comment("pending input events incl timer elapse");
508  EventSetDeclare(AA("pending_events"));
509  LineFeed(1);
510  Comment("events enabled by all generators");
511  EventSetDeclare(AA("enabled_events"));
512  LineFeed(1);
513 }
514 
515 // code blocks: variables (local)
517  // exec event
518  Comment("executed event (-1<>init, 0<>none)");
519  IntegerDeclare(AA("exec_event"),-1);
520  LineFeed(1);
521  // scheduled event
522  Comment("scheduled event (0<>none)");
523  IntegerDeclare(AA("sched_event"));
524  LineFeed(1);
525  // edge detection
526  if(LinesBegin()!=LinesEnd()){
527  Comment("line levels");
528  LineIterator lit=LinesBegin();
529  for(;lit!=LinesEnd();++lit) {
530  AA baddr = AA("line_level").Sub(lit->second.mBitAddress);
531  BooleanDeclare(baddr);
532  }
533  LineFeed(1);
534  }
535  // track loop count
537  Comment("loop flag");
538  BooleanDeclare(AA("first_loop"));
539  LineFeed(1);
540  }
541 }
542 
543 // code blocks: variables (local)
545  if(TimersBegin()!=TimersEnd()) {
546  Comment("timer states");
547  TimerIterator tit= TimersBegin();
548  for(;tit!=TimersEnd();++tit)
549  TimerDeclare(AA(tit->second.mAddress),tit->second.mInitialValue);
550  LineFeed(1);
551  }
552 }
553 
554 // code blocks: variables (local temp)
556  // additional aux variables
558  Comment("parse generator");
559  EventSetDeclare(AA("aux_locenabled"));
560  IntegerDeclare(AA("aux_parsetrans"));
561  IntegerDeclare(AA("aux_parseevent"));
562  LineFeed(1);
563  }
564  // aux enabled
565  Comment("enabled events that can be executed");
566  EventSetDeclare(AA("aux_executables"));
567  LineFeed(1);
568  // additional aux variables
569  Comment("aux maths and stack variables ");
570  WordDeclare(AA("aux_wordret"));
571  if(LinesBegin()!=LinesEnd()){
572  BooleanDeclare(AA("aux_edge"));
573  }
575  IntegerDeclare(AA("aux_wordaddr"));
576  IntegerDeclare(AA("aux_bitaddr"));
577  }
579  WordDeclare(AA("aux_bitmask"));
580  }
581  LineFeed(1);
582 }
583 
584 // code blocks: variables (large const)
586  // transition vector
588  for(size_t git=0; git<Size(); ++git) {
589  Comment("generator [" + At(git).Name() + "]");
591  CintarrayDeclare(AA("generator_states").Sub(git),mStateVector[git]);
592  }
593  CintarrayDeclare(AA("generator_transitions").Sub(git),mTransitionVector[git]);
594  LineFeed(1);
595  }
596  }
597 }
598 
599 // code blocks: variables (small const)
601  // bitmaks vector
602  if(mArrayForBitmasks) {
603  Comment("mask vectors");
605  CintarrayDeclare(AA("wordaddr_vector"),mWordAddressVector);
606  CwordarrayDeclare(AA("bitmask_vector"),mBitMaskVector);
607  LineFeed(1);
608  }
609 }
610 
611 // code blocks: symbol tables as array declarations
613  if(mEventNameLookup) {
614  std::vector<std::string> evlookup;\
615  evlookup.resize(mUsedEvents.Size()+1);
616  faudes::EventSet::Iterator eit=mUsedEvents.Begin();
617  for(;eit!=mUsedEvents.End();++eit) {
618  int tidx=EventTargetIdx(*eit);
619  if(((int) evlookup.size())<tidx+1) evlookup.resize(tidx+1);
620  evlookup[tidx]=mUsedEvents.SymbolicName(*eit);
621  }
622  for(std::size_t i=0; i<evlookup.size(); ++i) {
623  if(evlookup[i]=="") evlookup[i]="e0";
624  }
625  Comment("event name lookup table");
626  CstrarrayDeclare(AA("event_lookup"),evlookup);
627  LineFeed(1);
628  }
629 }
630 
631 // code blocks: symbol tables as array declarations
633  mHasStateNames.assign(Size(),false);
634  if(mStateNameLookup) {
635  bool hasnames=false;
636  for(size_t gid=0; gid<Size(); ++gid) {
637  const faudes::Generator& gen=At(gid);
638  std::vector<std::string> stlookup;\
639  faudes::StateSet::Iterator sit=gen.StatesBegin();
640  for(;sit!=gen.StatesEnd();++sit) {
641  int tidx=StateTargetIdx(gid,*sit);
642  if(((int) stlookup.size())<tidx+1) stlookup.resize(tidx+1);
643  std::string name = gen.StateName(*sit);
644  if(name!="") {
645  stlookup[tidx]=name;
646  mHasStateNames[gid]=true;
647  }
648  }
649  if(!mHasStateNames[gid]) continue;
650  hasnames=true;
651  for(std::size_t i=0; i<stlookup.size(); ++i)
652  if(stlookup[i]=="") stlookup[i]="s" + ToStringInteger(i);
653  Comment("state name lookup for generator [" + At(gid).Name() + "]");
654  CstrarrayDeclare(AA("state_lookup").Sub(gid),stlookup);
655  LineFeed(1);
656  }
657  if(!hasnames) {
658  FCG_VERB0("CodePrimitives::Compile(): no symbolic states found, no lookup-tables generated");
659  }
660  }
661 }
662 
663 // code blocks: reset
665  // say hello
666  Comment("************************************************");
667  Comment("* reset internal state *");
668  LineFeed(1);
669  Comment("set internal reset flag");
670  IfTrue(TargetExpression(AA("reset")));
671  IndentInc();
672  IntegerAssign(AA("exec_event"),-1);
673  IndentDec();
674  IfEnd();
675  LineFeed();
676  Comment("do reset core");
677  IfTrue(IntegerIsEq(AA("exec_event"),-1));
678  Comment("clear status");
679  IntegerAssign(AA("status"),0);
680  Comment("set initial state");
681  for(Idx gid=0; gid< Size(); gid++) {
682  AA statevar;
683  if(mArrayForState)
684  statevar=IntarrayAccess(AA("parallel_state"), gid);
685  else
686  statevar= AA("parallel_state").Sub(gid);
687  IntegerAssign(statevar,StateTargetIdx(gid,*At(gid).InitStatesBegin()));
688  }
689  Comment("clear scheduled event");
690  IntegerAssign(AA("sched_event"),0);
691  Comment("clear recent event");
692  IntegerAssign(AA("recent_event"),0);
693  Comment("clear pending/enabled events");
694  EventSetClear(AA("pending_events"));
695  EventSetClear(AA("enabled_events"));
696  if(TimersBegin()!=TimersEnd()) {
697  Comment("reset timer");
698  TimerIterator tit= TimersBegin();
699  for(;tit!=TimersEnd();++tit) {
700  TimerStop(AA(tit->second.mAddress));
701  TimerReset(AA(tit->second.mAddress) ,tit->second.mInitialValue);
702  }
703  }
704  IfEnd();
705  LineFeed(1);
706 }
707 
708 // code blocks: reset
710  // say hello
711  Comment("************************************************");
712  Comment("* bail out on external reset *");
713  LineFeed(1);
714  IfTrue(TargetExpression(AA("reset")));
715  IndentInc();
716  FunctionReturn();
717  IndentDec();
718  IfEnd();
719  LineFeed(1+2);
720 }
721 
722 // code blocks: inputs
724  // skip this section
725  if(FlagsBegin()==FlagsEnd())
726  if(LinesBegin()==LinesEnd())
727  return;
728  // say hello
729  Comment("************************************************");
730  Comment("* sense input events *");
731  LineFeed(1);
732  // my iterators
733  EventSet::Iterator eit;
734  LineIterator lit;
735  FlagIterator fit;
736  // reset edges, sense statics
737  if(LinesBegin()!=LinesEnd()) {
738  Comment("init: reset all line data and generate statics");
739  IfTrue(IntegerIsEq(AA("exec_event"),-1));
740  lit=LinesBegin();
741  for(;lit!=LinesEnd();++lit) {
742  AA baddr = AA("line_level").Sub(lit->second.mBitAddress);
743  BooleanAssign(baddr,ReadInputLine(AA(lit->second.mAddress))); // this is actually an expresssion
744  if(lit->second.mPosStatics.Empty() && lit->second.mNegStatics.Empty()) continue;
745  if(!lit->second.mPosStatics.Empty())
746  IfTrue(TargetExpression(baddr));
747  eit=lit->second.mPosStatics.Begin();
748  for(;eit!=lit->second.mPosStatics.End();++eit) {
749  Comment("positive value: trigger init event [" + EventName(*eit) + "]");
750  EventSetInsert(AA("pending_events"),*eit);
751  }
752  if(!lit->second.mPosStatics.Empty())
753  if(lit->second.mNegStatics.Empty())
754  IfEnd();
755  if(!lit->second.mPosStatics.Empty())
756  if(!lit->second.mNegStatics.Empty())
757  IfElse();
758  if(lit->second.mPosStatics.Empty())
759  if(!lit->second.mNegStatics.Empty())
760  IfFalse(TargetExpression(baddr));
761  eit=lit->second.mNegStatics.Begin();
762  for(;eit!=lit->second.mNegStatics.End();++eit) {
763  Comment("negative value: trigger init event [" + EventName(*eit) + "]");
764  EventSetInsert(AA("pending_events"),*eit);
765  }
766  if(!lit->second.mNegStatics.Empty())
767  IfEnd();
768  }
769  IfEnd();
770  LineFeed(1);
771  Comment("normal operation: read lines and detect edges");
772  IfTrue(IntegerIsNotEq(AA("exec_event"),-1));
773  lit=LinesBegin();
774  for(;lit!=LinesEnd();++lit) {
775  AA baddr = AA("line_level").Sub(lit->second.mBitAddress);
776  Comment("read line [" + lit->second.mAddress + "]");
777  BooleanAssign(AA("aux_edge"),ReadInputLine(lit->second.mAddress));
778  IfTrue(BooleanIsNotEq(AA("aux_edge"),baddr));
779  if(!lit->second.mPosEvents.Empty()) {
780  IfTrue(TargetExpression(AA("aux_edge")));
781  eit=lit->second.mPosEvents.Begin();
782  for(;eit!=lit->second.mPosEvents.End();++eit) {
783  Comment("positive edge: trigger input event [" + EventName(*eit) + "]");
784  EventSetInsert(AA("pending_events"),*eit);
785  IntegerAssign(AA("sched_event"),0);
786  }
787  IfEnd();
788  }
789  if(!lit->second.mNegEvents.Empty()) {
790  IfTrue(TargetExpression(baddr));
791  eit=lit->second.mNegEvents.Begin();
792  for(;eit!=lit->second.mNegEvents.End();++eit) {
793  Comment("negative edge trigger input event [" + EventName(*eit) + "]");
794  EventSetInsert(AA("pending_events"),*eit);
795  IntegerAssign(AA("sched_event"),0);
796  }
797  IfEnd();
798  }
799  BooleanAssign(baddr,TargetExpression(AA("aux_edge")));
800  IfEnd();
801  }
802  IfEnd();
803  LineFeed(1);
804  }
805  // detect flags
806  if(FlagsBegin()!=FlagsEnd()) {
807  //Comment("scanning flags");
808  fit=FlagsBegin();
809  for(;fit!=FlagsEnd();++fit) {
810  Comment("testing flag [" + fit->second.mAddress + "]");
811  IfTrue(InputExpression(fit->second.mAddress));
812  eit=fit->second.mEvents.Begin();
813  for(;eit!=fit->second.mEvents.End();++eit) {
814  Comment("trigger input event [" + EventName(*eit) + "]");
815  EventSetInsert(AA("pending_events"),*eit);
816  IntegerAssign(AA("sched_event"),0);
817  }
818  IfEnd();
819  }
820  LineFeed(1);
821  }
822  LineFeed(2);
823 }
824 
825 
826 // code blocks: sense timer elapse
828  // skip this section
829  if(TimersBegin()==TimersEnd()) return;
830  // say hello
831  Comment("************************************************");
832  Comment("* sense timer elapse *");
833  LineFeed(1);
834  // loop all timer definitions
835  TimerIterator tit= TimersBegin();
836  for(;tit!=TimersEnd();++tit) {
837  IfTrue(TimerIsElapsed(AA(tit->second.mAddress)));
838  TimerStop(AA(tit->second.mAddress));
839  EventSetInsert(AA("pending_events"),EventIndex(tit->second.mElapseEvent));
840  IntegerAssign(AA("sched_event"),0);
841  IfEnd();
842  }
843  LineFeed(1+2);
844 }
845 
846 
847 // code blocks: loop enabled events
849  if(! (mLoopEnabledOutputs || mLoopPendingInputs)) return;
850  Comment("************************************************");
851  Comment("* event execution loop *");
852  LineFeed(1);
853  Comment("clear status to waiting");
854  IntegerAssign(AA("status"),0);
855  Comment("set entry flag");
856  BooleanAssign(AA("first_loop"),true);
857  LoopBegin();
858  IndentDec();
859  LineFeed(1+2);
860 }
861 
862 
863 // code blocks: enabled events
865  Comment("************************************************");
866  Comment("* update enabled events after execution *");
867  LineFeed(1);
868  // doit: set up enabled events
869  Comment("if event was executed (and on initialisation)");
870  IfTrue(IntegerIsNotEq(AA("exec_event"),0));
871  Comment("set all to enabled");
872  EventSetFull(AA("enabled_events"));
873  LineFeed(1);
874  // for each generator
875  for(Idx gid=0; gid< Size(); gid++) {
876  Comment("restricting enabled events by [" + At(gid).Name() + "]");
877  AA statevar;
878  if(mArrayForState)
879  statevar=IntarrayAccess(AA("parallel_state"), gid);
880  else
881  statevar= AA("parallel_state").Sub(gid);
882  SwitchBegin(statevar);
883  // cases for each state
884  StateSet::Iterator sit;
885  for(sit=At(gid).StatesBegin(); sit!=At(gid).StatesEnd(); sit++) {
886  EventSet disset= At(gid).Alphabet();
887  disset.EraseSet(At(gid).ActiveEventSet(*sit));
888  if(disset.Empty()) continue;
889  SwitchCase(statevar,*sit);
890  EventSetErase(AA("enabled_events"),disset);
891  SwitchBreak();
892  }
893  SwitchEnd();
894  LineFeed(1);
895  } // end: for each generator
896  Comment("dispose event");
897  IntegerAssign(AA("exec_event"),0);
898  IntegerAssign(AA("sched_event"),0);
899  IfEnd();
900  LineFeed(1+2);
901 }
902 
903 
904 // code blocks: enabled events
907  FCG_ERR("CodePrimitives::UpdateEnabledByInterpreter(): vector representation not available");
908  Comment("************************************************");
909  Comment("* update enabled events after execution *");
910  LineFeed(1);
911  // doit: set up enabled events
912  Comment("if event was executed (and on init)");
913  IfTrue(IntegerIsNotEq(AA("exec_event"),0));
914  LineFeed(1);
915  // special case: only one generator
916  if(Size()==1) {
917  EventSet empty;
918  Comment("setup enabled events by [" + At(0).Name() + "]");
919  AA statevar;
920  if(mArrayForState)
921  statevar=IntarrayAccess(AA("parallel_state"),0);
922  else
923  statevar= AA("parallel_state").Sub(0);
924  AA gentrans= AA("generator_transitions").Sub(0);
925  AA genstates= AA("generator_states").Sub(0);
926  EventSetAssign(AA("enabled_events"),empty);
928  IntegerAssign(AA("aux_parsetrans"),TargetExpression(CintarrayAccess(genstates,statevar)));
929  } else {
930  IntegerAssign(AA("aux_parsetrans"),TargetExpression(statevar));
931  }
932  LoopBegin();
933  IntegerAssign(AA("aux_parseevent"),TargetExpression(CintarrayAccess(gentrans,AA("aux_parsetrans"))));
934  LoopBreak(IntegerIsEq(AA("aux_parseevent"),0));
935  EventSetInsert(AA("enabled_events"),AA("aux_parseevent"),At(0).Alphabet());
936  IntegerIncrement(AA("aux_parsetrans"),2);
937  LoopEnd();
938  }
939  // general case
940  if(Size()>1) {
941  Comment("set all to enabled");
942  //EventSetFull(AA("enabled_events"));
943  EventSetAssign(AA("enabled_events"),mUsedEvents);
944  LineFeed(1);
945  // for each generator
946  for(Idx gid=0; gid< Size(); gid++) {
947  Comment("setup enabled events by [" + At(gid).Name() + "]");
948  AA statevar;
949  if(mArrayForState)
950  statevar=IntarrayAccess(AA("parallel_state"), gid);
951  else
952  statevar= AA("parallel_state").Sub(gid);
953  AA gentrans= AA("generator_transitions").Sub(gid);
954  AA genstates= AA("generator_states").Sub(gid);
955  EventSetAssign(AA("aux_locenabled"),Alphabet()- At(gid).Alphabet());
957  IntegerAssign(AA("aux_parsetrans"),TargetExpression(CintarrayAccess(genstates,statevar)));
958  } else {
959  IntegerAssign(AA("aux_parsetrans"),TargetExpression(statevar));
960  }
961  LoopBegin();
962  IntegerAssign(AA("aux_parseevent"),TargetExpression(CintarrayAccess(gentrans,AA("aux_parsetrans"))));
963  LoopBreak(IntegerIsEq(AA("aux_parseevent"),0));
964  EventSetInsert(AA("aux_locenabled"),AA("aux_parseevent"),At(gid).Alphabet());
965  IntegerIncrement(AA("aux_parsetrans"),2);
966  LoopEnd();
967  Comment("restrict enabled events");
968  EventSetRestrict(AA("enabled_events"),AA("aux_locenabled"));
969  LineFeed(1);
970  } // end: for each generator
971  }
972  Comment("dispose event");
973  IntegerAssign(AA("exec_event"),0);
974  IntegerAssign(AA("sched_event"),0);
975  IfEnd();
976  LineFeed(1+2);
977 }
978 
979 // wrapper
983  else
985 }
986 
987 
988 // code blocks: enabled events
990  Comment("************************************************");
991  Comment("* schedule next event to execute *");
992  LineFeed(1);
993  IfTrue(IntegerIsEq(AA("sched_event"),0));
994  LineFeed(1);
995  Comment("setup candidate set to \"pending or internal\"");
996  EventSetUnion(AA("aux_executables"),AA("pending_events"),mInternalEvents + mOutputEvents);
997  Comment("restrict candidate set by \"enabled\"");
998  EventSetRestrict(AA("aux_executables"),AA("enabled_events"));
999  LineFeed(1);
1000  Comment("find highest priority event (lowest bitaddress)");
1001  EventSetFindHighestPriority(AA("aux_executables"),AA("sched_event"));
1002  LineFeed(1);
1003  Comment("remove scheduled event from pending events");
1004  IfTrue(IntegerIsGreater(AA("sched_event"),0));
1005  EventSetErase(AA("pending_events"),AA("sched_event"));
1006  IfEnd();
1007  LineFeed(1);
1008  Comment("detect sync error");
1009  IfTrue(IntegerIsEq(AA("sched_event"),0));
1010  EventSetIsNotEmpty(AA("pending_events"),AA("aux_wordret"));
1011  IfTrue(WordIsNotEq(AA("aux_wordret"),0));
1012  WordOr(AA("status"),WordConstant(0x02));
1013  IfEnd();
1014  IfEnd();
1015  LineFeed(1);
1017  Comment("cancel pending events if no event could be scheduled ");
1018  IfTrue(IntegerIsEq(AA("sched_event"),0));
1019  EventSetClear(AA("pending_events"));
1020  IfEnd();
1021  }
1022  LineFeed(1);
1023  IfEnd();
1024  LineFeed(1+2);
1025 }
1026 
1027 
1028 // code blocks: break loop
1030  if(! (mLoopEnabledOutputs || mLoopPendingInputs)) return;
1031  Comment("************************************************");
1032  Comment("* break execution loop *");
1033  LineFeed(1);
1034  LoopBreak(IntegerIsEq(AA("sched_event"),0));
1035  Idx max=mLastInputEvent+1;
1037  if(max<mUsedEvents.Size()) {
1038  IfFalse(TargetExpression(AA("first_loop")));
1039  LoopBreak(IntegerIsGreater(AA("sched_event"),max));
1040  IfEnd();
1041  }
1042  BooleanAssign(AA("first_loop"),false);
1043  LineFeed(1+2);
1044 }
1045 
1046 // execution hooks (dummy)
1048  if((mEventExecutionHook!="") || (mStateUpdateHook!=""))
1049  FCG_ERR("CodePrimitives::InsertExecHooks(): no hooks supported by target platform");
1050 }
1051 
1052 
1053 // code blocks: execute event
1055  Comment("************************************************");
1056  Comment("* execute scheduled event *");
1057  LineFeed(1);
1058  IfTrue(IntegerIsNotEq(AA("sched_event"),0));
1059  LineFeed(1);
1060  IntegerAssign(AA("exec_event"),TargetExpression(AA("sched_event")));
1061  IntegerAssign(AA("sched_event"),0);
1062  WordOr(AA("status"),WordConstant(0x01));
1063  LineFeed(1);
1064  for(Idx gid=0; gid< Size(); gid++) {
1065  Comment("execute event for [" + At(gid).Name() + "]");
1066  // loop states
1067  AA statevar;
1068  if(mArrayForState)
1069  statevar=IntarrayAccess(AA("parallel_state"), gid);
1070  else
1071  statevar= AA("parallel_state").Sub(gid);
1072  SwitchBegin(statevar);
1073  StateSet::Iterator sit;
1074  for(sit=At(gid).StatesBegin(); sit!=At(gid).StatesEnd(); sit++) {
1075  // cases for each state
1076  SwitchCase(statevar,*sit);
1077  // consolidate sub-cases aka same target state for multiple events
1078  std::map< int , int > casedata;
1079  std::set< std::set< int > > casesets;
1080  TransSet::Iterator tit;
1081  for(tit=At(gid).TransRelBegin(*sit); tit!=At(gid).TransRelEnd(*sit); tit++)
1082  casedata[EventTargetIdx(tit->Ev)]= tit->X2;
1083  ConsolidateCaseSets<int>(casedata,casesets);
1084  // loop transitions
1085  SwitchBegin(AA("exec_event"));
1086  std::set< std::set<int> >::iterator cit=casesets.begin();
1087  for(; cit!=casesets.end(); ++cit) {
1088  SwitchCases(AA("exec_event"),*cit);
1089  IntegerAssign(statevar,casedata[*cit->begin()]);
1090  SwitchBreak();
1091  }
1092  SwitchEnd();
1093  SwitchBreak();
1094  }
1095  SwitchEnd();
1096  LineFeed(1);
1097  } // end for each generator
1098  // record
1099  IntegerAssign(AA("recent_event"),TargetExpression(AA("exec_event")));
1100  // call hooks
1101  InsertExecHooks();
1102  // done
1103  IfEnd();
1104  LineFeed(1+2);
1105 }
1106 
1107 // code blocks: execute event
1109  Comment("************************************************");
1110  Comment("* execute scheduled event *");
1111  LineFeed(1);
1112  if(!mArrayForTransitions) {
1113  FCG_ERR("CodePrimitives::ExecuteByInterpreter(): vector representation not available");
1114  }
1115  // execute by array interpreter
1116  IfTrue(IntegerIsNotEq(AA("sched_event"),0));
1117  LineFeed(1);
1118  IntegerAssign(AA("exec_event"),TargetExpression(AA("sched_event")));
1119  IntegerAssign(AA("sched_event"),0);
1120  WordOr(AA("status"),WordConstant(0x01));
1121  LineFeed(1);
1122  for(Idx gid=0; gid< Size(); gid++) {
1123  Comment("execute event for [" + At(gid).Name() + "]");
1124  // vector to find event
1125  AA statevar;
1126  if(mArrayForState)
1127  statevar=IntarrayAccess(AA("parallel_state"), gid);
1128  else
1129  statevar= AA("parallel_state").Sub(gid);
1130  AA gentrans= AA("generator_transitions").Sub(gid);
1131  AA genstates= AA("generator_states").Sub(gid);
1132  if(mMaintainStateIndices) {
1133  IntegerAssign(AA("aux_parsetrans"),TargetExpression(CintarrayAccess(genstates,statevar)));
1134  } else {
1135  IntegerAssign(AA("aux_parsetrans"),TargetExpression(statevar));
1136  }
1137  LoopBegin();
1138  IntegerAssign(AA("aux_parseevent"),TargetExpression(CintarrayAccess(gentrans,AA("aux_parsetrans"))));
1139  LoopBreak(IntegerIsEq(AA("aux_parseevent"),TargetExpression(AA("exec_event"))));
1140  LoopBreak(IntegerIsEq(AA("aux_parseevent"),0));
1141  IntegerIncrement(AA("aux_parsetrans"),2);
1142  LoopEnd();
1143  IfTrue(IntegerIsGreater(AA("aux_parseevent"),0));
1144  IntegerIncrement(AA("aux_parsetrans"));
1145  IntegerAssign(statevar,TargetExpression(CintarrayAccess(gentrans,AA("aux_parsetrans"))));
1146  IfEnd();
1147  LineFeed(1);
1148  } // end for each generator
1149  // record
1150  IntegerAssign(AA("recent_event"),TargetExpression(AA("exec_event")));
1151  // call hooks
1152  InsertExecHooks();
1153  // done
1154  IfEnd();
1155  LineFeed(1+2);
1156 }
1157 
1158 // wrapper
1162  else
1164 }
1165 
1166 // code blocks: excute timers
1168  //skip this section
1169  if(TimerActionsBegin()==TimerActionsEnd()) return;
1170  Comment("************************************************");
1171  Comment("* operate timers *");
1172  LineFeed(1);
1173  // consolidate cases aka same timer actions for multiple event
1174  std::map< int , TimerAction> casedata;
1175  std::set< std::set< int > > casesets;
1176  for(int tev=1; tev<=EventBitMaskSize(); ++tev) {
1177  // test for valid record, i.e., whether switch case exists
1178  std::string ev=EventName(EventFaudesIdx(tev));
1179  TimerActionIterator eit= mTimerActions.find(ev);
1180  if(eit==mTimerActions.end()) continue;
1181  // record
1182  casedata[tev]= eit->second;
1183  }
1184  ConsolidateCaseSets<TimerAction>(casedata,casesets);
1185  // if an event was executed
1186  IfTrue(IntegerIsGreater(AA("exec_event"),0));
1187  // switch events
1188  SwitchBegin(AA("exec_event"));
1189  // loop over merged switch cases
1190  std::set< std::set< int > >::iterator cit;
1191  for(cit=casesets.begin(); cit!=casesets.end(); ++cit) {
1192  SwitchCases(AA("exec_event"),*cit);
1193  TimerAction tac = casedata[*cit->begin()];
1194  std::set< std::string >::iterator ait;
1195  ait = tac.mTimerStops.begin();
1196  for(; ait != tac.mTimerStops.end(); ++ait) {
1197  TimerStop(AA(*ait));
1198  }
1199  ait = tac.mTimerResets.begin();
1200  for(; ait != tac.mTimerResets.end(); ++ait) {
1201  TimerIterator tit = mTimers.find(*ait);
1202  if(tit==mTimers.end()) {
1203  FCG_ERR("CodePrimitives: internal error on timer records -- sorry");
1204  }
1205  TimerReset(AA(*ait),tit->second.mInitialValue);
1206  }
1207  ait = tac.mTimerStarts.begin();
1208  for(; ait != tac.mTimerStarts.end(); ++ait) {
1209  TimerStart(AA(*ait));
1210  }
1211  SwitchBreak();
1212  }
1213  SwitchEnd();
1214  IfEnd();
1215  LineFeed(1+2);
1216 }
1217 
1218 
1219 // code blocks: execute outputs
1221  Comment("************************************************");
1222  Comment("* operate outputs *");
1223  LineFeed(1);
1224  // test whether exec is an output
1225  IfTrue(IntegerIsGreater(AA("exec_event"),mLastInputEvent+1));
1226  if(mLastOutputEvent+1< (int) mUsedEvents.Size())
1227  IfTrue(IntegerIsLess(AA("exec_event"),mLastOutputEvent+2));
1228  SwitchBegin(AA("exec_event"));
1229  for(EventSet::Iterator eit=mOutputEvents.Begin(); eit!=mOutputEvents.End(); eit++) {
1230  const std::vector<AttributeCodeGeneratorEvent::OutputAction>& actions = mAlphabet.Attribute(*eit).mActions;
1231  if(actions.size()==0) continue;
1232  SwitchCase(AA("exec_event"),EventTargetIdx(*eit));
1233  Comment("outputs for [" + EventName(*eit) + "]");
1234  for(size_t i=0; i<actions.size(); i++) {
1235  if(actions[i].mSet) RunActionSet(actions[i].mAddress);
1236  if(actions[i].mClr) RunActionClr(actions[i].mAddress);
1237  if(actions[i].mExe) RunActionExe(AX(actions[i].mAddress));
1238  }
1239  SwitchBreak();
1240  }
1241  SwitchEnd();
1242  if(mLastOutputEvent+1< (int) mUsedEvents.Size())
1243  IfEnd();
1244  IfEnd();
1245  LineFeed(1+2);
1246 }
1247 
1248 
1249 // code blocks: loop enabled outputs
1251  if(! (mLoopEnabledOutputs || mLoopPendingInputs)) return;
1252  Comment("************************************************");
1253  Comment("* end execution loop *");
1254  LineFeed(1);
1255  IndentInc();
1256  LoopEnd();
1257  LineFeed(1+2);
1258 }
1259 
1260 
1261 // code blocks: literal append from configuration
1263  if(mLiteralAppend.size()==0) return;
1264  Comment("************************************************");
1265  Comment("* append code snippet from configuration *");
1266  LineFeed(2);
1267  Output() << mLiteralAppend;
1268  LineFeed(2+2);
1269 }
1270 
1271 
1272 // DoGenerate()
1274  FD_DCG("CodePrimitives(" << this << ")::DoGenerateDeclarations()");
1275  Comment("************************************************");
1276  Comment("* declaration of variables and constants *");
1277  LineFeed(1);
1278  DeclareStatus();
1279  DeclareReset();
1283  DeclareLoopState();
1284  DeclareTimers();
1285  DeclareAux();
1290 }
1291 
1292 // DoGenerateResetCode()
1294  FD_DCG("CodePrimitives(" << this << ")::DoGenerateResetCode()");
1295  Comment("************************************************");
1296  Comment("* executor core cyclic code: reset/initialise *");
1297  Comment("************************************************");
1298  LineFeed(1+1);
1299  ResetState();
1300  LineFeed(1+1);
1301  ResetReturn();
1302 }
1303 
1304 // DoGenerateCyclicCode()
1306  FD_DCG("CodePrimitives(" << this << ")::DoGenerateCyclicCode()");
1307  Comment("************************************************");
1308  Comment("* executor core cyclic code: begin *");
1309  Comment("************************************************");
1310  LineFeed(1+2);
1311  SenseInputs();
1312  SenseTimerElapse();
1314  UpdateEnabled();
1315  ScheduleEvent();
1317  ExecuteEvent();
1318  OperateTimers();
1319  OperateOutputs();
1320  EndExecutionLoop();
1321  LineFeed(1);
1322  Comment("************************************************");
1323  Comment("* executor core cyclic code: end *");
1324  Comment("************************************************");
1325 }
1326 
1327 // DoGenerate()
1329  // clear my data
1330  mBitarrays.clear();
1331  // generate my modules
1332  LiteralPrepend();
1334  LineFeed(2);
1336  LineFeed(2+1);
1337  LiteralAppend();
1338 }
1339 
1340 
1341 
1342 /*
1343 ******************************************************************
1344 ******************************************************************
1345 ******************************************************************
1346 
1347 CodePrimitives implementation --- generate atomic snippets
1348 
1349 ******************************************************************
1350 ******************************************************************
1351 ******************************************************************
1352 */
1353 
1354 // cosmetics (base only records the text, need to rimplement in derived classes
1355 void CodePrimitives::Comment(const std::string& text) {
1356  CodeGenerator::Comment(text);
1357 }
1358 
1359 // declaration template (optional)
1360 void CodePrimitives::VariableDeclare(const std::string& laddr, const std::string& ltype) {
1361  (void) laddr;
1362  (void) ltype;
1363  FCG_ERR("CodePrimitives::VariableDeclare(): not implemented");
1364 }
1365 
1366 // declaration template (optional)
1367 void CodePrimitives::VariableDeclare(const std::string& laddr, const std::string& ltype, const std::string& lval) {
1368  (void) laddr;
1369  (void) ltype;
1370  (void) lval;
1371  FCG_ERR("CodePrimitives::VariableDeclare(): not implemented");
1372 }
1373 
1374 // integer maths
1375 void CodePrimitives::IntegerDecrement(const AA& address, int val) {
1376  IntegerIncrement(address,-val);
1377 }
1378 
1379 // integer maths
1380 CodePrimitives::AX CodePrimitives::IntegerQuotient(const AX& expression, int val) {
1381  (void) expression;
1382  (void) val;
1383  FCG_ERR("CodePrimitives::Integer(): maths not available");
1384  return AX();
1385  }
1386 CodePrimitives::AX CodePrimitives::IntegerRemainder(const AX& expression, int val) {
1387  (void) expression;
1388  (void) val;
1389  FCG_ERR("CodePrimitives::Integer(): maths not available");
1390  return AX();
1391 }
1392 CodePrimitives::AX CodePrimitives::IntegerBitmask(const AX& expression) {
1393  (void) expression;
1394  FCG_ERR("CodePrimitives::Integer(): maths not available");
1395  return AX();
1396 }
1397 bool CodePrimitives::HasIntmaths(void) {
1398  return false;
1399 }
1400 CodePrimitives::AX CodePrimitives::IntegerIsEq(const AA& address, int val) {
1401  (void) address;
1402  (void) val;
1403  FCG_ERR("CodePrimitives::Conditionals(): construct not available");
1404  return AX();
1405 }
1406 CodePrimitives::AX CodePrimitives::IntegerIsEq(const AA& address, const AX& expression) {
1407  (void) address;
1408  (void) expression;
1409  FCG_ERR("CodePrimitives::Conditionals(): construct not available");
1410  return AX();
1411 }
1412 CodePrimitives::AX CodePrimitives::IntegerIsNotEq(const AA& address, int val) {
1413  (void) address;
1414  (void) val;
1415  FCG_ERR("CodePrimitives::Conditionals(): construct not available");
1416  return AX();
1417 }
1418 CodePrimitives::AX CodePrimitives::IntegerIsNotEq(const AA& address, const AX& expression) {
1419  (void) address;
1420  (void) expression;
1421  FCG_ERR("CodePrimitives::Conditionals(): construct not available");
1422  return AX();
1423 }
1424 CodePrimitives::AX CodePrimitives::IntegerIsGreater(const AA& address, int val) {
1425  (void) address;
1426  (void) val;
1427  FCG_ERR("CodePrimitives::Conditionals(): construct not available");
1428  return AX();
1429 }
1430 CodePrimitives::AX CodePrimitives::IntegerIsLess(const AA& address, int val) {
1431  (void) address;
1432  (void) val;
1433  FCG_ERR("CodePrimitives::Conditionals(): construct not available");
1434  return AX();
1435 }
1436 
1437 
1438 // word-of-bits (optional)
1439 void CodePrimitives::WordDeclare(const AA& address) {
1440  (void) address;
1441  FCG_ERR("CodePrimitives::Word(): word-of-bits type not available");
1442 }
1443 void CodePrimitives::WordDeclare(const AA& address, word_t val) {
1444  (void) address;
1445  (void) val;
1446  FCG_ERR("CodePrimitives::Word(): word-of-bits type not available");
1447 }
1448 void CodePrimitives::WordAssign(const AA& address, word_t val) {
1449  (void) address;
1450  (void) val;
1451  FCG_ERR("CodePrimitives::Word(): word-of-bits type not available");
1452 }
1453 void CodePrimitives::WordAssign(const AA& address, const AX& expression) {
1454  (void) address;
1455  (void) expression;
1456  FCG_ERR("CodePrimitives::Word(): word-of-bits type not available");
1457 }
1458 void CodePrimitives::WordOr(const AA& address, word_t val) {
1459  (void) address;
1460  (void) val;
1461  FCG_ERR("CodePrimitives::Word(): word-of-bits type not available");
1462 }
1463 void CodePrimitives::WordOr(const AA& address, const AX& expression) {
1464  (void) address;
1465  (void) expression;
1466  FCG_ERR("CodePrimitives::Word(): word-of-bits type not available");
1467 }
1468 void CodePrimitives::WordOr(const AA& address, const AA& op1, const AA& op2) {
1469  (void) address;
1470  (void) op1;
1471  (void) op2;
1472  FCG_ERR("CodePrimitives::Word(): word-of-bits type not available");
1473 }
1474 void CodePrimitives::WordOr(const AA& address, const AA& op1, word_t op2) {
1475  (void) address;
1476  (void) op1;
1477  (void) op2;
1478  FCG_ERR("CodePrimitives::Word(): word-of-bits type not available");
1479 }
1480 void CodePrimitives::WordAnd(const AA& address, word_t val) {
1481  (void) address;
1482  (void) val;
1483  FCG_ERR("CodePrimitives::Word(): word-of-bits type not available");
1484 }
1485 void CodePrimitives::WordAnd(const AA& address, const AX& expression) {
1486  (void) address;
1487  (void) expression;
1488  FCG_ERR("CodePrimitives::Word(): word-of-bits type not available");
1489 }
1490 void CodePrimitives::WordAnd(const AA& address, const AA& op1, const AA& op2) {
1491  (void) address;
1492  (void) op1;
1493  (void) op2;
1494  FCG_ERR("CodePrimitives::Word(): word-of-bits type not available");
1495 }
1496 void CodePrimitives::WordAnd(const AA& address, const AA& op1, word_t op2) {
1497  (void) address;
1498  (void) op1;
1499  (void) op2;
1500  FCG_ERR("CodePrimitives::Word(): word-of-bits type not available");
1501 }
1502 void CodePrimitives::WordNand(const AA& address, const AX& expression) {
1503  (void) address;
1504  (void) expression;
1505  FCG_ERR("CodePrimitives::Word(): word-of-bits type not available");
1506 }
1507 CodePrimitives::AX CodePrimitives::WordIsEq(const AA& address, word_t val) {
1508  (void) address;
1509  (void) val;
1510  FCG_ERR("CodePrimitives::Conditionals(): construct not available");
1511  return AX();
1512 }
1513 CodePrimitives::AX CodePrimitives::WordIsNotEq(const AA& address, word_t val) {
1514  (void) address;
1515  (void) val;
1516  FCG_ERR("CodePrimitives::Conditionals(): construct not available");
1517  return AX();
1518 }
1519 CodePrimitives::AX CodePrimitives::WordIsBitSet(const AA& address, int idx) {
1520  (void) address;
1521  (void) idx;
1522  FCG_ERR("CodePrimitives::Conditionals(): construct not available");
1523  return AX();
1524 }
1525 CodePrimitives::AX CodePrimitives::WordIsBitClr(const AA& address, int idx) {
1526  (void) address;
1527  (void) idx;
1528  FCG_ERR("CodePrimitives::Conditionals(): construct not available");
1529  return AX();
1530 }
1531 CodePrimitives::AX CodePrimitives::WordIsMaskSet(const AA& address, word_t idx) {
1532  (void) address;
1533  (void) idx;
1534  FCG_ERR("CodePrimitives::Conditionals(): construct not available");
1535  return AX();
1536 }
1537 CodePrimitives::AX CodePrimitives::WordConstant(word_t val) {
1538  (void) val;
1539  FCG_ERR("CodePrimitives::Word(): word-of-bits type not available");
1540  return AX();
1541 }
1542 
1543 
1544 // fallback implementation of booleans as integers
1545 void CodePrimitives::BooleanDeclare(const AA& address) {
1546  IntegerDeclare(address);
1547 }
1548 void CodePrimitives::BooleanDeclare(const AA& address, int val) {
1549  IntegerDeclare(address,val ? 1 : 0);
1550 }
1551 void CodePrimitives::BooleanAssign(const AA& address, const AX& expression) {
1552  IntegerAssign(address,expression);
1553 }
1554 void CodePrimitives::BooleanAssign(const AA& address, int val) {
1555  IntegerAssign(address, val ? 1 : 0);
1556 }
1557 CodePrimitives::AX CodePrimitives::BooleanIsEq(const AA& op1, const AA& op2) {
1558  return IntegerIsEq(op1,TargetExpression(op2));
1559 }
1560 CodePrimitives::AX CodePrimitives::BooleanIsNotEq(const AA& op1, const AA& op2) {
1561  return IntegerIsNotEq(op1,TargetExpression(op2));
1562 }
1563 
1564 
1568 // default const-int-array: not supported
1569 void CodePrimitives::CintarrayDeclare(const AA& address, const std::vector<int>& val) {
1570  (void) address;
1571  (void) val;
1572  FCG_ERR("CodePrimitives::Cintarray(): constant-int-arrays not defined");
1573 };
1574 CodePrimitives::AA CodePrimitives::CintarrayAccess(const AA& address, int index) {
1575  (void) address;
1576  (void) index;
1577  FCG_ERR("CodePrimitives::Cintarray(): constant-int-arrays not defined");
1578  return AA();
1579 };
1580 CodePrimitives::AA CodePrimitives::CintarrayAccess(const AA& address, const AA& indexaddr){
1581  (void) address;
1582  (void) indexaddr;
1583  FCG_ERR("CodePrimitives::Cintarray(): constant-int-arrays not defined");
1584  return AA();
1585 };
1586 bool CodePrimitives::HasCintarray(void) {
1587  return false;
1588 };
1589 
1590 // default const-word-array: not supported
1591 void CodePrimitives::CwordarrayDeclare(const AA& address, const std::vector<word_t>& val) {
1592  (void) address;
1593  (void) val;
1594  FCG_ERR("CodePrimitives::Cwordarray(): constant-word-arrays not defined");
1595 };
1596 CodePrimitives::AA CodePrimitives::CwordarrayAccess(const AA& address, int index) {
1597  (void) address;
1598  (void) index;
1599  FCG_ERR("CodePrimitives::Cwordarray(): constant-word-arrays not defined");
1600  return AA();
1601 };
1602 CodePrimitives::AA CodePrimitives::CwordarrayAccess(const AA& address, const AA& indexaddr){
1603  (void) address;
1604  (void) indexaddr;
1605  FCG_ERR("CodePrimitives::Cwordarray(): constant-word-arrays not defined");
1606  return AA();
1607 };
1608 bool CodePrimitives::HasCwordarray(void) {
1609  return false;
1610 };
1611 
1612 
1613 // default word-array: not supported
1614 void CodePrimitives::WordarrayDeclare(const AA& address, int len) {
1615  (void) address;
1616  (void) len;
1617  FCG_ERR("CodePrimitives::Wordarray(): word-arrays not available");
1618 };
1619 void CodePrimitives::WordarrayDeclare(const AA& address, const std::vector<word_t>& val) {
1620  (void) address;
1621  (void) val;
1622  FCG_ERR("CodePrimitives::Wordarray(): word-arrays not available");
1623 };
1624 CodePrimitives::AA CodePrimitives::WordarrayAccess(const AA& address, int index) {
1625  (void) address;
1626  (void) index;
1627  FCG_ERR("CodePrimitives::Wordarray(): word-arrays not available");
1628  return AA();
1629 };
1630 CodePrimitives::AA CodePrimitives::WordarrayAccess(const AA& address, const AA& indexaddr){
1631  (void) address;
1632  (void) indexaddr;
1633  FCG_ERR("CodePrimitives::Wordarray(): word-arrays not available");
1634  return AA();
1635 };
1636 bool CodePrimitives::HasWordarray(void) {
1637  return false;
1638 };
1639 
1640 
1642 void CodePrimitives::IntarrayDeclare(const AA& address, int len) {
1643  (void) address;
1644  (void) len;
1645  FCG_ERR("CodePrimitives::Intarray(): int-arrays not available");
1646 };
1647 void CodePrimitives::IntarrayDeclare(const AA& address, const std::vector<int>& val) {
1648  (void) address;
1649  (void) val;
1650  FCG_ERR("CodePrimitives::Intarray(): int-arrays not available");
1651 };
1653  (void) address;
1654  (void) index;
1655  FCG_ERR("CodePrimitives::Intarray(): int-arrays not available");
1656  return AA();
1657 };
1658 CodePrimitives::AA CodePrimitives::IntarrayAccess(const AA& address, const AA& indexaddr){
1659  (void) address;
1660  (void) indexaddr;
1661  FCG_ERR("CodePrimitives::Intarray(): int-arrays not available");
1662  return AA();
1663 };
1665  return false;
1666 };
1667 
1668 // default const-string-array: not supported
1669 CodePrimitives::AX CodePrimitives::StringConstant(const std::string &val) {
1670  (void) val;
1671  FCG_ERR("CodePrimitives::Cstrarray(): constant-str-arrays not defined");
1672  return AX();
1673 };
1674 void CodePrimitives::CstrarrayDeclare(const AA& address, const std::vector<std::string>& val) {
1675  (void) address;
1676  (void) val;
1677  FCG_ERR("CodePrimitives::Cstrarray(): constant-str-arrays not defined");
1678 };
1679 CodePrimitives::AA CodePrimitives::CstrarrayAccess(const AA& address, int index) {
1680  (void) address;
1681  (void) index;
1682  FCG_ERR("CodePrimitives::Cstrarray(): constant-str-arrays not defined");
1683  return AA();
1684 };
1685 CodePrimitives::AA CodePrimitives::CstrarrayAccess(const AA& address, const AA& indexaddr){
1686  (void) address;
1687  (void) indexaddr;
1688  FCG_ERR("CodePrimitives::Cstrarray(): constant-str-arrays not defined");
1689  return AA();
1690 };
1691 bool CodePrimitives::HasCstrarray(void) {
1692  return false;
1693 };
1694 
1695 
1696 // declare bit array as record of words
1697 void CodePrimitives::BitarrayDeclare(const AA& address, int blen) {
1698  // figure dimension
1699  int wlen = (blen + mWordSize - 1) / mWordSize;
1700  // declare as array or words
1701  if(mArrayForBitarray) {
1702  WordarrayDeclare(address, wlen);
1703  }
1704  // declare as array separate words
1705  if(!mArrayForBitarray) {
1706  for(int i=0; i<wlen; i++) {
1707  AA baddr= address.Sub(i);
1708  WordDeclare(baddr);
1709  }
1710  }
1711  // record (dummy value)
1712  bitarray_rec newbitarray;
1713  newbitarray.blen= blen;
1714  mBitarrays[address]=newbitarray;
1715 }
1716 
1717 // declare bit array as record of words
1718 void CodePrimitives::BitarrayDeclare(const AA& address, const std::vector<bool>& val) {
1719  // figure dimension
1720  int blen = (int) val.size();
1721  int wlen = (blen + mWordSize - 1) / mWordSize;
1722  // declare as array or words
1723  if(mArrayForBitarray) {
1724  WordarrayDeclare(address, WordVectorFromBitVector(val));
1725  }
1726  // declare as array separate words
1727  if(!mArrayForBitarray) {
1728  for(int i=0; i<wlen; i++) {
1729  AA baddr = address.Sub(i);
1730  WordDeclare(baddr,WordFromBitVector(val,i));
1731  }
1732  }
1733  // record
1734  bitarray_rec newbitarray;
1735  newbitarray.blen= blen;
1736  newbitarray.value= val;
1737  mBitarrays[address]=newbitarray;
1738 }
1739 
1740 // bitarray
1741 void CodePrimitives::BitarrayAssign(const AA& address, const std::vector<bool>& val) {
1742  // lookup
1743  int blen= mBitarrays[address].blen;
1744  int wlen = (blen + mWordSize - 1) / mWordSize;
1745  // loop words
1746  for(int i=0; i<wlen; ++i) {
1747  AA waddr;
1748  if(mArrayForBitarray) waddr= WordarrayAccess(address,i);
1749  else waddr = address.Sub(i);
1750  word_t wval=WordFromBitVector(val,i);
1751  WordAssign(waddr,wval);
1752  }
1753 }
1754 
1755 // bitarray
1756 void CodePrimitives::BitarrayAssign(const AA& address, const AA& otherarray) {
1757  // lookup
1758  int blen= mBitarrays[address].blen;
1759  int wlen = (blen + mWordSize - 1) / mWordSize;
1760  // must match
1761  if(blen!=mBitarrays[otherarray].blen) {
1762  FCG_ERR("CodePrimitives(): BitarrayAssign(): internal error");
1763  }
1764  // loop words
1765  for(int i=0; i<wlen; ++i) {
1766  AA waddr;
1767  if(mArrayForBitarray) waddr= WordarrayAccess(address,i);
1768  else waddr = address.Sub(i);
1769  AA oaddr;
1770  if(mArrayForBitarray) oaddr= WordarrayAccess(address,i);
1771  else oaddr = address.Sub(i);
1772  WordAssign(waddr,TargetExpression(oaddr));
1773  }
1774 }
1775 
1776 // bitarray
1777 void CodePrimitives::BitarrayClear(const AA& address){
1778  // lookup
1779  int blen= mBitarrays[address].blen;
1780  int wlen = (blen + mWordSize - 1) / mWordSize;
1781  // loop all words
1782  for(int i=0; i<wlen; i++) {
1783  AA waddr;
1784  if(mArrayForBitarray) waddr= WordarrayAccess(address,i);
1785  else waddr = address.Sub(i);
1786  WordAssign(waddr, 0x0UL);
1787  }
1788 }
1789 
1790 // bitarray
1791 void CodePrimitives::BitarrayFull(const AA& address){
1792  // lookup
1793  int blen= mBitarrays[address].blen;
1794  int wlen = (blen + mWordSize - 1) / mWordSize;
1795  int bllen = blen - (wlen-1) * mWordSize;
1796  // loop all words
1797  for(int i=0; i<wlen; i++) {
1798  AA waddr;
1799  if(mArrayForBitarray) waddr= WordarrayAccess(address,i);
1800  else waddr = address.Sub(i);
1801  word_t val= ~0x0UL;
1802  if(i==wlen-1) val= (1ULL<<bllen)-1;
1803  WordAssign(waddr, val);
1804  }
1805 }
1806 
1807 // bitarray
1808 void CodePrimitives::BitarrayOrAllWords(const AA& address, const AA& result) {
1809  // lookup
1810  int blen= mBitarrays[address].blen;
1811  int wlen = (blen + mWordSize - 1) / mWordSize;
1812  int bllen = blen - (wlen-1) * mWordSize;
1813  // one word case
1814  if(wlen==1) {
1815  AA waddr;
1816  if(mArrayForBitarray) waddr= WordarrayAccess(address,0);
1817  else waddr = address.Sub(0);
1818  WordAssign(result,TargetExpression(waddr));
1819  return;
1820  }
1821  // loop all words
1822  for(int i=0; i<wlen; i++) {
1823  AA waddr;
1824  if(mArrayForBitarray) waddr= WordarrayAccess(address,i);
1825  else waddr = address.Sub(i);
1826  if(i==wlen-1) WordAnd(waddr,WordConstant((1ULL<<bllen)-1));
1827  if(i==0) WordAssign(result,TargetExpression(waddr));
1828  if(i>0) WordOr(result,TargetExpression(waddr));
1829  }
1830 }
1831 
1832 // bitarray set by const index
1833 void CodePrimitives::BitarraySetBit(const AA& address, int index){
1834  // figure word/bit
1835  int windex=index / mWordSize;
1836  int bindex= index % mWordSize;
1837  // set
1838  AA waddr;
1839  if(mArrayForBitarray) waddr= WordarrayAccess(address,windex);
1840  else waddr = address.Sub(windex);
1841  WordOr(waddr,WordConstant( 1UL << bindex));
1842 }
1843 
1844 // bitarray set by var index
1845 void CodePrimitives::BitarraySetBit(const AA& address, const AA& indexaddr, int offset, const std::vector<bool>& hint){
1846  // lookup
1847  int blen= mBitarrays[address].blen;
1848  int wlen = (blen + mWordSize - 1) / mWordSize;
1849  bool gotaddress=false;
1850  // use precompiled masks to obtain address
1851  if(mArrayForBitmasks && (wlen > 1)) {
1852  IntegerAssign(AA("aux_bitaddr"),TargetExpression(indexaddr));
1853  IntegerDecrement(AA("aux_bitaddr"));
1854  IntegerAssign(AA("aux_wordaddr"),TargetExpression(CintarrayAccess(AA("wordaddr_vector"),AA("aux_bitaddr"))));
1855  IntegerAssign(AA("aux_bitmask"),TargetExpression(CwordarrayAccess(AA("bitmask_vector"),AA("aux_bitaddr"))));
1856  gotaddress=true;
1857  }
1858  // compute address
1859  if((!gotaddress) && mBitAddressArithmetic && (wlen > 1)) {
1860  IntegerAssign(AA("aux_bitaddr"),TargetExpression(indexaddr));
1861  IntegerDecrement(AA("aux_bitaddr"),offset);
1862  IntegerAssign(AA("aux_wordaddr"),IntegerQuotient(TargetExpression(AA("aux_bitaddr")),mWordSize));
1863  IntegerAssign(AA("aux_bitaddr"),IntegerRemainder(TargetExpression(AA("aux_bitaddr")),mWordSize));
1864  IntegerAssign(AA("aux_bitmask"),IntegerBitmask(TargetExpression(AA("aux_bitaddr"))));
1865  gotaddress=true;
1866  }
1867  // use precompiled masks, simple case
1868  if((!gotaddress) && mArrayForBitmasks && (wlen == 1)) {
1869  IntegerAssign(AA("aux_bitaddr"),TargetExpression(indexaddr));
1870  IntegerDecrement(AA("aux_bitaddr"),offset);
1871  IntegerAssign(AA("aux_bitmask"),TargetExpression(CwordarrayAccess(AA("bitmask_vector"),AA("aux_bitaddr"))));
1872  gotaddress=true;
1873  }
1874  // compute address, simple case
1875  if((!gotaddress) && mBitAddressArithmetic && (wlen == 1)) {
1876  IntegerAssign(AA("aux_bitaddr"),TargetExpression(indexaddr));
1877  IntegerDecrement(AA("aux_bitaddr"),offset);
1878  IntegerAssign(AA("aux_wordaddr"),IntegerQuotient(TargetExpression(AA("aux_bitaddr")),mWordSize));
1879  IntegerAssign(AA("aux_bitaddr"),IntegerRemainder(TargetExpression(AA("aux_bitaddr")),mWordSize));
1880  IntegerAssign(AA("aux_bitmask"),IntegerBitmask(TargetExpression(AA("aux_bitaddr"))));
1881  gotaddress=true;
1882  }
1883  // perform with word array
1884  if(gotaddress && mArrayForBitarray) {
1885  WordOr(WordarrayAccess(address, AA("aux_wordaddr")),TargetExpression(AA("aux_bitmask")));
1886  return;
1887  }
1888  // perform by switch
1889  if(gotaddress && (wlen > 1)) {
1890  SwitchBegin(AA("aux_wordaddr"));
1891  for(int i=0; i<wlen; i++) {
1892  if(hint.size()>0)
1893  if(WordFromBitVector(hint,i)==0) continue;
1894  SwitchCase(AA("aux_wordadd"),i);
1895  AA waddr = address.Sub(i);
1896  WordOr(waddr, TargetExpression(AA("aux_bitmask")));
1897  SwitchBreak();
1898  }
1899  SwitchEnd();
1900  return;
1901  }
1902  // perform simple case
1903  if(gotaddress && (wlen == 1)) {
1904  AA waddr = address.Sub(0);
1905  WordOr(waddr, TargetExpression(AA("aux_bitmask")));
1906  return;
1907  }
1908  // fallback: switch using the provided hint
1909  SwitchBegin(indexaddr);
1910  int baddr;
1911  for(baddr=0;baddr<blen;baddr++) {
1912  if(hint.size()>0)
1913  if(!hint[baddr])
1914  continue;
1915  SwitchCase(indexaddr,baddr+offset);
1916  BitarraySetBit(address,baddr);
1917  SwitchBreak();
1918  }
1919  SwitchEnd();
1920 }
1921 
1922 // bitarray test set by var index
1923 void CodePrimitives::BitarrayIsBitSet(const AA& address, const AA& indexaddr, const AA& result, int offset, const std::vector<bool>& hint){
1924  // lookup
1925  int blen= mBitarrays[address].blen;
1926  int wlen = (blen + mWordSize - 1) / mWordSize;
1927  bool gotaddress=false;
1928  // use precompiled masks to obtain address
1929  if(mArrayForBitmasks && (wlen > 1)) {
1930  IntegerAssign(AA("aux_bitaddr"),TargetExpression(indexaddr));
1931  IntegerDecrement(AA("aux_bitaddr"),offset);
1932  IntegerAssign(AA("aux_wordaddr"),TargetExpression(CintarrayAccess(AA("wordaddr_vector"),AA("aux_bitaddr"))));
1933  IntegerAssign(AA("aux_bitmask"),TargetExpression(CwordarrayAccess(AA("bitmask_vector"),AA("aux_bitaddr"))));
1934  gotaddress=true;
1935  }
1936  // compute address
1937  if((!gotaddress) && mBitAddressArithmetic && (wlen > 1)) {
1938  IntegerAssign(AA("aux_bitaddr"),TargetExpression(indexaddr));
1939  IntegerDecrement(AA("aux_bitaddr"),offset);
1940  IntegerAssign(AA("aux_wordaddr"),IntegerQuotient(TargetExpression(AA("aux_bitaddr")),mWordSize));
1941  IntegerAssign(AA("aux_bitaddr"),IntegerRemainder(TargetExpression(AA("aux_bitaddr")),mWordSize));
1942  IntegerAssign(AA("aux_bitmask"),IntegerBitmask(TargetExpression(AA("aux_bitaddr"))));
1943  gotaddress=true;
1944  }
1945  // use precompiled masks, simple case
1946  if((!gotaddress) && mArrayForBitmasks && (wlen == 1)) {
1947  IntegerAssign(AA("aux_bitaddr"),TargetExpression(indexaddr));
1948  IntegerDecrement(AA("aux_bitaddr"),offset);
1949  IntegerAssign(AA("aux_bitmask"),TargetExpression(CwordarrayAccess(AA("bitmask_vector"),AA("aux_bitaddr"))));
1950  gotaddress=true;
1951  }
1952  // compute address, simple case
1953  if((!gotaddress) && mBitAddressArithmetic && (wlen == 1)) {
1954  IntegerAssign(AA("aux_bitaddr"),TargetExpression(indexaddr));
1955  IntegerDecrement(AA("aux_bitaddr"),offset);
1956  IntegerAssign(AA("aux_wordaddr"),IntegerQuotient(TargetExpression(AA("aux_bitaddr")),mWordSize));
1957  IntegerAssign(AA("aux_bitaddr"),IntegerRemainder(TargetExpression(AA("aux_bitaddr")),mWordSize));
1958  IntegerAssign(AA("aux_bitmask"),IntegerBitmask(TargetExpression(AA("aux_bitaddr"))));
1959  gotaddress=true;
1960  }
1961  // perform with word array
1962  if(gotaddress && mArrayForBitarray) {
1963  WordAnd(result,WordarrayAccess(address, AA("aux_wordaddr")),AA("aux_bitmask"));
1964  }
1965  // perform by switch
1966  if(gotaddress && (wlen > 1)) {
1967  SwitchBegin(AA("aux_wordaddr"));
1968  for(int i=0; i<wlen; i++) {
1969  if(hint.size()>0)
1970  if(WordFromBitVector(hint,i)==0) continue;
1971  SwitchCase(AA("aux_wordadd"),i);
1972  AA waddr = address.Sub(i);
1973  WordAnd(result,waddr,AA("aux_bitmask"));
1974  SwitchBreak();
1975  }
1976  SwitchEnd();
1977  return;
1978  }
1979  // perform simple case
1980  if(gotaddress && (wlen == 1)) {
1981  AA waddr = address.Sub(0);
1982  WordAnd(result,waddr,AA("aux_bitmask"));
1983  return;
1984  }
1985  // fallback: switch not implemented
1986  FCG_ERR("CodePrimitives::Bitarray(): BitAddressArithmetic or ArrayForBitmasks required for test by variable");
1987 }
1988 
1989 // bitarray
1990 void CodePrimitives::BitarrayClrBit(const AA& address, int index){
1991  // figure word/bit
1992  int windex=index / mWordSize;
1993  int bindex= index % mWordSize;
1994  // clear
1995  AA waddr;
1996  if(mArrayForBitarray) waddr= WordarrayAccess(address,windex);
1997  else waddr = address.Sub(windex);
1998  WordNand(waddr,WordConstant( 1UL << bindex));
1999 }
2000 
2001 // bitarray clear bit by index
2002 void CodePrimitives::BitarrayClrBit(const AA& address, const AA& indexaddr, int offset, const std::vector<bool>& hint){
2003  // lookup
2004  int blen= mBitarrays[address].blen;
2005  int wlen = (blen + mWordSize - 1) / mWordSize;
2006  bool gotaddress=false;
2007  // use precompiled masks to obtain address
2008  if(mArrayForBitmasks && (wlen > 1)) {
2009  IntegerAssign(AA("aux_bitaddr"),TargetExpression(indexaddr));
2010  IntegerDecrement(AA("aux_bitaddr"),offset);
2011  IntegerAssign(AA("aux_wordaddr"),TargetExpression(CintarrayAccess(AA("wordaddr_vector"),AA("aux_bitaddr"))));
2012  IntegerAssign(AA("aux_bitmask"),TargetExpression(CwordarrayAccess(AA("bitmask_vector"),AA("aux_bitaddr"))));
2013  gotaddress=true;
2014  }
2015  // compute address
2016  if((!gotaddress) && mBitAddressArithmetic && (wlen > 1)) {
2017  IntegerAssign(AA("aux_bitaddr"),TargetExpression(indexaddr));
2018  IntegerDecrement(AA("aux_bitaddr"),offset);
2019  IntegerAssign(AA("aux_wordaddr"),IntegerQuotient(TargetExpression(AA("aux_bitaddr")),mWordSize));
2020  IntegerAssign(AA("aux_bitaddr"),IntegerRemainder(TargetExpression(AA("aux_bitaddr")),mWordSize));
2021  IntegerAssign(AA("aux_bitmask"),IntegerBitmask(TargetExpression(AA("aux_bitaddr"))));
2022  gotaddress=true;
2023  }
2024  // use precompiled masks, simple case
2025  if((!gotaddress) && mArrayForBitmasks && (wlen == 1)) {
2026  IntegerAssign(AA("aux_bitaddr"),TargetExpression(indexaddr));
2027  IntegerDecrement(AA("aux_bitaddr"),offset);
2028  IntegerAssign(AA("aux_bitmask"),TargetExpression(CwordarrayAccess(AA("bitmask_vector"),AA("aux_bitaddr"))));
2029  gotaddress=true;
2030  }
2031  // compute address, simple case
2032  if((!gotaddress) && mBitAddressArithmetic && (wlen == 1)) {
2033  IntegerAssign(AA("aux_bitaddr"),TargetExpression(indexaddr));
2034  IntegerDecrement(AA("aux_bitaddr"),offset);
2035  IntegerAssign(AA("aux_wordaddr"),IntegerQuotient(TargetExpression(AA("aux_bitaddr")),mWordSize));
2036  IntegerAssign(AA("aux_bitaddr"),IntegerRemainder(TargetExpression(AA("aux_bitaddr")),mWordSize));
2037  IntegerAssign(AA("aux_bitmask"),IntegerBitmask(TargetExpression(AA("aux_bitaddr"))));
2038  gotaddress=true;
2039  }
2040  // perform with word array
2041  if(gotaddress && mArrayForBitarray) {
2042  WordNand(WordarrayAccess(address, AA("aux_wordaddr")),TargetExpression(AA("aux_bitmask")));
2043  return;
2044  }
2045  // perform by switch
2046  if(gotaddress && (wlen > 1)) {
2047  SwitchBegin(AA("aux_wordaddr"));
2048  for(int i=0; i<wlen; i++) {
2049  if(hint.size()>0)
2050  if(WordFromBitVector(hint,i)==0) continue;
2051  SwitchCase(AA("aux_wordadd"),i);
2052  AA waddr = address.Sub(i);
2053  WordNand(waddr, TargetExpression(AA("aux_bitmask")));
2054  SwitchBreak();
2055  }
2056  SwitchEnd();
2057  return;
2058  }
2059  // perform simple case
2060  if(gotaddress && (wlen == 1)) {
2061  AA waddr = address.Sub(0);
2062  WordNand(waddr, TargetExpression(AA("aux_bitmask")));
2063  return;
2064  }
2065  // fallback: switch using the provided hint
2066  SwitchBegin(indexaddr);
2067  int baddr;
2068  for(baddr=0;baddr<blen;baddr++) {
2069  if(hint.size()>0)
2070  if(!hint[baddr])
2071  continue;
2072  SwitchCase(indexaddr,baddr+offset);
2073  BitarrayClrBit(address,baddr);
2074  SwitchBreak();
2075  }
2076  SwitchEnd();
2077 }
2078 
2079 // bitarray
2080 void CodePrimitives::BitarrayOr(const AA& address, const std::vector<bool>& val) {
2081  // lookup
2082  int blen= mBitarrays[address].blen;
2083  int wlen = (blen + mWordSize - 1) / mWordSize;
2084  // iterate words
2085  for(int w=0; w<wlen; ++w) {
2086  word_t wval=WordFromBitVector(val,w);
2087  if(wval==0) continue;
2088  AA waddr;
2089  if(mArrayForBitarray) waddr= WordarrayAccess(address,w);
2090  else waddr = address.Sub(w);
2091  WordOr(waddr,wval);
2092  }
2093 }
2094 
2095 
2096 // bitarray
2097 void CodePrimitives::BitarrayOr(const AA& address, const AA &op1, const std::vector<bool>& op2) {
2098  // lookup
2099  int blen= mBitarrays[address].blen;
2100  int wlen = (blen + mWordSize - 1) / mWordSize;
2101  // iterate words
2102  for(int w=0; w<wlen; ++w) {
2103  word_t wval=WordFromBitVector(op2,w);
2104  AA waddr;
2105  AA wop1;
2106  if(mArrayForBitarray) waddr= WordarrayAccess(address,w);
2107  else waddr = address.Sub(w);
2108  if(mArrayForBitarray) wop1= WordarrayAccess(op1,w);
2109  else wop1 = op1.Sub(w);
2110  if(wval!=0)
2111  WordOr(waddr,wop1,wval);
2112  else
2113  WordAssign(waddr,TargetExpression(wop1));
2114  }
2115 }
2116 
2117 // bitarray
2118 void CodePrimitives::BitarrayAnd(const AA& address, const std::vector<bool>& val) {
2119  // lookup
2120  int blen= mBitarrays[address].blen;
2121  int wlen = (blen + mWordSize - 1) / mWordSize;
2122  // iterate words
2123  for(int w=0; w<wlen; ++w) {
2124  word_t wval=WordFromBitVector(val,w);
2125  if(wval== (1UL << mWordSize) - 1) continue;
2126  AA waddr;
2127  if(mArrayForBitarray) waddr= WordarrayAccess(address,w);
2128  else waddr = address.Sub(w);
2129  WordAnd(waddr,wval);
2130  }
2131 }
2132 
2133 // intersect
2134 void CodePrimitives::BitarrayAnd(const AA& address, const AA& otherarray) {
2135  // lookup
2136  int blen= mBitarrays[address].blen;
2137  int wlen = (blen + mWordSize - 1) / mWordSize;
2138  // iterate words
2139  for(int w=0; w<wlen; ++w) {
2140  AA waddr;
2141  if(mArrayForBitarray) waddr= WordarrayAccess(address,w);
2142  else waddr = address.Sub(w);
2143  AA oaddr;
2144  if(mArrayForBitarray) oaddr= WordarrayAccess(otherarray,w);
2145  else oaddr = otherarray.Sub(w);
2146  WordAnd(waddr,TargetExpression(oaddr));
2147  }
2148 }
2149 
2150 // intersect
2151 void CodePrimitives::BitarrayAnd(const AA& address, const AA &op1, const std::vector<bool>& op2) {
2152  // lookup
2153  int blen= mBitarrays[address].blen;
2154  int wlen = (blen + mWordSize - 1) / mWordSize;
2155  // iterate words
2156  for(int w=0; w<wlen; ++w) {
2157  word_t wval=WordFromBitVector(op2,w);
2158  AA waddr;
2159  AA wop1;
2160  if(mArrayForBitarray) waddr= WordarrayAccess(address,w);
2161  else waddr = address.Sub(w);
2162  if(mArrayForBitarray) wop1= WordarrayAccess(op1,w);
2163  else wop1 = op1.Sub(w);
2164  if(wval!= (1UL << mWordSize) - 1)
2165  WordAnd(waddr,wop1,wval);
2166  else
2167  WordAssign(waddr,TargetExpression(wop1));
2168  }
2169 }
2170 
2171 // intersect
2172 void CodePrimitives::BitarrayAnd(const AA& address, const AA& op1, const AA& op2) {
2173  // lookup
2174  int blen= mBitarrays[address].blen;
2175  int wlen = (blen + mWordSize - 1) / mWordSize;
2176  // iterate words
2177  for(int w=0; w<wlen; ++w) {
2178  AA waddr;
2179  if(mArrayForBitarray) waddr= WordarrayAccess(address,w);
2180  else waddr = address.Sub(w);
2181  AA op1addr;
2182  if(mArrayForBitarray) op1addr= WordarrayAccess(op1,w);
2183  else op1addr = op1.Sub(w);
2184  AA op2addr;
2185  if(mArrayForBitarray) op2addr= WordarrayAccess(op2,w);
2186  else op2addr = op2.Sub(w);
2187  WordAnd(waddr,op1addr,op2addr);
2188  }
2189 }
2190 
2191 // find lowest index with bit set (result as an address)
2192 void CodePrimitives::BitarrayFindFirst(const AA& address, const AA& result, int offset) {
2193  // prepare result
2194  IntegerAssign(result,offset-1);
2195  // lookup
2196  int blen= mBitarrays[address].blen;
2197  // iterate words
2198  for(int w=0; w< (blen + mWordSize -1) / mWordSize; ++w) {
2199  AA waddr;
2200  if(mArrayForBitarray) waddr= WordarrayAccess(address,w);
2201  else waddr = address.Sub(w);
2202  int ifcnt=0;
2203  /* as of the second word we only search if nothing found so far */
2204  if(w>0) {
2205  IfTrue(IntegerIsEq(result,offset-1));
2206  ++ifcnt;
2207  }
2208  /* search the current word only if non-zero */
2209  IfTrue(WordIsNotEq(waddr,0));
2210  ++ifcnt;
2211  /* simple case: only one bit left to search */
2212  if(w*mWordSize + 1 == blen) {
2213  IntegerAssign(result,w*mWordSize+offset);
2214  for(;ifcnt>0;--ifcnt) IfEnd();
2215  continue;
2216  }
2217  /* naive approach O(mWordSize)*/
2218  if(!mBisectionForBitfind) {
2219  for(int b=0; b<mWordSize;++b) {
2220  int index=w*mWordSize + b;
2221  if(index>=blen) break;
2222  if(b==0) {
2223  IfTrue(WordIsBitSet(waddr,b));
2224  ++ifcnt;
2225  } else {
2226  IfElseIfTrue(WordIsBitSet(waddr,b));
2227  }
2228  IntegerAssign(result,index+offset);
2229  }
2230  }
2231  /* interval search O(log(mWordSize)) */
2232  if(mBisectionForBitfind) {
2233  int wsize=mWordSize;
2234  int bleft=blen-w*mWordSize;
2235  if(bleft>wsize) bleft=wsize;
2236  while(wsize/2>=bleft) wsize=wsize/2;
2237  bool hl=true;
2238  int pos=0;
2239  int size=wsize;
2240  while(size<=wsize) {
2241  /* break on out of range */
2242  if(!(pos<bleft)) break;
2243  /* figure range to process */
2244  if(hl) {
2245  /* restrict size to remaining bits */
2246  while(pos+size/2>=bleft) size=size/2;
2247  /* process bit range [pos,pos+size) */
2248  // FD_WARN("range [" << pos << ", " << pos+size << ")");
2249  }
2250  /* subdivide to process lower half */
2251  if(hl && (size>2)) {
2252  word_t ltest= (1UL << size/2) -1;
2253  ltest=ltest<<pos;
2254  IfTrue(WordIsMaskSet(waddr,ltest));
2255  ++ifcnt;
2256  size=size/2;
2257  continue;
2258  }
2259  /* resolve range of size 2 */
2260  if(hl && (size==2)) {
2261  IfTrue(WordIsMaskSet(waddr,(1UL << pos)));
2262  IntegerAssign(result, w*mWordSize + pos + offset);
2263  IfElse();
2264  IntegerAssign(result,w*mWordSize + pos + 1 + offset);
2265  IfEnd();
2266  size=2*size;
2267  hl=false;
2268  continue;
2269  }
2270  /* resolve range of size 1 */
2271  if(hl && (size==1)) {
2272  IntegerAssign(result, w*mWordSize + pos + offset);
2273  size=2*size;
2274  hl=false;
2275  continue;
2276  }
2277  /* sense lower half done, set up for for higher half */
2278  if((!hl) && ((pos % size) == 0)) {
2279  size=size/2;
2280  pos+=size;
2281  hl=true;
2282  if(pos<bleft) IfElse();
2283  continue;
2284  }
2285  /* sense higher half done, return to parent */
2286  if((!hl) && ((pos % size) != 0)) {
2287  --ifcnt;
2288  IfEnd();
2289  pos-=size/2;
2290  size=size*2;
2291  }
2292  }
2293  }
2294  /* close open ifs */
2295  for(;ifcnt>0;--ifcnt)
2296  IfEnd();
2297  } // end: loop words
2298 }
2299 
2300 
2301 // event set
2302 void CodePrimitives::EventSetDeclare(const AA& address) {
2303  BitarrayDeclare(address,EventBitMaskSize());
2304 }
2305 
2306 // event set
2307 void CodePrimitives::EventSetDeclare(const AA& address, const EventSet& evset) {
2308  std::vector<bool> evmask = EventBitMask(evset);
2309  BitarrayDeclare(address,evmask);
2310 }
2311 
2312 // event set
2313 void CodePrimitives::EventSetClear(const AA& address) {
2314  BitarrayClear(address);
2315 }
2316 
2317 // event set
2318 void CodePrimitives::EventSetFull(const AA& address) {
2319  BitarrayFull(address);
2320 }
2321 
2322 // set is empty
2323 void CodePrimitives::EventSetIsNotEmpty(const AA& address, const AA& result) {
2324  BitarrayOrAllWords(address,result);
2325 }
2326 
2327 // event insert
2328 void CodePrimitives::EventSetAssign(const AA& address, const EventSet& evset) {
2329  std::vector<bool> evmask = EventBitMask(evset);
2330  BitarrayAssign(address,evmask);
2331 }
2332 
2333 // event insert
2334 void CodePrimitives::EventSetInsert(const AA& address, const EventSet& evset) {
2335  std::vector<bool> evmask = EventBitMask(evset);
2336  BitarrayOr(address,evmask);
2337 }
2338 
2339 // event insert
2340 void CodePrimitives::EventSetInsert(const AA& address, const AA& evaddrexpr) {
2341  BitarraySetBit(address,evaddrexpr,1);
2342 };
2343 
2344 // event insert, candidats known
2345 void CodePrimitives::EventSetInsert(const AA& address, const AA& evaddrexpr, const EventSet& hint) {
2346  std::vector<bool> evmask = EventBitMask(hint);
2347  BitarraySetBit(address,evaddrexpr,1,evmask);
2348 };
2349 
2350 // event insert
2351 void CodePrimitives::EventSetInsert(const AA& address, Idx ev) {
2352  BitarraySetBit(address,EventBitAddress(ev));
2353 }
2354 
2355 // event erase
2356 void CodePrimitives::EventSetErase(const AA& address, const EventSet& evset) {
2357  std::vector<bool> evmask = EventBitMask(evset);
2358  for(size_t i=0; i<evmask.size(); i++) evmask[i]= ! evmask[i];
2359  BitarrayAnd(address,evmask);
2360 }
2361 
2362 // event erase
2363 void CodePrimitives::EventSetErase(const AA& address, Idx ev) {
2364  BitarrayClrBit(address,EventBitAddress(ev));
2365 }
2366 
2367 // event erase
2368 void CodePrimitives::EventSetErase(const AA& address, const AA& evaddr) {
2369  BitarrayClrBit(address,evaddr,1);
2370 };
2371 
2372 // event test
2373 void CodePrimitives::EventSetExists(const AA& address, const AA& evaddr, const AA& result, const EventSet& hint) {
2374  std::vector<bool> evmask = EventBitMask(hint);
2375  BitarrayIsBitSet(address,evaddr,result,1,evmask);
2376 };
2377 
2378 // event erase, candidats known
2379 void CodePrimitives::EventSetErase(const AA& address, const AA& evaddr, const EventSet& hint) {
2380  std::vector<bool> evmask = EventBitMask(hint);
2381  BitarrayClrBit(address,evaddr,1,evmask);
2382 };
2383 
2384 // event restrict
2385 void CodePrimitives::EventSetRestrict(const AA& address, const AA& otherset) {
2386  BitarrayAnd(address,otherset);
2387 }
2388 
2389 // event union
2390 void CodePrimitives::EventSetUnion(const AA& address, const AA& op1, const EventSet& op2) {
2391  std::vector<bool> evmask = EventBitMask(op2);
2392  BitarrayOr(address,op1,evmask);
2393 }
2394 
2395 // event intersection
2396 void CodePrimitives::EventSetIntersection(const AA& address, const AA& op1, const EventSet& op2) {
2397  std::vector<bool> evmask = EventBitMask(op2);
2398  BitarrayAnd(address,op1,evmask);
2399 }
2400 
2401 // event set find lowest index (i.e. max priority)
2402 void CodePrimitives::EventSetFindHighestPriority(const AA& address, const AA& result) {
2403  BitarrayFindFirst(address,result,1);
2404 }
2405 
2406 
2407 
2408 // no relevant defaults in conditionals/loops
2409 void CodePrimitives::IfTrue(const AX& expression) {
2410  (void) expression;
2411  FCG_ERR("CodePrimitives::Conditionals(): construct not available");
2412 }
2413 // no relevant defaults in conditionals/loops
2414 void CodePrimitives::IfFalse(const AX& expression) {
2415  (void) expression;
2416  FCG_ERR("CodePrimitives::Conditionals(): construct not available");
2417 }
2418 // no relevant defaults in conditionals/loops
2419 void CodePrimitives::IfWord(const AX& expression) {
2420  (void) expression;
2421  FCG_ERR("CodePrimitives::Conditionals(): construct not available");
2422 }
2423 void CodePrimitives::IfElse(void) {
2424  FCG_ERR("CodePrimitives::Conditionals(): construct not available");
2425 }
2426 // no relevant defaults in conditionals/loops
2427 void CodePrimitives::IfElseIfTrue(const AX& expression) {
2428  (void) expression;
2429  FCG_ERR("CodePrimitives::Conditionals(): construct not available");
2430 }
2431 void CodePrimitives::IfEnd(void) {
2432  FCG_ERR("CodePrimitives::Conditionals(): construct not available");
2433 }
2434 void CodePrimitives::LoopBegin(void) {
2435  FCG_ERR("CodePrimitives::Loops(): construct not available");
2436 }
2437 void CodePrimitives::LoopBreak(const AX& expression) {
2438  (void) expression;
2439  FCG_ERR("CodePrimitives::Loops(): construct not available");
2440 }
2441 void CodePrimitives::LoopEnd(void) {
2442  FCG_ERR("CodePrimitives::Loops(): construct not available");
2443 }
2444 void CodePrimitives::FunctionReturn(void) {
2445  FCG_ERR("CodePrimitives::FunctionReturn(): construct not available");
2446 }
2447 
2448 // switch defaults to conditionsl
2449 void CodePrimitives::SwitchBegin(const AA& address){
2450  (void) address;
2451  FCG_ERR("CodePrimitives::Conditionals(): switch not available");
2452 }
2453 void CodePrimitives::SwitchCase(const AA& address, int val){
2454  (void) address;
2455  (void) val;
2456  FCG_ERR("CodePrimitives::Conditionals(): switch not available");
2457 }
2458 void CodePrimitives::SwitchCases(const AA& address, int from, int to){
2459  (void) address;
2460  (void) from;
2461  (void) to;
2462  FCG_ERR("CodePrimitives::Conditionals(): switch not available");
2463 }
2464 void CodePrimitives::SwitchCases(const AA& address, const std::set< int > & vals){
2465  (void) address;
2466  (void) vals;
2467  FCG_ERR("CodePrimitives::Conditionals(): switch not available");
2468 }
2469 void CodePrimitives::SwitchBreak(void){
2470  FCG_ERR("CodePrimitives::Conditionals(): switch not available");
2471 }
2472 void CodePrimitives::SwitchEnd(void){
2473  FCG_ERR("CodePrimitives::Conditionals(): switch not available");
2474 }
2475 bool CodePrimitives::HasMultiCase(void){
2476  return false;
2477 }
2478 
2479 
2480 // output actions (not available)
2481 void CodePrimitives::RunActionSet(const std::string& address) {
2482  (void) address;
2483  FCG_ERR("CodePrimitives::RunAction(): action not available");
2484 }
2485 void CodePrimitives::RunActionClr(const std::string& address) {
2486  (void) address;
2487  FCG_ERR("CodePrimitives::RunAction(): action not available");
2488 }
2489 void CodePrimitives::RunActionExe(const AX& expression) {
2490  (void) expression;
2491  FCG_ERR("CodePrimitives::RunAction(): action not available");
2492 }
2493 
2494 
2495 // read inputs (treat as native expression)
2496 CodePrimitives::AX CodePrimitives::ReadInputLine(const std::string& address) {
2497  return AX(address);
2498 }
2499 CodePrimitives::AX CodePrimitives::InputExpression(const std::string& expression) {
2500  return AX(expression);
2501 }
2502 
2503 
2504 // timer (not available)
2505 void CodePrimitives::TimerDeclare(const AA& address, const std::string &litval) {
2506  (void) address;
2507  (void) litval;
2508  FCG_ERR("CodePrimitives::Timer(): not available");
2509 }
2510 void CodePrimitives::TimerStart(const AA& address) {
2511  (void) address;
2512  FCG_ERR("CodePrimitives::Timer(): not available");
2513 }
2514 void CodePrimitives::TimerStop(const AA& address) {
2515  (void) address;
2516  FCG_ERR("CodePrimitives::Timer(): not available");
2517 }
2518 void CodePrimitives::TimerReset(const AA& address, const std::string &litval) {
2519  (void) address;
2520  (void) litval;
2521  FCG_ERR("CodePrimitives::Timer(): not available");
2522 }
2523 CodePrimitives::AX CodePrimitives::TimerIsElapsed(const AA& address) {
2524  (void) address;
2525  FCG_ERR("CodePrimitives::Timer(): not available");
2526  return AX();
2527 }
2528