gusucode.com > private工具箱matlab源码程序 > private/generate_code_for_charts_and_machine.m
function generate_code_for_charts_and_machine(fileNameInfo,codingRebuildAll) % Copyright 2003-2015 The MathWorks, Inc. global gMachineInfo global gTargetInfo incCodeGenInfo = compute_inc_codegen_info(fileNameInfo,codingRebuildAll); display_startup_message(fileNameInfo); mainMachineId = gMachineInfo.mainMachineId; machineName = gMachineInfo.machineName; mainMachineName = gMachineInfo.mainMachineName; targetName = gMachineInfo.targetName; gMachineInfo.thirdPartyUses = {}; gMachineInfo.updateBuildInfoArgs = {}; lastException = []; if ~gTargetInfo.codingHDL && ~gTargetInfo.codingPLC fileNameInfo.complex_number_types = ... strcmpi(get_param(mainMachineName, 'SupportComplex'), 'on'); % Later, in code_rtwtypesdoth(), we claim the MaxMultiwordBits is % 1024, which definitely requires multiword typedefs fileNameInfo.multiword_types = true; end if gTargetInfo.codingSFunction compute_autoinheritance_info(); end for i = 1:length(gMachineInfo.charts) chart = gMachineInfo.charts(i); chartFileNumber = sf('get',chart,'chart.chartFileNumber'); chartName = sf('get',chart,'.name'); numSpecs = length(gMachineInfo.specializations{i}); if gTargetInfo.codingSFunction for j = 1:numSpecs if(~incCodeGenInfo.flags{i}(j)) success = false; try mainSfunName = [gMachineInfo.mainMachineName '_sfun']; thirdPartyUses = feval(mainSfunName, 'get_third_party_uses_info', gMachineInfo.machineName, ... chartFileNumber, gMachineInfo.specializations{i}{j}); gMachineInfo.thirdPartyUses = [gMachineInfo.thirdPartyUses thirdPartyUses]; updateBuildInfoArgs = feval(mainSfunName, 'get_updateBuildInfo_args_info', gMachineInfo.machineName, ... chartFileNumber, gMachineInfo.specializations{i}{j}); gMachineInfo.updateBuildInfoArgs = [gMachineInfo.updateBuildInfoArgs updateBuildInfoArgs]; success = true; catch end if ~success incCodeGenInfo.flags{i}(j) = 1; end end end end if ~any(incCodeGenInfo.flags{i}) continue; end compute_chart_information(chart); if gTargetInfo.codingRTW rtwInstanceInfo = []; end % if/when we support library charts, the key will need to be augmented % to distinguish between specializations, and this flush will need to % be moved into the spec loop below. will also need a way to distinguish % keys from instances in different models. if gTargetInfo.codingSFunction ... && isfile([fullfile(matlabroot,'toolbox','fixedpoint','fixedpoint','+fixed','+internal','clearLog') '.' mexext]) % Do NOT test for min/max logging enabled - especially % important to flush when not enabled. fixed.internal.clearLog(['#' Simulink.ID.getSID(idToHandle(sfroot(), chart))]); end %Clear any chart cache auxInfo before generating code. sfprivate('auxInfoChartCache','clr',chart); numSpecs = length(gMachineInfo.specializations{i}); for j = 1:numSpecs thisSpec = gMachineInfo.specializations{i}{j}; if(~isempty(incCodeGenInfo.jitIncCodegenInfoForMachine)) jitIncCodegenInfoForSpec = incCodeGenInfo.jitIncCodegenInfoForMachine.(thisSpec); needsPreFallback = jitIncCodegenInfoForSpec.needsPreFallback; preFallBackReason = jitIncCodegenInfoForSpec.preFallBackReason; else needsPreFallback = true; preFallBackReason = 'feature off'; end if(~incCodeGenInfo.flags{i}(j)) continue; end %TLTODO: handle following block % Let EML know what charts need to be reconsidered for its resolved functions targetId = gTargetInfo.target; targetName = sf('get',targetId,'.name'); targetName0 = sfprivate('get_eml_metadata_target_name',targetName); machineName0 = sfprivate('get_eml_metadata_machine_name',machineName); rebuildMetaData = sf('get', mainMachineId, '.eml.rebuildMetaData'); if ~isempty(rebuildMetaData) && isfield(rebuildMetaData, targetName0) chartFiles = rebuildMetaData.(targetName0).(machineName0).rebuiltChartFiles; if ~any(chartFiles == chartFileNumber) chartFiles = sort([chartFiles chartFileNumber]); rebuildMetaData.(targetName0).(machineName0).rebuiltChartFiles = chartFiles; sf('set',mainMachineId,'.eml.rebuildMetaData', rebuildMetaData); end end % Even though the incremental codegen info says we need to % regenerate IR for this spec, it is possible this spec was % handled as part of another chart. Hence, try to relink before % we generate code and return early. if gTargetInfo.codingSFunction && ... ~needsPreFallback && ... Stateflow.JIT.Utils.relinkToExistingJITEngine(chart,thisSpec, false) gMachineInfo.codingLLVM{i}(j) = 1; continue; end display_chart_codegen_message(chart,sf('get',targetId,'target.name')); errorsOccurred = false; try needsPreFallback = construct_module(chart, 0.0, thisSpec, fileNameInfo,needsPreFallback,preFallBackReason); catch ME errorsOccurred = true; lastException = ME; sfprivate('sf_display', sprintf('Error: %s\n', ME.message)); end if ~errorsOccurred if gTargetInfo.codingSFunction && ... ~needsPreFallback && ... sfprivate('can_relink_to_existing_jit_engine',chart,thisSpec) gMachineInfo.codingLLVM{i}(j) = 1; sf('Cg','destroy_module',chart); continue; end sfprivate('sf_compile_stats', 'snap', targetName, mainMachineName, machineName, chartName, 'generate_code_for_chart', true); try create_project_dir_path_just_in_time(fileNameInfo); sf('set', chart, 'chart.codeGeneratedNow', 1); msgString = sprintf('Generating files:\n'); sfprivate('sf_display', msgString); code_chart_header_file(fileNameInfo,chart,j); code_chart_source_file(fileNameInfo,chart,j); spec_third_party_uses = sf('Cg','third_party_uses',chart); gMachineInfo.thirdPartyUses = [gMachineInfo.thirdPartyUses spec_third_party_uses]; spec_updateBuildInfoArgs = sf('Cg','updateBuildInfo_args',chart); gMachineInfo.updateBuildInfoArgs = [gMachineInfo.updateBuildInfoArgs spec_updateBuildInfoArgs]; catch ME % Make sure we destroy the module otherwise things leak. 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 rethrow(ME); end if (sf('feature', 'Single pass for RTW code generation') == 0) || ~gTargetInfo.codingRTW sf('Cg','destroy_module',chart); end sfprivate('sf_compile_stats', 'snap', targetName, mainMachineName, machineName, chartName, 'generate_code_for_chart', false); if gTargetInfo.codingRTW tlcFile = fileNameInfo.chartTLCFiles{i}{j}; outputFcn = fileNameInfo.chartOutputsFcns{i}{j}; initFcn = fileNameInfo.chartInitializeFcns{i}{j}; instanceInfo = get_instance_rtw_info(chart, thisSpec, tlcFile, outputFcn, initFcn, ... spec_third_party_uses, spec_updateBuildInfoArgs); rtwInstanceInfo = [rtwInstanceInfo instanceInfo]; %#ok<AGROW> end end end if gTargetInfo.codingRTW sf('set', chart, 'chart.rtwInfo.instanceInfo', rtwInstanceInfo); end end if gTargetInfo.codingSFunction && ~isempty(lastException) throwAsCaller(lastException); end % Compute if machine is fully jitted. if not we will have to run the % makemethod in targetman if gTargetInfo.codingSFunction && sf('Feature','Sim Through JIT') jitIncCodegenInfo = sf('get',mainMachineId,'machine.jitIncCodeGenInfo'); if(~isempty(jitIncCodegenInfo) && isfield(jitIncCodegenInfo,machineName)) jitIncCodegenInfoForMachine = jitIncCodegenInfo.(machineName); else jitIncCodegenInfoForMachine = []; end if ~isempty(gMachineInfo.charts) && ~isempty(jitIncCodegenInfoForMachine) codegenSpecCount = 0; foundInJitSpecCount = 0; foundInDllSpecCount = 0; for i = 1:length(gMachineInfo.charts) chart = gMachineInfo.charts(i); numSpecs = length(gMachineInfo.specializations{i}); for j=1:numSpecs thisSpec = gMachineInfo.specializations{i}{j}; jitIncCodegenInfoForSpec = jitIncCodegenInfoForMachine.info.(thisSpec); if(jitIncCodegenInfoForSpec.generateCode) codegenSpecCount = codegenSpecCount+1; break; elseif(jitIncCodegenInfoForSpec.generateJitEngine) if(~sfprivate('can_relink_to_existing_jit_engine',chart,thisSpec)) % must have been a late fallback codegenSpecCount = codegenSpecCount+1; else foundInJitSpecCount = foundInJitSpecCount+1; end elseif(jitIncCodegenInfoForSpec.foundInDll) foundInDllSpecCount = foundInDllSpecCount+1; else assert(jitIncCodegenInfoForSpec.foundInJit); foundInJitSpecCount = foundInJitSpecCount+1; end end end jitIncCodegenInfo.(machineName).codegenSpecCount = codegenSpecCount; if(jitIncCodegenInfo.(machineName).codegenSpecCount>0) jitIncCodegenInfo.(machineName).invokeMakeMethod = true; end jitIncCodegenInfo.(machineName).foundInJitSpecCount = foundInJitSpecCount; jitIncCodegenInfo.(machineName).foundInDllSpecCount = foundInDllSpecCount; sf('set',mainMachineId,'machine.jitIncCodeGenInfo',jitIncCodegenInfo); end fullyJittedLibs = []; for i = 1:length(fileNameInfo.linkMachines) linkMachineName = fileNameInfo.linkMachines{i}; if(jitIncCodegenInfo.(linkMachineName).codegenSpecCount==0 &&... jitIncCodegenInfo.(linkMachineName).foundInDllSpecCount==0) fullyJittedLibs(end+1) = i; %#ok <AGROW> end end fileNameInfo.linkMachines(fullyJittedLibs) = []; fileNameInfo.linkLibFullPaths(fullyJittedLibs) = []; fileNameInfo.linkObjListFullPaths (fullyJittedLibs) = []; fileNameInfo.linkMachinesInlinable(fullyJittedLibs) = []; codegenOccurred = false; for i = 1:length(fileNameInfo.linkMachines) linkMachineName = fileNameInfo.linkMachines{i}; if(jitIncCodegenInfo.(linkMachineName).codegenSpecCount>0) codegenOccurred = true; break; end end if(jitIncCodegenInfo.(machineName).codegenSpecCount>0) codegenOccurred = true; end if(~codegenOccurred) return; end jitIncCodegenInfo.(machineName).invokeMakeMethod = true; sf('set',mainMachineId,'machine.jitIncCodeGenInfo',jitIncCodegenInfo); end if gTargetInfo.codingSFunction gMachineInfo.thirdPartyUses = unique(gMachineInfo.thirdPartyUses); gMachineInfo.updateBuildInfoArgs = uniqueCell(gMachineInfo.updateBuildInfoArgs); end if ~gTargetInfo.codingHDL && ~gTargetInfo.codingPLC oldCtxInfo = []; % Only set when we create a temporary context for machine. if sf('feature', 'Single pass for RTW code generation') && gTargetInfo.codingRTW % Create a temporary context for machine since the current % context is the one from RTW and we do not want to pollute it % with machine information that are not compatible with RTW. % % To be consistent with other created contexts, this temporary % context will be destroyed the next time that we create a new % context and calling construct_module or construct_machine_module. % Thus, we do not need to destroy the context here. oldCtxInfo = gMachineInfo.ctxInfo; status = construct_context_for_machine([], true); if status ~= 0 construct_coder_error(gMachineInfo.machineId,'The construction of the context for the machine did not worked.',0); end end try sf('Cg','construct_machine_module',gMachineInfo.ctxInfo); catch ME lastException = ME; construct_coder_error(gMachineInfo.machineId,ME.message,0); end if isempty(lastException) assert(sfprivate('coder_error_count_man', 'get') == 0); sfprivate('sf_compile_stats', 'snap', targetName, mainMachineName, machineName, 'machine', 'generate_code_for_machine', true); create_project_dir_path_just_in_time(fileNameInfo); fileNameInfo = code_aux_support_files(fileNameInfo); if gTargetInfo.codingSFunction generate_sfcn_customcode_files(fileNameInfo); end code_machine_header_file(fileNameInfo); code_machine_source_file(fileNameInfo); code_interface_and_support_files(fileNameInfo); sfprivate('sf_compile_stats', 'snap', targetName, mainMachineName, machineName, 'machine', 'generate_code_for_machine', false); end if ~isempty(oldCtxInfo) % No need to delete the temporary context for the machine % (see the previous comment), but we need to restore the old context. gMachineInfo.ctxInfo = oldCtxInfo; end end if ~isempty(lastException) throwAsCaller(lastException); end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function display_startup_message(fileNameInfo) global gMachineInfo if(~sf('Feature','Sim Through JIT')) msgString = sprintf('Code Directory :\n "%s"\n',fileNameInfo.targetDirName); sfprivate('sf_display',msgString); msgString = sprintf('Machine (#%d): "%s" Target : "%s"\n',gMachineInfo.machineId,gMachineInfo.machineName,gMachineInfo.targetName); sfprivate('sf_display',msgString); end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function y_or_n = yes_or_no(val) if val y_or_n = 'Yes'; else y_or_n = 'No'; end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function instanceInfo = get_instance_rtw_info(chart, spec, tlcFile, outputFcn, initFcn, spec_third_party_uses, spec_updateBuildInfo_args) instanceInfo.specialization = spec; instanceInfo.TLCFile = tlcFile; instanceInfo.OutputsFcn = outputFcn; instanceInfo.InitializeFcn = initFcn; instanceInfo.ReusableOutputs = sf('get', chart, 'chart.rtwInfo.reusableOutputs'); instanceInfo.ExpressionableInputs = sf('get', chart, 'chart.rtwInfo.expressionableInputs'); instanceInfo.Inline = yes_or_no(sf('get', chart, 'chart.rtwInfo.chartWhollyInlinable')); instanceInfo.sfSymbols = sf('get', chart, 'chart.rtwInfo.sfSymbols'); instanceInfo.gatewayCannotBeInlinedMultipleTimes = sf('get', chart, 'chart.rtwInfo.gatewayCannotBeInlinedMultipleTimes'); instanceInfo.accessesMachineSymbols = sf('get', chart, 'chart.rtwInfo.accessesMachineSymbols'); instanceInfo.outputEventsWithMultipleCallers = sf('get', chart, 'chart.rtwInfo.outputEventsWithMultipleCallers'); instanceInfo.dworkInfo = sf('get', chart, 'chart.rtwInfo.dWorkVarInfo'); instanceInfo.dworkChecksum = sfprivate('md5', rmfield(instanceInfo.dworkInfo, {'varName', 'typeSize', 'isOpaque', 'bitWidth', 'description', 'extModeUpload', 'isTestPoint', 'objName', 'path', 'resolveToSignalObject'})); instanceInfo.requiredStackSize = sf('get', chart, 'chart.rtwInfo.requiredStackSize'); instanceInfo.thirdPartyUses = spec_third_party_uses; instanceInfo.updateBuildInfoArgs = spec_updateBuildInfo_args; instanceInfo.chartUsesVerify = sf('get', chart, 'chart.sfunInfo.chartUsesVerify'); function c = uniqueCell(c) % Behaves like a UNIQUE command but on a cell array. duplicateIdx = []; for i = 1:numel(c) if ~any(i == duplicateIdx) for j = i+1:numel(c) if isequal(c(i),c(j)) duplicateIdx = [duplicateIdx j]; %#ok<AGROW> end end end end c(duplicateIdx) = []; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function generate_sfcn_customcode_files(fileNameInfo) global gMachineInfo % Generate the extra files for the custom init/term functions % before calling the instrumenter if gMachineInfo.ctxInfo.sfcnTgtCustomCodeInfo.hasExtraCustomCodeFiles code_sfun_customcode_header_file(fileNameInfo); code_sfun_customcode_source_file(fileNameInfo); end % Code coverage special case: run the instrumenter before emitting the % machine code in order to include global instrumentation symbols if ~isempty(gMachineInfo.ctxInfo.sfcnTgtCustomCodeInfo.instrumenter) extraFilesToInstrument = []; if gMachineInfo.ctxInfo.sfcnTgtCustomCodeInfo.hasExtraCustomCodeFiles % Add the extra source file containing the custom init/term functions extraFilesToInstrument = {fullfile(fileNameInfo.targetDirName, fileNameInfo.customCodeSourceFile)}; end gMachineInfo.ctxInfo.sfcnTgtCustomCodeInfo.instrumenter.configureBuildInfo(fileNameInfo, extraFilesToInstrument); if ~gMachineInfo.ctxInfo.sfcnTgtCustomCodeInfo.instrumenter.instrument(gMachineInfo) % An error occured then ignore the code instrumentation gMachineInfo.ctxInfo.sfcnTgtCustomCodeInfo.instrumenter = []; end end % Generate the header file containing the forward declarations % for custom code coverage. if gMachineInfo.ctxInfo.sfcnTgtCustomCodeInfo.supportCoverage code_sfun_customcode_cov_header_file(fileNameInfo); end