30 FD_DCG(
"CodeGenerator()::CodeGenerator()");
40 FD_DCG(
"CodeGenerator()::~CodeGenerator()");
41 if(pOutBuffer)
delete pOutBuffer;
45 std::map< std::string, CodeGenerator* (*)(void) >* CodeGenerator::mpsRegistry=0;
49 if(!mpsRegistry) mpsRegistry =
new std::map< std::string, CodeGenerator* (*)(void) >;
50 (*mpsRegistry)[type]=newcg;
55 std::vector< std::string > res;
56 std::map< std::string, CodeGenerator* (*)(void) >::iterator rit;
57 for(rit=mpsRegistry->begin(); rit != mpsRegistry->end(); ++rit)
58 res.push_back(rit->first);
64 if(mpsRegistry->find(type)==mpsRegistry->end())
return 0;
65 return (*mpsRegistry)[type]();
70 FD_DCG(
"CodeGenerator()::Clear()");
80 FCG_VERB2(
"CodeGenerator::Generator(): from file " << rFileName);
81 TokenReader tr(rFileName);
88 FCG_VERB2(
"CodeGenerator::Generator(): found [" <<
mGenerators.back().Name() <<
"] " <<
89 "with #" <<
mGenerators.back().TransRelSize() <<
" transitions");
94 FCG_VERB2(
"CodeGenerator::Generator(): generator by reference");
98 FCG_VERB2(
"CodeGenerator::Generator(): found [" <<
mGenerators.back().Name() <<
"] " <<
99 "with #" <<
mGenerators.back().TransRelSize() <<
" transitions");
115 void CodeGenerator::DoReadGenerators(TokenReader& rTr) {
117 std::string dirname=
"";
118 if(rTr.SourceMode()==TokenReader::File)
119 dirname=ExtractDirectory(rTr.FileName());
121 FD_DCG(
"CodeGenerator()::DoReadGenerators(tr): dirname " << dirname);
123 rTr.ReadBegin(
"Generators");
125 while(!rTr.Eos(
"Generators")) {
128 if(token.Type()==Token::String) {
129 Insert(PrependDirectory(dirname,token.StringValue()));
134 if(token.Type()==Token::Begin)
135 if(token.StringValue()==
"Generator") {
142 std::stringstream errstr;
143 errstr <<
"Invalid token" << rTr.FileLine();
144 throw Exception(
"CodeGenerator::DoReadGenerators", errstr.str(), 502);
146 rTr.ReadEnd(
"Generators");
153 FD_DCG(
"CodeGenerator::DoRead()");
154 std::string label=rLabel;
155 if(label==
"") label=
"CodeGenerator";
158 rTr.ReadBegin(label,token);
159 if(token.ExistsAttributeString(
"name"))
160 Name(token.AttributeStringValue(
"name"));
162 while(!rTr.Eos(label)) {
165 if(token.Type()==Token::Begin)
166 if(token.StringValue()==
"TargetConfiguration") {
167 rTr.ReadBegin(
"TargetConfiguration");
169 rTr.ReadEnd(
"TargetConfiguration");
173 if(token.Type()==Token::Begin)
174 if(token.StringValue()==
"Generators") {
175 DoReadGenerators(rTr);
176 FCG_VERB1(
"CodeGenerator::Generator(): found #" <<
Size() <<
" generators");
180 if(token.Type()==Token::Begin)
181 if(token.StringValue()==
"EventConfiguration") {
182 mAlphabet.Read(rTr,
"EventConfiguration");
183 FCG_VERB1(
"CodeGenerator::Events(): found event configuration for #" <<
mAlphabet.Size() <<
" events");
187 std::stringstream errstr;
188 errstr <<
"Invalid token" << rTr.FileLine();
189 throw Exception(
"CodeGenerator::DoRead", errstr.str(), 502);
201 void CodeGenerator::DoWriteGenerators(TokenWriter& rTw)
const {
202 rTw.WriteBegin(
"Generators");
203 for(Idx i=0; i<
Size(); i++) {
213 rTw.WriteEnd(
"Generators");
221 std::string label=rLabel;
222 if(label==
"") label=
"CodeGenerator";
223 rTw.WriteBegin(label);
225 rTw.WriteBegin(
"TargetConfiguration");
227 rTw.WriteEnd(
"TargetConfiguration");
229 mAlphabet.Write(rTw,
"EventConfiguration");
231 DoWriteGenerators(rTw);
239 std::stringstream res;
240 res << COMPILEDES_VERSION <<
" (using " << faudes::VersionString() <<
")";
260 FCG_VERB0(
"CodeGenerator::Compile(): compile to internal representation");
265 FCG_VERB0(
"CodeGenerator::Compile(): done");
271 FD_DCG(
"CodeGenerator::DoCompile()");
274 for(
size_t git=0; git<
Size(); ++git) {
275 EventSet::Iterator eit=
At(git).AlphabetBegin();
276 for(; eit!=
At(git).AlphabetEnd(); ++eit) {
278 FCG_ERR(
"CodeGenerator::Compile(): event [" <<
EventName(*eit) <<
"] has unspecified execution semantics")
284 FCG_VERB0(
"CodeGenerator::Compile(): event configuration mismatch: #" << (
mAlphabet-
mUsedEvents).
Size() <<
" unused events");
287 EventSet::Iterator eit;
297 if(
mAlphabet.Attribute(*eit).Input())
continue;
298 if(
mAlphabet.Attribute(*eit).Timer())
continue;
299 if(
mAlphabet.Attribute(*eit).Output())
continue;
302 FCG_VERB0(
"CodeGenerator::Compile(): event statistics: overall used events: #" <<
mUsedEvents.Size());
303 FCG_VERB0(
"CodeGenerator::Compile(): event statistics: input events incl timer: #" <<
mInputEvents.Size());
304 FCG_VERB0(
"CodeGenerator::Compile(): event statistics: output events: #" <<
mOutputEvents.Size());
305 FCG_VERB0(
"CodeGenerator::Compile(): event statistics: internal events excl timer: #" <<
mInternalEvents.Size());
307 FD_DCG(
"CodeGenerator::DoCompile(): sorting events");
308 std::multimap<int, Idx> sortev;
312 if((prio<0) || (prio > 10000)) {
313 FCG_ERR(
"CodeGenerator::Compile(): priority out of range [0, 10000] for event [" <<
EventName(*eit) <<
"]");
319 sortev.insert(std::pair<int,Idx>(-prio,*eit));
322 FD_DCG(
"CodeGenerator::DoCompile(): set up bitaddress");
327 std::multimap<int, Idx>::iterator sit;
329 for(sit=sortev.begin(); sit!=sortev.end(); sit++) {
342 FCG_VERB1(
"CodeGenerator::Compile(): bitmask size #" <<
EventBitMaskSize() <<
" bits");
344 FD_DCG(
"CodeGenerator::DoCompie(): set up transition vector");
349 for(Idx gid=0; gid<
Size(); gid++) {
350 FD_DCG(
"CodeGenerator::DoCompile(): set up transition vector " << gid);
358 const Generator gen =
At(gid);
360 FCG_ERR(
"CodeGenerator::Complie(): generator must not be empty [" << gen.Name() <<
"]");
364 IndexSet::Iterator sit= gen.StatesBegin();
365 for(;sit!=gen.StatesEnd();++sit) {
366 vectoraddr[*sit]= (int) transvect.size();
367 faudesindex[(int) transvect.size()]= *sit;
368 TransSet::Iterator tit = gen.TransRelBegin(*sit);
369 TransSet::Iterator tit_end = gen.TransRelEnd(*sit);
370 for(;tit!=tit_end;++tit) {
371 transvect.push_back((
int) tit->Ev);
372 transvect.push_back((
int) tit->X2);
374 transvect.push_back(0);
377 for(
size_t vit=0; vit< transvect.size(); ++vit) {
378 int ev = transvect[vit];
381 int x2 = transvect[++vit];
383 transvect[vit]=vectoraddr[x2];
385 FCG_VERB0(
"CodeGenerator::Compile(): [" << gen.Name() <<
"] raw data for transition array #" 387 if(!usingvectoraddr) {
388 FCG_VERB0(
"CodeGenerator::Compile(): [" << gen.Name() <<
"] raw data for state-address array #" 391 FCG_VERB0(
"CodeGenerator::Compile(): [" << gen.Name() <<
"] using vector addresses as state indices");
400 if(!
mAlphabet.Attribute(*eit).Input())
continue;
401 const std::vector<AttributeCodeGeneratorEvent::InputTrigger>& triggers =
mAlphabet.Attribute(*eit).mTriggers;
402 for(
size_t i=0; i<triggers.size(); i++) {
403 if(triggers[i].mExe) {
404 std::string flagaddr=triggers[i].mAddress;
405 mFlags[flagaddr].mEvents.Insert(*eit);
406 mFlags[flagaddr].mAddress=flagaddr;
408 if((triggers[i].mNeg) || (triggers[i].mPos)) {
409 std::string lineaddr=triggers[i].mAddress;
411 if(
mLines[lineaddr].mStatic != triggers[i].mStatic)
412 FCG_ERR(
"CodeGenerator::Compile(): inconsistent static option on input line [" << lineaddr <<
"]");
414 mLines[lineaddr].mAddress=lineaddr;
415 if(triggers[i].mNeg)
mLines[lineaddr].mNegEvents.Insert(*eit);
416 if(triggers[i].mPos)
mLines[lineaddr].mPosEvents.Insert(*eit);
417 if(triggers[i].mNeg && triggers[i].mStatic)
mLines[lineaddr].mNegStatics.Insert(*eit);
418 if(triggers[i].mPos && triggers[i].mStatic)
mLines[lineaddr].mPosStatics.Insert(*eit);
419 mLines[lineaddr].mStatic=triggers[i].mStatic;
423 std::map<std::string, LineAddress>::iterator lit=
mLines.begin();
425 for(;lit!=
mLines.end();++lit) lit->second.mBitAddress=linecnt++;
426 FCG_VERB1(
"CodeGenerator::Compile(): monitoring #" <<
mLines.size() <<
" lines for edge detection");
434 if(!attr.
Timer())
continue;
439 mTimers[timerev].mAddress= timerev;
440 mTimers[timerev].mElapseEvent= timerev;
442 mTimers[timerev].mStartEvents= starts;
443 mTimers[timerev].mStopEvents= stops;
444 mTimers[timerev].mResetEvents= resets;
445 EventSet::Iterator ait;
446 ait = starts.Begin();
447 for(;ait!=starts.End();++ait)
450 for(;ait!=stops.End();++ait)
452 ait = resets.Begin();
453 for(;ait!=resets.End();++ait)
456 FCG_VERB1(
"CodeGenerator::Compile(): operating #" <<
mTimers.size() <<
" timers controlled by #" <<
mTimerActions.size() <<
" events");
463 if(!attr.
Output())
continue;
465 const std::vector<AttributeCodeGeneratorEvent::OutputAction>& actions =
mAlphabet.Attribute(*eit).mActions;
466 for(
size_t i=0; i<actions.size(); i++) {
467 std::string actaddr=actions[i].mAddress;
473 FCG_VERB1(
"CodeGenerator::Compile(): operating #" <<
mActionAddresses.size() <<
" action primitives controlled by #" << evcn <<
" events");
483 FD_DCG(
"CodeGenerator::DoCompile(): ok");
489 std::map<Idx,int>::const_iterator sit;
507 std::map<int,Idx>::const_iterator sit;
516 std::vector<bool> res;
518 while(res.size()< vsize) res.push_back(
false);
521 if(baddr<0)
return res;
530 std::vector<bool> res;
532 while(res.size()< vsize) res.push_back(
false);
534 EventSet::Iterator eit;
535 for(eit=eset.Begin(); eit!=eset.End(); eit++) {
537 if(baddr<0)
continue;
553 for(;(shift<
mWordSize) && (bidx<vect.size()); shift++,bidx++)
554 if(vect[bidx]) res |= (1UL<<shift);
560 std::vector< word_t > res;
562 for(
size_t vidx=0; vidx < vect.size(); ++vidx) {
563 if(!vect[vidx])
continue;
578 std::map<Idx,int>::const_iterator sit;
587 std::map<int,Idx>::const_iterator sit;
667 FCG_VERB0(
"CodeGenerator::Generate(): generating code to \"[" <<
mOutMode <<
"]\"");
669 bool tmpstream=
false;
672 if(pOutBuffer!=0)
delete pOutBuffer;
673 pOutBuffer =
new cgp_streambuf(
mOutMode);
681 FCG_VERB0(
"CodeGenerator::Generate(): generated " <<
LineCount() <<
" lines of code.");
696 static std::string ems(
"");
697 if(!pOutBuffer)
return ems;
698 return pOutBuffer->Buffer();
702 if(!pOutBuffer)
return;
704 if(!strbuf.empty()) FCG_VERB1(
"CodeGenerator::OutputString(): setting non-trivial not implemented")
710 if(!pOutBuffer)
return;
711 pOutBuffer->Mute(mode!=
'*');
717 if(!pOutBuffer)
return;
719 pOutBuffer->Mute(mute);
737 if(!pOutBuffer)
return;
738 pOutBuffer->IndentInc();
743 if(!pOutBuffer)
return;
744 pOutBuffer->IndentDec();
749 if(!pOutBuffer)
return;
750 pOutBuffer->XmlTextEscape(on);
755 if(!pOutBuffer)
return;
756 pOutBuffer->XmlCdataEscape(on);
764 if(pOutBuffer->Mute())
775 if(!pOutBuffer)
return;
776 pOutBuffer->MuteVspace(on);
782 if(!pOutBuffer)
return std::string();
783 std::stringstream res;
784 res <<
"#" << pOutBuffer->LineCount();
785 return std::string(res.str());
790 CodeGenerator::cgp_streambuf::cgp_streambuf(std::string mode) :
802 if(mode ==
"std::string") {
803 mMode =
"std::string";
807 else if(mode==
"std::cout") {
814 mpFOutStream =
new std::ofstream();
815 mpFOutStream->exceptions(std::ios::badbit|std::ios::failbit);
817 mpFOutStream->open(mode.c_str(), std::ios::out|std::ios::trunc);
819 catch (std::ios::failure&) {
820 std::stringstream errstr;
821 errstr <<
"Exception opening/writing file \""<< mode <<
"\"";
822 throw Exception(
"CodeGenerator::Generate()", errstr.str(), 1);
829 CodeGenerator::cgp_streambuf::~cgp_streambuf() {
832 mpFOutStream->close();
838 std::streambuf::int_type CodeGenerator::cgp_streambuf::overflow (int_type c) {
841 if(c == EOF)
return EOF;
845 if(mMuteVspace && (c==
'\n') && (mBuffer.size()==0))
return c;
848 mBuffer.push_back(c);
857 for(;scnt>0;--scnt) mBuffer.push_back(
' ');
863 { mBuffer +=
"<";
return c;}
865 { mBuffer +=
">";
return c;}
867 { mBuffer +=
"&";
return c;}
869 { mBuffer +=
"'";
return c;}
871 { mBuffer +=
""";
return c;}
875 if((c==
'>') && (mBuffer.size()>=2))
876 if(mBuffer.at(mBuffer.size()-1) ==
']')
877 if(mBuffer.at(mBuffer.size()-2) ==
']')
878 mBuffer +=
"]]><![CDATA[";
881 mBuffer.push_back(c);
887 void CodeGenerator::cgp_streambuf::Flush() {
892 (*pOutStream) << mBuffer;
893 (*pOutStream) << std::flush;
894 }
catch(std::ios::failure&) {
895 std::stringstream errstr;
896 errstr <<
"Exception writing to file \""<< mMode <<
"\"";
897 throw Exception(
"CodeGenerator::Generate()", errstr.str(), 1);
904 const std::string& CodeGenerator::cgp_streambuf::Buffer(){
909 void CodeGenerator::cgp_streambuf::Clear(
void){
917 int CodeGenerator::cgp_streambuf::LineCount() {
924 void CodeGenerator::cgp_streambuf::IndentInc() {
929 void CodeGenerator::cgp_streambuf::IndentDec() {
934 void CodeGenerator::cgp_streambuf::XmlTextEscape(
bool on) {
941 void CodeGenerator::cgp_streambuf::XmlCdataEscape(
bool on) {
948 void CodeGenerator::cgp_streambuf::Mute(
bool on) {
954 bool CodeGenerator::cgp_streambuf::Mute() {
959 void CodeGenerator::cgp_streambuf::MuteVspace(
bool on) {
virtual std::string LineCount(void)
LineFeed (convenience support for derived classes)
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, FlagExpression > mFlags
input event generation
virtual void MuteMode(char mode)
Set current mute mode.
EventSet mStartEvents
Events that start this timer.
virtual void DoGenerate(void)=0
pure virtual interface to code generation
Event attributes for the purpose of code generation.
std::vector< std::string > mGeneratorNames
list of filenames when generator are read from file
LineIterator LinesEnd()
Access to line records by iterator.
virtual void XmlCdataEscape(bool on)
XmlCdataEscape (escape "]]>")
TimeConstraint mTimeConstraint
Timer definition (indicate timer event iff mInitialValue non-empty)
virtual std::ostream & Output(void)
Output stream.
EventSet mUsedEvents
configured events that are referred to by some generator
EventSet mResetEvents
Events that reset this timer.
virtual void DoRead(TokenReader &rTr, const std::string &rLabel="", const Type *pContext=0)
Read the configuration from TokenReader, see faudes Type for public wrappers.
virtual void DoReadTargetConfiguration(TokenReader &rTr)
Reads global configuration from TokenReader, excl.
static CodeGenerator * New(const std::string &type)
Instantiate by identifier (returns 0 on unknown class)
std::string mOutMode
output file name (base)
std::vector< bool > EventBitMask(Idx idx)
Get vector representation for a single faudes event Idx.
int mWordSize
compressed boolean capacity of target type word
virtual void LineFeed(int lines=1)
LineFeed (convenience support for derived classes)
void Verbose(int level, std::ostream *altout=0)
Set verbosity level.
virtual void MuteComments(bool on)
Mute comments (convenience support for derived classes)
std::string mRecentMutedComment
recent muted comment
std::vector< bool > mUsingVectorAddressStates
configuration of state indexing per generator
std::ostream * pOutStream
output stream
cgEventSet mAlphabet
event configuration by attributes
Idx EventFaudesIdx(int idx)
Get faudes Idx from target Idx (aka from bit-address + 1)
virtual Idx StateFaudesIdx(size_t git, int idx)
Get faudes state index (refer to vector representation as default, overload in CodePrimitives) ...
int EventBitAddress(Idx idx)
Get event bit-address from faudes Idx (consecutive, starts at 0)
const std::string & OutputString(void)
Get accumulated output as string.
EventSet mOutputEvents
used events that are configured as outputs
TimerActionIterator TimerActionsBegin()
Access to timer records by iterator.
std::vector< word_t > WordVectorFromBitVector(const std::vector< bool > &vect)
Convert boolean vector to word array.
std::map< std::string, TimerConfiguration >::iterator TimerIterator
Access to timer records by iterator.
const std::vector< int > & TransitionVector(size_t git)
Get target state index (refer to vector representation as default, overload in CodePrimitives) ...
virtual void IndentInc()
Indentation (convenience support for derived classes)
FlagIterator FlagsBegin()
Access to flag records by iterator.
const TimedGenerator & At(int i) const
Direct access for read-only access of generators.
virtual void DoWrite(TokenWriter &rTw, const std::string &rLabel="", const Type *pContext=0) const
Writes the configuration to TokenWriter, see faudes Type for public wrappers.
std::vector< word_t > mBitMaskVector
Look-up table to map a bit-address to the word-bitmask.
std::vector< int > mWordAddressVector
Look-up table to map a bit-address to the word-index.
Idx EventIndex(const std::string &rName) const
Faudes-event index lookup.
std::map< std::string, TimerAction >::iterator TimerActionIterator
Access to timer records by iterator.
TimerActionIterator TimerActionsEnd()
Access to timer records by iterator.
std::map< std::string, FlagExpression >::iterator FlagIterator
Access to flag records by iterator.
std::map< std::string, TimerAction > mTimerActions
timer actions by event name
std::vector< std::map< Idx, int > > mStateVectorAddress
mapping from faudes state idx to vector index
static std::string VersionString(void)
Version (refers to macro COMPILEDES_VERSION, defined in cgp_codegenerator.h)
std::map< Idx, int > mEventBitAddress
mapping from faudes event idx to bit address (descending priority, range 0 .
virtual const std::string & Name(void) const
Get objects's name (reimplementing base faudes::Type)
int mIntegerSize
compressed boolean capacity of target type integer
std::ostream * pErrStream
error stream
virtual void DoWriteTargetConfiguration(TokenWriter &rTw) const
Write global configuration to TokenWriter, excl.
std::map< std::string, ActionAddress >::iterator ActionAddressIterator
Access to action record by iterator.
CodeGenerator(void)
Constructor.
static std::vector< std::string > Registry(void)
Access registry contents.
int mVerbLevel
diagnpstic-output level
int mLastInputEvent
highest bit-address with input (or timer) event (-1 for none)
virtual void XmlTextEscape(bool on)
XmlTextEscape (escape "<", ">", "&", "\"" and "'")
virtual void MuteCond(char mode)
Set mode condition.
std::vector< std::map< int, Idx > > mStateFaudesIndex
mapping from vector state idx to faudes index
unsigned long word_t
Code-generator internal data type of target words.
ActionAddressIterator ActionAddressesBegin()
Access to action addresses by iterator.
std::vector< std::vector< int > > mTransitionVector
compiled transition-sets, represented as vectors of integers with 0 as separator
virtual void Comment(const std::string &text)
Write a comment (reimplement in derived classes, call base)
void Insert(const std::string &file)
Add a Generator from file.
EventSet mInputEvents
used events that are configured as inputs (incl timer)
FlagIterator FlagsEnd()
Access to flag records by iterator.
virtual void Generate(void)
Generate code.
ActionAddressIterator ActionAddressesEnd()
Access to action addresses by iterator.
char mMuteMode
current output mode
virtual void Clear(void)
Clear all data.
std::map< std::string, ActionAddress > mActionAddresses
action addresses
virtual void Compile(void)
Compile input data for alternative representation.
virtual void IndentDec()
Indentation (convenience support for derived classes)
EventSet mStopEvents
Events that stop this timer.
word_t WordFromBitVector(const std::vector< bool > &vect, int wordindex)
Extract individual word from boolean vector.
std::map< std::string, LineAddress >::iterator LineIterator
Access to line records by iterator.
TimerIterator TimersBegin()
Access to timer records by iterator.
EventSet mInternalEvents
used events that are configured as internal events (excl.
std::map< int, Idx > mEventFaudesIdx
mapping from bit address to faudes event idx
Code-generator common base class.
virtual void DoCompile(void)
virtual hook to input parameter compilation
std::map< std::string, TimerConfiguration > mTimers
timer definitions
std::string EventName(Idx index) const
Faudes-event name lookup.
std::map< std::string, LineAddress > mLines
input event generation
LineIterator LinesBegin()
Access to line records by iterator.
Code-generation common base.
virtual void MuteVspace(bool on)
Mute empty lines (convenience support for derived classes)
std::string mInitialValue
Initial value (literal to allow for advanced units, empty string for "not a timer") ...
static void Register(const std::string &type, CodeGenerator *(*newcg)(void))
Insert derived class in the registry.
int mLastOutputEvent
highest bit-address with output event (-1 for none)
bool mMuteComments
mute comments
virtual int EventTargetIdx(Idx idx)
Get target event Idx from faudes Idx (use bit-address + 1)
virtual ~CodeGenerator(void)
Destructor.
std::vector< TimedGenerator > mGenerators
list of executors
int EventBitMaskSize(void)
Get overall number of events.
TimerIterator TimersEnd()
Access to timer records by iterator.