void vld_iter_vol (int (*func)(volume_handle *vol, void *arg), void *arg) { struct iter_vol_s vof; vof.func = func; vof.arg = arg; listiter (vol_list, iter_vol, &vof); }
void Sim_UsageCheck(tExecUnit *Root) { struct sUsage { int nSet; int nRead; } *usage; int nValues = 0; tLink **links; tElement **elements; GetLists(Root, &links, &elements, NULL); for( tLink *link = *links; link; link = link->Next ) link->Link = NULL; // Count values and allocate count space for( tLink *link = *links; link; link = link->Next ) { if(link->Link) continue; link->Link = link; for(tLink *l2 = link->Next; l2; l2 = l2->Next) { if(l2->Value == link->Value) l2->Link = link; } nValues ++; } usage = calloc(nValues, sizeof(*usage)); // Set the ->Link field to the usage structure { int i = 0; for( tLink *link = *links; link; link = link->Next ) { if( link->Link == link ) { assert(i < nValues); link->Value->Info = (void*)&usage[i++]; // '0' and '1' are suppressed if( Build_IsConstValue(link->Value) ) { usage[i-1].nRead = 1; usage[i-1].nSet= 1; } } else { } } } #define listiterv(count,items,field) do{\ for(int i=0;i<count;i++)\ ((struct sUsage*)(items)[i]->Value->Info)->field++;\ }while(0) #define listiter(list,field) listiterv(list.NItems, list.Items, field) // Mark inputs/outputs listiter(Root->Inputs, nSet); listiter(Root->Outputs, nRead); // Mark #display items for( tDisplayItem *disp = Root->DisplayItems; disp; disp = disp->Next ) { listiter(disp->Condition, nRead); listiter(disp->Values, nRead); } // Mark #testassert items for(tAssertion *a = Root->Assertions; a; a = a->Next) { listiter(a->Condition, nRead); listiter(a->Expected, nRead); listiter(a->Values, nRead); } // ((struct sUsage*)Root->CompletionCondition->Value->Info)->++; // listiter(Root->CompletionCond, nRead); // Iterate over elements for( tElement *ele = *elements; ele; ele = ele->Next ) { listiterv(ele->NInputs, ele->Inputs, nRead); listiterv(ele->NOutputs, ele->Outputs, nSet); } // Iterate over sub-units for( tExecUnitRef *ref = Root->SubUnits; ref; ref = ref->Next ) { listiter(ref->Inputs, nRead); listiter(ref->Outputs, nSet); } #undef listiter #undef listiterv // Complain for links that are not set/read for( tLink *link = *links; link; link = link->Next ) { assert(link != link->Next); assert(link->Link); assert(link->Value); assert(link->Value->Info); if(link->Link != link) continue ; struct sUsage *u = (void*)link->Value->Info; if( u->nSet && u->nRead ) { // Fully used, good } else { fprintf(stderr, "[%i,%i] Link set %s:(", u->nSet, u->nRead, Root->Name); assert(link->Value->FirstLink); for( tLink *l2 = link->Value->FirstLink; l2; l2 = l2->ValueNext ) { if( l2->Name[0] == '\0' ) fprintf(stderr, "%p", l2); else fprintf(stderr, "'%s'", l2->Name); if( l2->ValueNext ) fprintf(stderr, ","); } if( u->nSet ) { fprintf(stderr, ") is never read\n"); #if 0 for( tElement *ele = *elements; ele; ele = ele->Next ) { for( int i = 0; i < ele->NOutputs; i ++ ) { if( ele->Outputs[i]->Value == link->Value ) fprintf(stderr, "- %s %s...\n", ele->Type->Name, ele->Inputs[0]->Name); } } #endif } else if( u->nRead ) fprintf(stderr, ") is never set\n"); else fprintf(stderr, ") is never used\n"); } link->Link = NULL; } for(int i = 0; i < Root->Inputs.NItems; i ++) { if( ((struct sUsage*)Root->Inputs.Items[i]->Value->Info)->nSet != 1 ) fprintf(stderr, "notice: Input link %s:'%s' set\n", Root->Name, Root->Inputs.Items[i]->Name); } free(usage); }