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;