gusucode.com > private工具箱matlab源码程序 > private/construct_module.m
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function needsPreFallback = construct_module(chart, instanceHandle, specialization, fileNameInfo,needsPreFallback,preFallBackReason) % Copyright 2002-2014 The MathWorks, Inc. % CONSTRUCT_MODULE - This function attemps to generate code for a % particular chart. % WARNING: In the case of failure, an MException is thrown, but only % after module is destroyed first. % %%%%%%%%%%%% % NOTE: Module is NOT destroyed if no exception is thrown. %%%%%%%%%%%% global gTargetInfo gChartInfo gMachineInfo if nargin < 3 specialization = ''; end if nargin < 4 fileNameInfo = []; end compute_chart_instance_var_names(chart, specialization); compute_state_variable_names(chart, specialization); compute_state_event_enums(chart); mustExportChartFunctions = export_chart_functions(chart); targetName = sf('get',gMachineInfo.parentTarget,'target.name'); cdrModuleInfo.chartId = chart; cdrModuleInfo.instanceHandle = instanceHandle; cdrModuleInfo.specialization = specialization; cdrModuleInfo.codingMultiInstance = gTargetInfo.codingMultiInstance; cdrModuleInfo.mustExportChartFunctions = mustExportChartFunctions; cdrModuleInfo.chartInstanceTypedef = gChartInfo.chartInstanceTypedef; cdrModuleInfo.chartInputDataTypedef = gChartInfo.chartInputDataTypedef; cdrModuleInfo.chartOutputDataTypedef = gChartInfo.chartOutputDataTypedef; cdrModuleInfo.chartInstanceArgumentName = gChartInfo.chartInstanceArgumentName; cdrModuleInfo.chartInputDataArgumentName = gChartInfo.chartInputDataArgumentName; cdrModuleInfo.chartOutputDataArgumentName = gChartInfo.chartOutputDataArgumentName; cdrModuleInfo.codingNoInitializer = gTargetInfo.codingNoInitializer; cdrModuleInfo.rtwFcnName = ''; cdrModuleInfo.rtwUseSFS = 0; cdrModuleInfo.forceJitOff=false; gChartInfo.jitFallbackInfo = []; if(gTargetInfo.codingRTW) cdrModuleInfo.codingSharedUtils = rtw_gen_shared_utils(gMachineInfo.mainMachineName); cdrModuleInfo.usedTargetFunctionLib = gTargetInfo.rtwProps.usedTargetFunctionLib; % Use the TFL control object attached to the model for TFL replacements. % Pass this handle into construct module. cdrModuleInfo.usedTargetFunctionLibH = get_param(gMachineInfo.mainMachineName, 'TargetFcnLibHandle'); % set up the RTWFcnName field of cdrModuleInfo to be used for naming % atomic subchart functions. chartBlockH = sfprivate('chart2block', chart); if strcmpi(get_param(chartBlockH, 'RTWFcnNameOpts'), 'auto') || ... strcmpi(get_param(chartBlockH, 'RTWFcnNameOpts'), 'Use subsystem name') fcnName = get_param(chartBlockH, 'Name'); cdrModuleInfo.rtwUseSFS = 1; else fcnName = get_param(chartBlockH, 'RTWFcnName'); cdrModuleInfo.rtwUseSFS = 0; end % Remove the leading A.B. stuff in case this atomic subchart is used in % a nested context. fcnName = regexp(fcnName, '\w*$', 'match'); if ~isempty(fcnName) cdrModuleInfo.rtwFcnName = fcnName{1}; else cdrModuleInfo.rtwFcnName = ''; end elseif gTargetInfo.codingSFunction if(needsPreFallback) gChartInfo.jitFallbackInfo.fallbackType = 'pre'; gChartInfo.jitFallbackInfo.fallbackReason = preFallBackReason; cdrModuleInfo.forceJitOff = true; else gChartInfo.jitFallbackInfo.fallbackType = ''; gChartInfo.jitFallbackInfo.fallbackReason = ''; end gChartInfo.jitFallbackInfo.incompatibleSymbol = ''; cdrModuleInfo.codingSharedUtils = false; cdrModuleInfo.usedTargetFunctionLib = 'NULL'; cdrModuleInfo.usedTargetFunctionLibH = get_param(gMachineInfo.mainMachineName, 'SimTargetFcnLibHandle'); tfl_recording('start',cdrModuleInfo.usedTargetFunctionLibH); else cdrModuleInfo.codingSharedUtils = false; cdrModuleInfo.usedTargetFunctionLib = 'NULL'; cdrModuleInfo.usedTargetFunctionLibH = 0; end try [occurredFallbackType,hiddenFallbackType,fallbackReason,incompatibleSymbol] = sf('Cg','construct_module',cdrModuleInfo); if(gTargetInfo.codingSFunction) redoCodegen = false; switch(occurredFallbackType) case 'none' % no fallback occurred. check if we need to do a tfl late % fallback or fallback due to breakpoints in M-files on path [fallbackReason,incompatibleSymbol] = compute_tfl_late_fallback_info(cdrModuleInfo); if ~isempty(fallbackReason) fallbackType = 'late'; Stateflow.JIT.Utils.destroyJITEngineForChartSpecialization(chart,specialization); else [fallbackReason, fallbackType] = sfprivate('compute_breakpoints_in_resolved_functions', ... cdrModuleInfo.chartId, specialization); if ~isempty(fallbackReason) needsPreFallback = true; jitIncCodeGenInfo = sf('get',gMachineInfo.mainMachineId,'machine.jitIncCodeGenInfo'); specInfo = jitIncCodeGenInfo.(gMachineInfo.machineName).info.(specialization); specInfo.generateCode = true; specInfo.generateJitEngine = false; jitIncCodeGenInfo.(gMachineInfo.machineName).info.(specialization) = specInfo; sf('set',gMachineInfo.mainMachineId,'machine.jitIncCodeGenInfo', jitIncCodeGenInfo); end end if(~isempty(fallbackReason)) gChartInfo.jitFallbackInfo.fallbackType = fallbackType; gChartInfo.jitFallbackInfo.hiddenFallbackType = ''; gChartInfo.jitFallbackInfo.fallbackReason = fallbackReason; gChartInfo.jitFallbackInfo.hiddenFallbackReason = ''; gChartInfo.jitFallbackInfo.incompatibleSymbol = incompatibleSymbol; redoCodegen = true; end case 'pre' gChartInfo.jitFallbackInfo.fallbackType='pre'; gChartInfo.jitFallbackInfo.hiddenFallbackType = hiddenFallbackType; gChartInfo.jitFallbackInfo.fallbackReason = preFallBackReason; gChartInfo.jitFallbackInfo.hiddenFallbackReason = fallbackReason; gChartInfo.jitFallbackInfo.incompatibleSymbol = incompatibleSymbol; case 'early' gChartInfo.jitFallbackInfo.fallbackType='early'; gChartInfo.jitFallbackInfo.hiddenFallbackType = ''; gChartInfo.jitFallbackInfo.fallbackReason = fallbackReason; gChartInfo.jitFallbackInfo.hiddenFallbackReason = ''; gChartInfo.jitFallbackInfo.incompatibleSymbol = incompatibleSymbol; case {'late','very late'} gChartInfo.jitFallbackInfo.fallbackType=occurredFallbackType; gChartInfo.jitFallbackInfo.hiddenFallbackType = ''; gChartInfo.jitFallbackInfo.fallbackReason = fallbackReason; gChartInfo.jitFallbackInfo.hiddenFallbackReason = ''; gChartInfo.jitFallbackInfo.incompatibleSymbol = incompatibleSymbol; redoCodegen = true; end if(redoCodegen) sf('Cg','destroy_module',chart); cdrModuleInfo.forceJitOff = true; sf('Cg','construct_module',cdrModuleInfo); end if ~cdrModuleInfo.forceJitOff && ... Stateflow.JIT.Utils.relinkToExistingJITEngine(chart,specialization, false) % This means, we have just generated a jitEngine and it is in memory if(~sfprivate('chart_requests_zero_emissions',chart)) try [jitEngineByteCodeFile,jitEngineInfoMatFile] =... sfprivate('jit_engine_file_name_info',specialization); create_jit_project_dir_path_just_in_time(); Stateflow.JIT.Utils.serializeJITEngine(specialization,jitEngineByteCodeFile, ... jitEngineInfoMatFile); catch ME %#ok<NASGU> % ignore this error as it is not fatal end end else % this means, we did not use jit for this chart/spec combo % let's dump the information on why this did not happen % these MAT files can be examined to lock down jittability if(sf('feature','sim through jit')) display_chart_codegen_message(chart,'sfun',fallbackReason); % Add a few more fields to save in the MAT file jitFallbackInfo = gChartInfo.jitFallbackInfo; jitFallbackInfo.modelName = gMachineInfo.machineName; jitFallbackInfo.chartFileNumber = sf('get',chart,'chart.chartFileNumber'); jitFallbackInfo.specialization = specialization; jitFallbackInfo.lateFallback = double(strcmp(jitFallbackInfo.fallbackType,'late') || strcmp(jitFallbackInfo.fallbackType,'very late')); create_project_dir_path_just_in_time(fileNameInfo,'ji'); jitFallbackInfoFileName = sprintf('c%d_%s.mat',jitFallbackInfo.chartFileNumber,specialization); if(jitFallbackInfo.lateFallback) jitFallbackInfoFileName = fullfile(fileNameInfo.targetDirName,'ji',['late_',jitFallbackInfoFileName]); else jitFallbackInfoFileName = fullfile(fileNameInfo.targetDirName,'ji',['early_',jitFallbackInfoFileName]); end save(jitFallbackInfoFileName,'jitFallbackInfo'); end end tfl_recording('stop',cdrModuleInfo.usedTargetFunctionLibH); end collect_chart_aux_dependencies(chart, cdrModuleInfo, fileNameInfo); compute_implicit_event_information(); catch ME sf('Private','coder_error_count_man','add',1); if (sf('feature', 'Single pass for RTW code generation') == 0) || ~gTargetInfo.codingRTW % We delay the destruction at the end of mdlRTWCG(). Needs to be delayed in this case since the order of deletion can be different from the order of creation. sf('Cg','destroy_module',chart); end if gTargetInfo.codingSFunction tfl_recording('stop',cdrModuleInfo.usedTargetFunctionLibH); end rethrow(ME); end if(strcmp(targetName,'testgen') && gTargetInfo.codingForAutoVerifier) % WISH: This is a temporary hack for Bill to do his testgen % work. MUST GET RID OF IT AS SOON AS POSSIBLE!!!!!!! if exist('slavt_gateway.m','file') try slavt_gateway('chart_analyze',chart,true); catch ME disp(ME.message); end end end return; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Look for TFL auxInfo that forces late fallback function [fallbackReason,incompatibleSymbol] = compute_tfl_late_fallback_info(cdrModuleInfo) fallbackReason=''; incompatibleSymbol=''; % Get the TFL usage for the specified chartId. The TFL usage is % the 'recorded' usage, i.e., the per-chart usage. There is % currently no single API function to retrieve this data, so we % must iterate over the TFL controller's hit cache. tflControl = cdrModuleInfo.usedTargetFunctionLibH; hitCache = tflControl.HitCache; numEnts = length(hitCache); for idx = 1:numEnts if hitCache(idx).RecordedUsageCount ~= 0 hit = hitCache(idx); name = hit.Implementation.SourceFile; if ~isempty(name) fallbackReason='TFL Source Files'; incompatibleSymbol=name; return; end for i = 1:numel(hit.AdditionalSourceFiles) name = hit.AdditionalSourceFiles{i}; if ~isempty(name) fallbackReason='TFL Source Files'; incompatibleSymbol=name; return; end end for i = 1:numel(hit.AdditionalLinkObjs) name = hit.AdditionalLinkObjs{i}; if ~isempty(name) fallbackReason='TFL Link Objects'; incompatibleSymbol=name; return; end end end end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Collect the TFL and MATLAB function auxiliary build dependency info function collect_chart_aux_dependencies(chartId, cdrModuleInfo, fileNameInfo) global gTargetInfo shouldCacheAuxInfo = gTargetInfo.codingSFunction || (gTargetInfo.codingRTW && ~gTargetInfo.codingIRConstructionForRTW); if ~shouldCacheAuxInfo return; end % Get the MATLAB function aux buildinfo for the chart auxInfo = sf('Cg','get_recorded_eml_buildinfo',chartId); if gTargetInfo.codingSFunction && isempty(auxInfo.includeFiles) check_include_custom_header(chartId); end if gTargetInfo.codingSFunction auxInfo = cgxeprivate('collect_crl_dependencies',cdrModuleInfo.usedTargetFunctionLibH, ... fileNameInfo.targetDirName, auxInfo); end sfprivate('auxInfoChartCache','set',chartId,auxInfo); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function tfl_recording(method,tfl) switch(method) case 'start' % Indicate to the TFL that TLC will not be invoked. This prevents TFL entries that % contain TLC code gen callbacks from being used as replacements. Also, start recording % TFL replacements. This is needed so that we can ensure the correct (minimal) set of header % files is included into the chart source file. tfl.TLCSupported = false; tfl.Recording = true; case 'stop' % stop recording as we are done with the codegen for this chart tfl.TLCSupported = true; tfl.Recording = false; end return; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function compute_chart_instance_var_names(chart, specialization) global gTargetInfo gChartInfo chartUniqueName = sf('CodegenNameOf',chart,specialization); if(gTargetInfo.codingRTW) gChartInfo.chartInstanceTypedef = ''; gChartInfo.chartInstanceArgumentName = ''; else gChartInfo.chartInstanceTypedef = ['SF',chartUniqueName,'InstanceStruct']; gChartInfo.chartInstanceArgumentName = 'chartInstance'; end gChartInfo.chartInputDataTypedef = ['SF',chartUniqueName,'InputDataStruct']; gChartInfo.chartOutputDataTypedef = ['SF',chartUniqueName,'OutputDataStruct']; gChartInfo.chartInputDataArgumentName = 'chartInputData'; gChartInfo.chartOutputDataArgumentName = 'chartOutputData'; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function compute_state_variable_names(chart, specialization) global gChartInfo for state = [chart,gChartInfo.states] uniqStateName = sf('CodegenNameOf',state,specialization); if(state==chart || sf('get',state,'state.type')==1) % chart, AND states get their own bit fieldName = ['is_active_',uniqStateName]; sf('set',state,'.unique.isActive',fieldName); else % optimize it away sf('set',state,'.unique.isActive',''); end subStates = sf('SubstatesOf',state); if(~isempty(subStates)) switch sf('get',state,'.decomposition') case 0 % CLUSTER_STATE fieldName = ['is_',uniqStateName]; sf('set',state,'.unique.activeChild',fieldName); if sf('get',state,'.history') fieldName = ['was_',uniqStateName]; sf('set',state,'.unique.prevActiveChild',fieldName); end case 1 % SET_STATE otherwise construct_coder_error(state,'Bad decomposition'); end end end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function compute_state_event_enums(chart) global gMachineInfo gChartInfo if(~isempty(gChartInfo.chartEvents)) chartEventNumbers = sf('get',gChartInfo.chartEvents,'event.number')+gMachineInfo.machineEventThreshold; sf('set',gChartInfo.chartEvents,'event.number',chartEventNumbers); end file = ''; % Dummy argument, not used in the functions compute_event_enum_values(chart,file,1); compute_state_enums(file,chart); return; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function compute_implicit_event_information() global gChartInfo gChartInfo.statesWithEntryEvent = sf('find',gChartInfo.states,'state.hasEntryEvent',1); gChartInfo.statesWithExitEvent = sf('find',gChartInfo.states,'state.hasExitEvent',1); gChartInfo.dataWithChangeEvent = sf('find',gChartInfo.chartData,'data.hasChangeEvent',1); % Machine-level explicit or implicit events are not supported; so there is no need to account % for them. gChartInfo.dataChangeEventThreshold = 0; if(~isempty(gChartInfo.chartEvents)) gChartInfo.dataChangeEventThreshold = max(sf('get',gChartInfo.chartEvents,'event.number'))+1; end gChartInfo.stateEntryEventThreshold = gChartInfo.dataChangeEventThreshold + length(gChartInfo.dataWithChangeEvent); gChartInfo.stateExitEventThreshold = gChartInfo.stateEntryEventThreshold + length(gChartInfo.statesWithEntryEvent); return;