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() {
889 if(!pOutStream)
return;
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) {
Code-generator common base class.
Event attributes for the purpose of code generation.
TimeConstraint mTimeConstraint
Timer definition (indicate timer event iff mInitialValue non-empty)
EventSet mResetEvents
Events that reset this timer.
std::string mInitialValue
Initial value (literal to allow for advanced units, empty string for "not a timer")
EventSet mStopEvents
Events that stop this timer.
EventSet mStartEvents
Events that start this timer.
Code-generation common base.
std::string mOutMode
output file name (base)
virtual std::string LineCount(void)
LineFeed (convenience support for derived classes)
char mMuteMode
current output mode
std::string EventName(Idx index) const
Faudes-event name lookup.
virtual void LineFeed(int lines=1)
LineFeed (convenience support for derived classes)
virtual void XmlCdataEscape(bool on)
XmlCdataEscape (escape "]]>")
std::map< Idx, int > mEventBitAddress
mapping from faudes event idx to bit address (descending priority, range 0 .
int EventBitAddress(Idx idx)
Get event bit-address from faudes Idx (consecutive, starts at 0)
LineIterator LinesEnd()
Access to line records by iterator.
static std::vector< std::string > Registry(void)
Access registry contents.
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 XmlTextEscape(bool on)
XmlTextEscape (escape "<", ">", "&", "\"" and "'")
virtual void MuteComments(bool on)
Mute comments (convenience support for derived classes)
std::vector< std::map< int, Idx > > mStateFaudesIndex
mapping from vector state idx to faudes index
virtual void DoReadTargetConfiguration(TokenReader &rTr)
Reads global configuration from TokenReader, excl.
std::map< std::string, LineAddress >::iterator LineIterator
Access to line records by iterator.
virtual void DoGenerate(void)=0
pure virtual interface to code generation
std::ostream * pErrStream
error stream
std::string mRecentMutedComment
recent muted comment
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.
static CodeGenerator * New(const std::string &type)
Instantiate by identifier (returns 0 on unknown class)
TimerIterator TimersBegin()
Access to timer records by iterator.
static void Register(const std::string &type, CodeGenerator *(*newcg)(void))
Insert derived class in the registry.
virtual void IndentInc()
Indentation (convenience support for derived classes)
virtual ~CodeGenerator(void)
Destructor.
EventSet mOutputEvents
used events that are configured as outputs
TimerIterator TimersEnd()
Access to timer records by iterator.
Idx EventIndex(const std::string &rName) const
Faudes-event index lookup.
std::map< std::string, TimerConfiguration >::iterator TimerIterator
Access to timer records by iterator.
std::map< std::string, LineAddress > mLines
input event generation
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::map< int, Idx > mEventFaudesIdx
mapping from bit address to faudes event idx
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.
virtual void MuteMode(char mode)
Set current mute mode.
virtual void DoRead(TokenReader &rTr, const std::string &rLabel="", const Type *pContext=0)
Read the configuration from TokenReader, see faudes Type for public wrappers.
std::ostream * pOutStream
output stream
std::vector< TimedGenerator > mGenerators
list of executors
bool mMuteComments
mute comments
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 mVerbLevel
diagnpstic-output level
void Insert(const std::string &file)
Add a Generator from file.
int mIntegerSize
compressed boolean capacity of target type integer
std::map< std::string, ActionAddress > mActionAddresses
action addresses
EventSet mInputEvents
used events that are configured as inputs (incl timer)
FlagIterator FlagsEnd()
Access to flag records by iterator.
virtual std::ostream & Output(void)
Output stream.
std::map< std::string, TimerAction > mTimerActions
timer actions by event name
std::map< std::string, FlagExpression >::iterator FlagIterator
Access to flag records by iterator.
virtual void MuteCond(char mode)
Set mode condition.
std::vector< word_t > WordVectorFromBitVector(const std::vector< bool > &vect)
Convert boolean vector to word array.
void Verbose(int level, std::ostream *altout=0)
Set verbosity level.
virtual void MuteVspace(bool on)
Mute empty lines (convenience support for derived classes)
static std::string VersionString(void)
Version (refers to macro COMPILEDES_VERSION, defined in cgp_codegenerator.h)
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
virtual void Compile(void)
Compile input data for alternative representation.
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.
CodeGenerator(void)
Constructor.
virtual const std::string & Name(void) const
Get objects's name (reimplementing base faudes::Type)
const std::string & OutputString(void)
Get accumulated output as string.
virtual void Clear(void)
Clear all data.
const std::vector< int > & TransitionVector(size_t git)
Get target state index (refer to vector representation as default, overload in CodePrimitives)
std::vector< std::string > mGeneratorNames
list of filenames when generator are read from file
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
virtual void Generate(void)
Generate code.
const TimedGenerator & At(int i) const
Direct access for read-only access of generators.
virtual void IndentDec()
Indentation (convenience support for derived classes)
ActionAddressIterator ActionAddressesEnd()
Access to action addresses by iterator.
std::map< std::string, ActionAddress >::iterator ActionAddressIterator
Access to action record by iterator.
TimerActionIterator TimerActionsEnd()
Access to timer records by iterator.
virtual void DoWriteTargetConfiguration(TokenWriter &rTw) const
Write global configuration to TokenWriter, excl.
ActionAddressIterator ActionAddressesBegin()
Access to action addresses by iterator.
std::map< std::string, FlagExpression > mFlags
input event generation
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.