Пример #1
0
        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);
        }
Пример #2
0
 private bool AreOperationsFinishing(int startTime, Assay assay)
 {
     return(CurrentlyRunningOpertions.Count > 0 && (assay.IsEmpty() || startTime >= CurrentlyRunningOpertions.First().EndTime));
 }
Пример #3
0
        /**
         *  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());
        }