CompileDES 3.14
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
20CodePrimitives 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";
50 mArrayForTransitions=HasCintarray();
52 mArrayForBitmasks=HasCwordarray();
54 mArrayForBitarray= HasWordarray();
56 mArrayForState=false;
61 mEventNameLookup=false;
62 mStateNameLookup=false;
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)
211void 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
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");
379 }
380 if(mArrayForBitmasks && !HasCwordarray()) {
381 FCG_VERB1("CodePrimitives::Compile(): cannot generate compiled bit-masks for the specified target");
382 mArrayForBitmasks=false;
383 }
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");
393 }
395 FCG_VERB1("CodePrimitives::Compile(): reject option eventsets-for-performance for specified target");
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 }
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");
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
430CodePrimitives implementation: internal data organisation
431
432******************************************************************
433******************************************************************
434******************************************************************
435*/
436
437
438// mangle an arbitrary string to a valid target symbol
439std::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
453int 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
461Idx 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
475CodePrimitives 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);
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");
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");
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
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;
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");
717 for(;tit!=TimersEnd();++tit) {
718 TimerStop(AA(tit->second.mAddress));
719 TimerReset(AA(tit->second.mAddress) ,tit->second.mInitialValue);
720 }
721 }
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
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;
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;
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;
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());
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
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
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);
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
1177 // done
1178 IfEnd();
1179 LineFeed(1+2);
1180}
1181
1182// wrapper
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);
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();
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();
1338 UpdateEnabled();
1339 ScheduleEvent();
1341 ExecuteEvent();
1342 OperateTimers();
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
1358 LineFeed(2);
1360 LineFeed(2+1);
1361 LiteralAppend();
1362}
1363
1364
1365
1366/*
1367******************************************************************
1368******************************************************************
1369******************************************************************
1370
1371CodePrimitives implementation --- generate atomic snippets
1372
1373******************************************************************
1374******************************************************************
1375******************************************************************
1376*/
1377
1378// cosmetics (base only records the text, need to rimplement in derived classes
1379void CodePrimitives::Comment(const std::string& text) {
1381}
1382
1383// declaration template (optional)
1384void 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)
1391void 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
1399void CodePrimitives::IntegerDecrement(const AA& address, int val) {
1400 IntegerIncrement(address,-val);
1401}
1402
1403// integer maths
1404CodePrimitives::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 }
1410CodePrimitives::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}
1416CodePrimitives::AX CodePrimitives::IntegerBitmask(const AX& expression) {
1417 (void) expression;
1418 FCG_ERR("CodePrimitives::Integer(): maths not available");
1419 return AX();
1420}
1421bool CodePrimitives::HasIntmaths(void) {
1422 return false;
1423}
1424CodePrimitives::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}
1430CodePrimitives::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}
1436CodePrimitives::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}
1442CodePrimitives::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}
1448CodePrimitives::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}
1454CodePrimitives::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)
1463void CodePrimitives::WordDeclare(const AA& address) {
1464 (void) address;
1465 FCG_ERR("CodePrimitives::Word(): word-of-bits type not available");
1466}
1467void 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}
1472void 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}
1477void 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}
1482void 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}
1487void 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}
1492void 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}
1498void 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}
1504void 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}
1509void 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}
1514void 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}
1520void 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}
1526void 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}
1531CodePrimitives::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}
1537CodePrimitives::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}
1543CodePrimitives::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}
1549CodePrimitives::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}
1555CodePrimitives::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}
1561CodePrimitives::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
1569void CodePrimitives::BooleanDeclare(const AA& address) {
1570 IntegerDeclare(address);
1571}
1572void CodePrimitives::BooleanDeclare(const AA& address, int val) {
1573 IntegerDeclare(address,val ? 1 : 0);
1574}
1575void CodePrimitives::BooleanAssign(const AA& address, const AX& expression) {
1576 IntegerAssign(address,expression);
1577}
1578void CodePrimitives::BooleanAssign(const AA& address, int val) {
1579 IntegerAssign(address, val ? 1 : 0);
1580}
1581CodePrimitives::AX CodePrimitives::BooleanIsEq(const AA& op1, const AA& op2) {
1582 return IntegerIsEq(op1,TargetExpression(op2));
1583}
1584CodePrimitives::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
1593void 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};
1599CodePrimitives::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};
1605CodePrimitives::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};
1611bool CodePrimitives::HasCintarray(void) {
1612 return false;
1613};
1614
1615// default const-word-array: not supported
1616void 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};
1622CodePrimitives::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};
1628CodePrimitives::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};
1634bool CodePrimitives::HasCwordarray(void) {
1635 return false;
1636};
1637
1638
1639// default word-array: not supported
1640void 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};
1646void 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};
1652CodePrimitives::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};
1658CodePrimitives::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};
1664bool CodePrimitives::HasWordarray(void) {
1665 return false;
1666};
1667
1668
1670void 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};
1676void 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};
1688CodePrimitives::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
1699CodePrimitives::AX CodePrimitives::StringConstant(const std::string &val) {
1700 (void) val;
1701 FCG_ERR("CodePrimitives::Cstrarray(): constant-str-arrays not defined");
1702 return AX();
1703};
1704void 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};
1710CodePrimitives::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};
1716CodePrimitives::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};
1722bool CodePrimitives::HasCstrarray(void) {
1723 return false;
1724};
1725
1726
1727// declare bit array as record of words
1728void 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
1749void 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
1772void 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
1787void 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
1808void 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
1822void 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
1839void 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
1864void 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
1876void 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
1954void 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
2021void 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
2033void 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
2111void 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
2128void 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
2149void 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
2165void 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
2182void 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
2203void 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)
2223void 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)*/
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)) */
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
2333void CodePrimitives::EventSetDeclare(const AA& address) {
2334 BitarrayDeclare(address,EventBitMaskSize());
2335}
2336
2337// event set
2338void CodePrimitives::EventSetDeclare(const AA& address, const EventSet& evset) {
2339 std::vector<bool> evmask = EventBitMask(evset);
2340 BitarrayDeclare(address,evmask);
2341}
2342
2343// event set
2344void CodePrimitives::EventSetClear(const AA& address) {
2345 BitarrayClear(address);
2346}
2347
2348// event set
2349void CodePrimitives::EventSetFull(const AA& address) {
2350 BitarrayFull(address);
2351}
2352
2353// set is empty
2354void CodePrimitives::EventSetIsNotEmpty(const AA& address, const AA& result) {
2355 BitarrayOrAllWords(address,result);
2356}
2357
2358// event insert
2359void CodePrimitives::EventSetAssign(const AA& address, const EventSet& evset) {
2360 std::vector<bool> evmask = EventBitMask(evset);
2361 BitarrayAssign(address,evmask);
2362}
2363
2364// event insert
2365void CodePrimitives::EventSetInsert(const AA& address, const EventSet& evset) {
2366 std::vector<bool> evmask = EventBitMask(evset);
2367 BitarrayOr(address,evmask);
2368}
2369
2370// event insert
2371void CodePrimitives::EventSetInsert(const AA& address, const AA& evaddrexpr) {
2372 BitarraySetBit(address,evaddrexpr,1);
2373};
2374
2375// event insert, candidats known
2376void 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
2382void CodePrimitives::EventSetInsert(const AA& address, Idx ev) {
2383 BitarraySetBit(address,EventBitAddress(ev));
2384}
2385
2386// event erase
2387void 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
2394void CodePrimitives::EventSetErase(const AA& address, Idx ev) {
2395 BitarrayClrBit(address,EventBitAddress(ev));
2396}
2397
2398// event erase
2399void CodePrimitives::EventSetErase(const AA& address, const AA& evaddr) {
2400 BitarrayClrBit(address,evaddr,1);
2401};
2402
2403// event test
2404void 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
2410void 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
2416void CodePrimitives::EventSetRestrict(const AA& address, const AA& otherset) {
2417 BitarrayAnd(address,otherset);
2418}
2419
2420// event union
2421void 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
2427void 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)
2433void CodePrimitives::EventSetFindHighestPriority(const AA& address, const AA& result) {
2434 BitarrayFindFirst(address,result,1);
2435}
2436
2437
2438
2439// no relevant defaults in conditionals/loops
2440void CodePrimitives::IfTrue(const AX& expression) {
2441 (void) expression;
2442 FCG_ERR("CodePrimitives::Conditionals(): construct not available");
2443}
2444// no relevant defaults in conditionals/loops
2445void CodePrimitives::IfFalse(const AX& expression) {
2446 (void) expression;
2447 FCG_ERR("CodePrimitives::Conditionals(): construct not available");
2448}
2449// no relevant defaults in conditionals/loops
2450void CodePrimitives::IfWord(const AX& expression) {
2451 (void) expression;
2452 FCG_ERR("CodePrimitives::Conditionals(): construct not available");
2453}
2454void CodePrimitives::IfElse(void) {
2455 FCG_ERR("CodePrimitives::Conditionals(): construct not available");
2456}
2457// no relevant defaults in conditionals/loops
2458void CodePrimitives::IfElseIfTrue(const AX& expression) {
2459 (void) expression;
2460 FCG_ERR("CodePrimitives::Conditionals(): construct not available");
2461}
2462void CodePrimitives::IfEnd(void) {
2463 FCG_ERR("CodePrimitives::Conditionals(): construct not available");
2464}
2465void CodePrimitives::LoopBegin(void) {
2466 FCG_ERR("CodePrimitives::Loops(): construct not available");
2467}
2468void CodePrimitives::LoopBreak(const AX& expression) {
2469 (void) expression;
2470 FCG_ERR("CodePrimitives::Loops(): construct not available");
2471}
2472void CodePrimitives::LoopEnd(void) {
2473 FCG_ERR("CodePrimitives::Loops(): construct not available");
2474}
2475void CodePrimitives::FunctionReturn(void) {
2476 FCG_ERR("CodePrimitives::FunctionReturn(): construct not available");
2477}
2478
2479// switch defaults to conditionsl
2480void CodePrimitives::SwitchBegin(const AA& address){
2481 (void) address;
2482 FCG_ERR("CodePrimitives::Conditionals(): switch not available");
2483}
2484void CodePrimitives::SwitchCase(const AA& address, int val){
2485 (void) address;
2486 (void) val;
2487 FCG_ERR("CodePrimitives::Conditionals(): switch not available");
2488}
2489void 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}
2495void 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}
2500void CodePrimitives::SwitchBreak(void){
2501 FCG_ERR("CodePrimitives::Conditionals(): switch not available");
2502}
2503void CodePrimitives::SwitchEnd(void){
2504 FCG_ERR("CodePrimitives::Conditionals(): switch not available");
2505}
2506bool CodePrimitives::HasMultiCase(void){
2507 return false;
2508}
2509
2510
2511// output actions (not available)
2512void CodePrimitives::RunActionSet(const std::string& address) {
2513 (void) address;
2514 FCG_ERR("CodePrimitives::RunAction(): action not available");
2515}
2516void CodePrimitives::RunActionClr(const std::string& address) {
2517 (void) address;
2518 FCG_ERR("CodePrimitives::RunAction(): action not available");
2519}
2520void 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)
2527CodePrimitives::AX CodePrimitives::ReadInputLine(const std::string& address) {
2528 return AX(address);
2529}
2530CodePrimitives::AX CodePrimitives::InputExpression(const std::string& expression) {
2531 return AX(expression);
2532}
2533
2534
2535// timer (not available)
2536void CodePrimitives::TimerDeclare(const AA& address, const std::string &litval) {
2537 (void) address;
2538 (void) litval;
2539 FCG_ERR("CodePrimitives::Timer(): not available");
2540}
2541void CodePrimitives::TimerStart(const AA& address) {
2542 (void) address;
2543 FCG_ERR("CodePrimitives::Timer(): not available");
2544}
2545void CodePrimitives::TimerStop(const AA& address) {
2546 (void) address;
2547 FCG_ERR("CodePrimitives::Timer(): not available");
2548}
2549void CodePrimitives::TimerReset(const AA& address, const std::string &litval) {
2550 (void) address;
2551 (void) litval;
2552 FCG_ERR("CodePrimitives::Timer(): not available");
2553}
2554CodePrimitives::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)
virtual const std::string & Name(void) const
Get objects's name (reimplementing base faudes::Type)
int EventBitAddress(Idx idx)
Get event bit-address from faudes Idx (consecutive, starts at 0)
const TimedGenerator & At(int i) const
Direct access for read-only access of generators.
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::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.
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.
std::map< std::string, TimerConfiguration >::iterator TimerIterator
Access to timer records by iterator.
virtual std::ostream & Output(void)
Output stream.
std::map< std::string, TimerAction > mTimerActions
timer actions by event name
std::vector< word_t > WordVectorFromBitVector(const std::vector< bool > &vect)
Convert boolean vector to word array.
std::map< std::string, LineAddress >::iterator LineIterator
Access to line records by iterator.
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.
const cgEventSet & Alphabet(void) const
Access alphabet (incl event attributes)
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
std::map< std::string, FlagExpression >::iterator FlagIterator
Access to flag records by iterator.
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