00001 #include "stdafx.h"
00002 #include <stdio.h>
00003 #include "BONComponent.h"
00004
00005 #define DEFAULT_PRIORITY 100
00006
00007 #define INT_TYPE 0 // must match order in edf
00008 #define DOUBLE_TYPE 1
00009 #define CHAR_TYPE 2
00010 #define POINTER_TYPE 3
00011
00012 int idCounter = 0;
00013 CParameterList CParameterBuilder::instances;
00014 CPrimitiveTable CPrimitiveBuilder::contextTable;
00015
00016 bool IsValidName(const char *name)
00017 {
00018 char c = *(name++);
00019 if(!__iscsymf(c))
00020 return false;
00021 while((c = *(name++)) != 0)
00022 if(!iscsym(c))
00023 return false;
00024 return true;
00025 }
00026
00027 void CComponent::CheckScriptTypes (CPrimitiveList* primitives)
00028 {
00029 ScriptCollection keepAcuracy;
00030 ScriptDescriptor* currentDescription;
00031 const CBuilderAtomList* inparams;
00032 const CBuilderAtomList* params;
00033
00034 POSITION listPos = primitives->GetHeadPosition();
00035
00036 while (listPos)
00037 {
00038 CPrimitiveBuilder *primitive = primitives->GetNext(listPos);
00039
00040 if (primitive->GetName())
00041 {
00042 inparams = primitive->GetAtoms("InputParameters");
00043 params = primitive->GetAtoms("Parameters");
00044 int numberParams = inparams->GetCount() + params->GetCount();
00045 if (numberParams > 0) {
00046 POSITION inparamPos = inparams->GetHeadPosition();
00047 currentDescription = new ScriptDescriptor(primitive->GetName(), primitive->GetScriptName(), numberParams);
00048
00049 while (inparamPos)
00050 {
00051 CInputParameterBuilder* inparam = (CInputParameterBuilder*)inparams->GetNext(inparamPos);
00052 currentDescription->AddParamLine(inparam->GetName(),inparam->GetPartName(), inparam->GetSize(), inparam->GetDataType());
00053 }
00054
00055 POSITION paramPos = params->GetHeadPosition();
00056
00057 while (paramPos)
00058 {
00059 CParameterBuilder* param = (CParameterBuilder*)params->GetNext(paramPos);
00060 currentDescription->AddParamLine(param->GetName(), param->GetPartName(), param->GetSize(), param->GetDataType());
00061 }
00062 int isOk = keepAcuracy.AddDescriptor(currentDescription);
00063 if (isOk)
00064 { AfxMessageBox("The primitive model " + primitive->GetName() + " with script: '" + primitive->GetScriptName() + "' has different parameters than " + keepAcuracy.GetModelName(isOk - 1) + " which has the same script name."); }
00065 }
00066
00067 }
00068 }
00069
00070 }
00071
00072 void CComponent::InvokeEx(CBuilder &builder,CBuilderObject *focus, CBuilderObjectList &selected, long param)
00073 {
00074
00075
00076 if (!focus && !selected.IsEmpty()) {
00077 focus = selected.GetHead();
00078 }
00079 if(!focus || !focus->IsKindOf(RUNTIME_CLASS(CCompoundBuilder))) {
00080 AfxMessageBox("Interpretation must start from a Compound model!");
00081 return;
00082 }
00083
00084 CString filebase = focus->GetName();
00085 CString cfile = filebase + ".c";
00086 CString hfile = filebase + ".h";
00087
00088
00089
00090 CPrimitiveList primitives;
00091 ((CProcessingBuilder *)focus)->Traverse(primitives);
00092
00093 CheckScriptTypes(&primitives);
00094
00095 FILE *fpt = fopen(hfile,"wt");
00096 if(!fpt) {
00097 AfxMessageBox("Error opening file " + hfile);
00098 return;
00099 }
00100
00101 CPrimitiveBuilder::WriteScriptProto(fpt);
00102 CPrimitiveBuilder::WriteContextDefs(fpt);
00103 CParameterBuilder::WriteGlobals(fpt);
00104 fprintf(fpt,"\n");
00105
00106 POSITION pos = primitives.GetHeadPosition();
00107 while(pos)
00108 primitives.GetNext(pos)->WriteContextCreate(fpt);
00109
00110
00111
00112 fclose(fpt);
00113
00114 fpt = fopen(cfile,"wt");
00115 if(!fpt) {
00116 AfxMessageBox("Error opening file " + cfile);
00117 return;
00118 }
00119
00120 fprintf(fpt,"#include <string.h>\n");
00121 fprintf(fpt,"#include <mgk60.h>\n");
00122 fprintf(fpt,"#include \"%s\"\n\n",hfile);
00123
00124 CParameterBuilder::WriteGlobals(fpt,false);
00125 fprintf(fpt,"\n");
00126
00127 pos = primitives.GetHeadPosition();
00128 while(pos)
00129 primitives.GetNext(pos)->WriteContextCreate(fpt,false);
00130 fprintf(fpt,"\n");
00131
00132 fprintf(fpt,"\nvoid register_scripts()\n{\n");
00133 CPrimitiveBuilder::WriteScriptRegs(fpt);
00134 fprintf(fpt,"}\n\n");
00135
00136 fprintf(fpt,"\nvoid build()\n{\n");
00137
00138 pos = primitives.GetHeadPosition();
00139 while(pos)
00140 primitives.GetNext(pos)->WriteActorCreate(fpt);
00141 fprintf(fpt,"\n");
00142
00143 pos = primitives.GetHeadPosition();
00144 while(pos)
00145 primitives.GetNext(pos)->WriteSetContext(fpt);
00146 fprintf(fpt,"\n");
00147
00148 pos = primitives.GetHeadPosition();
00149 while(pos)
00150 primitives.GetNext(pos)->WriteActorConnect(fpt);
00151
00152 fprintf(fpt,"}\n");
00153 fclose(fpt);
00154
00155 AfxMessageBox(cfile + " and " + hfile + " generated");
00156
00157 idCounter = 0;
00158 }
00159
00161
00162 IMPLEMENT_CUSTOMMODEL(CProcessingBuilder, CBuilderModel, "")
00163
00164 IMPLEMENT_CUSTOMMODEL(CCompoundBuilder, CProcessingBuilder, "Compound")
00165
00166 void CCompoundBuilder::Traverse(CPrimitiveList &primitives)
00167 {
00168 if(!IsValidName((LPCTSTR)GetName()))
00169 DisplayError("Invalid Name! You Must Use C Syntax!");
00170 const CBuilderModelList *list = GetModels();
00171 POSITION pos = list->GetHeadPosition();
00172 while(pos)
00173 ((CProcessingBuilder *)(list->GetNext(pos)))->Traverse(primitives);
00174 }
00175
00176 void CCompoundBuilder::Initialize()
00177 {
00178 }
00179
00180 IMPLEMENT_CUSTOMMODEL(CPrimitiveBuilder,CProcessingBuilder, "Primitive")
00181
00182 void CPrimitiveBuilder::Initialize()
00183 {
00184 firing = 0;
00185
00186 if(!IsValidName((LPCTSTR)GetName()))
00187 DisplayError("Invalid Name! You Must Use C Syntax!");
00188
00189 static bool init = false;
00190 if(!init) {
00191 contextTable.InitHashTable(29);
00192 init = true;
00193 }
00194 }
00195
00196 CPrimitiveBuilder::~CPrimitiveBuilder()
00197 {
00198 contextTable.RemoveAll();
00199 }
00200
00201 void CPrimitiveBuilder::SetPriority()
00202 {
00203 priority = DEFAULT_PRIORITY;
00204 CString number;
00205 if(!GetAttribute("Priority",priority))
00206 DisplayError("Error getting Priority attribute!");
00207 }
00208
00209 void CPrimitiveBuilder::SetScript()
00210 {
00211 if(!GetAttribute("Script",script))
00212 DisplayError("Error getting Script attribute!");
00213 else {
00214 CPrimitiveBuilder *cntxdef = 0;
00215 if(!contextTable.Lookup(script,cntxdef))
00216 contextTable[script] = this;
00217 }
00218 }
00219
00220 void CPrimitiveBuilder::SetFiring()
00221 {
00222
00223 if(!GetAttribute("Firing",firing))
00224 DisplayError("Error getting Firing Condition attribute!");
00225 }
00226
00227 void CPrimitiveBuilder::SetActorName()
00228 {
00229 char txt[32];
00230 sprintf(txt,"_actor_%d",id);
00231 actorName = GetName() + txt;
00232 }
00233
00234 void CPrimitiveBuilder::SetPorts(const CBuilderAtomList *ports)
00235 {
00236 POSITION outer = ports->GetHeadPosition();
00237 while(outer) {
00238 CSignalBuilder *p1 = (CSignalBuilder *)(ports->GetNext(outer));
00239 POSITION inner = outer;
00240 while(inner) {
00241 CSignalBuilder *p2 = (CSignalBuilder *)(ports->GetNext(inner));
00242 ((p1->yloc >= p2->yloc) ? p1 : p2)->IncrementPort();
00243 }
00244 }
00245 }
00246
00247 void CPrimitiveBuilder::Traverse(CPrimitiveList &primitives)
00248 {
00249 primitives.AddTail(this);
00250 id = idCounter++;
00251 SetScript();
00252 SetPriority();
00253 SetFiring();
00254 SetActorName();
00255
00256 const CBuilderAtomList *list = GetAtoms("OutputSignals");
00257 ASSERT(list);
00258 outputPortNo = list->GetCount();
00259 POSITION pos = list->GetHeadPosition();
00260 int n = 0;
00261 while(pos) {
00262 CSignalBuilder *signal = (CSignalBuilder *)(list->GetNext(pos));
00263 signal->SetLocation();
00264 CBuilderAtomicObjectList conns;
00265 signal->GetDirectOutConnections("DataflowConn",conns);
00266 if(conns.IsEmpty())
00267 DisplayError("OutputSignal " + signal->GetName() + " not connected!");
00268 POSITION connPos = conns.GetHeadPosition();
00269 while(connPos) {
00270 CSignalBuilder *dst = (CSignalBuilder *)(conns.GetNext(connPos));
00271 ASSERT(dst);
00272 if(dst->GetParent()->IsKindOf(RUNTIME_CLASS(CPrimitiveBuilder))) {
00273 signal->AddConnection(dst);
00274 dst->AddConnection(signal);
00275 }
00276 }
00277 conns.RemoveAll();
00278 }
00279 SetPorts(list);
00280
00281 list = GetAtoms("InputSignals");
00282 ASSERT(list);
00283 inputPortNo = list->GetCount();
00284 pos = list->GetHeadPosition();
00285 n = 0;
00286 while(pos) {
00287 CSignalBuilder *signal = (CSignalBuilder *)(list->GetNext(pos));
00288 signal->SetLocation();
00289 }
00290 SetPorts(list);
00291
00292 list = GetAtoms("Parameters");
00293 ASSERT(list);
00294 pos = list->GetHeadPosition();
00295 while(pos) {
00296 CParameterBuilder *parameter = (CParameterBuilder *)(list->GetNext(pos));
00297 parameter->AddToList();
00298 parameters.AddTail(parameter);
00299 }
00300 list = GetAtoms("InputParameters");
00301 ASSERT(list);
00302 pos = list->GetHeadPosition();
00303 while(pos) {
00304 CInputParameterBuilder *inp = (CInputParameterBuilder *)(list->GetNext(pos));
00305 inputParameters.AddTail(inp);
00306 CBuilderAtomicObjectList conns;
00307 inp->GetDirectInConnections("ParameterConn",conns);
00308 if(conns.IsEmpty())
00309 DisplayError("InputParameter " + inp->GetName() + " not connected!");
00310 else {
00311 if(conns.GetCount() > 1)
00312 DisplayError("InputParameter " + inp->GetName() + " connected multiple times!");
00313 CBuilderAtom *src = (CBuilderAtom *)(conns.GetHead());
00314 ASSERT(src);
00315 if(src->IsKindOf(RUNTIME_CLASS(CParameterBuilder))) {
00316 inp->source = (CParameterBuilder *)src;
00317 inp->source->AddToList();
00318 }
00319 else
00320 DisplayError("InputParameter " + inp->GetName() + " not connected to a Parameter!");
00321 }
00322 }
00323 }
00324
00325 void CPrimitiveBuilder::WriteScriptRegs(FILE *fpt)
00326 {
00327 POSITION pos = contextTable.GetStartPosition();
00328 while(pos) {
00329 CPrimitiveBuilder *prim = 0;
00330 CString nm;
00331 contextTable.GetNextAssoc(pos,nm,prim);
00332 fprintf(fpt," mgk_register_script(%s,\"%s\");\n",prim->script,prim->script);
00333 }
00334 }
00335
00336 void CPrimitiveBuilder::WriteScriptProto(FILE *fpt)
00337 {
00338 POSITION pos = contextTable.GetStartPosition();
00339 while(pos) {
00340 CPrimitiveBuilder *prim = 0;
00341 CString nm;
00342 contextTable.GetNextAssoc(pos,nm,prim);
00343 fprintf(fpt,"extern void %s(void);\n",prim->script);
00344 }
00345 fprintf(fpt,"\n");
00346 }
00347
00348 void CPrimitiveBuilder::WriteContextDefs(FILE *fpt)
00349 {
00350 POSITION pos = contextTable.GetStartPosition();
00351 while(pos) {
00352 CPrimitiveBuilder *prim = 0;
00353 CString nm;
00354 contextTable.GetNextAssoc(pos,nm,prim);
00355 prim->WriteContextDef(fpt);
00356 }
00357 }
00358
00359 void CPrimitiveBuilder::WriteContextDef(FILE *fpt)
00360 {
00361 if(parameters.IsEmpty() && inputParameters.IsEmpty())
00362 return;
00363 fprintf(fpt,"typedef struct {\n");
00364 POSITION pos = parameters.GetHeadPosition();
00365 while(pos) {
00366 CParameterBuilder *parameter = parameters.GetNext(pos);
00367 parameter->WriteContextDef(fpt,parameter->GetName());
00368 }
00369 pos = inputParameters.GetHeadPosition();
00370 while(pos) {
00371 CInputParameterBuilder *parameter = inputParameters.GetNext(pos);
00372 if(parameter->source)
00373 parameter->source->WriteContextDef(fpt,parameter->GetName());
00374 else
00375 fprintf(fpt,"/* ERROR: InputParameter %s not connected! */\n",parameter->GetName());
00376 }
00377 fprintf(fpt,"} %s_context;\n\n",script);
00378 }
00379
00380 void CPrimitiveBuilder::WriteContextCreate(FILE *fpt,bool ext)
00381 {
00382 if(parameters.IsEmpty() && inputParameters.IsEmpty())
00383 return;
00384 fprintf(fpt,"%s%s_context %s_context;\n",ext ? "extern " : "",script,actorName);
00385 }
00386
00387 void CPrimitiveBuilder::WriteSetContext(FILE *fpt)
00388 {
00389 if(parameters.IsEmpty() && inputParameters.IsEmpty())
00390 return;
00391 POSITION pos = parameters.GetHeadPosition();
00392 while(pos) {
00393 CParameterBuilder *parameter = parameters.GetNext(pos);
00394 parameter->WriteContextInit(fpt,actorName,parameter->GetName());
00395 }
00396 pos = inputParameters.GetHeadPosition();
00397 while(pos) {
00398 CInputParameterBuilder *parameter = inputParameters.GetNext(pos);
00399 if(parameter->source)
00400 parameter->source->WriteContextInit(fpt,actorName,parameter->GetName());
00401 }
00402 fprintf(fpt," mgk_set_node_context( %s, &%s_context,T_ARRAY(sizeof(%s_context)) | T_CHAR);\n",
00403 actorName,
00404 actorName,
00405 script);
00406 }
00407
00408 void CPrimitiveBuilder::WriteActorCreate(FILE *fpt)
00409 {
00410 char scr[128];
00411 sprintf(scr,"\"%s\"",script);
00412 fprintf(fpt," mgk_nodep %-18s = mgk_create_node_indirect( %-18s,%3d,%3d,%4d, %s, 0 );\n",
00413 actorName,scr,inputPortNo,outputPortNo,priority,firing ? "AT_IFANY" : "AT_IFALL");
00414 }
00415
00416 void CPrimitiveBuilder::WriteActorConnect(FILE *fpt)
00417 {
00418 const CBuilderAtomList *list = GetAtoms("OutputSignals");
00419 POSITION pos = list->GetHeadPosition();
00420 while(pos) {
00421 CSignalBuilder *signal = (CSignalBuilder *)(list->GetNext(pos));
00422 POSITION dstPos = signal->connections.GetHeadPosition();
00423 while(dstPos) {
00424 CSignalBuilder *dst = signal->connections.GetNext(dstPos);
00425 fprintf(fpt," mgk_connect_nodes( %-18s,%3d, %-18s,%3d );\n",
00426 actorName,signal->port,
00427 ((CPrimitiveBuilder *)dst->GetParent())->GetActorName(),dst->port);
00428 }
00429 }
00430 }
00431
00432 IMPLEMENT_CUSTOMATOM(CSignalBuilder,CBuilderAtom,"InputSignal,OutputSignal")
00433
00434 void CSignalBuilder::SetLocation()
00435 {
00436 CRect loc;
00437 if(!GetLocation(CString("SignalFlowAspect"),loc))
00438 DisplayError("Error Getting Location!");
00439 yloc = loc.top;
00440 }
00441
00442 IMPLEMENT_CUSTOMATOM(CParameterBuilder,CBuilderAtom,"Param")
00443
00444 void CParameterBuilder::Initialize()
00445 {
00446 listed = false;
00447
00448 if(!IsValidName((LPCTSTR)GetName()))
00449 DisplayError("Invalid Name! You Must Use C Syntax!");
00450
00451 GetNamePath(longName);
00452
00453 if(!GetAttribute("Global",global))
00454 DisplayError("Error getting Global attribute!");
00455
00456 CString tempDT;
00457 if(!GetAttribute("DataType",tempDT))
00458 DisplayError("Error getting Datatype attribute!");
00459
00460 if (tempDT == "Integer") datatype = 0;
00461 else if (tempDT == "Double") datatype = 1;
00462 else if (tempDT == "Character") datatype = 2;
00463 else if (tempDT == "Pointer") datatype = 3;
00464
00465 if(!GetAttribute("Size",size))
00466 DisplayError("Error getting Size attribute!");
00467 if(size < 1) {
00468 size = 1;
00469 DisplayWarning("Size attribute out of range. Resetting to 1");
00470 }
00471 else if(size > 1024) {
00472 size = 1024;
00473 DisplayWarning("Size attribute out of range. Resetting to 1024");
00474 }
00475
00476 if(!GetAttribute("InitValue",initval))
00477 DisplayError("Error getting Initial Value attribute!");
00478 }
00479
00480 CParameterBuilder::~CParameterBuilder()
00481 {
00482 instances.RemoveAll();
00483 }
00484
00485 void CParameterBuilder::AddToList()
00486 {
00487 if(!listed) {
00488 instances.AddTail(this);
00489 listed = true;
00490 }
00491 }
00492
00493 void CParameterBuilder::WriteGlobals(FILE *fpt,bool ext)
00494 {
00495 POSITION pos = instances.GetHeadPosition();
00496 while(pos)
00497 instances.GetNext(pos)->WriteGlobal(fpt,ext);
00498 }
00499
00500 void CParameterBuilder::WriteGlobal(FILE *fpt,bool ext)
00501 {
00502 if(datatype == POINTER_TYPE)
00503 return;
00504 if(global || (!ext && size > 1 && !initval.IsEmpty())) {
00505 char *type = (datatype == INT_TYPE) ?
00506 "int" : (datatype == DOUBLE_TYPE) ?
00507 "double" :
00508 "char";
00509 if(size > 1) {
00510 fprintf(fpt,"%s%s %s[%d]",ext ? "extern " : "",type,longName,size);
00511 if(initval.IsEmpty() || ext)
00512 fprintf(fpt,";\n");
00513 else if(datatype == CHAR_TYPE)
00514 fprintf(fpt," = \"%s\";\n",initval);
00515 else
00516 fprintf(fpt," = { %s };\n",initval);
00517 }
00518 else {
00519 fprintf(fpt,"%s%s %s",ext ? "extern " : "",type,longName);
00520 if(!ext) {
00521 if(datatype == CHAR_TYPE)
00522 fprintf(fpt," = '%s';\n",initval.IsEmpty() ? "\\0" : initval);
00523 else
00524 fprintf(fpt," = %s;\n",initval.IsEmpty() ? "0" : initval);
00525 }
00526 else
00527 fprintf(fpt,";\n");
00528 }
00529 }
00530 }
00531
00532 void CParameterBuilder::WriteContextDef(FILE *fpt,const CString &fieldName)
00533 {
00534 if(datatype == POINTER_TYPE) {
00535 fprintf(fpt," void *%s;\n",fieldName);
00536 return;
00537 }
00538 char *type = (datatype == INT_TYPE) ?
00539 "int" : (datatype == DOUBLE_TYPE) ?
00540 "double" :
00541 "char";
00542 char field[64];
00543 if(global && size > 1)
00544 sprintf(field,"(*%s)",fieldName);
00545 else
00546 sprintf(field,"%s%s",global ? "*" : " ",fieldName);
00547 char subs[64] = "";
00548 if(size > 1)
00549 sprintf(subs,"[%d]",size);
00550 fprintf(fpt," %s %s%s;\n",type,field,subs);
00551 }
00552
00553 void CParameterBuilder::WriteContextInit(FILE *fpt,CString &actorName,const CString &fieldName)
00554 {
00555 if(datatype == POINTER_TYPE)
00556 fprintf(fpt," %s_context.%s = 0;\n",actorName,fieldName);
00557 else if(global)
00558 fprintf(fpt," %s_context.%s = &%s;\n",actorName,fieldName,longName);
00559 else if(!initval.IsEmpty()) {
00560 if(size > 1)
00561 fprintf(fpt," memcpy(%s_context.%s,%s,sizeof(%s));\n",actorName,fieldName,longName,longName);
00562 else {
00563 fprintf(fpt," %s_context.%s",actorName,fieldName);
00564 if(datatype == CHAR_TYPE)
00565 fprintf(fpt," = '%s';\n",initval);
00566 else
00567 fprintf(fpt," = %s;\n",initval);
00568 }
00569 }
00570 }
00571
00572 IMPLEMENT_CUSTOMATOM(CInputParameterBuilder,CBuilderAtom,"InputParam")
00573
00574 void CInputParameterBuilder::Initialize()
00575 {
00576 source = 0;
00577
00578 if(!IsValidName((LPCTSTR)GetName()))
00579 DisplayError("Invalid Name! You Must Use C Syntax!");
00580
00581 CString tempDT;
00582 if(!GetAttribute("DataType",tempDT))
00583 DisplayError("Error getting Datatype attribute!");
00584
00585 if (tempDT == "Integer") datatype = 0;
00586 else if (tempDT == "Double") datatype = 1;
00587 else if (tempDT == "Character") datatype = 2;
00588 else if (tempDT == "Pointer") datatype = 3;
00589
00590 CString number;
00591 if(!GetAttribute("Size",size))
00592 DisplayError("Error getting Size attribute!");
00593 if(size < 1) {
00594 size = 1;
00595 DisplayWarning("Size attribute out of range. Resetting to 1");
00596 }
00597 else if(size > 1024) {
00598 size = 1024;
00599 DisplayWarning("Size attribute out of range. Resetting to 1024");
00600 }
00601
00602 }
00603
00604