CompileDES  3.11
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  // figure which generators provide statenames
304  mExistStateNames=false;
305  mHasStateNames.assign(Size(),false);
306  for(size_t gid=0; gid<Size(); ++gid) {
307  const faudes::Generator& gen=At(gid);
308  int mem=0;
309  faudes::StateSet::Iterator sit=gen.StatesBegin();
310  for(;sit!=gen.StatesEnd();++sit)
311  mem += (int) gen.StateName(*sit).size();
312  if(mem>0) {
313  mHasStateNames[gid]=true;
314  mExistStateNames=true;
315  }
316  // report
317  if(mem>0) {
318  FCG_VERB0("CodeGenerator::Compile(): [" << gen.Name() << "] state names amount to #"
319  << mem << " bytes");
320  }
321  }
322  // figure which state index scheme to use
323  if((!mStateUpdateHook.empty()) && (!mMaintainStateIndices)) {
324  FCG_VERB1("CodePrimitives::Compile(): state update hook implies to maintain state indices as provided");
326  }
327  if(mStateNameLookup && !HasCstrarray()) {
328  FCG_VERB1("CodePrimitives::Compile(): cannot generate lookup tables for the specified platforms");
329  mStateNameLookup=false;
330  }
332  FCG_VERB1("CodePrimitives::Compile(): no state names found --- will generate dummy loopkups only");
333  }
334  // set up address scheme flags
335  mUsingVectorAddressStates.assign(Size(),true);
336  if(mStateNameLookup) {
337  for(size_t gid=0; gid<Size(); ++gid) {
338  if(mHasStateNames[gid]) mUsingVectorAddressStates[gid]=false;
339  }
340  }
342  mUsingVectorAddressStates.assign(Size(),false);
343  }
344  // have consecutive states when possible/sensible
345  if(!mMaintainStateIndices) {
346  for(size_t git=0; git<Size(); ++git) {
347  if(At(git).MaxStateIndex()==At(git).States().Size()) continue;
349  FCG_VERB0("CodeGenerator::Generator(): generator [" << At(git).Name() << "] " <<
350  "has non-consecutive state indices --- applying MinStateIndex()");
351  mGenerators[git].MinStateIndex();
352  }
353  }
354  // produce warnings for non-consecutive states where relevant
355  for(size_t git=0; git<Size(); ++git) {
356  int gap = At(git).MaxStateIndex() - At(git).States().Size();
357  if(gap==0) continue;
359  FCG_VERB0("CodeGenerator::Generator(): generator [" << At(git).Name() << "] " <<
360  "has non-consecutive state indices --- this will introduce an inefficient address table with #"
361  << gap << " dummy entries");
362  }
363  if(mStateNameLookup && mHasStateNames[git]) {
364  FCG_VERB0("CodeGenerator::Generator(): generator [" << At(git).Name() << "] " <<
365  "has non-consecutive state indices --- this will introduce an inefficient symboltable with #"
366  << gap << " dummy entries"); continue;
367  }
368  }
369 
370  // call base, incl transitionvector setup
372 
373  // continue test conformance
374  FD_DCG("CodePrimitives(" << this << ")::DoCompile()");
375  // check and fix configuration
376  if(mArrayForTransitions && !HasCintarray()) {
377  FCG_VERB1("CodePrimitives::Compile(): cannot generate compiled arrays for the specified target");
378  mArrayForTransitions=false;
379  }
380  if(mArrayForBitmasks && !HasCwordarray()) {
381  FCG_VERB1("CodePrimitives::Compile(): cannot generate compiled bit-masks for the specified target");
382  mArrayForBitmasks=false;
383  }
384  if(mArrayForBitmasks && (mWordSize>8))
385  FCG_VERB1("CodePrimitives::Compile(): compiled bitmasks not recommended for word-size #" << mWordSize);
386  if(mArrayForBitmasks && (mWordSize>16)) {
387  FCG_VERB1("CodePrimitives::Compile(): reject compiled bitmasks for word-size #" << mWordSize);
388  mArrayForBitmasks = false;
389  }
390  if(mBitAddressArithmetic && !HasIntmaths()) {
391  FCG_VERB1("CodePrimitives::Compile(): bit address-maths not available for the specified target");
392  mBitAddressArithmetic=false;
393  }
395  FCG_VERB1("CodePrimitives::Compile(): reject option eventsets-for-performance for specified target");
396  mEventsetsForPerformance = false;
397  }
398  /*
399  if(mLoopEnabledOutputs && !mEventsetsForPerformance) {
400  FCG_VERB1("CodePrimitives::Compile(): option loop-enabled-outputs suggests eventsets-for-performance");
401  }
402  */
404  FCG_VERB1("CodePrimitives::Compile(): option loop-enabled-outputs implies loop-enabled-inputs");
405  }
406  if(mLoopEnabledOutputs) {
407  if(mLastOutputEvent+1+mInternalEvents.Size() != mUsedEvents.Size()) {
408  FCG_ERR("CodePrimitives::Compile(): option loop-enabled-outputs requires high priority for output events");
409  }
410  }
411  if(mEventNameLookup && !HasCstrarray()) {
412  FCG_VERB1("CodePrimitives::Compile(): cannot generate lookup tables for the specified platform");
413  mEventNameLookup=false;
414  }
415  if((!mStateUpdateHook.empty()) && (!HasIntarray())) {
416  FCG_VERB1("CodePrimitives::Compile(): cannot implement state-update hook for the specified platform");
417  mStateUpdateHook="";
418  }
419  if((!mStateUpdateHook.empty()) && (!mArrayForState)) {
420  FCG_VERB1("CodePrimitives::Compile(): state-update hook implies array representation of overall state");
421  mArrayForState=true;
422  }
423 }
424 
425 /*
426 ******************************************************************
427 ******************************************************************
428 ******************************************************************
429 
430 CodePrimitives implementation: internal data organisation
431 
432 ******************************************************************
433 ******************************************************************
434 ******************************************************************
435 */
436 
437 
438 // mangle an arbitrary string to a valid target symbol
439 std::string CodePrimitives::TargetSymbol(const std::string& str) {
440  // could have a static lookup here ... avoid doublets aso .. use synthetic symbols
441  std::string res;
442  std::string::const_iterator sit=str.begin();
443  for(;sit!=str.end();++sit){
444  if(std::isalpha(*sit)) { res.push_back(*sit); continue; };
445  if(std::isdigit(*sit) && res.size()>0) { res.push_back(*sit); continue; }
446  if(res.size()>0) res.push_back('_');
447  }
448  return res;
449 }
450 
451 
452 // effective target state index
453 int CodePrimitives::StateTargetIdx(size_t git, Idx idx) {
454  // if we compile with transition array, let base respond for vetor address when applicable
456  // else default to original index, which is consecutive starting with 1
457  return idx;
458 }
459 
460 // retrieve faudes state idx
461 Idx CodePrimitives::StateFaudesIdx(size_t git, int idx) {
462  // if we compile with transition array, let base respond for vetor addrss when applicable
464  // else default to original index, which is consecutive starting with 1
465  return idx;
466 }
467 
468 
469 
470 /*
471 ******************************************************************
472 ******************************************************************
473 ******************************************************************
474 
475 CodePrimitives implementation --- generate code blocks
476 
477 ******************************************************************
478 ******************************************************************
479 ******************************************************************
480 */
481 
482 
483 // code blocks: literal prepend from configuration
485  if(mLiteralPrepend.size()==0) return;
486  Comment("************************************************");
487  Comment("* prepend code snippet from configuration *");
488  LineFeed(2);
489  Output() << mLiteralPrepend;
490  LineFeed(2+2);
491 }
492 
493 
494 // code blocks: variables (global)
496  Comment("status (0x00 <> waiting, 0x01<>executing, 0x02<>err)");
497  WordDeclare(AA("status"));
498  LineFeed(1);
499 }
500 
501 // code blocks: variables (global)
503  Comment("external reset");
504  BooleanDeclare(AA("reset"), false);
505  LineFeed(1);
506 }
507 
508 // code blocks: variables (global)
510  Comment("recent event (0<>none)");
511  IntegerDeclare(AA("recent_event"));
512  LineFeed(1);
513 }
514 
515 
516 // code blocks: variables (opt global)
518  Comment("parallel state");
519  if(mArrayForState) {
520  IntarrayDeclare(AA("parallel_state"),0,Size());
521  } else {
522  for(Idx gid=0; gid< Size(); gid++)
523  IntegerDeclare(AA("parallel_state").Sub(gid));
524  }
525  LineFeed(1);
526 }
527 
528 // code blocks: variables (opt global)
530  // std event sets
531  Comment("pending input events incl timer elapse");
532  EventSetDeclare(AA("pending_events"));
533  LineFeed(1);
534  Comment("events enabled by all generators");
535  EventSetDeclare(AA("enabled_events"));
536  LineFeed(1);
537 }
538 
539 // code blocks: variables (local)
541  // exec event
542  Comment("executed event (-1<>init, 0<>none)");
543  IntegerDeclare(AA("exec_event"),-1);
544  LineFeed(1);
545  // scheduled event
546  Comment("scheduled event (0<>none)");
547  IntegerDeclare(AA("sched_event"));
548  LineFeed(1);
549  // edge detection
550  if(LinesBegin()!=LinesEnd()){
551  Comment("line levels");
552  LineIterator lit=LinesBegin();
553  for(;lit!=LinesEnd();++lit) {
554  AA baddr = AA("line_level").Sub(lit->second.mBitAddress);
555  BooleanDeclare(baddr);
556  }
557  LineFeed(1);
558  }
559  // track loop count
561  Comment("loop flag");
562  BooleanDeclare(AA("first_loop"));
563  LineFeed(1);
564  }
565 }
566 
567 // code blocks: variables (local)
569  if(TimersBegin()!=TimersEnd()) {
570  Comment("timer states");
571  TimerIterator tit= TimersBegin();
572  for(;tit!=TimersEnd();++tit)
573  TimerDeclare(AA(tit->second.mAddress),tit->second.mInitialValue);
574  LineFeed(1);
575  }
576 }
577 
578 // code blocks: variables (local temp)
580  // additional aux variables
582  Comment("parse generator");
583  EventSetDeclare(AA("aux_locenabled"));
584  IntegerDeclare(AA("aux_parsetrans"));
585  IntegerDeclare(AA("aux_parseevent"));
586  LineFeed(1);
587  }
588  // aux enabled
589  Comment("enabled events that can be executed");
590  EventSetDeclare(AA("aux_executables"));
591  LineFeed(1);
592  // additional aux variables
593  Comment("aux maths and stack variables ");
594  WordDeclare(AA("aux_wordret"));
595  if(LinesBegin()!=LinesEnd()){
596  BooleanDeclare(AA("aux_edge"));
597  }
599  IntegerDeclare(AA("aux_wordaddr"));
600  IntegerDeclare(AA("aux_bitaddr"));
601  }
603  WordDeclare(AA("aux_bitmask"));
604  }
605  LineFeed(1);
606 }
607 
608 // code blocks: variables (large const)
610  // transition vector
612  for(size_t git=0; git<Size(); ++git) {
613  const Generator& gen = At(git);
614  Comment("generator [" + gen.Name() + "]");
615  if(!mUsingVectorAddressStates[git]) {
616  // set up statevector
617  std::vector< int > statevect(gen.MaxStateIndex(),0);
618  IndexSet::Iterator sit= gen.StatesBegin();
619  for(;sit!=gen.StatesEnd();++sit)
620  statevect[*sit-1]=mStateVectorAddress[git][*sit];
621  // declare state vector
622  CintarrayDeclare(AA("generator_states").Sub(git),1,statevect);
623  }
624  // declare transition vector
625  CintarrayDeclare(AA("generator_transitions").Sub(git),0,mTransitionVector[git]);
626  LineFeed(1);
627  }
628  }
629 }
630 
631 // code blocks: variables (small const)
633  // bitmaks vector
634  if(mArrayForBitmasks) {
635  Comment("mask vectors");
637  CintarrayDeclare(AA("wordaddr_vector"),0,mWordAddressVector);
638  CwordarrayDeclare(AA("bitmask_vector"),0,mBitMaskVector);
639  LineFeed(1);
640  }
641 }
642 
643 // code blocks: symbol tables as array declarations
645  if(!mEventNameLookup) return;
646  std::vector<std::string> evlookup;\
647  evlookup.resize(mUsedEvents.Size());
648  faudes::EventSet::Iterator eit=mUsedEvents.Begin();
649  for(;eit!=mUsedEvents.End();++eit) {
650  int tidx=EventTargetIdx(*eit);
651  if(((int) evlookup.size())<tidx) evlookup.resize(tidx);
652  evlookup[tidx-1]=mUsedEvents.SymbolicName(*eit);
653  }
654  Comment("event name lookup table");
655  CstrarrayDeclare(AA("event_lookup"),1,evlookup);
656  LineFeed(1);
657 }
658 
659 // code blocks: symbol tables as array declarations
661  if(!mStateNameLookup) return;
662  for(size_t gid=0; gid<Size(); ++gid) {
663  if(!mHasStateNames[gid]) continue;
664  const faudes::Generator& gen=At(gid);
665  std::vector<std::string> stlookup;\
666  faudes::StateSet::Iterator sit=gen.StatesBegin();
667  for(;sit!=gen.StatesEnd();++sit) {
668  int tidx=StateTargetIdx(gid,*sit);
669  if(((int) stlookup.size())<tidx) stlookup.resize(tidx);
670  std::string name=gen.StateName(*sit);
671  if(name=="") name="#"+ToStringInteger(tidx);
672  stlookup[tidx-1]=name;
673 
674  }
675  Comment("state name lookup for generator [" + At(gid).Name() + "]");
676  CstrarrayDeclare(AA("state_lookup").Sub(gid),1,stlookup);
677  LineFeed(1);
678  }
679 }
680 
681 // code blocks: reset
683  // say hello
684  Comment("************************************************");
685  Comment("* reset internal state *");
686  LineFeed(1);
687  Comment("set internal reset flag");
688  IfTrue(TargetExpression(AA("reset")));
689  IndentInc();
690  IntegerAssign(AA("exec_event"),-1);
691  IndentDec();
692  IfEnd();
693  LineFeed();
694  Comment("do reset core");
695  IfTrue(IntegerIsEq(AA("exec_event"),-1));
696  Comment("clear status");
697  IntegerAssign(AA("status"),0);
698  Comment("set initial state");
699  for(Idx gid=0; gid< Size(); gid++) {
700  AA statevar;
701  if(mArrayForState)
702  statevar=IntarrayAccess(AA("parallel_state"), gid);
703  else
704  statevar= AA("parallel_state").Sub(gid);
705  IntegerAssign(statevar,StateTargetIdx(gid,*At(gid).InitStatesBegin()));
706  }
707  Comment("clear scheduled event");
708  IntegerAssign(AA("sched_event"),0);
709  Comment("clear recent event");
710  IntegerAssign(AA("recent_event"),0);
711  Comment("clear pending/enabled events");
712  EventSetClear(AA("pending_events"));
713  EventSetClear(AA("enabled_events"));
714  if(TimersBegin()!=TimersEnd()) {
715  Comment("reset timer");
716  TimerIterator tit= TimersBegin();
717  for(;tit!=TimersEnd();++tit) {
718  TimerStop(AA(tit->second.mAddress));
719  TimerReset(AA(tit->second.mAddress) ,tit->second.mInitialValue);
720  }
721  }
722  IfEnd();
723  LineFeed(1);
724 }
725 
726 // code blocks: reset
728  // say hello
729  Comment("************************************************");
730  Comment("* bail out on external reset *");
731  LineFeed(1);
732  IfTrue(TargetExpression(AA("reset")));
733  IndentInc();
734  FunctionReturn();
735  IndentDec();
736  IfEnd();
737  LineFeed(1+2);
738 }
739 
740 // code blocks: inputs
742  // skip this section
743  if(FlagsBegin()==FlagsEnd())
744  if(LinesBegin()==LinesEnd())
745  return;
746  // say hello
747  Comment("************************************************");
748  Comment("* sense input events *");
749  LineFeed(1);
750  // my iterators
751  EventSet::Iterator eit;
752  LineIterator lit;
753  FlagIterator fit;
754  // reset edges, sense statics
755  if(LinesBegin()!=LinesEnd()) {
756  Comment("init: reset all line data and generate statics");
757  IfTrue(IntegerIsEq(AA("exec_event"),-1));
758  lit=LinesBegin();
759  for(;lit!=LinesEnd();++lit) {
760  AA baddr = AA("line_level").Sub(lit->second.mBitAddress);
761  BooleanAssign(baddr,ReadInputLine(AA(lit->second.mAddress))); // this is actually an expresssion
762  if(lit->second.mPosStatics.Empty() && lit->second.mNegStatics.Empty()) continue;
763  if(!lit->second.mPosStatics.Empty())
764  IfTrue(TargetExpression(baddr));
765  eit=lit->second.mPosStatics.Begin();
766  for(;eit!=lit->second.mPosStatics.End();++eit) {
767  Comment("positive value: trigger init event [" + EventName(*eit) + "]");
768  EventSetInsert(AA("pending_events"),*eit);
769  }
770  if(!lit->second.mPosStatics.Empty())
771  if(lit->second.mNegStatics.Empty())
772  IfEnd();
773  if(!lit->second.mPosStatics.Empty())
774  if(!lit->second.mNegStatics.Empty())
775  IfElse();
776  if(lit->second.mPosStatics.Empty())
777  if(!lit->second.mNegStatics.Empty())
778  IfFalse(TargetExpression(baddr));
779  eit=lit->second.mNegStatics.Begin();
780  for(;eit!=lit->second.mNegStatics.End();++eit) {
781  Comment("negative value: trigger init event [" + EventName(*eit) + "]");
782  EventSetInsert(AA("pending_events"),*eit);
783  }
784  if(!lit->second.mNegStatics.Empty())
785  IfEnd();
786  }
787  IfEnd();
788  LineFeed(1);
789  Comment("normal operation: read lines and detect edges");
790  IfTrue(IntegerIsNotEq(AA("exec_event"),-1));
791  lit=LinesBegin();
792  for(;lit!=LinesEnd();++lit) {
793  AA baddr = AA("line_level").Sub(lit->second.mBitAddress);
794  Comment("read line [" + lit->second.mAddress + "]");
795  BooleanAssign(AA("aux_edge"),ReadInputLine(lit->second.mAddress));
796  IfTrue(BooleanIsNotEq(AA("aux_edge"),baddr));
797  if(!lit->second.mPosEvents.Empty()) {
798  IfTrue(TargetExpression(AA("aux_edge")));
799  eit=lit->second.mPosEvents.Begin();
800  for(;eit!=lit->second.mPosEvents.End();++eit) {
801  Comment("positive edge: trigger input event [" + EventName(*eit) + "]");
802  EventSetInsert(AA("pending_events"),*eit);
803  IntegerAssign(AA("sched_event"),0);
804  }
805  IfEnd();
806  }
807  if(!lit->second.mNegEvents.Empty()) {
808  IfTrue(TargetExpression(baddr));
809  eit=lit->second.mNegEvents.Begin();
810  for(;eit!=lit->second.mNegEvents.End();++eit) {
811  Comment("negative edge trigger input event [" + EventName(*eit) + "]");
812  EventSetInsert(AA("pending_events"),*eit);
813  IntegerAssign(AA("sched_event"),0);
814  }
815  IfEnd();
816  }
817  BooleanAssign(baddr,TargetExpression(AA("aux_edge")));
818  IfEnd();
819  }
820  IfEnd();
821  LineFeed(1);
822  }
823  // detect flags
824  if(FlagsBegin()!=FlagsEnd()) {
825  //Comment("scanning flags");
826  fit=FlagsBegin();
827  for(;fit!=FlagsEnd();++fit) {
828  Comment("testing flag [" + fit->second.mAddress + "]");
829  IfTrue(InputExpression(fit->second.mAddress));
830  eit=fit->second.mEvents.Begin();
831  for(;eit!=fit->second.mEvents.End();++eit) {
832  Comment("trigger input event [" + EventName(*eit) + "]");
833  EventSetInsert(AA("pending_events"),*eit);
834  IntegerAssign(AA("sched_event"),0);
835  }
836  IfEnd();
837  }
838  LineFeed(1);
839  }
840  LineFeed(2);
841 }
842 
843 
844 // code blocks: sense timer elapse
846  // skip this section
847  if(TimersBegin()==TimersEnd()) return;
848  // say hello
849  Comment("************************************************");
850  Comment("* sense timer elapse *");
851  LineFeed(1);
852  // loop all timer definitions
853  TimerIterator tit= TimersBegin();
854  for(;tit!=TimersEnd();++tit) {
855  IfTrue(TimerIsElapsed(AA(tit->second.mAddress)));
856  TimerStop(AA(tit->second.mAddress));
857  EventSetInsert(AA("pending_events"),EventIndex(tit->second.mElapseEvent));
858  IntegerAssign(AA("sched_event"),0);
859  IfEnd();
860  }
861  LineFeed(1+2);
862 }
863 
864 
865 // code blocks: loop enabled events
867  if(! (mLoopEnabledOutputs || mLoopPendingInputs)) return;
868  Comment("************************************************");
869  Comment("* event execution loop *");
870  LineFeed(1);
871  Comment("clear status to waiting");
872  IntegerAssign(AA("status"),0);
873  Comment("clear event report");
874  IntegerAssign(AA("recent_event"),0);
875  Comment("set entry flag");
876  BooleanAssign(AA("first_loop"),true);
877  LoopBegin();
878  IndentDec();
879  LineFeed(1+2);
880 }
881 
882 
883 // code blocks: enabled events
885  Comment("************************************************");
886  Comment("* update enabled events after execution *");
887  LineFeed(1);
888  // doit: set up enabled events
889  Comment("if event was executed (and on initialisation)");
890  IfTrue(IntegerIsNotEq(AA("exec_event"),0));
891  Comment("set all to enabled");
892  EventSetFull(AA("enabled_events"));
893  LineFeed(1);
894  // for each generator
895  for(Idx gid=0; gid< Size(); gid++) {
896  Comment("restricting enabled events by [" + At(gid).Name() + "]");
897  AA statevar;
898  if(mArrayForState)
899  statevar=IntarrayAccess(AA("parallel_state"), gid);
900  else
901  statevar= AA("parallel_state").Sub(gid);
902  SwitchBegin(statevar);
903  // cases for each state
904  StateSet::Iterator sit;
905  for(sit=At(gid).StatesBegin(); sit!=At(gid).StatesEnd(); sit++) {
906  EventSet disset= At(gid).Alphabet();
907  disset.EraseSet(At(gid).ActiveEventSet(*sit));
908  if(disset.Empty()) continue;
909  SwitchCase(statevar,*sit);
910  EventSetErase(AA("enabled_events"),disset);
911  SwitchBreak();
912  }
913  SwitchEnd();
914  LineFeed(1);
915  } // end: for each generator
916  Comment("dispose event");
917  IntegerAssign(AA("exec_event"),0);
918  IntegerAssign(AA("sched_event"),0);
919  IfEnd();
920  LineFeed(1+2);
921 }
922 
923 
924 // code blocks: enabled events
927  FCG_ERR("CodePrimitives::UpdateEnabledByInterpreter(): vector representation not available");
928  Comment("************************************************");
929  Comment("* update enabled events after execution *");
930  LineFeed(1);
931  // doit: set up enabled events
932  Comment("if event was executed (and on init)");
933  IfTrue(IntegerIsNotEq(AA("exec_event"),0));
934  LineFeed(1);
935  // special case: only one generator
936  if(Size()==1) {
937  EventSet empty;
938  Comment("setup enabled events by [" + At(0).Name() + "]");
939  AA statevar;
940  if(mArrayForState)
941  statevar=IntarrayAccess(AA("parallel_state"),0);
942  else
943  statevar= AA("parallel_state").Sub(0);
944  AA gentrans= AA("generator_transitions").Sub(0);
945  AA genstates= AA("generator_states").Sub(0);
946  EventSetAssign(AA("enabled_events"),empty);
948  IntegerAssign(AA("aux_parsetrans"),TargetExpression(statevar));
949  } else {
950  IntegerAssign(AA("aux_parsetrans"),TargetExpression(CintarrayAccess(genstates,statevar)));
951  }
952  LoopBegin();
953  IntegerAssign(AA("aux_parseevent"),TargetExpression(CintarrayAccess(gentrans,AA("aux_parsetrans"))));
954  LoopBreak(IntegerIsEq(AA("aux_parseevent"),0));
955  EventSetInsert(AA("enabled_events"),AA("aux_parseevent"),At(0).Alphabet());
956  IntegerIncrement(AA("aux_parsetrans"),2);
957  LoopEnd();
958  }
959  // general case
960  if(Size()>1) {
961  Comment("set all to enabled");
962  //EventSetFull(AA("enabled_events"));
963  EventSetAssign(AA("enabled_events"),mUsedEvents);
964  LineFeed(1);
965  // for each generator
966  for(Idx gid=0; gid< Size(); gid++) {
967  Comment("setup enabled events by [" + At(gid).Name() + "]");
968  AA statevar;
969  if(mArrayForState)
970  statevar=IntarrayAccess(AA("parallel_state"), gid);
971  else
972  statevar= AA("parallel_state").Sub(gid);
973  AA gentrans= AA("generator_transitions").Sub(gid);
974  AA genstates= AA("generator_states").Sub(gid);
975  EventSetAssign(AA("aux_locenabled"),Alphabet()- At(gid).Alphabet());
976  if(mUsingVectorAddressStates[gid]) {
977  IntegerAssign(AA("aux_parsetrans"),TargetExpression(statevar));
978  } else {
979  IntegerAssign(AA("aux_parsetrans"),TargetExpression(CintarrayAccess(genstates,statevar)));
980  }
981  LoopBegin();
982  IntegerAssign(AA("aux_parseevent"),TargetExpression(CintarrayAccess(gentrans,AA("aux_parsetrans"))));
983  LoopBreak(IntegerIsEq(AA("aux_parseevent"),0));
984  EventSetInsert(AA("aux_locenabled"),AA("aux_parseevent"),At(gid).Alphabet());
985  IntegerIncrement(AA("aux_parsetrans"),2);
986  LoopEnd();
987  Comment("restrict enabled events");
988  EventSetRestrict(AA("enabled_events"),AA("aux_locenabled"));
989  LineFeed(1);
990  } // end: for each generator
991  }
992  Comment("dispose event");
993  IntegerAssign(AA("exec_event"),0);
994  IntegerAssign(AA("sched_event"),0);
995  IfEnd();
996  LineFeed(1+2);
997 }
998 
999 // wrapper
1003  else
1005 }
1006 
1007 
1008 // code blocks: enabled events
1010  Comment("************************************************");
1011  Comment("* schedule next event to execute *");
1012  LineFeed(1);
1013  IfTrue(IntegerIsEq(AA("sched_event"),0));
1014  LineFeed(1);
1015  Comment("setup candidate set to \"pending or internal\"");
1016  EventSetUnion(AA("aux_executables"),AA("pending_events"),mInternalEvents + mOutputEvents);
1017  Comment("restrict candidate set by \"enabled\"");
1018  EventSetRestrict(AA("aux_executables"),AA("enabled_events"));
1019  LineFeed(1);
1020  Comment("find highest priority event (lowest bitaddress)");
1021  EventSetFindHighestPriority(AA("aux_executables"),AA("sched_event"));
1022  LineFeed(1);
1023  Comment("remove scheduled event from pending events");
1024  IfTrue(IntegerIsGreater(AA("sched_event"),0));
1025  EventSetErase(AA("pending_events"),AA("sched_event"));
1026  IfEnd();
1027  LineFeed(1);
1028  Comment("detect sync error");
1029  IfTrue(IntegerIsEq(AA("sched_event"),0));
1030  EventSetIsNotEmpty(AA("pending_events"),AA("aux_wordret"));
1031  IfTrue(WordIsNotEq(AA("aux_wordret"),0));
1032  WordOr(AA("status"),WordConstant(0x02));
1033  IfEnd();
1034  IfEnd();
1035  LineFeed(1);
1037  Comment("cancel pending events if no event could be scheduled ");
1038  IfTrue(IntegerIsEq(AA("sched_event"),0));
1039  EventSetClear(AA("pending_events"));
1040  IfEnd();
1041  }
1042  LineFeed(1);
1043  IfEnd();
1044  LineFeed(1+2);
1045 }
1046 
1047 
1048 // code blocks: break loop
1050  if(! (mLoopEnabledOutputs || mLoopPendingInputs)) return;
1051  Comment("************************************************");
1052  Comment("* break execution loop *");
1053  LineFeed(1);
1054  LoopBreak(IntegerIsEq(AA("sched_event"),0));
1055  Idx max=mLastInputEvent+1;
1057  if(max<mUsedEvents.Size()) {
1058  IfFalse(TargetExpression(AA("first_loop")));
1059  LoopBreak(IntegerIsGreater(AA("sched_event"),max));
1060  IfEnd();
1061  }
1062  BooleanAssign(AA("first_loop"),false);
1063  LineFeed(1+2);
1064 }
1065 
1066 // execution hooks (dummy)
1068  if((mEventExecutionHook!="") || (mStateUpdateHook!=""))
1069  FCG_ERR("CodePrimitives::InsertExecHooks(): no hooks supported by target platform");
1070 }
1071 
1072 
1073 // code blocks: execute event
1075  Comment("************************************************");
1076  Comment("* execute scheduled event *");
1077  LineFeed(1);
1078  IfTrue(IntegerIsNotEq(AA("sched_event"),0));
1079  LineFeed(1);
1080  IntegerAssign(AA("exec_event"),TargetExpression(AA("sched_event")));
1081  IntegerAssign(AA("sched_event"),0);
1082  WordOr(AA("status"),WordConstant(0x01));
1083  LineFeed(1);
1084  for(Idx gid=0; gid< Size(); gid++) {
1085  Comment("execute event for [" + At(gid).Name() + "]");
1086  // loop states
1087  AA statevar;
1088  if(mArrayForState)
1089  statevar=IntarrayAccess(AA("parallel_state"), gid);
1090  else
1091  statevar= AA("parallel_state").Sub(gid);
1092  SwitchBegin(statevar);
1093  StateSet::Iterator sit;
1094  for(sit=At(gid).StatesBegin(); sit!=At(gid).StatesEnd(); sit++) {
1095  // cases for each state
1096  SwitchCase(statevar,*sit);
1097  // consolidate sub-cases aka same target state for multiple events
1098  std::map< int , int > casedata;
1099  std::set< std::set< int > > casesets;
1100  TransSet::Iterator tit;
1101  for(tit=At(gid).TransRelBegin(*sit); tit!=At(gid).TransRelEnd(*sit); tit++)
1102  casedata[EventTargetIdx(tit->Ev)]= tit->X2;
1103  ConsolidateCaseSets<int>(casedata,casesets);
1104  // loop transitions
1105  SwitchBegin(AA("exec_event"));
1106  std::set< std::set<int> >::iterator cit=casesets.begin();
1107  for(; cit!=casesets.end(); ++cit) {
1108  SwitchCases(AA("exec_event"),*cit);
1109  IntegerAssign(statevar,casedata[*cit->begin()]);
1110  SwitchBreak();
1111  }
1112  SwitchEnd();
1113  SwitchBreak();
1114  }
1115  SwitchEnd();
1116  LineFeed(1);
1117  } // end for each generator
1118  // record
1119  Comment("record");
1120  IntegerAssign(AA("recent_event"),TargetExpression(AA("exec_event")));
1121  // call hooks
1122  InsertExecHooks();
1123  // done
1124  IfEnd();
1125  LineFeed(1+2);
1126 }
1127 
1128 // code blocks: execute event
1130  Comment("************************************************");
1131  Comment("* execute scheduled event *");
1132  LineFeed(1);
1133  if(!mArrayForTransitions) {
1134  FCG_ERR("CodePrimitives::ExecuteByInterpreter(): vector representation not available");
1135  }
1136  // execute by array interpreter
1137  IfTrue(IntegerIsNotEq(AA("sched_event"),0));
1138  LineFeed(1);
1139  IntegerAssign(AA("exec_event"),TargetExpression(AA("sched_event")));
1140  IntegerAssign(AA("sched_event"),0);
1141  WordOr(AA("status"),WordConstant(0x01));
1142  LineFeed(1);
1143  for(Idx gid=0; gid< Size(); gid++) {
1144  Comment("execute event for [" + At(gid).Name() + "]");
1145  // vector to find event
1146  AA statevar;
1147  if(mArrayForState)
1148  statevar=IntarrayAccess(AA("parallel_state"), gid);
1149  else
1150  statevar= AA("parallel_state").Sub(gid);
1151  AA gentrans= AA("generator_transitions").Sub(gid);
1152  AA genstates= AA("generator_states").Sub(gid);
1153 
1154  if(mUsingVectorAddressStates[gid]) {
1155  IntegerAssign(AA("aux_parsetrans"),TargetExpression(statevar));
1156  } else {
1157  IntegerAssign(AA("aux_parsetrans"),TargetExpression(CintarrayAccess(genstates,statevar)));
1158  }
1159  LoopBegin();
1160  IntegerAssign(AA("aux_parseevent"),TargetExpression(CintarrayAccess(gentrans,AA("aux_parsetrans"))));
1161  LoopBreak(IntegerIsEq(AA("aux_parseevent"),TargetExpression(AA("exec_event"))));
1162  LoopBreak(IntegerIsEq(AA("aux_parseevent"),0));
1163  IntegerIncrement(AA("aux_parsetrans"),2);
1164  LoopEnd();
1165  IfTrue(IntegerIsGreater(AA("aux_parseevent"),0));
1166  IntegerIncrement(AA("aux_parsetrans"));
1167  IntegerAssign(statevar,TargetExpression(CintarrayAccess(gentrans,AA("aux_parsetrans"))));
1168  IfEnd();
1169  LineFeed(1);
1170  } // end for each generator
1171  // record
1172  Comment("record");
1173  IntegerAssign(AA("recent_event"),TargetExpression(AA("exec_event")));
1174  // call hooks
1175  InsertExecHooks();
1176  // done
1177  IfEnd();
1178  LineFeed(1+2);
1179 }
1180 
1181 // wrapper
1185  else
1187 }
1188 
1189 // code blocks: excute timers
1191  //skip this section
1192  if(TimerActionsBegin()==TimerActionsEnd()) return;
1193  Comment("************************************************");
1194  Comment("* operate timers *");
1195  LineFeed(1);
1196  // consolidate cases aka same timer actions for multiple event
1197  std::map< int , TimerAction> casedata;
1198  std::set< std::set< int > > casesets;
1199  for(int tev=1; tev<=EventBitMaskSize(); ++tev) {
1200  // test for valid record, i.e., whether switch case exists
1201  std::string ev=EventName(EventFaudesIdx(tev));
1202  TimerActionIterator eit= mTimerActions.find(ev);
1203  if(eit==mTimerActions.end()) continue;
1204  // record
1205  casedata[tev]= eit->second;
1206  }
1207  ConsolidateCaseSets<TimerAction>(casedata,casesets);
1208  // if an event was executed
1209  IfTrue(IntegerIsGreater(AA("exec_event"),0));
1210  // switch events
1211  SwitchBegin(AA("exec_event"));
1212  // loop over merged switch cases
1213  std::set< std::set< int > >::iterator cit;
1214  for(cit=casesets.begin(); cit!=casesets.end(); ++cit) {
1215  SwitchCases(AA("exec_event"),*cit);
1216  TimerAction tac = casedata[*cit->begin()];
1217  std::set< std::string >::iterator ait;
1218  ait = tac.mTimerStops.begin();
1219  for(; ait != tac.mTimerStops.end(); ++ait) {
1220  TimerStop(AA(*ait));
1221  }
1222  ait = tac.mTimerResets.begin();
1223  for(; ait != tac.mTimerResets.end(); ++ait) {
1224  TimerIterator tit = mTimers.find(*ait);
1225  if(tit==mTimers.end()) {
1226  FCG_ERR("CodePrimitives: internal error on timer records -- sorry");
1227  }
1228  TimerReset(AA(*ait),tit->second.mInitialValue);
1229  }
1230  ait = tac.mTimerStarts.begin();
1231  for(; ait != tac.mTimerStarts.end(); ++ait) {
1232  TimerStart(AA(*ait));
1233  }
1234  SwitchBreak();
1235  }
1236  SwitchEnd();
1237  IfEnd();
1238  LineFeed(1+2);
1239 }
1240 
1241 
1242 // code blocks: execute outputs
1244  Comment("************************************************");
1245  Comment("* operate outputs *");
1246  LineFeed(1);
1247  // test whether exec is an output
1248  IfTrue(IntegerIsGreater(AA("exec_event"),mLastInputEvent+1));
1249  if(mLastOutputEvent+1< (int) mUsedEvents.Size())
1250  IfTrue(IntegerIsLess(AA("exec_event"),mLastOutputEvent+2));
1251  SwitchBegin(AA("exec_event"));
1252  for(EventSet::Iterator eit=mOutputEvents.Begin(); eit!=mOutputEvents.End(); eit++) {
1253  const std::vector<AttributeCodeGeneratorEvent::OutputAction>& actions = mAlphabet.Attribute(*eit).mActions;
1254  if(actions.size()==0) continue;
1255  SwitchCase(AA("exec_event"),EventTargetIdx(*eit));
1256  Comment("outputs for [" + EventName(*eit) + "]");
1257  for(size_t i=0; i<actions.size(); i++) {
1258  if(actions[i].mSet) RunActionSet(actions[i].mAddress);
1259  if(actions[i].mClr) RunActionClr(actions[i].mAddress);
1260  if(actions[i].mExe) RunActionExe(AX(actions[i].mAddress));
1261  }
1262  SwitchBreak();
1263  }
1264  SwitchEnd();
1265  if(mLastOutputEvent+1< (int) mUsedEvents.Size())
1266  IfEnd();
1267  IfEnd();
1268  LineFeed(1+2);
1269 }
1270 
1271 
1272 // code blocks: loop enabled outputs
1274  if(! (mLoopEnabledOutputs || mLoopPendingInputs)) return;
1275  Comment("************************************************");
1276  Comment("* end execution loop *");
1277  LineFeed(1);
1278  IndentInc();
1279  LoopEnd();
1280  LineFeed(1+2);
1281 }
1282 
1283 
1284 // code blocks: literal append from configuration
1286  if(mLiteralAppend.size()==0) return;
1287  Comment("************************************************");
1288  Comment("* append code snippet from configuration *");
1289  LineFeed(2);
1290  Output() << mLiteralAppend;
1291  LineFeed(2+2);
1292 }
1293 
1294 
1295 // DoGenerate()
1297  FD_DCG("CodePrimitives(" << this << ")::DoGenerateDeclarations()");
1298  Comment("************************************************");
1299  Comment("* declaration of variables and constants *");
1300  LineFeed(1);
1301  DeclareStatus();
1302  DeclareReset();
1306  DeclareLoopState();
1307  DeclareTimers();
1308  DeclareAux();
1313 }
1314 
1315 // DoGenerateResetCode()
1317  FD_DCG("CodePrimitives(" << this << ")::DoGenerateResetCode()");
1318  Comment("************************************************");
1319  Comment("* executor core cyclic code: reset/initialise *");
1320  Comment("************************************************");
1321  LineFeed(1+1);
1322  ResetState();
1323  LineFeed(1+1);
1324  ResetReturn();
1325 }
1326 
1327 // DoGenerateCyclicCode()
1329  FD_DCG("CodePrimitives(" << this << ")::DoGenerateCyclicCode()");
1330  Comment("************************************************");
1331  Comment("* executor core cyclic code: begin *");
1332  Comment("************************************************");
1333  LineFeed(1+2);
1334  SenseInputs();
1335  SenseTimerElapse();
1337  UpdateEnabled();
1338  ScheduleEvent();
1340  ExecuteEvent();
1341  OperateTimers();
1342  OperateOutputs();
1343  EndExecutionLoop();
1344  LineFeed(1);
1345  Comment("************************************************");
1346  Comment("* executor core cyclic code: end *");
1347  Comment("************************************************");
1348 }
1349 
1350 // DoGenerate()
1352  // clear my data
1353  mBitarrays.clear();
1354  // generate my modules
1355  LiteralPrepend();
1357  LineFeed(2);
1359  LineFeed(2+1);
1360  LiteralAppend();
1361 }
1362 
1363 
1364 
1365 /*
1366 ******************************************************************
1367 ******************************************************************
1368 ******************************************************************
1369 
1370 CodePrimitives implementation --- generate atomic snippets
1371 
1372 ******************************************************************
1373 ******************************************************************
1374 ******************************************************************
1375 */
1376 
1377 // cosmetics (base only records the text, need to rimplement in derived classes
1378 void CodePrimitives::Comment(const std::string& text) {
1379  CodeGenerator::Comment(text);
1380 }
1381 
1382 // declaration template (optional)
1383 void CodePrimitives::VariableDeclare(const std::string& laddr, const std::string& ltype) {
1384  (void) laddr;
1385  (void) ltype;
1386  FCG_ERR("CodePrimitives::VariableDeclare(): not implemented");
1387 }
1388 
1389 // declaration template (optional)
1390 void CodePrimitives::VariableDeclare(const std::string& laddr, const std::string& ltype, const std::string& lval) {
1391  (void) laddr;
1392  (void) ltype;
1393  (void) lval;
1394  FCG_ERR("CodePrimitives::VariableDeclare(): not implemented");
1395 }
1396 
1397 // integer maths
1398 void CodePrimitives::IntegerDecrement(const AA& address, int val) {
1399  IntegerIncrement(address,-val);
1400 }
1401 
1402 // integer maths
1403 CodePrimitives::AX CodePrimitives::IntegerQuotient(const AX& expression, int val) {
1404  (void) expression;
1405  (void) val;
1406  FCG_ERR("CodePrimitives::Integer(): maths not available");
1407  return AX();
1408  }
1409 CodePrimitives::AX CodePrimitives::IntegerRemainder(const AX& expression, int val) {
1410  (void) expression;
1411  (void) val;
1412  FCG_ERR("CodePrimitives::Integer(): maths not available");
1413  return AX();
1414 }
1415 CodePrimitives::AX CodePrimitives::IntegerBitmask(const AX& expression) {
1416  (void) expression;
1417  FCG_ERR("CodePrimitives::Integer(): maths not available");
1418  return AX();
1419 }
1420 bool CodePrimitives::HasIntmaths(void) {
1421  return false;
1422 }
1423 CodePrimitives::AX CodePrimitives::IntegerIsEq(const AA& address, int val) {
1424  (void) address;
1425  (void) val;
1426  FCG_ERR("CodePrimitives::Conditionals(): construct not available");
1427  return AX();
1428 }
1429 CodePrimitives::AX CodePrimitives::IntegerIsEq(const AA& address, const AX& expression) {
1430  (void) address;
1431  (void) expression;
1432  FCG_ERR("CodePrimitives::Conditionals(): construct not available");
1433  return AX();
1434 }
1435 CodePrimitives::AX CodePrimitives::IntegerIsNotEq(const AA& address, int val) {
1436  (void) address;
1437  (void) val;
1438  FCG_ERR("CodePrimitives::Conditionals(): construct not available");
1439  return AX();
1440 }
1441 CodePrimitives::AX CodePrimitives::IntegerIsNotEq(const AA& address, const AX& expression) {
1442  (void) address;
1443  (void) expression;
1444  FCG_ERR("CodePrimitives::Conditionals(): construct not available");
1445  return AX();
1446 }
1447 CodePrimitives::AX CodePrimitives::IntegerIsGreater(const AA& address, int val) {
1448  (void) address;
1449  (void) val;
1450  FCG_ERR("CodePrimitives::Conditionals(): construct not available");
1451  return AX();
1452 }
1453 CodePrimitives::AX CodePrimitives::IntegerIsLess(const AA& address, int val) {
1454  (void) address;
1455  (void) val;
1456  FCG_ERR("CodePrimitives::Conditionals(): construct not available");
1457  return AX();
1458 }
1459 
1460 
1461 // word-of-bits (optional)
1462 void CodePrimitives::WordDeclare(const AA& address) {
1463  (void) address;
1464  FCG_ERR("CodePrimitives::Word(): word-of-bits type not available");
1465 }
1466 void CodePrimitives::WordDeclare(const AA& address, word_t val) {
1467  (void) address;
1468  (void) val;
1469  FCG_ERR("CodePrimitives::Word(): word-of-bits type not available");
1470 }
1471 void CodePrimitives::WordAssign(const AA& address, word_t val) {
1472  (void) address;
1473  (void) val;
1474  FCG_ERR("CodePrimitives::Word(): word-of-bits type not available");
1475 }
1476 void CodePrimitives::WordAssign(const AA& address, const AX& expression) {
1477  (void) address;
1478  (void) expression;
1479  FCG_ERR("CodePrimitives::Word(): word-of-bits type not available");
1480 }
1481 void CodePrimitives::WordOr(const AA& address, word_t val) {
1482  (void) address;
1483  (void) val;
1484  FCG_ERR("CodePrimitives::Word(): word-of-bits type not available");
1485 }
1486 void CodePrimitives::WordOr(const AA& address, const AX& expression) {
1487  (void) address;
1488  (void) expression;
1489  FCG_ERR("CodePrimitives::Word(): word-of-bits type not available");
1490 }
1491 void CodePrimitives::WordOr(const AA& address, const AA& op1, const AA& op2) {
1492  (void) address;
1493  (void) op1;
1494  (void) op2;
1495  FCG_ERR("CodePrimitives::Word(): word-of-bits type not available");
1496 }
1497 void CodePrimitives::WordOr(const AA& address, const AA& op1, word_t op2) {
1498  (void) address;
1499  (void) op1;
1500  (void) op2;
1501  FCG_ERR("CodePrimitives::Word(): word-of-bits type not available");
1502 }
1503 void CodePrimitives::WordAnd(const AA& address, word_t val) {
1504  (void) address;
1505  (void) val;
1506  FCG_ERR("CodePrimitives::Word(): word-of-bits type not available");
1507 }
1508 void CodePrimitives::WordAnd(const AA& address, const AX& expression) {
1509  (void) address;
1510  (void) expression;
1511  FCG_ERR("CodePrimitives::Word(): word-of-bits type not available");
1512 }
1513 void CodePrimitives::WordAnd(const AA& address, const AA& op1, const AA& op2) {
1514  (void) address;
1515  (void) op1;
1516  (void) op2;
1517  FCG_ERR("CodePrimitives::Word(): word-of-bits type not available");
1518 }
1519 void CodePrimitives::WordAnd(const AA& address, const AA& op1, word_t op2) {
1520  (void) address;
1521  (void) op1;
1522  (void) op2;
1523  FCG_ERR("CodePrimitives::Word(): word-of-bits type not available");
1524 }
1525 void CodePrimitives::WordNand(const AA& address, const AX& expression) {
1526  (void) address;
1527  (void) expression;
1528  FCG_ERR("CodePrimitives::Word(): word-of-bits type not available");
1529 }
1530 CodePrimitives::AX CodePrimitives::WordIsEq(const AA& address, word_t val) {
1531  (void) address;
1532  (void) val;
1533  FCG_ERR("CodePrimitives::Conditionals(): construct not available");
1534  return AX();
1535 }
1536 CodePrimitives::AX CodePrimitives::WordIsNotEq(const AA& address, word_t val) {
1537  (void) address;
1538  (void) val;
1539  FCG_ERR("CodePrimitives::Conditionals(): construct not available");
1540  return AX();
1541 }
1542 CodePrimitives::AX CodePrimitives::WordIsBitSet(const AA& address, int idx) {
1543  (void) address;
1544  (void) idx;
1545  FCG_ERR("CodePrimitives::Conditionals(): construct not available");
1546  return AX();
1547 }
1548 CodePrimitives::AX CodePrimitives::WordIsBitClr(const AA& address, int idx) {
1549  (void) address;
1550  (void) idx;
1551  FCG_ERR("CodePrimitives::Conditionals(): construct not available");
1552  return AX();
1553 }
1554 CodePrimitives::AX CodePrimitives::WordIsMaskSet(const AA& address, word_t idx) {
1555  (void) address;
1556  (void) idx;
1557  FCG_ERR("CodePrimitives::Conditionals(): construct not available");
1558  return AX();
1559 }
1560 CodePrimitives::AX CodePrimitives::WordConstant(word_t val) {
1561  (void) val;
1562  FCG_ERR("CodePrimitives::Word(): word-of-bits type not available");
1563  return AX();
1564 }
1565 
1566 
1567 // fallback implementation of booleans as integers
1568 void CodePrimitives::BooleanDeclare(const AA& address) {
1569  IntegerDeclare(address);
1570 }
1571 void CodePrimitives::BooleanDeclare(const AA& address, int val) {
1572  IntegerDeclare(address,val ? 1 : 0);
1573 }
1574 void CodePrimitives::BooleanAssign(const AA& address, const AX& expression) {
1575  IntegerAssign(address,expression);
1576 }
1577 void CodePrimitives::BooleanAssign(const AA& address, int val) {
1578  IntegerAssign(address, val ? 1 : 0);
1579 }
1580 CodePrimitives::AX CodePrimitives::BooleanIsEq(const AA& op1, const AA& op2) {
1581  return IntegerIsEq(op1,TargetExpression(op2));
1582 }
1583 CodePrimitives::AX CodePrimitives::BooleanIsNotEq(const AA& op1, const AA& op2) {
1584  return IntegerIsNotEq(op1,TargetExpression(op2));
1585 }
1586 
1587 
1591 // default const-int-array: not supported
1592 void CodePrimitives::CintarrayDeclare(const AA& address, int offset, const std::vector<int>& val) {
1593  (void) address;
1594  (void) val;
1595  (void) offset;
1596  FCG_ERR("CodePrimitives::Cintarray(): constant-int-arrays not defined");
1597 };
1598 CodePrimitives::AA CodePrimitives::CintarrayAccess(const AA& address, int index) {
1599  (void) address;
1600  (void) index;
1601  FCG_ERR("CodePrimitives::Cintarray(): constant-int-arrays not defined");
1602  return AA();
1603 };
1604 CodePrimitives::AA CodePrimitives::CintarrayAccess(const AA& address, const AA& indexaddr){
1605  (void) address;
1606  (void) indexaddr;
1607  FCG_ERR("CodePrimitives::Cintarray(): constant-int-arrays not defined");
1608  return AA();
1609 };
1610 bool CodePrimitives::HasCintarray(void) {
1611  return false;
1612 };
1613 
1614 // default const-word-array: not supported
1615 void CodePrimitives::CwordarrayDeclare(const AA& address, int offset, const std::vector<word_t>& val) {
1616  (void) address;
1617  (void) offset;
1618  (void) val;
1619  FCG_ERR("CodePrimitives::Cwordarray(): constant-word-arrays not defined");
1620 };
1621 CodePrimitives::AA CodePrimitives::CwordarrayAccess(const AA& address, int index) {
1622  (void) address;
1623  (void) index;
1624  FCG_ERR("CodePrimitives::Cwordarray(): constant-word-arrays not defined");
1625  return AA();
1626 };
1627 CodePrimitives::AA CodePrimitives::CwordarrayAccess(const AA& address, const AA& indexaddr){
1628  (void) address;
1629  (void) indexaddr;
1630  FCG_ERR("CodePrimitives::Cwordarray(): constant-word-arrays not defined");
1631  return AA();
1632 };
1633 bool CodePrimitives::HasCwordarray(void) {
1634  return false;
1635 };
1636 
1637 
1638 // default word-array: not supported
1639 void CodePrimitives::WordarrayDeclare(const AA& address, int offset, int len) {
1640  (void) address;
1641  (void) offset;
1642  (void) len;
1643  FCG_ERR("CodePrimitives::Wordarray(): word-arrays not available");
1644 };
1645 void CodePrimitives::WordarrayDeclare(const AA& address, int offset, const std::vector<word_t>& val) {
1646  (void) address;
1647  (void) offset;
1648  (void) val;
1649  FCG_ERR("CodePrimitives::Wordarray(): word-arrays not available");
1650 };
1651 CodePrimitives::AA CodePrimitives::WordarrayAccess(const AA& address, int index) {
1652  (void) address;
1653  (void) index;
1654  FCG_ERR("CodePrimitives::Wordarray(): word-arrays not available");
1655  return AA();
1656 };
1657 CodePrimitives::AA CodePrimitives::WordarrayAccess(const AA& address, const AA& indexaddr){
1658  (void) address;
1659  (void) indexaddr;
1660  FCG_ERR("CodePrimitives::Wordarray(): word-arrays not available");
1661  return AA();
1662 };
1663 bool CodePrimitives::HasWordarray(void) {
1664  return false;
1665 };
1666 
1667 
1669 void CodePrimitives::IntarrayDeclare(const AA& address, int offset, int len) {
1670  (void) address;
1671  (void) offset;
1672  (void) len;
1673  FCG_ERR("CodePrimitives::Intarray(): int-arrays not available");
1674 };
1675 void CodePrimitives::IntarrayDeclare(const AA& address, int offset, const std::vector<int>& val) {
1676  (void) address;
1677  (void) offset;
1678  (void) val;
1679  FCG_ERR("CodePrimitives::Intarray(): int-arrays not available");
1680 };
1682  (void) address;
1683  (void) index;
1684  FCG_ERR("CodePrimitives::Intarray(): int-arrays not available");
1685  return AA();
1686 };
1687 CodePrimitives::AA CodePrimitives::IntarrayAccess(const AA& address, const AA& indexaddr){
1688  (void) address;
1689  (void) indexaddr;
1690  FCG_ERR("CodePrimitives::Intarray(): int-arrays not available");
1691  return AA();
1692 };
1694  return false;
1695 };
1696 
1697 // default const-string-array: not supported
1698 CodePrimitives::AX CodePrimitives::StringConstant(const std::string &val) {
1699  (void) val;
1700  FCG_ERR("CodePrimitives::Cstrarray(): constant-str-arrays not defined");
1701  return AX();
1702 };
1703 void CodePrimitives::CstrarrayDeclare(const AA& address, int offset, const std::vector<std::string>& val) {
1704  (void) address;
1705  (void) offset;
1706  (void) val;
1707  FCG_ERR("CodePrimitives::Cstrarray(): constant-str-arrays not defined");
1708 };
1709 CodePrimitives::AA CodePrimitives::CstrarrayAccess(const AA& address, int index) {
1710  (void) address;
1711  (void) index;
1712  FCG_ERR("CodePrimitives::Cstrarray(): constant-str-arrays not defined");
1713  return AA();
1714 };
1715 CodePrimitives::AA CodePrimitives::CstrarrayAccess(const AA& address, const AA& indexaddr){
1716  (void) address;
1717  (void) indexaddr;
1718  FCG_ERR("CodePrimitives::Cstrarray(): constant-str-arrays not defined");
1719  return AA();
1720 };
1721 bool CodePrimitives::HasCstrarray(void) {
1722  return false;
1723 };
1724 
1725 
1726 // declare bit array as record of words
1727 void CodePrimitives::BitarrayDeclare(const AA& address, int blen) {
1728  // figure dimension
1729  int wlen = (blen + mWordSize - 1) / mWordSize;
1730  // declare as array or words
1731  if(mArrayForBitarray) {
1732  WordarrayDeclare(address, 0, wlen);
1733  }
1734  // declare as array separate words
1735  if(!mArrayForBitarray) {
1736  for(int i=0; i<wlen; i++) {
1737  AA baddr= address.Sub(i);
1738  WordDeclare(baddr);
1739  }
1740  }
1741  // record (dummy value)
1742  bitarray_rec newbitarray;
1743  newbitarray.blen= blen;
1744  mBitarrays[address]=newbitarray;
1745 }
1746 
1747 // declare bit array as record of words
1748 void CodePrimitives::BitarrayDeclare(const AA& address, const std::vector<bool>& val) {
1749  // figure dimension
1750  int blen = (int) val.size();
1751  int wlen = (blen + mWordSize - 1) / mWordSize;
1752  // declare as array or words
1753  if(mArrayForBitarray) {
1754  WordarrayDeclare(address, 0, WordVectorFromBitVector(val));
1755  }
1756  // declare as array separate words
1757  if(!mArrayForBitarray) {
1758  for(int i=0; i<wlen; i++) {
1759  AA baddr = address.Sub(i);
1760  WordDeclare(baddr,WordFromBitVector(val,i));
1761  }
1762  }
1763  // record
1764  bitarray_rec newbitarray;
1765  newbitarray.blen= blen;
1766  newbitarray.value= val;
1767  mBitarrays[address]=newbitarray;
1768 }
1769 
1770 // bitarray
1771 void CodePrimitives::BitarrayAssign(const AA& address, const std::vector<bool>& val) {
1772  // lookup
1773  int blen= mBitarrays[address].blen;
1774  int wlen = (blen + mWordSize - 1) / mWordSize;
1775  // loop words
1776  for(int i=0; i<wlen; ++i) {
1777  AA waddr;
1778  if(mArrayForBitarray) waddr= WordarrayAccess(address,i);
1779  else waddr = address.Sub(i);
1780  word_t wval=WordFromBitVector(val,i);
1781  WordAssign(waddr,wval);
1782  }
1783 }
1784 
1785 // bitarray
1786 void CodePrimitives::BitarrayAssign(const AA& address, const AA& otherarray) {
1787  // lookup
1788  int blen= mBitarrays[address].blen;
1789  int wlen = (blen + mWordSize - 1) / mWordSize;
1790  // must match
1791  if(blen!=mBitarrays[otherarray].blen) {
1792  FCG_ERR("CodePrimitives(): BitarrayAssign(): internal error");
1793  }
1794  // loop words
1795  for(int i=0; i<wlen; ++i) {
1796  AA waddr;
1797  if(mArrayForBitarray) waddr= WordarrayAccess(address,i);
1798  else waddr = address.Sub(i);
1799  AA oaddr;
1800  if(mArrayForBitarray) oaddr= WordarrayAccess(address,i);
1801  else oaddr = address.Sub(i);
1802  WordAssign(waddr,TargetExpression(oaddr));
1803  }
1804 }
1805 
1806 // bitarray
1807 void CodePrimitives::BitarrayClear(const AA& address){
1808  // lookup
1809  int blen= mBitarrays[address].blen;
1810  int wlen = (blen + mWordSize - 1) / mWordSize;
1811  // loop all words
1812  for(int i=0; i<wlen; i++) {
1813  AA waddr;
1814  if(mArrayForBitarray) waddr= WordarrayAccess(address,i);
1815  else waddr = address.Sub(i);
1816  WordAssign(waddr, 0x0UL);
1817  }
1818 }
1819 
1820 // bitarray
1821 void CodePrimitives::BitarrayFull(const AA& address){
1822  // lookup
1823  int blen= mBitarrays[address].blen;
1824  int wlen = (blen + mWordSize - 1) / mWordSize;
1825  int bllen = blen - (wlen-1) * mWordSize;
1826  // loop all words
1827  for(int i=0; i<wlen; i++) {
1828  AA waddr;
1829  if(mArrayForBitarray) waddr= WordarrayAccess(address,i);
1830  else waddr = address.Sub(i);
1831  word_t val= ~0x0UL;
1832  if(i==wlen-1) val= (1ULL<<bllen)-1;
1833  WordAssign(waddr, val);
1834  }
1835 }
1836 
1837 // bitarray
1838 void CodePrimitives::BitarrayOrAllWords(const AA& address, const AA& result) {
1839  // lookup
1840  int blen= mBitarrays[address].blen;
1841  int wlen = (blen + mWordSize - 1) / mWordSize;
1842  int bllen = blen - (wlen-1) * mWordSize;
1843  // one word case
1844  if(wlen==1) {
1845  AA waddr;
1846  if(mArrayForBitarray) waddr= WordarrayAccess(address,0);
1847  else waddr = address.Sub(0);
1848  WordAssign(result,TargetExpression(waddr));
1849  return;
1850  }
1851  // loop all words
1852  for(int i=0; i<wlen; i++) {
1853  AA waddr;
1854  if(mArrayForBitarray) waddr= WordarrayAccess(address,i);
1855  else waddr = address.Sub(i);
1856  if(i==wlen-1) WordAnd(waddr,WordConstant((1ULL<<bllen)-1));
1857  if(i==0) WordAssign(result,TargetExpression(waddr));
1858  if(i>0) WordOr(result,TargetExpression(waddr));
1859  }
1860 }
1861 
1862 // bitarray set by const index
1863 void CodePrimitives::BitarraySetBit(const AA& address, int index){
1864  // figure word/bit
1865  int windex=index / mWordSize;
1866  int bindex= index % mWordSize;
1867  // set
1868  AA waddr;
1869  if(mArrayForBitarray) waddr= WordarrayAccess(address,windex);
1870  else waddr = address.Sub(windex);
1871  WordOr(waddr,WordConstant( 1UL << bindex));
1872 }
1873 
1874 // bitarray set by var index
1875 void CodePrimitives::BitarraySetBit(const AA& address, const AA& indexaddr, int offset, const std::vector<bool>& hint){
1876  // lookup
1877  int blen= mBitarrays[address].blen;
1878  int wlen = (blen + mWordSize - 1) / mWordSize;
1879  bool gotaddress=false;
1880  // use precompiled masks to obtain address
1881  if(mArrayForBitmasks && (wlen > 1)) {
1882  IntegerAssign(AA("aux_bitaddr"),TargetExpression(indexaddr));
1883  IntegerDecrement(AA("aux_bitaddr"));
1884  IntegerAssign(AA("aux_wordaddr"),TargetExpression(CintarrayAccess(AA("wordaddr_vector"),AA("aux_bitaddr"))));
1885  IntegerAssign(AA("aux_bitmask"),TargetExpression(CwordarrayAccess(AA("bitmask_vector"),AA("aux_bitaddr"))));
1886  gotaddress=true;
1887  }
1888  // compute address
1889  if((!gotaddress) && mBitAddressArithmetic && (wlen > 1)) {
1890  IntegerAssign(AA("aux_bitaddr"),TargetExpression(indexaddr));
1891  IntegerDecrement(AA("aux_bitaddr"),offset);
1892  IntegerAssign(AA("aux_wordaddr"),IntegerQuotient(TargetExpression(AA("aux_bitaddr")),mWordSize));
1893  IntegerAssign(AA("aux_bitaddr"),IntegerRemainder(TargetExpression(AA("aux_bitaddr")),mWordSize));
1894  IntegerAssign(AA("aux_bitmask"),IntegerBitmask(TargetExpression(AA("aux_bitaddr"))));
1895  gotaddress=true;
1896  }
1897  // use precompiled masks, simple case
1898  if((!gotaddress) && mArrayForBitmasks && (wlen == 1)) {
1899  IntegerAssign(AA("aux_bitaddr"),TargetExpression(indexaddr));
1900  IntegerDecrement(AA("aux_bitaddr"),offset);
1901  IntegerAssign(AA("aux_bitmask"),TargetExpression(CwordarrayAccess(AA("bitmask_vector"),AA("aux_bitaddr"))));
1902  gotaddress=true;
1903  }
1904  // compute address, simple case
1905  if((!gotaddress) && mBitAddressArithmetic && (wlen == 1)) {
1906  IntegerAssign(AA("aux_bitaddr"),TargetExpression(indexaddr));
1907  IntegerDecrement(AA("aux_bitaddr"),offset);
1908  IntegerAssign(AA("aux_wordaddr"),IntegerQuotient(TargetExpression(AA("aux_bitaddr")),mWordSize));
1909  IntegerAssign(AA("aux_bitaddr"),IntegerRemainder(TargetExpression(AA("aux_bitaddr")),mWordSize));
1910  IntegerAssign(AA("aux_bitmask"),IntegerBitmask(TargetExpression(AA("aux_bitaddr"))));
1911  gotaddress=true;
1912  }
1913  // perform with word array
1914  if(gotaddress && mArrayForBitarray) {
1915  WordOr(WordarrayAccess(address, AA("aux_wordaddr")),TargetExpression(AA("aux_bitmask")));
1916  return;
1917  }
1918  // perform by switch
1919  if(gotaddress && (wlen > 1)) {
1920  SwitchBegin(AA("aux_wordaddr"));
1921  for(int i=0; i<wlen; i++) {
1922  if(hint.size()>0)
1923  if(WordFromBitVector(hint,i)==0) continue;
1924  SwitchCase(AA("aux_wordadd"),i);
1925  AA waddr = address.Sub(i);
1926  WordOr(waddr, TargetExpression(AA("aux_bitmask")));
1927  SwitchBreak();
1928  }
1929  SwitchEnd();
1930  return;
1931  }
1932  // perform simple case
1933  if(gotaddress && (wlen == 1)) {
1934  AA waddr = address.Sub(0);
1935  WordOr(waddr, TargetExpression(AA("aux_bitmask")));
1936  return;
1937  }
1938  // fallback: switch using the provided hint
1939  SwitchBegin(indexaddr);
1940  int baddr;
1941  for(baddr=0;baddr<blen;baddr++) {
1942  if(hint.size()>0)
1943  if(!hint[baddr])
1944  continue;
1945  SwitchCase(indexaddr,baddr+offset);
1946  BitarraySetBit(address,baddr);
1947  SwitchBreak();
1948  }
1949  SwitchEnd();
1950 }
1951 
1952 // bitarray test set by var index
1953 void CodePrimitives::BitarrayIsBitSet(const AA& address, const AA& indexaddr, const AA& result, int offset, const std::vector<bool>& hint){
1954  // lookup
1955  int blen= mBitarrays[address].blen;
1956  int wlen = (blen + mWordSize - 1) / mWordSize;
1957  bool gotaddress=false;
1958  // use precompiled masks to obtain address
1959  if(mArrayForBitmasks && (wlen > 1)) {
1960  IntegerAssign(AA("aux_bitaddr"),TargetExpression(indexaddr));
1961  IntegerDecrement(AA("aux_bitaddr"),offset);
1962  IntegerAssign(AA("aux_wordaddr"),TargetExpression(CintarrayAccess(AA("wordaddr_vector"),AA("aux_bitaddr"))));
1963  IntegerAssign(AA("aux_bitmask"),TargetExpression(CwordarrayAccess(AA("bitmask_vector"),AA("aux_bitaddr"))));
1964  gotaddress=true;
1965  }
1966  // compute address
1967  if((!gotaddress) && mBitAddressArithmetic && (wlen > 1)) {
1968  IntegerAssign(AA("aux_bitaddr"),TargetExpression(indexaddr));
1969  IntegerDecrement(AA("aux_bitaddr"),offset);
1970  IntegerAssign(AA("aux_wordaddr"),IntegerQuotient(TargetExpression(AA("aux_bitaddr")),mWordSize));
1971  IntegerAssign(AA("aux_bitaddr"),IntegerRemainder(TargetExpression(AA("aux_bitaddr")),mWordSize));
1972  IntegerAssign(AA("aux_bitmask"),IntegerBitmask(TargetExpression(AA("aux_bitaddr"))));
1973  gotaddress=true;
1974  }
1975  // use precompiled masks, simple case
1976  if((!gotaddress) && mArrayForBitmasks && (wlen == 1)) {
1977  IntegerAssign(AA("aux_bitaddr"),TargetExpression(indexaddr));
1978  IntegerDecrement(AA("aux_bitaddr"),offset);
1979  IntegerAssign(AA("aux_bitmask"),TargetExpression(CwordarrayAccess(AA("bitmask_vector"),AA("aux_bitaddr"))));
1980  gotaddress=true;
1981  }
1982  // compute address, simple case
1983  if((!gotaddress) && mBitAddressArithmetic && (wlen == 1)) {
1984  IntegerAssign(AA("aux_bitaddr"),TargetExpression(indexaddr));
1985  IntegerDecrement(AA("aux_bitaddr"),offset);
1986  IntegerAssign(AA("aux_wordaddr"),IntegerQuotient(TargetExpression(AA("aux_bitaddr")),mWordSize));
1987  IntegerAssign(AA("aux_bitaddr"),IntegerRemainder(TargetExpression(AA("aux_bitaddr")),mWordSize));
1988  IntegerAssign(AA("aux_bitmask"),IntegerBitmask(TargetExpression(AA("aux_bitaddr"))));
1989  gotaddress=true;
1990  }
1991  // perform with word array
1992  if(gotaddress && mArrayForBitarray) {
1993  WordAnd(result,WordarrayAccess(address, AA("aux_wordaddr")),AA("aux_bitmask"));
1994  }
1995  // perform by switch
1996  if(gotaddress && (wlen > 1)) {
1997  SwitchBegin(AA("aux_wordaddr"));
1998  for(int i=0; i<wlen; i++) {
1999  if(hint.size()>0)
2000  if(WordFromBitVector(hint,i)==0) continue;
2001  SwitchCase(AA("aux_wordadd"),i);
2002  AA waddr = address.Sub(i);
2003  WordAnd(result,waddr,AA("aux_bitmask"));
2004  SwitchBreak();
2005  }
2006  SwitchEnd();
2007  return;
2008  }
2009  // perform simple case
2010  if(gotaddress && (wlen == 1)) {
2011  AA waddr = address.Sub(0);
2012  WordAnd(result,waddr,AA("aux_bitmask"));
2013  return;
2014  }
2015  // fallback: switch not implemented
2016  FCG_ERR("CodePrimitives::Bitarray(): BitAddressArithmetic or ArrayForBitmasks required for test by variable");
2017 }
2018 
2019 // bitarray
2020 void CodePrimitives::BitarrayClrBit(const AA& address, int index){
2021  // figure word/bit
2022  int windex=index / mWordSize;
2023  int bindex= index % mWordSize;
2024  // clear
2025  AA waddr;
2026  if(mArrayForBitarray) waddr= WordarrayAccess(address,windex);
2027  else waddr = address.Sub(windex);
2028  WordNand(waddr,WordConstant( 1UL << bindex));
2029 }
2030 
2031 // bitarray clear bit by index
2032 void CodePrimitives::BitarrayClrBit(const AA& address, const AA& indexaddr, int offset, const std::vector<bool>& hint){
2033  // lookup
2034  int blen= mBitarrays[address].blen;
2035  int wlen = (blen + mWordSize - 1) / mWordSize;
2036  bool gotaddress=false;
2037  // use precompiled masks to obtain address
2038  if(mArrayForBitmasks && (wlen > 1)) {
2039  IntegerAssign(AA("aux_bitaddr"),TargetExpression(indexaddr));
2040  IntegerDecrement(AA("aux_bitaddr"),offset);
2041  IntegerAssign(AA("aux_wordaddr"),TargetExpression(CintarrayAccess(AA("wordaddr_vector"),AA("aux_bitaddr"))));
2042  IntegerAssign(AA("aux_bitmask"),TargetExpression(CwordarrayAccess(AA("bitmask_vector"),AA("aux_bitaddr"))));
2043  gotaddress=true;
2044  }
2045  // compute address
2046  if((!gotaddress) && mBitAddressArithmetic && (wlen > 1)) {
2047  IntegerAssign(AA("aux_bitaddr"),TargetExpression(indexaddr));
2048  IntegerDecrement(AA("aux_bitaddr"),offset);
2049  IntegerAssign(AA("aux_wordaddr"),IntegerQuotient(TargetExpression(AA("aux_bitaddr")),mWordSize));
2050  IntegerAssign(AA("aux_bitaddr"),IntegerRemainder(TargetExpression(AA("aux_bitaddr")),mWordSize));
2051  IntegerAssign(AA("aux_bitmask"),IntegerBitmask(TargetExpression(AA("aux_bitaddr"))));
2052  gotaddress=true;
2053  }
2054  // use precompiled masks, simple case
2055  if((!gotaddress) && mArrayForBitmasks && (wlen == 1)) {
2056  IntegerAssign(AA("aux_bitaddr"),TargetExpression(indexaddr));
2057  IntegerDecrement(AA("aux_bitaddr"),offset);
2058  IntegerAssign(AA("aux_bitmask"),TargetExpression(CwordarrayAccess(AA("bitmask_vector"),AA("aux_bitaddr"))));
2059  gotaddress=true;
2060  }
2061  // compute address, simple case
2062  if((!gotaddress) && mBitAddressArithmetic && (wlen == 1)) {
2063  IntegerAssign(AA("aux_bitaddr"),TargetExpression(indexaddr));
2064  IntegerDecrement(AA("aux_bitaddr"),offset);
2065  IntegerAssign(AA("aux_wordaddr"),IntegerQuotient(TargetExpression(AA("aux_bitaddr")),mWordSize));
2066  IntegerAssign(AA("aux_bitaddr"),IntegerRemainder(TargetExpression(AA("aux_bitaddr")),mWordSize));
2067  IntegerAssign(AA("aux_bitmask"),IntegerBitmask(TargetExpression(AA("aux_bitaddr"))));
2068  gotaddress=true;
2069  }
2070  // perform with word array
2071  if(gotaddress && mArrayForBitarray) {
2072  WordNand(WordarrayAccess(address, AA("aux_wordaddr")),TargetExpression(AA("aux_bitmask")));
2073  return;
2074  }
2075  // perform by switch
2076  if(gotaddress && (wlen > 1)) {
2077  SwitchBegin(AA("aux_wordaddr"));
2078  for(int i=0; i<wlen; i++) {
2079  if(hint.size()>0)
2080  if(WordFromBitVector(hint,i)==0) continue;
2081  SwitchCase(AA("aux_wordadd"),i);
2082  AA waddr = address.Sub(i);
2083  WordNand(waddr, TargetExpression(AA("aux_bitmask")));
2084  SwitchBreak();
2085  }
2086  SwitchEnd();
2087  return;
2088  }
2089  // perform simple case
2090  if(gotaddress && (wlen == 1)) {
2091  AA waddr = address.Sub(0);
2092  WordNand(waddr, TargetExpression(AA("aux_bitmask")));
2093  return;
2094  }
2095  // fallback: switch using the provided hint
2096  SwitchBegin(indexaddr);
2097  int baddr;
2098  for(baddr=0;baddr<blen;baddr++) {
2099  if(hint.size()>0)
2100  if(!hint[baddr])
2101  continue;
2102  SwitchCase(indexaddr,baddr+offset);
2103  BitarrayClrBit(address,baddr);
2104  SwitchBreak();
2105  }
2106  SwitchEnd();
2107 }
2108 
2109 // bitarray
2110 void CodePrimitives::BitarrayOr(const AA& address, const std::vector<bool>& val) {
2111  // lookup
2112  int blen= mBitarrays[address].blen;
2113  int wlen = (blen + mWordSize - 1) / mWordSize;
2114  // iterate words
2115  for(int w=0; w<wlen; ++w) {
2116  word_t wval=WordFromBitVector(val,w);
2117  if(wval==0) continue;
2118  AA waddr;
2119  if(mArrayForBitarray) waddr= WordarrayAccess(address,w);
2120  else waddr = address.Sub(w);
2121  WordOr(waddr,wval);
2122  }
2123 }
2124 
2125 
2126 // bitarray
2127 void CodePrimitives::BitarrayOr(const AA& address, const AA &op1, const std::vector<bool>& op2) {
2128  // lookup
2129  int blen= mBitarrays[address].blen;
2130  int wlen = (blen + mWordSize - 1) / mWordSize;
2131  // iterate words
2132  for(int w=0; w<wlen; ++w) {
2133  word_t wval=WordFromBitVector(op2,w);
2134  AA waddr;
2135  AA wop1;
2136  if(mArrayForBitarray) waddr= WordarrayAccess(address,w);
2137  else waddr = address.Sub(w);
2138  if(mArrayForBitarray) wop1= WordarrayAccess(op1,w);
2139  else wop1 = op1.Sub(w);
2140  if(wval!=0)
2141  WordOr(waddr,wop1,wval);
2142  else
2143  WordAssign(waddr,TargetExpression(wop1));
2144  }
2145 }
2146 
2147 // bitarray
2148 void CodePrimitives::BitarrayAnd(const AA& address, const std::vector<bool>& val) {
2149  // lookup
2150  int blen= mBitarrays[address].blen;
2151  int wlen = (blen + mWordSize - 1) / mWordSize;
2152  // iterate words
2153  for(int w=0; w<wlen; ++w) {
2154  word_t wval=WordFromBitVector(val,w);
2155  if(wval== (1UL << mWordSize) - 1) continue;
2156  AA waddr;
2157  if(mArrayForBitarray) waddr= WordarrayAccess(address,w);
2158  else waddr = address.Sub(w);
2159  WordAnd(waddr,wval);
2160  }
2161 }
2162 
2163 // intersect
2164 void CodePrimitives::BitarrayAnd(const AA& address, const AA& otherarray) {
2165  // lookup
2166  int blen= mBitarrays[address].blen;
2167  int wlen = (blen + mWordSize - 1) / mWordSize;
2168  // iterate words
2169  for(int w=0; w<wlen; ++w) {
2170  AA waddr;
2171  if(mArrayForBitarray) waddr= WordarrayAccess(address,w);
2172  else waddr = address.Sub(w);
2173  AA oaddr;
2174  if(mArrayForBitarray) oaddr= WordarrayAccess(otherarray,w);
2175  else oaddr = otherarray.Sub(w);
2176  WordAnd(waddr,TargetExpression(oaddr));
2177  }
2178 }
2179 
2180 // intersect
2181 void CodePrimitives::BitarrayAnd(const AA& address, const AA &op1, const std::vector<bool>& op2) {
2182  // lookup
2183  int blen= mBitarrays[address].blen;
2184  int wlen = (blen + mWordSize - 1) / mWordSize;
2185  // iterate words
2186  for(int w=0; w<wlen; ++w) {
2187  word_t wval=WordFromBitVector(op2,w);
2188  AA waddr;
2189  AA wop1;
2190  if(mArrayForBitarray) waddr= WordarrayAccess(address,w);
2191  else waddr = address.Sub(w);
2192  if(mArrayForBitarray) wop1= WordarrayAccess(op1,w);
2193  else wop1 = op1.Sub(w);
2194  if(wval!= (1UL << mWordSize) - 1)
2195  WordAnd(waddr,wop1,wval);
2196  else
2197  WordAssign(waddr,TargetExpression(wop1));
2198  }
2199 }
2200 
2201 // intersect
2202 void CodePrimitives::BitarrayAnd(const AA& address, const AA& op1, const AA& op2) {
2203  // lookup
2204  int blen= mBitarrays[address].blen;
2205  int wlen = (blen + mWordSize - 1) / mWordSize;
2206  // iterate words
2207  for(int w=0; w<wlen; ++w) {
2208  AA waddr;
2209  if(mArrayForBitarray) waddr= WordarrayAccess(address,w);
2210  else waddr = address.Sub(w);
2211  AA op1addr;
2212  if(mArrayForBitarray) op1addr= WordarrayAccess(op1,w);
2213  else op1addr = op1.Sub(w);
2214  AA op2addr;
2215  if(mArrayForBitarray) op2addr= WordarrayAccess(op2,w);
2216  else op2addr = op2.Sub(w);
2217  WordAnd(waddr,op1addr,op2addr);
2218  }
2219 }
2220 
2221 // find lowest index with bit set (result as an address)
2222 void CodePrimitives::BitarrayFindFirst(const AA& address, const AA& result, int offset) {
2223  // prepare result
2224  IntegerAssign(result,offset-1);
2225  // lookup
2226  int blen= mBitarrays[address].blen;
2227  // iterate words
2228  for(int w=0; w< (blen + mWordSize -1) / mWordSize; ++w) {
2229  AA waddr;
2230  if(mArrayForBitarray) waddr= WordarrayAccess(address,w);
2231  else waddr = address.Sub(w);
2232  int ifcnt=0;
2233  /* as of the second word we only search if nothing found so far */
2234  if(w>0) {
2235  IfTrue(IntegerIsEq(result,offset-1));
2236  ++ifcnt;
2237  }
2238  /* search the current word only if non-zero */
2239  IfTrue(WordIsNotEq(waddr,0));
2240  ++ifcnt;
2241  /* simple case: only one bit left to search */
2242  if(w*mWordSize + 1 == blen) {
2243  IntegerAssign(result,w*mWordSize+offset);
2244  for(;ifcnt>0;--ifcnt) IfEnd();
2245  continue;
2246  }
2247  /* naive approach O(mWordSize)*/
2248  if(!mBisectionForBitfind) {
2249  for(int b=0; b<mWordSize;++b) {
2250  int index=w*mWordSize + b;
2251  if(index>=blen) break;
2252  if(b==0) {
2253  IfTrue(WordIsBitSet(waddr,b));
2254  ++ifcnt;
2255  } else {
2256  IfElseIfTrue(WordIsBitSet(waddr,b));
2257  }
2258  IntegerAssign(result,index+offset);
2259  }
2260  }
2261  /* interval search O(log(mWordSize)) */
2262  if(mBisectionForBitfind) {
2263  int wsize=mWordSize;
2264  int bleft=blen-w*mWordSize;
2265  if(bleft>wsize) bleft=wsize;
2266  while(wsize/2>=bleft) wsize=wsize/2;
2267  bool hl=true;
2268  int pos=0;
2269  int size=wsize;
2270  while(size<=wsize) {
2271  /* break on out of range */
2272  if(!(pos<bleft)) break;
2273  /* figure range to process */
2274  if(hl) {
2275  /* restrict size to remaining bits */
2276  while(pos+size/2>=bleft) size=size/2;
2277  /* process bit range [pos,pos+size) */
2278  // FD_WARN("range [" << pos << ", " << pos+size << ")");
2279  }
2280  /* subdivide to process lower half */
2281  if(hl && (size>2)) {
2282  word_t ltest= (1UL << size/2) -1;
2283  ltest=ltest<<pos;
2284  IfTrue(WordIsMaskSet(waddr,ltest));
2285  ++ifcnt;
2286  size=size/2;
2287  continue;
2288  }
2289  /* resolve range of size 2 */
2290  if(hl && (size==2)) {
2291  IfTrue(WordIsMaskSet(waddr,(1UL << pos)));
2292  IntegerAssign(result, w*mWordSize + pos + offset);
2293  IfElse();
2294  IntegerAssign(result,w*mWordSize + pos + 1 + offset);
2295  IfEnd();
2296  size=2*size;
2297  hl=false;
2298  continue;
2299  }
2300  /* resolve range of size 1 */
2301  if(hl && (size==1)) {
2302  IntegerAssign(result, w*mWordSize + pos + offset);
2303  size=2*size;
2304  hl=false;
2305  continue;
2306  }
2307  /* sense lower half done, set up for for higher half */
2308  if((!hl) && ((pos % size) == 0)) {
2309  size=size/2;
2310  pos+=size;
2311  hl=true;
2312  if(pos<bleft) IfElse();
2313  continue;
2314  }
2315  /* sense higher half done, return to parent */
2316  if((!hl) && ((pos % size) != 0)) {
2317  --ifcnt;
2318  IfEnd();
2319  pos-=size/2;
2320  size=size*2;
2321  }
2322  }
2323  }
2324  /* close open ifs */
2325  for(;ifcnt>0;--ifcnt)
2326  IfEnd();
2327  } // end: loop words
2328 }
2329 
2330 
2331 // event set
2332 void CodePrimitives::EventSetDeclare(const AA& address) {
2333  BitarrayDeclare(address,EventBitMaskSize());
2334 }
2335 
2336 // event set
2337 void CodePrimitives::EventSetDeclare(const AA& address, const EventSet& evset) {
2338  std::vector<bool> evmask = EventBitMask(evset);
2339  BitarrayDeclare(address,evmask);
2340 }
2341 
2342 // event set
2343 void CodePrimitives::EventSetClear(const AA& address) {
2344  BitarrayClear(address);
2345 }
2346 
2347 // event set
2348 void CodePrimitives::EventSetFull(const AA& address) {
2349  BitarrayFull(address);
2350 }
2351 
2352 // set is empty
2353 void CodePrimitives::EventSetIsNotEmpty(const AA& address, const AA& result) {
2354  BitarrayOrAllWords(address,result);
2355 }
2356 
2357 // event insert
2358 void CodePrimitives::EventSetAssign(const AA& address, const EventSet& evset) {
2359  std::vector<bool> evmask = EventBitMask(evset);
2360  BitarrayAssign(address,evmask);
2361 }
2362 
2363 // event insert
2364 void CodePrimitives::EventSetInsert(const AA& address, const EventSet& evset) {
2365  std::vector<bool> evmask = EventBitMask(evset);
2366  BitarrayOr(address,evmask);
2367 }
2368 
2369 // event insert
2370 void CodePrimitives::EventSetInsert(const AA& address, const AA& evaddrexpr) {
2371  BitarraySetBit(address,evaddrexpr,1);
2372 };
2373 
2374 // event insert, candidats known
2375 void CodePrimitives::EventSetInsert(const AA& address, const AA& evaddrexpr, const EventSet& hint) {
2376  std::vector<bool> evmask = EventBitMask(hint);
2377  BitarraySetBit(address,evaddrexpr,1,evmask);
2378 };
2379 
2380 // event insert
2381 void CodePrimitives::EventSetInsert(const AA& address, Idx ev) {
2382  BitarraySetBit(address,EventBitAddress(ev));
2383 }
2384 
2385 // event erase
2386 void CodePrimitives::EventSetErase(const AA& address, const EventSet& evset) {
2387  std::vector<bool> evmask = EventBitMask(evset);
2388  for(size_t i=0; i<evmask.size(); i++) evmask[i]= ! evmask[i];
2389  BitarrayAnd(address,evmask);
2390 }
2391 
2392 // event erase
2393 void CodePrimitives::EventSetErase(const AA& address, Idx ev) {
2394  BitarrayClrBit(address,EventBitAddress(ev));
2395 }
2396 
2397 // event erase
2398 void CodePrimitives::EventSetErase(const AA& address, const AA& evaddr) {
2399  BitarrayClrBit(address,evaddr,1);
2400 };
2401 
2402 // event test
2403 void CodePrimitives::EventSetExists(const AA& address, const AA& evaddr, const AA& result, const EventSet& hint) {
2404  std::vector<bool> evmask = EventBitMask(hint);
2405  BitarrayIsBitSet(address,evaddr,result,1,evmask);
2406 };
2407 
2408 // event erase, candidats known
2409 void CodePrimitives::EventSetErase(const AA& address, const AA& evaddr, const EventSet& hint) {
2410  std::vector<bool> evmask = EventBitMask(hint);
2411  BitarrayClrBit(address,evaddr,1,evmask);
2412 };
2413 
2414 // event restrict
2415 void CodePrimitives::EventSetRestrict(const AA& address, const AA& otherset) {
2416  BitarrayAnd(address,otherset);
2417 }
2418 
2419 // event union
2420 void CodePrimitives::EventSetUnion(const AA& address, const AA& op1, const EventSet& op2) {
2421  std::vector<bool> evmask = EventBitMask(op2);
2422  BitarrayOr(address,op1,evmask);
2423 }
2424 
2425 // event intersection
2426 void CodePrimitives::EventSetIntersection(const AA& address, const AA& op1, const EventSet& op2) {
2427  std::vector<bool> evmask = EventBitMask(op2);
2428  BitarrayAnd(address,op1,evmask);
2429 }
2430 
2431 // event set find lowest index (i.e. max priority)
2432 void CodePrimitives::EventSetFindHighestPriority(const AA& address, const AA& result) {
2433  BitarrayFindFirst(address,result,1);
2434 }
2435 
2436 
2437 
2438 // no relevant defaults in conditionals/loops
2439 void CodePrimitives::IfTrue(const AX& expression) {
2440  (void) expression;
2441  FCG_ERR("CodePrimitives::Conditionals(): construct not available");
2442 }
2443 // no relevant defaults in conditionals/loops
2444 void CodePrimitives::IfFalse(const AX& expression) {
2445  (void) expression;
2446  FCG_ERR("CodePrimitives::Conditionals(): construct not available");
2447 }
2448 // no relevant defaults in conditionals/loops
2449 void CodePrimitives::IfWord(const AX& expression) {
2450  (void) expression;
2451  FCG_ERR("CodePrimitives::Conditionals(): construct not available");
2452 }
2453 void CodePrimitives::IfElse(void) {
2454  FCG_ERR("CodePrimitives::Conditionals(): construct not available");
2455 }
2456 // no relevant defaults in conditionals/loops
2457 void CodePrimitives::IfElseIfTrue(const AX& expression) {
2458  (void) expression;
2459  FCG_ERR("CodePrimitives::Conditionals(): construct not available");
2460 }
2461 void CodePrimitives::IfEnd(void) {
2462  FCG_ERR("CodePrimitives::Conditionals(): construct not available");
2463 }
2464 void CodePrimitives::LoopBegin(void) {
2465  FCG_ERR("CodePrimitives::Loops(): construct not available");
2466 }
2467 void CodePrimitives::LoopBreak(const AX& expression) {
2468  (void) expression;
2469  FCG_ERR("CodePrimitives::Loops(): construct not available");
2470 }
2471 void CodePrimitives::LoopEnd(void) {
2472  FCG_ERR("CodePrimitives::Loops(): construct not available");
2473 }
2474 void CodePrimitives::FunctionReturn(void) {
2475  FCG_ERR("CodePrimitives::FunctionReturn(): construct not available");
2476 }
2477 
2478 // switch defaults to conditionsl
2479 void CodePrimitives::SwitchBegin(const AA& address){
2480  (void) address;
2481  FCG_ERR("CodePrimitives::Conditionals(): switch not available");
2482 }
2483 void CodePrimitives::SwitchCase(const AA& address, int val){
2484  (void) address;
2485  (void) val;
2486  FCG_ERR("CodePrimitives::Conditionals(): switch not available");
2487 }
2488 void CodePrimitives::SwitchCases(const AA& address, int from, int to){
2489  (void) address;
2490  (void) from;
2491  (void) to;
2492  FCG_ERR("CodePrimitives::Conditionals(): switch not available");
2493 }
2494 void CodePrimitives::SwitchCases(const AA& address, const std::set< int > & vals){
2495  (void) address;
2496  (void) vals;
2497  FCG_ERR("CodePrimitives::Conditionals(): switch not available");
2498 }
2499 void CodePrimitives::SwitchBreak(void){
2500  FCG_ERR("CodePrimitives::Conditionals(): switch not available");
2501 }
2502 void CodePrimitives::SwitchEnd(void){
2503  FCG_ERR("CodePrimitives::Conditionals(): switch not available");
2504 }
2505 bool CodePrimitives::HasMultiCase(void){
2506  return false;
2507 }
2508 
2509 
2510 // output actions (not available)
2511 void CodePrimitives::RunActionSet(const std::string& address) {
2512  (void) address;
2513  FCG_ERR("CodePrimitives::RunAction(): action not available");
2514 }
2515 void CodePrimitives::RunActionClr(const std::string& address) {
2516  (void) address;
2517  FCG_ERR("CodePrimitives::RunAction(): action not available");
2518 }
2519 void CodePrimitives::RunActionExe(const AX& expression) {
2520  (void) expression;
2521  FCG_ERR("CodePrimitives::RunAction(): action not available");
2522 }
2523 
2524 
2525 // read inputs (treat as native expression)
2526 CodePrimitives::AX CodePrimitives::ReadInputLine(const std::string& address) {
2527  return AX(address);
2528 }
2529 CodePrimitives::AX CodePrimitives::InputExpression(const std::string& expression) {
2530  return AX(expression);
2531 }
2532 
2533 
2534 // timer (not available)
2535 void CodePrimitives::TimerDeclare(const AA& address, const std::string &litval) {
2536  (void) address;
2537  (void) litval;
2538  FCG_ERR("CodePrimitives::Timer(): not available");
2539 }
2540 void CodePrimitives::TimerStart(const AA& address) {
2541  (void) address;
2542  FCG_ERR("CodePrimitives::Timer(): not available");
2543 }
2544 void CodePrimitives::TimerStop(const AA& address) {
2545  (void) address;
2546  FCG_ERR("CodePrimitives::Timer(): not available");
2547 }
2548 void CodePrimitives::TimerReset(const AA& address, const std::string &litval) {
2549  (void) address;
2550  (void) litval;
2551  FCG_ERR("CodePrimitives::Timer(): not available");
2552 }
2553 CodePrimitives::AX CodePrimitives::TimerIsElapsed(const AA& address) {
2554  (void) address;
2555  FCG_ERR("CodePrimitives::Timer(): not available");
2556  return AX();
2557 }
2558 
std::string mWordType
target data type for word
bool mLoopEnabledOutputs
code option: loop until all enabled outputs are executed
virtual void DeclareRecentEvent(void)
Declare "recent_event".
std::map< std::string, TimerAction >::iterator TimerActionIterator
Access to timer records by iterator.
TimerActionIterator TimerActionsEnd()
Access to timer records by iterator.
std::map< std::string, FlagExpression >::iterator FlagIterator
Access to flag records by iterator.
std::vector< std::map< Idx, int > > mStateVectorAddress
mapping from faudes state idx to vector index
virtual bool HasIntarray(void)
default int-array: not supported
virtual void DeclareTimers(void)
Use target implementation to declare timers, typically "timer_run_*" and "timer_cnt_*".
Code-generation common base.
TimerIterator TimersEnd()
Access to timer records by iterator.
virtual void DeclareReset(void)
Declare "reset".
virtual void DoWriteTargetConfiguration(TokenWriter &rTw) const
re-implement token i/o for extra configuration
bool mBitAddressArithmetic
code option: compute bit and word address on target
virtual void OperateOutputs(void)
Operate output lines w.r.t. "exec_event".
virtual void InsertExecHooks(void)
Helper to insert target code for execution hooks.
Compiled record per event on how it affects timers.
std::vector< bool > mUsingVectorAddressStates
configuration of state indexing per generator
LineIterator LinesEnd()
Access to line records by iterator.
virtual void UpdateEnabled(void)
Update "enabled_events" from "parallel_state" if "exec_event" was set.
virtual AA IntarrayAccess(const AA &address, int index)
default int-array: not supported
virtual void DeclareSmallCarray(void)
Declare bit-mask loop-ups.
virtual void BeginExecutionLoop(void)
Execution Loop, begin.
virtual void DoReadTargetConfiguration(TokenReader &rTr)
re-implement token i/o for extra configuration
std::string mIntegerType
target data type for integer
virtual int StateTargetIdx(size_t git, Idx idx)
Overload base class to use the vector address only if the respective code option is active) ...
EventSet mUsedEvents
configured events that are referred to by some generator
virtual void DoReadTargetConfiguration(TokenReader &rTr)
Reads global configuration from TokenReader, excl.
virtual void IndentDec()
Indentation (convenience support for derived classes)
Abstract expression; see also Absstract_Addresses.
word_t WordFromBitVector(const std::vector< bool > &vect, int wordindex)
Extract individual word from boolean vector.
virtual void DoGenerateDeclarations(void)
cut-and-paste template for code snippet assembly
virtual void DeclareStatus(void)
Declare "status".
std::map< std::string, LineAddress >::iterator LineIterator
Access to line records by iterator.
virtual void DeclareLoopState(void)
Declare loop state, i.e. line levels, loop flag.
std::vector< word_t > WordVectorFromBitVector(const std::vector< bool > &vect)
Convert boolean vector to word array.
std::set< std::string > mTimerResets
timers to reset
virtual void DoCompile(void)
virtual hook to input parameter compilation
virtual void Clear(void)
Clear all data.
virtual void LiteralAppend(void)
Cosmetic: append literally from configuration.
const TimedGenerator & At(int i) const
Direct access for read-only access of generators.
std::map< std::string, TimerConfiguration > mTimers
timer definitions
std::string mStateUpdateHook
code option: state change hook
std::string mLiteralAppend
extra code to prepend
std::string EventName(Idx index) const
Faudes-event name lookup.
EventSet mInternalEvents
used events that are configured as internal events (excl.
bool mEventNameLookup
code option: event name lookup
virtual void ExecuteEventBySwitching(void)
Alternative implementation of ExecuteEvent()
virtual void IntarrayDeclare(const AA &address, int offset, int len)
default int-array: not supported
virtual Idx StateFaudesIdx(size_t git, int idx)
Get faudes state index (refer to vector representation as default, overload in CodePrimitives) ...
virtual int EventTargetIdx(Idx idx)
Get target event Idx from faudes Idx (use bit-address + 1)
bool mExistStateNames
record whether there exist statenames at all
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.
bool mArrayForBitarray
code option: use const array to represent bit-masks
virtual ~CodePrimitives(void)
Explicit destructor.
virtual void OperateTimers(void)
Start/stop/reset timers w.r.t. "exec_event".
int EventBitMaskSize(void)
Get overall number of events.
LineIterator LinesBegin()
Access to line records by iterator.
const cgEventSet & Alphabet(void) const
Access alphabet (incl event attributes)
EventSet mOutputEvents
used events that are configured as outputs
Idx Size(void) const
Number of generators.
virtual void DoGenerate(void)
cut-and-paste template for code snippet assembly
int mLastOutputEvent
highest bit-address with output event (-1 for none)
bool mLoopPendingInputs
code option: loop until all inputs are resolved
bool mArrayForState
code option: use int arrays to represent that overall state
bool mArrayForBitmasks
code option: use const array to represent bit-masks
std::vector< std::vector< int > > mTransitionVector
compiled transition-sets, represented as vectors of integers with 0 as separator
virtual void DeclareAux(void)
Declare variables local to the provided snippets, e.g. helpers for bit-mask computation.
std::vector< int > mWordAddressVector
Look-up table to map a bit-address to the word-index.
Idx EventIndex(const std::string &rName) const
Faudes-event index lookup.
virtual void DeclareLargeCarray(void)
Declare compiled transition relations.
std::vector< bool > value
initialisation value
Abstract address; see also Absstract_Addresses.
virtual void DeclareEventNameLookup(void)
Declare symbolic name lookup tables.
std::map< std::string, TimerAction > mTimerActions
timer actions by event name
std::string mPrefix
universal prefix (pseudo name space)
virtual void DoCompile(void)
virtual hook to extend compiled data
virtual std::ostream & Output(void)
Output stream.
virtual std::string TargetSymbol(const std::string &str)
Mangle string to valid target symbol.
virtual void ExecuteEventByInterpreter(void)
Alternative implementation of ExecuteEventBy()
virtual void SenseInputs(void)
Sense input events and add to "pending_events".
virtual void ScheduleEvent(void)
Select event to execute from "pending_and_enabled_events" or "enabled_events".
bool mEventsetsForPerformance
code option: eventsets for performance
int mWordSize
compressed boolean capacity of target type word
virtual void ExecuteEvent(void)
Take transition and figure new state.
virtual void EndExecutionLoop(void)
Loop end.
virtual void Clear(void)
Clear all data.
virtual void ResetReturn(void)
Reset bail out.
int mLastInputEvent
highest bit-address with input (or timer) event (-1 for none)
unsigned long word_t
Code-generator internal data type of target words.
CodePrimitives(void)
Constructor.
bool mMaintainStateIndices
code option: use state indices as provided
std::vector< bool > mHasStateNames
record per generator whether there is a lookup table
virtual void ResetState(void)
Reset state.
std::vector< bool > EventBitMask(Idx idx)
Get vector representation for a single faudes event Idx.
bool mStrictEventSynchronisation
code option: strict event synchronisation
TimerIterator TimersBegin()
Access to timer records by iterator.
bool mBisectionForBitfind
code option: use bisection to fing lowest set bit
virtual void Comment(const std::string &text)
Write a comment (reimplement in derived classes, call base)
virtual void LineFeed(int lines=1)
LineFeed (convenience support for derived classes)
virtual void VariableDeclare(const std::string &laddr, const std::string &ltype)
declaration template (optional to facilitate declaration constructs)
virtual void DoGenerateCyclicCode(void)
cut-and-paste template for code snippet assembly
Record declared bit-arrays.
cgEventSet mAlphabet
event configuration by attributes
virtual void DeclarePendingEvents(void)
Declare "pending_events" and "enabled_events".
virtual void UpdateEnabledByInterpreter(void)
Alternative implementations UpdateEnabled()
std::string mEventExecutionHook
code option: event exec hook
Idx EventFaudesIdx(int idx)
Get faudes Idx from target Idx (aka from bit-address + 1)
FlagIterator FlagsEnd()
Access to flag records by iterator.
int EventBitAddress(Idx idx)
Get event bit-address from faudes Idx (consecutive, starts at 0)
std::string mLiteralPrepend
extra code to prepend
bool mArrayForTransitions
code option: use const array to represent transitions
bool mStateNameLookup
code option: state name lookup
std::set< std::string > mTimerStops
timers to stop
virtual void LiteralPrepend(void)
Cosmetic: prepend literally from configuration data.
TimerActionIterator TimerActionsBegin()
Access to timer records by iterator.
virtual void SenseTimerElapse(void)
Sense timer elapse vents and add to "pending_events".
Code-generator with abstract types and operations.
virtual Idx StateFaudesIdx(size_t git, int idx)
Overload base class to use the vector address only if the respective code option is active) ...
std::map< std::string, TimerConfiguration >::iterator TimerIterator
Access to timer records by iterator.
virtual void IndentInc()
Indentation (convenience support for derived classes)
FlagIterator FlagsBegin()
Access to flag records by iterator.
virtual void DoGenerateResetCode(void)
cut-and-paste template for code snippet assembly
virtual void BreakExecutionLoop(void)
Execution Loop, break.
std::vector< TimedGenerator > mGenerators
list of executors
std::vector< word_t > mBitMaskVector
Look-up table to map a bit-address to the word-bitmask.
virtual void UpdateEnabledBySwitching(void)
Alternative implementations UpdateEnabled()
std::set< std::string > mTimerStarts
timers to start
virtual int StateTargetIdx(size_t git, Idx idx)
Get target state index (refer to vector representation as default, overload in CodePrimitives) ...
virtual void DeclareStateNameLookup(void)
Declare symbolic name lookup tables.
virtual AX TargetExpression(const AA &address)=0
Convert abstract address to target expression of the respective value.
virtual void DeclareParallelState(void)
Declare "parallel_state".
virtual const std::string & Name(void) const
Get objects&#39;s name (reimplementing base faudes::Type)
int mIntegerSize
compressed boolean capacity of target type integer
virtual void DoWriteTargetConfiguration(TokenWriter &rTw) const
Write global configuration to TokenWriter, excl.