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