411 lines
19 KiB
Matlab
411 lines
19 KiB
Matlab
% Copyright 2024 Volvo Car Corporation
|
|
% Licensed under Apache 2.0.
|
|
|
|
function [ allVariables ] = parseCalMeasData( system )
|
|
% parseCalMeasData Parse calibration measurement data
|
|
%
|
|
% See also parseModelInfo
|
|
|
|
allVariables=struct;
|
|
evalin('base', [system '_par']);
|
|
allVariables.local_vars=struct;
|
|
allVariables.calib_consts=struct;
|
|
|
|
tmp=sortSystemByClass(system);
|
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
% Measurable variables
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
blocksTmp=tmp.CVC_DISP;
|
|
% find all TL_Outports (should not be included in measurement variables
|
|
% as they should be included in the outports key
|
|
outports = find_system(topLevelSystem(system), 'FindAll', 'on', ...
|
|
'LookUnderMasks', 'all', 'MaskType', 'TL_Outport');
|
|
blocks = setdiff(blocksTmp, outports);
|
|
allVariables = Create_Standard_Struct(system, allVariables, blocks, 'local_vars', 'output');
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
% Cal variables
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
blocks=tmp.CVC_CAL;
|
|
allVariables = Create_Standard_Struct(system, allVariables, blocks, 'calib_consts', 'output');
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
% Prelookups
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
blocks=find_system(get_param(system,'handle'), 'lookundermasks', 'on', 'masktype', 'TL_IndexSearch');
|
|
allVariables = Create_Standard_Struct(system, allVariables, blocks, 'calib_consts', 'input');
|
|
|
|
blocks=find_system(get_param(system,'handle'), 'lookundermasks', 'on', 'masktype', 'TL_PreLookup');
|
|
allVariables = Create_Standard_Struct(system, allVariables, blocks, 'calib_consts', 'input');
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
% Lookups
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
blocks=find_system(get_param(system,'handle'), 'lookundermasks', 'on', 'regexp', 'on', 'masktype', 'TL_Interpolation.*');
|
|
allVariables = Create_Standard_Struct(system, allVariables, blocks, 'calib_consts', 'table');
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
% Stateflow
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
stateflow=find_system(get_param(system, 'handle'), 'FindAll', 'on', ...
|
|
'lookundermasks', 'on', 'masktype', 'Stateflow');
|
|
for i=1:length(stateflow)
|
|
allVariables = Create_Struct_SFlow(system, allVariables, stateflow(i));
|
|
end
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
% CustomCode blocks
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
customCode=find_system(get_param(system, 'handle'), 'FindAll', 'on', ...
|
|
'lookundermasks', 'on', 'masktype', 'TL_CustomCode');
|
|
for i=1:length(customCode)
|
|
allVariables = createStructCustCode(system, allVariables, customCode(i));
|
|
end
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
% TCM specific blocks
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
% Lookup1D
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
blocks = find_system(get_param(system, 'handle'), 'lookundermasks', 'on', ...
|
|
'masktype','TL_Lookup1D');
|
|
allVariables = Create_Standard_Struct(system, allVariables, blocks, 'calib_consts', 'input');
|
|
allVariables = Create_Standard_Struct(system, allVariables, blocks, 'calib_consts', 'table');
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
% Lookup2D
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
blocks = find_system(get_param(system,'handle'),'lookundermasks','on','masktype','TL_Lookup2D');
|
|
allVariables = Create_Standard_Struct(system, allVariables, blocks, 'calib_consts', 'row');
|
|
allVariables = Create_Standard_Struct(system, allVariables, blocks, 'calib_consts', 'col');
|
|
allVariables = Create_Standard_Struct(system, allVariables, blocks, 'calib_consts', 'table');
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
end
|
|
|
|
function allVariables = Create_Standard_Struct(systemIn, allVariables, ...
|
|
blocks, structName, field)
|
|
|
|
if ~isempty(blocks)
|
|
TLFields={'type', 'unit', 'description', 'max', 'min', 'lsb', ...
|
|
'offset', 'class'};
|
|
system = regexprep(systemIn,'(\w+?)(__.*){0,1}','$1');
|
|
for block = blocks'
|
|
class=tl_getfast(block, [field '.class']);
|
|
if ~isempty(class) && ~strcmp(class, 'default')
|
|
name=tl_getfast(block, [field '.name']);
|
|
res = regexp(name, '(\$[SD])', 'match', 'once');
|
|
if ~isempty(res)
|
|
o = sprintf('Warning %s in block <a href = "matlab:Hilite_This_System(''%s'')">%s</a>', ...
|
|
res, getPath(block), getName(block));
|
|
disp(o)
|
|
%hilite_system(block)
|
|
else
|
|
variableName=Get_Full_Name(block, name, system);
|
|
if sum(isstrprop(variableName, 'wspace')) > 0
|
|
o = sprintf('Illegal characters in the name property in block <a href = "matlab:Hilite_This_System(''%s'')">%s</a>', ...
|
|
getPath(block), getName(block));
|
|
disp(o)
|
|
error('aborting')
|
|
end
|
|
%VariableName = VariableName(isstrprop(VariableName, 'wspace') == 0);
|
|
if ~isempty(variableName)
|
|
for tlField = TLFields
|
|
tmp_tlField = tlField{1};
|
|
if ismember(get_param(block, 'masktype'), ...
|
|
{'TL_RelationalOperator', 'TL_LogicalOperator'}) && ...
|
|
ismember(tmp_tlField , {'max', 'min', 'lsb', 'offset'})
|
|
allVariables.(structName).(variableName).(tmp_tlField) = '-';
|
|
elseif ismember(get_param(block, 'masktype'), {'TL_BitwiseOperator'}) ...
|
|
&& ismember(tmp_tlField , {'max', 'min', 'lsb', 'offset', 'unit'})
|
|
allVariables.(structName).(variableName).(tmp_tlField) = '-';
|
|
else
|
|
Value=tl_getfast(block, [field '.' tmp_tlField]);
|
|
if iscell(Value)
|
|
Value = Value{1};
|
|
end
|
|
if strcmp(Value, 'IMPLICIT_ENUM')
|
|
Value = getEnumName(block);
|
|
end
|
|
allVariables.(structName).(variableName).(tmp_tlField) = checkValue(Value);
|
|
end
|
|
end
|
|
allVariables.(structName).(variableName).handle = getPath(block);
|
|
consumerBlks = getConsumerBlocks(block);
|
|
if isempty(consumerBlks)
|
|
allVariables.(structName).(variableName).configs = getCodeSwitches(block);
|
|
else
|
|
codeSwTmp = {};
|
|
for j=1:length(consumerBlks)
|
|
consBlk = consumerBlks(j);
|
|
codeSwTmp{j} = getCodeSwitches(consBlk);
|
|
end
|
|
allVariables.(structName).(variableName).configs = removeConfigDuplicates(codeSwTmp);
|
|
end
|
|
if ismember(get_param(block, 'masktype'), {'TL_IndexSearch', 'TL_Interpolation', 'TL_Lookup1D', 'TL_Lookup2D'}) ...
|
|
&& ~strcmp(field,'output')
|
|
[inputValueRef, errorFlag, ~] = tl_get(block, [field '.value']);
|
|
if errorFlag > 0
|
|
inputValueRef = tl_getfast(block, [field '.value']);
|
|
end
|
|
InputValue=evalin('base', inputValueRef);
|
|
VarSize=size(InputValue);
|
|
allVariables.(structName).(variableName).width = VarSize;
|
|
elseif strcmp(get_param(block, 'masktype'), 'TL_Constant') && strcmp(field,'output')
|
|
ConstantValue=evalin('base', tl_getfast(block, [field '.value']));
|
|
VarSize=size(ConstantValue);
|
|
if VarSize(2) == 1
|
|
allVariables.(structName).(variableName).width = 1;
|
|
else
|
|
allVariables.(structName).(variableName).width = VarSize;
|
|
end
|
|
elseif strcmp(get_param(block, 'masktype'), 'TL_IndexSearch') && strcmp(field, 'output')
|
|
if tl_getfast(block, 'outputmode') == 2
|
|
VarSize = [1,2];
|
|
else
|
|
VarSize = 1;
|
|
end
|
|
allVariables.(structName).(variableName).width = VarSize;
|
|
else
|
|
allVariables.(structName).(variableName).width = 1;
|
|
end
|
|
allVariables.(structName).(variableName) = modifyEnumStructField(allVariables.(structName).(variableName));
|
|
if length(variableName) > 63
|
|
% Can't store the full name as a struct key as matlab only supports key lengths < 64
|
|
o = sprintf('Warning variable name %s is longer than 63 chars, consider shortening it.', variableName);
|
|
disp(o)
|
|
allVariables.(structName).(variableName).unshortenedName = variableName;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function allVariables = Create_Struct_SFlow(system, allVariables, sFlow)
|
|
configs = getCodeSwitches(sFlow);
|
|
% Handle stateflow outports
|
|
tmp_SFObj = get_param(sFlow, 'Object');
|
|
chartObj = tmp_SFObj.find('-isa', 'Stateflow.Chart');
|
|
sfDataArr = chartObj.find('-isa', 'Stateflow.Data');
|
|
idArr = arrayfun(@(x) x.Id, sfDataArr);
|
|
sfHandles = tl_get_sfobjects(sFlow, {'SF Output', 'SF Local'});
|
|
for i=1:length(sfHandles)
|
|
SfHandle = sfHandles(i);
|
|
idx = idArr == SfHandle;
|
|
sfData = sfDataArr(idx);
|
|
tlClass = tl_get(SfHandle, 'class');
|
|
if checkClass(tlClass, sFlow, sfData)
|
|
continue % do nothing, if NVM, default class, or name error. NVM is handled elsewhere
|
|
end
|
|
tlName = tl_get(SfHandle, 'name');
|
|
res = regexp(tlName, '(\$[SDCB])', 'tokens');
|
|
if isempty(res)
|
|
allVariables = copyFields(system, allVariables, sFlow, SfHandle, configs, sfData.port);
|
|
else
|
|
err_msg = res{1}{1};
|
|
if isnan(sfData.port)
|
|
port = '';
|
|
else
|
|
port = [':' num2str(sfData.port)];
|
|
end
|
|
o = sprintf('Warning %s in <a href = "matlab:Hilite_This_System(''%s'')">%s - %s (%s%s)</a>', ...
|
|
err_msg, getPath(sFlow), get_param(sFlow, 'name'), sfData.name, sfData.scope, port);
|
|
disp(o)
|
|
end
|
|
end
|
|
end
|
|
|
|
function allVariables = createStructCustCode(system, allVariables, custCodeBlk)
|
|
custFields={'type', 'unit', 'description', 'max', 'min', 'lsb', ...
|
|
'offset', 'class'};
|
|
parTypes = {'state', 'work', 'param', 'input', 'output'};
|
|
structName = {'local_vars', 'local_vars', 'calib_consts', 'local_vars', 'local_vars'};
|
|
numTypes = cellfun(@(x) tl_get(custCodeBlk, ['num' x 's']), parTypes, 'uni', false);
|
|
for pti = 1:length(parTypes)
|
|
pType = parTypes{pti};
|
|
for idx=1:numTypes{pti}
|
|
class = tl_get(custCodeBlk, [pType '(' num2str(idx) ').class']);
|
|
if ~ismember(class, {'default', 'STATIC_LOCAL_MACRO'})
|
|
name = tl_get(custCodeBlk, [pType '(' num2str(idx) ').name']);
|
|
if ~ismember(pType, {'output'}) && ~isempty(regexp(name, '\$L', 'once'))
|
|
error('Can not use $L macro in non output parameters')
|
|
end
|
|
if ~isempty(regexp(name, '\$S', 'once'))
|
|
error('Can not use $S macro in name.')
|
|
end
|
|
varName = getSignalName(system, custCodeBlk, name, idx);
|
|
for fldidx = 1:length(custFields)
|
|
fld = custFields{fldidx};
|
|
value = val2str(tl_get(custCodeBlk, [ pType '(' num2str(idx) ').' fld ]));
|
|
if strcmp(value, 'IMPLICIT_ENUM')
|
|
allVariables.(structName{pti}).(varName).(fld) = getEnumName(custCodeBlk);
|
|
else
|
|
allVariables.(structName{pti}).(varName).(fld) = value;
|
|
end
|
|
end
|
|
if strcmp(pType, 'param')
|
|
inputValue=evalin('base', tl_get(custCodeBlk, [pType '(' num2str(idx) ').value']));
|
|
varSize=size(inputValue);
|
|
allVariables.(structName{pti}).(varName).width = varSize;
|
|
else
|
|
%TODO: Check width parameter?
|
|
allVariables.(structName{pti}).(varName).width = 1;
|
|
end
|
|
allVariables.(structName{pti}).(varName) = modifyEnumStructField(allVariables.(structName{pti}).(varName));
|
|
allVariables.(structName{pti}).(varName).handle = getPath(custCodeBlk);
|
|
allVariables.(structName{pti}).(varName).configs = getCodeSwitches(custCodeBlk);
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function allVariables = copyFields(system, allVariables, sFlow, sfHandle, configs, outPortNbr)
|
|
|
|
sfFields={'type', 'unit', 'description', 'max', 'min', 'lsb', ...
|
|
'offset', 'class'};
|
|
|
|
variableName = getSfSignalName(system, sFlow, sfHandle, outPortNbr);
|
|
allVariables.local_vars.(variableName).configs = configs;
|
|
|
|
for j=1:length(sfFields)
|
|
fieldName = sfFields{j};
|
|
value = tl_get(sfHandle, fieldName);
|
|
if strcmp(value, 'IMPLICIT_ENUM')
|
|
value = getEnumName(sfHandle);
|
|
end
|
|
allVariables.local_vars.(variableName).(fieldName) = checkValue(value);
|
|
end
|
|
|
|
allVariables.local_vars.(variableName) = modifyEnumStructField(allVariables.local_vars.(variableName));
|
|
end
|
|
|
|
function value = val2str(val_in)
|
|
if ~ischar(val_in)
|
|
if isnan(val_in)
|
|
value = '-';
|
|
elseif isempty(val_in)
|
|
value = '-';
|
|
else
|
|
value = num2str(val_in);
|
|
end
|
|
else
|
|
value=val_in;
|
|
end
|
|
end
|
|
|
|
function newStr = stripIllegalChar(value)
|
|
% replace all non word characters with space
|
|
newStr = regexprep(value, '(?![\w/]).', ' ');
|
|
end
|
|
|
|
function newVal = checkValue(value)
|
|
if ischar(value)
|
|
newVal=strtrim(value);
|
|
elseif isnan(value)
|
|
newVal='-';
|
|
elseif length(value) > 1
|
|
newVal = {};
|
|
for i=1:length(value)
|
|
newVal{i} = checkValue(value(i));
|
|
end
|
|
else
|
|
newVal=value;
|
|
end
|
|
end
|
|
|
|
function nok = checkClass(tlClass, sFlow, sfData)
|
|
if regexp(tlClass, '(?:default|CVC_DISP_NVM)')
|
|
nok = 1;
|
|
return % do nothing, NVM is handled elsewhere
|
|
end
|
|
if isempty(strfind(tlClass, 'CVC_DISP'))
|
|
if isnan(sfData.port)
|
|
port = '';
|
|
else
|
|
port = [':' num2str(sfData.port)];
|
|
end
|
|
o = sprintf('Warning - <a href = "matlab:Hilite_This_System(''%s'')">unknown class %s in %s - %s (%s%s)</a>', ...
|
|
getPath(sFlow), tlClass, get_param(sFlow, 'name'), sfData.name, sfData.scope, port);
|
|
disp(o)
|
|
nok = 0;
|
|
return
|
|
end
|
|
nok = 0;
|
|
end
|
|
|
|
function name = getSfSignalName(systemIn, block, sfHandle, outPortNbr)
|
|
% function to get the name of a in/out-port of a block.
|
|
macro = tl_get(sfHandle, 'name');
|
|
system = getTLModelName(systemIn);
|
|
nameTmp = macro;
|
|
res = regexp(macro, '\$O', 'tokens');
|
|
if ~isempty(res)
|
|
tmp_SFObj = get_param(block, 'Object');
|
|
chartObj = tmp_SFObj.find('-isa', 'Stateflow.Chart');
|
|
sfData = chartObj.find('-isa', 'Stateflow.Data');
|
|
idArr = arrayfun(@(x) x.Id, sfData);
|
|
idx = idArr == sfHandle;
|
|
nameTmp = regexprep(nameTmp,'\$O', sfData(idx).name);
|
|
end
|
|
res = regexp(macro, '\$L', 'tokens');
|
|
if ~isempty(res)
|
|
slPortHandles = get_param(block, 'PortHandles');
|
|
ph = slPortHandles.Outport(outPortNbr);
|
|
signal = get_param(get_param(ph, 'line'), 'name');
|
|
if isempty(signal)
|
|
%TODO: Consider removing the turning on of the propagated
|
|
% signals
|
|
if strcmp(get_param(ph, 'ShowPropagatedSignals'), 'off')
|
|
set_param(ph, 'ShowPropagatedSignals', 'on')
|
|
end
|
|
signal = get_param(ph, 'PropagatedSignals');
|
|
if isempty(signal)
|
|
error('signal') % fix warning
|
|
end
|
|
end
|
|
nameTmp = regexprep(nameTmp,'\$L', signal);
|
|
end
|
|
nameTmp = regexprep(nameTmp,'\$B', get_param(block, 'Name'));
|
|
nameTmp = regexprep(nameTmp,'\$N', system);
|
|
name = regexprep(nameTmp,' ', '');
|
|
end
|
|
|
|
function name = getSignalName(systemIn, block, macro, outPortNbr)
|
|
% function to get the name of a in/out-port of a block.
|
|
res = regexp(macro, '(\$L)', 'tokens');
|
|
system = regexprep(systemIn,'(\w+?)(__.*){0,1}','$1');
|
|
nameTmp = macro;
|
|
if ~isempty(res)
|
|
slPortHandles = get_param(block, 'PortHandles');
|
|
ph = slPortHandles.Outport(outPortNbr);
|
|
signal = get_param(get_param(ph, 'line'), 'name');
|
|
if isempty(signal)
|
|
%TODO: Consider removing the turning on of the propagated
|
|
% signals
|
|
if strcmp(get_param(ph, 'ShowPropagatedSignals'), 'off')
|
|
set_param(ph, 'ShowPropagatedSignals', 'on')
|
|
end
|
|
signal = get_param(ph, 'PropagatedSignals');
|
|
if isempty(signal)
|
|
error('signal') % fix warning
|
|
end
|
|
end
|
|
nameTmp = regexprep(nameTmp,'\$L', signal);
|
|
end
|
|
nameTmp = regexprep(nameTmp,'\$B', get_param(block, 'Name'));
|
|
nameTmp = regexprep(nameTmp,'\$N', system);
|
|
name = regexprep(nameTmp,' ', '');
|
|
end
|