/// <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); }
/// <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; }