/* to take over. */ void E2FilterIORB (PIORB pIORB) { NPRecHeader pUnitRec; /* Ptr to unit rec for IORB */ NPIORBQueue pQueue; /* Ptr to queue for IORB */ if (pIORB->CommandCode==IOCC_CONFIGURATION) /* For configuration IORBs: */ pUnitRec= (NPRecHeader) VirtUnits; /* Assign IORB to the first */ /* virtual unit. (For queue) */ else pUnitRec= (NPRecHeader) pIORB->UnitHandle; /* Get pointer to unit */ /* from the unit handle */ /* Check to see if pUnitRec is a pointer to a valid unit record. */ if (!(IS_ELEMENT(pUnitRec,BaseUnits,NumBaseUnits)|| IS_ELEMENT(pUnitRec,VirtUnits,NumVirtUnits))) { IORBError (pIORB,IOERR_NO_SUCH_UNIT); /* Tell them they are crazy! */ NotifyDone (pIORB); /* Notify that we are done */ } else { pQueue= &(pUnitRec->IORBQueue); /* Get pointer to IORB queue */ DISABLE /* Same safety... */ AddIORBToQueue (pQueue,pIORB); /* Add IORB to queue */ ENABLE /* Re-enable interrupts */ StartIORBQueue (pQueue); /* Try to restart the queue */ } }
/* %start-doc actions SmartDisperse The @code{SmartDisperse([All|Selected])} action is a special-purpose optimization for dispersing elements. Run with @code{:SmartDisperse()} or @code{:SmartDisperse(Selected)} (you can also say @code{:SmartDisperse(All)}, but that's the default). %end-doc */ static int smartdisperse (int argc, char **argv, Coord x, Coord y) { char *function = ARG(0); NetListType *Nets; char *visited; // PointerListType stack = { 0, 0, NULL }; int all; // int changed = 0; // int i; if (! function) { all = 1; } else if (strcmp(function, "All") == 0) { all = 1; } else if (strcmp(function, "Selected") == 0) { all = 0; } else { AFAIL (smartdisperse); } Nets = ProcNetlist (&PCB->NetlistLib); if (! Nets) { Message (_("Can't use SmartDisperse because no netlist is loaded.\n")); return 0; } /* remember which elements we finish with */ visited = calloc (PCB->Data->ElementN, sizeof(*visited)); /* if we're not doing all, mark the unselected elements as "visited" */ ELEMENT_LOOP (PCB->Data); { if (! (all || TEST_FLAG (SELECTEDFLAG, element))) { visited[n] = 1; } } END_LOOP; /* initialize variables for place() */ minx = GAP; miny = GAP; maxx = GAP; maxy = GAP; /* * Pick nets with two connections. This is the start of a more * elaborate algorithm to walk serial nets, but the datastructures * are too gross so I'm going with the 80% solution. */ NET_LOOP (Nets); { ConnectionType *conna, *connb; ElementType *ea, *eb; // ElementType *epp; if (net->ConnectionN != 2) continue; conna = &net->Connection[0]; connb = &net->Connection[1]; if (!IS_ELEMENT(conna) || !IS_ELEMENT(conna)) continue; ea = (ElementType *) conna->ptr1; eb = (ElementType *) connb->ptr1; /* place this pair if possible */ if (VISITED((GList *)ea) || VISITED((GList *)eb)) continue; VISITED ((GList *)ea) = 1; VISITED ((GList *)eb) = 1; /* a weak attempt to get the linked pads side-by-side */ if (padorder(conna, connb)) { place ((ElementType *) ea); place ((ElementType *) eb); } else { place (eb); place (ea); } } END_LOOP; /* Place larger nets, still grouping by net */ NET_LOOP (Nets); { CONNECTION_LOOP (net); { ElementType *element; if (! IS_ELEMENT(connection)) continue; element = (ElementType *) connection->ptr1; /* place this one if needed */ if (VISITED ((GList *) element)) continue; VISITED ((GList *) element) = 1; place (element); } END_LOOP; } END_LOOP; /* Place up anything else */ ELEMENT_LOOP (PCB->Data); { if (! visited[n]) { place (element); } } END_LOOP; free (visited); IncrementUndoSerialNumber (); Redraw (); SetChangedFlag (1); return 0; }
/* being serviced before entering the service loop. */ void StartIORBQueue (NPIORBQueue pQueue) { PIORB pIORB; /* Ptr to IORB to execute */ NPRecHeader pUnitRec; /* Pointer to unit record */ DISABLE if (!(pQueue->Flags&F_SERVER_ACTIVE)) /* Check to no one is busy */ /* servicing this queue */ { pQueue->Flags|=F_SERVER_ACTIVE; /* Grap control of queue */ /* If we get where we have exclusize access to the queue. */ while ((!(pQueue->Flags&F_REQUEST_BUSY))&& ((pIORB= GetIORBFromQueue (pQueue))!=NULL)) /* Loop while there is an */ /* IORB ready to be serviced */ /* and the previous IORB is */ /* finished. */ { pQueue->Flags|=F_REQUEST_BUSY; /* Show request in progress */ ENABLE if (pIORB->CommandCode==IOCC_CONFIGURATION) /* For configuration IORBs: */ pUnitRec= (NPRecHeader) VirtUnits; /* Assign IORB to the first */ /* virtual unit. (For queue) */ else pUnitRec= (NPRecHeader) pIORB->UnitHandle; /* Get pointer to unit */ /* from the unit handle */ /* We will handle (de)allocation and allocation checks here since it is */ /* common between the two parts- filter and virtual units. */ if (pIORB->CommandCode==IOCC_UNIT_CONTROL) /* Unit control command? */ { if (pIORB->CommandModifier==IOCM_ALLOCATE_UNIT) { /* Allocate unit??? */ if (pUnitRec->Flags&F_ALLOCATED) IORBError (pIORB,IOERR_UNIT_ALLOCATED); /* Error if allocated */ else pUnitRec->Flags|=F_ALLOCATED; /* Else allocate the unit */ pQueue->Flags&=~F_REQUEST_BUSY; /* Indicate queue finished */ NotifyDone (pIORB); continue; /* Service next request */ } if (pIORB->CommandModifier==IOCM_DEALLOCATE_UNIT) { /* Deallocate unit??? */ if (!(pUnitRec->Flags&F_ALLOCATED)) IORBError (pIORB,IOERR_UNIT_NOT_ALLOCATED); /* Error if not allocated */ else pUnitRec->Flags&=~F_ALLOCATED; /* Else deallocate unit */ pQueue->Flags&=~F_REQUEST_BUSY; /* Indicate queue finished */ NotifyDone (pIORB); continue; /* Service next request */ } } /* Do allocations checks... if notify points to us, skip check. */ if (!(pUnitRec->Flags&F_ALLOCATED)) /* If unit is not allocated: */ if (pIORB->NotifyAddress!=&PartNotifyWrapper) /* and we didn't make request */ if (pIORB->CommandCode!=IOCC_CONFIGURATION) /* and not configuration */ { IORBError (pIORB,IOERR_UNIT_NOT_ALLOCATED); /* Then it is an error */ pQueue->Flags&=~F_REQUEST_BUSY; /* Indicate queue finished */ NotifyDone (pIORB); continue; /* Service next request */ } if (IS_ELEMENT(pUnitRec,BaseUnits,NumBaseUnits)) FilterHandler (pIORB); /* Handler for base units */ else if (IS_ELEMENT(pUnitRec,VirtUnits,NumVirtUnits)) PartHandler (pIORB); /* Handler for virtual units */ DISABLE } /* Tell others that this server is not active any more... */ pQueue->Flags&=~F_SERVER_ACTIVE; }