Code covered by the BSD License  

Highlights from
Address Specific Parameter Custom Storage Class

Address Specific Parameter Custom Storage Class

by

 

14 May 2007 (Updated )

MemMap: A custom storage class that allows the user to specify the memory addresses of parameters in

MemMapVariableCheck(modelName)
function [str, status] = MemMapVariableCheck(modelName)

%% Check for MemMap parameters

str =sprintf('Checking MemMap custom storage class parameters for model ''%s.''',modelName);
disp(str)
status =1;
standardtypes = {'auto'; 'double'; 'single'; 'int32'; 'uint32'; 'int16'; 'uint16'; 'int8'; 'uint8'};

% Add code to check the memory map for the MemMap data objects to insure
% that none of the data objects memory specifications overlap.

%% Find all of the parameters of type MemMap in the model.

% refWSVars is a structure containing the names of the referenced
% variables along with the handles to the blocks that reference the
% variable

%% Get all the referenced WS variables that are MemMap parameters
refWSVars = get_param(modelName, 'ReferencedWSVars');
refVarNames = cell(size(refWSVars));
match=cell(1);
numcount = 0;
for i=1:length(refWSVars)
    refVarNames{i} = refWSVars(i).Name;
    obj = evalin('base',refWSVars(i).Name);
    if isa(obj,'Simulink.Data')
        if (strcmp(obj.RTWInfo.CustomStorageClass,'MemoryAddress') ...
                && strcmp(obj.RTWInfo.StorageClass,'Custom'))
            numcount = numcount + 1;
            match{numcount}=refWSVars(i).Name;
        end
    end
end
% Truncate the list to those that match

%% Get the list of MemoryAddress variables in the base workspace
if(~isempty(match{1})) % If any exists, check the addresses, etc.
% Step through the list and create a memory map then check for uniqueness
    addresses = cell(1);
    hexaddresses = cell(1);
    nummatch = length(match);
    stepsize = zeros(1,nummatch);
    hexstep = cell(1);
    matchprint = cell(1);
    datatype = cell(1);
    numelements = zeros(1,nummatch);
    baseaddress = zeros(1,nummatch);
    maxvar = 10;
    maxtype = 4;
% % %     startrange = [];
% % %     endrange = [];
    numcols = zeros(1,nummatch);
    for ii = 1:nummatch
        dim = evalin('base',[match{ii},'.dimensions']);
        numcols(ii) = dim(2);
        numelements(ii) = dim(1) * dim(2);
        if(numelements(ii) > 1)
            matchprint{ii} = [match{ii}, '(', num2str(dim(1)),',', num2str(dim(2)),')'];
        else
            matchprint{ii} = match{ii};
        end
        maxvar = max(maxvar,length(matchprint{ii}));
%Account for user-defined data types: AliasType,Numerictype, fixdt
% Determine the data type
        datatype{ii} = evalin('base',[match{ii},'.DataType']);
        maxtype = max(maxtype,length(datatype{ii}));
% Check for non-standard data types
        if isempty(strmatch(datatype{ii},standardtypes))
% Get the nonstandard data type
            if (strncmpi(datatype{ii},'fixdt',5))
% Strip out the word length
                [Signed, remainder] = strtok(datatype{ii},','); 
                WordLength = strtok(remainder,','); 
                switchtype = 'Fixed';
            else
                vartype = evalin('base',['class(',datatype{ii},')']);
                if strcmpi(vartype,'Simulink.NumericType')
                    switchtype = evalin('base',[datatype{ii},'.DataTypeMode']);
% Check if the numeric type is non-standard data type
                    if isempty(strmatch(switchtype,standardtypes))
                        WordLength = evalin('base',[datatype{ii},'.WordLength']); 
                        switchtype = 'Fixed';
                    end
                end
                if strcmpi(vartype,'Simulink.AliasType')
                    tmptype = evalin('base',[datatype{ii},'.BaseType']);
                    if isempty(strmatch(tmptype,standardtypes))
                        vartype = evalin('base',['class(',tmptype,')']);
                        if strcmpi(vartype,'Simulink.NumericType')
                            switchtype = evalin('base',[tmptype,'.DataTypeMode']);
