/// <summary>
        /// Performs resource allocation and binding.
        /// </summary>
        /// <param name="dpb">datapath builder to use</param>
        /// <returns>resulting flow matrix</returns>
        public FlowMatrix Allocate(IDatapathBuilder dpb)
        {
            // Step 1: create intermediate storage for each instruction output slot
            var tempSignals = new SLVSignal[_func.SlotTypes.Length];

            for (int i = 0; i < _func.SlotTypes.Length; i++)
            {
                int width   = TypeLowering.Instance.GetWireWidth(_func.SlotTypes[i]);
                var initial = StdLogicVector.Us(width);
                tempSignals[i] = (SLVSignal)Signals.CreateInstance(initial);
                tempSignals[i].Descriptor.TagTemporary(i);
            }

            // Step 2: Allocate and establish unit bindings
            Action <IXILMapping> onAlloc = map => dpb.AddFU(map.TASite.Host);

            _alloc.OnFUAllocation += onAlloc;
            var mappings = new Dictionary <int, IXILMapping>();

            foreach (var xil3i in _func.Instructions)
            {
                TypeDescriptor[] otypes = xil3i.OperandSlots.Select(i => _func.SlotTypes[i]).ToArray();
                TypeDescriptor[] rtypes = xil3i.ResultSlots.Select(i => _func.SlotTypes[i]).ToArray();
                long             cstep  = CStep[xil3i];
                var mapping             = _alloc.TryBind(xil3i, cstep, otypes, rtypes);
                if (mapping == null)
                {
                    throw new XILSchedulingFailedException("Realization failed: " + xil3i.Command);
                }
                mappings[xil3i.Index] = mapping;
                mapping.TASite.Establish(dpb.FUBinder);
                Allocator.Policy.TellMapping(xil3i, cstep, mapping);
            }
            _alloc.OnFUAllocation -= onAlloc;

            // Step 3: Assemble flow matrix
            var result = new FlowMatrix();

            foreach (var xil3i in _func.Instructions)
            {
                long cstep   = CStep[xil3i];
                var  mapping = mappings[xil3i.Index];
                result.AddNeutral(mapping.TASite.DoNothing());
                var impl = mapping.Realize(
                    xil3i.OperandSlots.Select(s => tempSignals[s].AsSignalSource <StdLogicVector>()).ToArray(),
                    xil3i.ResultSlots.Select(s => tempSignals[s].AsCombSink()).ToArray());
                if (impl.Count() - Latency[xil3i] > 1)
                {
                    throw new XILSchedulingFailedException("Mapping length exceeds scheduled latency");
                }
                result.Add((int)cstep, impl);
                result.AppendComment((int)cstep, ToComment(xil3i));
                _mappingCache[xil3i.Index] = mapping;
            }

            return(result);
        }
