public int HandleFinishingOperations(Block nextOperation, int currentTime, Assay assay) { /*(*)TODO fix edge case, where the drops are routed/operations are scheduled, * so that in the mean time, some operations finishes. This might lead to routing problems. */ //If some operations finishes (or one needs to wait for this to happen, before any more scheduling can happen), //the board needs to be saved: if (AreOperationsFinishing(currentTime, assay) && !(nextOperation is VariableBlock)) { rectanglesAtDifferentTimes.Add(currentTime, board.CopyAllRectangles()); } //In the case that operations are finishing (or there are no operations that can be executed, before this is true), //the finishing operations droplets needs to be placed on the board, //and operations that now might be able to run, needs to be marked as such: while (AreOperationsFinishing(currentTime, assay)) { List <FluidBlock> nextBatchOfFinishedOperations = GetNextBatchOfFinishedOperations(); //In the case that the operations have finished while routing was performed, //it is still impossible to go back in time. Therefore, the max of the two are chosen. currentTime = Math.Max(nextBatchOfFinishedOperations.Last().EndTime + 1, currentTime + 1); foreach (var finishedOperation in nextBatchOfFinishedOperations) { BoardFluid dropletOutputFluid; if (!(finishedOperation is StaticUseageBlock)) { //If a module is not static, and it is not used anymore, it is "disolved", //leaving the droplets that is inside the module behind: finishedOperation.UpdateInternalDropletConcentrations(); (dropletOutputFluid, currentTime) = RecordNewFluidType(finishedOperation.OutputVariable, currentTime, finishedOperation); List <Droplet> replacingDroplets = board.replaceWithDroplets(finishedOperation.BoundModule, dropletOutputFluid); } else { if (finishedOperation is HeaterUsage heaterOperation) { //When a heater operation has finished, the droplets inside the heater needs to be moved out of the module, //so that it can be used again, by other droplets: //General method: //ExtractInternalDropletsAndPlaceThemOnTheBoard(board, finishedOperation); //For the special case that the heater has size 3x3, with only one droplet inside it: (dropletOutputFluid, currentTime) = RecordNewFluidType(finishedOperation.OutputVariable, currentTime, finishedOperation); Droplet droplet = new Droplet(dropletOutputFluid); droplet.SetFluidConcentrations(heaterOperation.InputRoutes.First().Value.First().routedDroplet); bool couldBePlaced = board.FastTemplatePlace(droplet); //Temporarily placing a droplet on the initial position of the heater, for routing purposes: Droplet routingDroplet = new Droplet(new BoardFluid("Routing @ droplet")); routingDroplet.Shape = Rectangle.Translocate(routingDroplet.Shape, heaterOperation.BoundModule.Shape.x, heaterOperation.BoundModule.Shape.y); board.UpdateGridAtGivenLocation(routingDroplet, heaterOperation.BoundModule.Shape); if (!couldBePlaced) { throw new RuntimeException("Not enough space available to place a Droplet."); } Route dropletRoute = Router.RouteDropletToNewPosition(routingDroplet, droplet, board, currentTime); currentTime = dropletRoute.getEndTime() + 1; heaterOperation.OutputRoutes.Add(heaterOperation.OutputVariable, new List <Route>() { dropletRoute }); heaterOperation.EndTime = currentTime; currentTime++; board.UpdateGridAtGivenLocation(heaterOperation.BoundModule, heaterOperation.BoundModule.Shape); //Now the heater is not occupied anymore: a new heater operation can be executed: ((HeaterModule)heaterOperation.BoundModule).IsInUse = false; } } assay.UpdateReadyOperations(finishedOperation); } rectanglesAtDifferentTimes.Add(currentTime, board.CopyAllRectangles()); } return(currentTime); }
private bool AreOperationsFinishing(int startTime, Assay assay) { return(CurrentlyRunningOpertions.Count > 0 && (assay.IsEmpty() || startTime >= CurrentlyRunningOpertions.First().EndTime)); }
/** * Implements/based on the list scheduling based algorithm found in * "Fault-tolerant digital microfluidic biochips - compilation and synthesis" page 72. */ public int ListScheduling <T>(DFG <Block> dfg, CommandExecutor <T> executor) { rectanglesAtDifferentTimes.Clear(); ScheduledOperations.Clear(); OutputtedDroplets.Clear(); NewVariablesCreatedInThisScope.Clear(); //Setup: int currentTime = 0; rectanglesAtDifferentTimes.Add(currentTime, board.CopyAllRectangles()); Assay assay = new Assay(dfg); foreach (Block nextOperation in assay) { int oldTime = currentTime; nextOperation.Update <T>(Variables, executor, FluidVariableLocations); switch (nextOperation) { case VariableBlock varBlock: UpdateVariables <T>(varBlock, executor); UpdateSchedule(nextOperation, currentTime, oldTime); assay.UpdateReadyOperations(nextOperation); break; case Union unionBlock: currentTime = HandleUnionOperation(currentTime, unionBlock); UpdateSchedule(nextOperation, currentTime, oldTime); assay.UpdateReadyOperations(nextOperation); break; case StaticDeclarationBlock decBlock: assay.UpdateReadyOperations(nextOperation); break; case Fluid renameBlock: currentTime = HandleFluidTransfers(currentTime, renameBlock); UpdateSchedule(nextOperation, currentTime, oldTime); assay.UpdateReadyOperations(nextOperation); break; case SetArrayFluid arrayRenameBlock: currentTime = HandleFluidTransfers(currentTime, arrayRenameBlock); UpdateSchedule(nextOperation, currentTime, oldTime); assay.UpdateReadyOperations(nextOperation); break; case FluidBlock fluidBlock: currentTime = HandleFluidOperations(currentTime, fluidBlock); UpdateSchedule(nextOperation, currentTime, oldTime); break; default: throw new InternalRuntimeException("The given block/operation type is unhandeled by the scheduler. " + Environment.NewLine + "The operation is: " + nextOperation.ToString()); } //When operations finishes, while the routing associated with nextOperation was performed, //this needs to be handled. Note that handleFinishingOperations will also wait for operations to finish, //in the case that there are no more operations that can be executed, before this happen: currentTime = HandleFinishingOperations(nextOperation, currentTime, assay); } if (CurrentlyRunningOpertions.Count > 0) { throw new InternalRuntimeException("ERROR!!!"); } SortScheduledOperations(); return(GetCompletionTime()); }