% Check if the numeric type is non-standard data type
                            if isempty(strmatch(switchtype,standardtypes))
                                WordLength = evalin('base',[tmptype,'.WordLength']); 
                                switchtype = 'Fixed';
                            end
                        end
                    end
                else
                    switchtype = tmptype;
                end
            end
        else
            switchtype = datatype{ii};
        end
        switch switchtype
            case 'Fixed'
                stepsize(ii) = WordLength; % Fixed-point data type
            case 'single'
                stepsize(ii) = 32; % 4 bytes (32 bits) for a single
            case {'int32', 'uint32'}
                stepsize(ii) = 32; % 4 bytes (32 bits) for a int32
            case {'int16', 'uint16'}
                stepsize(ii) = 16; % 2 bytes (16 bits) for a int16
            case {'int8', 'uint8'}
                stepsize(ii) = 8; % 1 bytes (8 bits) for a int8
            case 'boolean'
                stepsize(ii) = 8; % 1 bytes (8 bits) for a boolean
            case {'double', 'auto'}
                stepsize(ii) = 64; % 8 bytes (64 bits) for a double/auto
            otherwise
                error(['Non supported data type: ', datatype{ii}]);
        end
        address = evalin('base',[match{ii},'.RTWInfo.CustomAttributes.MemoryAddress']);
        baseaddress(ii) = hex2dec(address(2:end));
        for jj = 1:numelements(ii)
            addresses{ii,jj} = (baseaddress(ii) + (jj-1)*stepsize(ii));
            hexaddresses{ii,jj} = ['0x',dec2hex(addresses{ii,jj}, 8)];
        end
    end

    %% Sort based on memory location

    [newlist, indx] = sort(baseaddress);
    %reorder other items
    nmatch = cell(1);
    nmatchprint = cell(1);
    ndatatype = cell(1);
    naddresses = cell(1);
    nhexaddresses = cell(1);
    stepsize = stepsize(indx);
    for ii = 1:nummatch
        nmatch{ii} = match{indx(ii)};
        nmatchprint{ii} = matchprint{indx(ii)};
        ndatatype{ii} = datatype{indx(ii)};
        for jj = 1:max(numelements)
            naddresses{ii,jj} = addresses{indx(ii),jj};
            nhexaddresses{ii,jj} = hexaddresses{indx(ii),jj};
        end
        hexstep{ii} = [num2str(stepsize(ii)), '(0x', dec2hex(stepsize(ii),2),')'];
    end
    match = nmatch;
    matchprint = nmatchprint;
    datatype = ndatatype;
    addresses = naddresses;
    hexaddresses = nhexaddresses;
    numelements = numelements(indx);
    numcols = numcols(indx);

    %% Check the addresses for overlap
    overlapflag = 0;
    [nrows,ncols] = size(addresses);

    % Find next valid addresses
    check = zeros(1,nrows);
    check(1) = addresses{1,1};
    checkhex = cell(1);
    checkhex{1} = hexaddresses{1};
    for ii = 1:nrows
        for jj = 1:ncols % Find the next valid address
            if (~isempty(addresses{ii,jj}))
                check(ii+1) = addresses{ii,jj} + stepsize(ii);
                checkhex{ii+1} = ['0x',dec2hex(check(ii+1), 8)];
            end
        end
    end
    for ii = 2:nrows
        if(addresses{ii,1} < check(ii))
            overlapflag = 1;
            break;   %  Exit for loop if there is an overlap
        end
    end

    %% Display memory map
    button = questdlg(sprintf('Model contains Custom Storage Class MemMap parameters\nShow memory map?'));

    % Format the memory table
    if (strcmpi(button,'yes'))
        hdrst1 ='Variable  ';
        hdrst2 ='          ';
        hdrst3 ='          ';
        for ss = length(hdrst1):maxvar % pad with trailing spaces as needed
            hdrst1 = [hdrst1, ' '];
            hdrst2 = [hdrst2, ' '];
            hdrst3 = [hdrst3, ' '];
        end
        hdrst1 = [hdrst1, ' Data '];
        hdrst2 = [hdrst2, ' Type '];
        hdrst3 = [hdrst3, '      '];
        for ss = length(hdrst1):maxtype % pad with trailing spaces as needed
            hdrst1 = [hdrst1, ' '];
            hdrst2 = [hdrst2, ' '];
            hdrst3 = [hdrst3, ' '];
        end
        hdrst1 = [hdrst1, '   Word      '];
        hdrst2 = [hdrst2, '   Length    '];
        hdrst3 = [hdrst3, '             '];
        hdrst1 = [hdrst1, 'Available  '];
        hdrst2 = [hdrst2, 'Starting   '];
        hdrst3 = [hdrst3, 'Address    '];
        hdrst1 = [hdrst1, '   Assigned '];
        hdrst2 = [hdrst2, '   Addresses'];
        addressindx = strfind(hdrst1,'Assigned');
        disp(' ');
        disp(' ');
        disp('*****     Custom Storage Class MemMap Parameters: Memory Map     *****');
        disp(' ');
        disp(hdrst1);
        disp(hdrst2);
        disp(hdrst3);
        for kk = 1:nrows
            bstr = 'sprintf(''%s';
            for ss = length(matchprint{kk}):maxvar % pad with trailing spaces as needed
                bstr = [bstr, ' '];
            end
            bstr = [bstr, ' %s'];
            for ss = length(datatype{kk}):maxtype % pad with trailing spaces as needed
                bstr = [bstr, ' '];
            end
            bstr = [bstr, ' %8s  %s    '];
            numacross = min(numcols(kk),10);
            for ll = 1:numelements(kk)
                if (mod(ll,numacross)==0 && ll ~= numelements(kk))
                    if(numacross ~= numcols(kk))
                        bstr = [bstr '%s  %% Columns wrapped\n'];
                    else
                        bstr = [bstr '%s\n'];
                    end
                    for ss = 1:addressindx-1
                        bstr = [bstr, ' '];
                    end
                else
                    bstr = [bstr '%s '];
                end
            end
            bstr = [bstr ''''];
            bstr = [bstr ',matchprint{kk}, datatype{kk}, hexstep{kk}, checkhex{kk}, hexaddresses{kk,1:numelements(kk)})'];
            disp(eval(bstr));
        end
        disp(' ');
        disp(' ');
        disp(' ');
    end

    %% Send an errorand stop build process
    if(overlapflag)
        error('Memory address overlap in MemMap parameters between parameter:\n%s and %s \nCheck memory map',match{ii-1}, match{ii});
    end
end
end % end of MemMapVariableCheck function

%% Notes


Contact us