示例#2
0
        /// <summary>
        /// Executes the HLS design flow.
        /// </summary>
        /// <param name="design">the design</param>
        /// <param name="host">the hosting component</param>
        /// <param name="proc">the process being subject to HLS</param>
        /// <param name="targetProject">the target project</param>
        /// <remarks>Inside the hosting component, the process will be replaced by the synthesized hardware.</remarks>
        public void Execute(DesignContext design, Component host, ProcessDescriptor proc, IProject targetProject)
        {
            Contract.Requires<ArgumentNullException>(design != null);
            Contract.Requires<ArgumentNullException>(host != null);
            Contract.Requires<ArgumentNullException>(proc != null);
            Contract.Requires<ArgumentNullException>(targetProject != null);

            design.CurrentProcess = proc.Instance;

            var clk = proc.Sensitivity[0];
            SignalBase clkI;
            var sdClk = clk as SignalDescriptor;
            if (sdClk == null)
                clkI = ((SignalDescriptor)((PortDescriptor)clk).BoundSignal).Instance;
            else
                clkI = sdClk.Instance;
            
            var state = new HLSState(this, design, host, proc, targetProject);
            proc.AddAttribute(state);

            if (_beginHLS != null)
                _beginHLS(state);

            var dpb = new DefaultDatapathBuilder(host, clkI, proc.Name);
            state.InterconnectBuilder = InterconnectBuilder.Create(host, dpb.ICBinder);
            state.ControlpathBuilder = ControlPathBuilder.Create(host, dpb.FUBinder);
            state.ControlpathBuilder.PersonalizePlan(this);

            do
            {
                XILSFunction fnasm;
                if (!proc.HasAttribute<XILSFunction>())
                {
                    var func = proc.Implementation;
                    IEnumerable<Function> inlinedFunctions;
                    func = func.InlineCalls(out inlinedFunctions);
                    if (ConvertFieldsToLocals)
                    {
                        Variable[] newLocals;
                        func = func.ConvertFieldsToLocals(out newLocals);
                    }
                    state.PreprocessedFunction = func;

                    fnasm = state.PreprocessedFunction.Compile(DefaultInstructionSet.Instance);
                }
                else
                {
                    fnasm = proc.QueryAttribute<XILSFunction>();
                }
                fnasm.SanityCheck();
                state.XILSInput = fnasm;
                IList<XILSInstr> instrs = state.XILSInput.Instructions.ToList();
                foreach (var rw in XILSTransformations)
                {
                    instrs = rw.Rewrite(instrs);
                    fnasm = new XILSFunction(fnasm.Name, fnasm.Arguments, fnasm.Locals, instrs.ToArray());
                    fnasm.SanityCheck();
                }
                state.XILSTransformed = fnasm;

                XIL3Function fnasm3 = fnasm.ToXIL3();
                state.XIL3Input = fnasm3;

                foreach (IXIL3Rewriter rw in XIL3Transformations)
                {
                    fnasm3 = rw.Rewrite(fnasm3);
                    fnasm3.SanityCheck();
                }

                state.XIL3Transformed = fnasm3;
                state.NotifyProgress(EHLSProgress.Compiled);
            } while (state._repeat);
            if (state._cancel)
                return;

            SchedulingConstraints constraints;

            do
            {
                var xmm = new XILMapperManager();
                foreach (var dpu in Enumerable.Reverse(XILMappers))
                    xmm.AddMapper(dpu);

                DesignContext.Push();

                var xilsa = new XILSchedulingAdapter(state.XIL3Transformed, xmm, host, targetProject);
                if (AllocationPolicy != null)
                    xilsa.Allocator.Policy = AllocationPolicy.Create();
                if (_onFUCreated != null)
                    xilsa.Allocator.OnFUAllocation += _onFUCreated;
                state.SchedulingAdapter = xilsa;
                state.NotifyProgress(EHLSProgress.AboutToSchedule);

                constraints = SchedulingConstraints;
                if (constraints == null)
                {
                    if (proc.Implementation != null)
                        constraints = proc.Implementation.QueryAttribute<SchedulingConstraints>();
                    if (constraints == null)
                        constraints = new SchedulingConstraints();
                }
                state.Constraints = constraints;

                if (constraints.MinimizeNumberOfFUs)
                {
                    foreach (var instr in state.XIL3Transformed.Instructions)
                    {
                        xilsa.SetMaxFUAllocation(xilsa.IClass[instr], 1);
                    }
                }

                Scheduler.Schedule(xilsa.CFG, constraints, xilsa);
                DesignContext.Pop();

                state.NotifyProgress(EHLSProgress.Scheduled);
            } while (state._repeat);

            ComputeCStepsForBranchTargets(state.SchedulingAdapter);

            do
            {
                state.ControlpathBuilder.PrepareAllocation(state.SchedulingAdapter.ComputeCStepCount());
                var flowSpec = state.SchedulingAdapter.Allocate(dpb);
                state.RawFlows = flowSpec;
                var realFlow = new FlowMatrix();
                state.InterconnectBuilder.CreateInterconnect(flowSpec, realFlow);
                state.RealFlows = realFlow;
                state.NotifyProgress(EHLSProgress.InterconnectCreated);
            } while (state._repeat);
            if (state._cancel)
                return;

            Debug.Assert(state.RealFlows.FlowSources.All(sr => sr.Desc.Owner != null));
            Debug.Assert(state.RealFlows.FlowTargets.All(sr => sr.Desc.Owner != null));

            do
            {
                state.ControlpathBuilder.CreateControlpath(state.RealFlows, proc.Name);
                foreach (var prof in constraints.Profilers)
                    prof.ExtractFrom(state.XIL3Transformed, state.SchedulingAdapter);
                state.NotifyProgress(EHLSProgress.ControlpathCreated);
            } while (state._repeat);
            if (state._cancel)
                return;
        }