Skip to content
Snippets Groups Projects
SCDclass_expcode.m 39.7 KiB
Newer Older
classdef SCDclass_expcode
    %A SCD expcode object
    %   This object is a virgin SCD expode
    %   its constructor builds an expode 
    %   with all templates algorithms
    
    properties (Access = private)     
        activenodes         % numerical list of configured active nodes
        activecpus          % numerical list of configured CPUs
        %nodeddlist         % list of data dictionaries at node level
        wrapperlist         % list of configured wrappers
        algoobjlist         % list of loaded algorithm objects
        algonamelist        % List of loaded algorithm names 
        algoddlist          % list of data dictionaries at algorithm level
        mdscontainer        % container class for MDS+ interface objects
        taskcontainer       % container class for generic init and term task objects
        exportedtps         % list of tunable parameters variable to be exported
        stdinits            % list of standard inits scripts
        modeltoactualize    % name of the algorithm to actualize ('all' means all coonfigured) 
    end
    
    properties
        % Main properties
        name              % Expcode main name
        maincode          % Expcode numerical code
        status            % Expcode development status
        loadverbose       % Verbosity level of the loading (currently 0 or 1)        
        % Per node properties structs
        node01
        node02
        node03
        node04
        node05
        node06
        node07
        node08
    end
    
    methods(Static)
      function node = defaultnode(nodenr)
            
            node01.active = 0;
            node01.ncpu = 1;
            node01.type = 'std1cpu2015a';
            node01.timing.t_start = -4.5;
            node01.timing.t_stop = 3;
            node01.timing.dt = 1e-4;
            node01.buildcfg.conffile{1} = 'standard';
            node01.buildcfg.initscdbeforecomp = 0;
            node01.usewavegen = 0;
            node01.datadict='SCD_rtc_01.sldd';
            
            node02.active = 0;
            node02.ncpu = 4;
            node02.type = 'std1cpu2015a';
            node02.timing.t_start = -4.5;
            node02.timing.t_stop = 3;
            node02.timing.dt = 1e-4;
            node02.thperiod = [1.0000e-03 1.0000e-03 1.0000e-03 1.0000e-03];
            node02.buildcfg.conffile{1} = 'standard';
            node02.buildcfg.conffile{2} = 'standard';
            node02.buildcfg.conffile{3} = 'standard';
            node02.buildcfg.conffile{4} = 'standard';
            node02.buildcfg.conffile=node02.buildcfg.conffile';
            node02.buildcfg.initscdbeforecomp = 0;
            node02.usewavegen = 0;
            node02.datadict='SCD_rtc_02.sldd';
            
            node03.active = 0;
            node03.ncpu = 4;
            node03.type = '4cpus2015a';
            node03.timing.t_start = -2.0;
            node03.timing.t_stop = 2.75;
            node03.timing.dt = 1e-3;
            node03.thdwsample = [0 0 0 0];
            node03.thperiod = [1.0000e-03 1.0000e-03 1.0000e-03 1.0000e-03];
            node03.buildcfg.conffile{1} = 'standard';
            node03.buildcfg.conffile{2} = 'standard';
            node03.buildcfg.conffile{3} = 'standard';
            node03.buildcfg.conffile{4} = 'standard';
            node03.buildcfg.conffile=node03.buildcfg.conffile';
            node03.buildcfg.initscdbeforecomp = [0 0 0 0];
            node03.usewavegen = 0;
            node03.useethcat1 = 0;
            node03.datadict='SCD_rtc_03.sldd';            
            
            node04.active = 0;
            node04.ncpu = 4;
            node04.type = 'std1cpu2015a';
            node04.timing.t_start = -4.5;
            node04.timing.t_stop = 3;
            node04.timing.dt = 1e-4;
            node04.buildcfg.conffile{1} = 'standard';
            node04.buildcfg.initscdbeforecomp = 0;
            node04.usewavegen = 0;

            node05.active = 0;
            node05.ncpu = 1;
            node05.type = 'std1cpu2015a';
            node05.timing.t_start = -4.5;
            node05.timing.t_stop = 3;
            node05.timing.dt = 1e-4;
            node05.buildcfg.conffile{1} = 'standard';
            node05.buildcfg.initscdbeforecomp = 0;
            node05.usewavegen = 0;

            node06.active = 0;
            node06.ncpu = 4;
            node06.type = '4cpus2015a';
            node06.timing.t_start = 0.0;
            node06.timing.t_stop = 2.75;
            node06.timing.dt = 1e-3;
            node06.thdwsample = [0 0 0 0];
            node06.thperiod = [1.0000e-03 1.0000e-03 1.0000e-03 1.0000e-03];
            node06.buildcfg.conffile{1} = 'standard';
            node06.buildcfg.conffile{2} = 'standard';
            node06.buildcfg.conffile{3} = 'standard';
            node06.buildcfg.conffile{4} = 'standard';
            node06.buildcfg.conffile=node06.buildcfg.conffile';
            node06.buildcfg.initscdbeforecomp = [0 0 0 0];
            node06.usewavegen = 0;
            node06.datadict='SCD_rtc_06.sldd';                        
            
            node07.active = 0;
            node07.ncpu = 4;
            node07.type = '4cpus2015a';
            node07.timing.t_start = -0.5;
            node07.timing.t_stop = 2.5;
            node07.timing.dt = 1e-3;
            node07.thdwsample = [0 0 0 0];
            node07.thperiod = [1.0000e-03 1.0000e-03 1.0000e-03 1.0000e-03];
            node07.buildcfg.conffile{1} = 'standard';
            node07.buildcfg.conffile{2} = 'standard';
            node07.buildcfg.conffile{3} = 'standard';
            node07.buildcfg.conffile{4} = 'standard';
            node07.buildcfg.conffile=node07.buildcfg.conffile';
            node07.buildcfg.initscdbeforecomp = [0 0 0 0];
            node07.usewavegen = 0;
            node07.datadict='SCD_rtc_07.sldd';

            node08.active = 0;
            node08.ncpu = 1;
            node08.type = '4cpus2015a';
            node08.timing.t_start = -0.5;
            node08.timing.t_stop = 2.5;
            node08.timing.dt = 1e-3;
            node08.thdwsample = [0 0 0 0];
            node08.thperiod = [1.0000e-03 1.0000e-03 1.0000e-03 1.0000e-03];
            node08.buildcfg.conffile{1} = 'standard';
            node08.buildcfg.conffile{2} = 'standard';
            node08.buildcfg.conffile{3} = 'standard';
            node08.buildcfg.conffile{4} = 'standard';
            node08.buildcfg.conffile=node08.buildcfg.conffile';
            node08.buildcfg.initscdbeforecomp = [0 0 0 0];
            node08.usewavegen = 0;
            node08.datadict='SCD_rtc_08.sldd';            
  
            node = eval(sprintf('node%02d',nodenr));
            % general part]
            node.wrapper = cell(node.ncpu,1);
            node.wrapdatadicts=cell(node.ncpu,1);
            node.varalgo = ones(node.ncpu,1);
            node.cpuactive = zeros(node.ncpu,1);
            for iwrap=1:node.ncpu
              node.wrapper{iwrap} = sprintf('SCDwrap_template%02d%02d.slx',nodenr,iwrap);
              node.wrapdatadicts{iwrap} = sprintf('SCDwrap_template%02d%02d.sldd',nodenr,iwrap);
            end
      end
      
      function build_nodes(compileslx_list)
        for mynodeslx = compileslx_list
             fprintf(' *** Buiding Node %s ***\n',mynodeslx{1});
             rtwbuild(mynodeslx{1});
        end
      end
      function myslx = getslx(inode,icpu)
        if nargin==0
          myslx = 'tcv';
        elseif nargin==1
            assert(isnumeric(inode))
            myslx = sprintf('SCD_rtc_%02d',inode);
          elseif nargin==2
            myslx = sprintf('SCD_rtccode_%02d_%02d',inode,icpu);
          else
            error('invalid number of arguments');
        end
      function setcachefolder(obj)
        %% Set Cache Folder for experimental code (avoid conflicts with other tmp files)
        CacheFolder = fullfile(fileparts(mfilename('fullpath')),'..','..',...
          'gencodes',sprintf('CacheFolder-%d',obj.maincode));
        fprintf('Setting Simulink Cache folder to %s\n',CacheFolder)
        Simulink.fileGenControl('set',...
          'CacheFolder',CacheFolder,...
          'createdir',true);
      end
      
      function setcodegenfolder(obj)
        CodeGenFolder = fullfile(fileparts(mfilename('fullpath')),'..','..',...
          'gencodes',sprintf('CodeGenFolder-%d',obj.maincode));
        
        fprintf('Setting code generation folder to %s\n',CodeGenFolder)
        Simulink.fileGenControl('set',...
          'CodeGenFolder',CodeGenFolder,...
          'createdir',true);
      end
      
      function close_all()
        while ~isempty(bdroot)
          fprintf('Closing %s\n',bdroot)
          close_system(bdroot)
        end
      end
    end
    
    methods
        function obj=SCDclass_expcode()
           % All templates constructor
       
            obj.name = 'template';
            obj.maincode = 1;
            obj.status = 'debug';
            obj.loadverbose = 1;
            
            obj.activenodes=[1 2 3 6 7 8];
            obj.activecpus=[ {1}; ...
                             {1:4}; ...
                             {1:4}; ...
                             {1:4}; ...
                             {1:4}; ...
                             {1}]; 
            obj.algonamelist={};
            obj.algoddlist={};
            obj.wrapperlist={};
            obj.exportedtps = [];
            
            obj.mdscontainer = SCDclass_mdsobjcontainer;
            obj.taskcontainer = SCDclass_taskcontainer;

            for nodenr = 1:8
              obj.(sprintf('node%02d',nodenr)) = SCDclass_expcode.defaultnode(nodenr);
            end
        end
        
        function printinfo(obj)
           fprintf('*****************************************************\n');
           fprintf('* SCD expcode: ''%s'', main code: %d\n',obj.name,obj.maincode); 
           fprintf('*****************************************************\n');           
           fprintf('* Configured wrappers:\n')
           if(numel(obj.wrapperlist)>0)
               for ii=1:numel(obj.wrapperlist)
                   fprintf('  Node: %d, CPU: %d, varalgo: %d, wrapper: ''%s'', datadict: ''%s''\n', ...
                        obj.wrapperlist{ii}{1}, ...
                        obj.wrapperlist{ii}{2}, ...
                        obj.wrapperlist{ii}{3}, ...
                        obj.wrapperlist{ii}{4}, ...
                        obj.wrapperlist{ii}{5} ...
                    );
               end
           end
           fprintf('* Configured algorithms:\n');
           if(numel(obj.algonamelist)>0)
               for ii=1:numel(obj.algonamelist), fprintf('  ''%s''\n', char(obj.algonamelist{ii})); end 
           end
           fprintf('* Configured algorithm data dictionaries:\n')
           if(numel(obj.algoddlist)>0)
               for ii=1:numel(obj.algoddlist), fprintf('  ''%s''\n', char(obj.algoddlist{ii})); end 
           end
           fprintf('* Configured exported tunparams structures:\n')
           if(numel(obj.exportedtps)>0)
               for ii=1:numel(obj.exportedtps), fprintf('  ''%s''\n', char(obj.exportedtps{ii})); end
           end
           fprintf('* Configured MDS tunparams objects: %d (use printparameters method for details)\n', obj.mdscontainer.numparams);
           fprintf('* Configured MDS wavegens objects: %d (use printwavegens method for details)\n', obj.mdscontainer.numwavegens);
           fprintf('* Configured general purpose tasks: %d (use printtasks method for details)\n', obj.taskcontainer.numtasks);
           fprintf('* Configured init scripts: %d (use printinits method for details)\n', numel(obj.stdinits));
        end
        
        function obj = addwrapper(obj, node, cpu, varalgo, wrappername, varargin) 
            
            p=inputParser;
            checknodes = @(x) ismember(x,obj.activenodes );
            checkcpu = @(x) ismember(x,obj.activecpus{node});
          
            addRequired(p, 'node', checknodes); 
            addRequired(p, 'cpu', checkcpu); 
            addRequired(p, 'varalgo');
            addRequired(p, 'modelname', @(x) ischar(x));
            addOptional(p, 'datadictionary', '', @(x) ischar(x));
            
            parse(p, node, cpu, varalgo, wrappername, varargin{:});
            
            % In data dcitionary is not specified it is assumed having
            % the same name than the model
            if(isempty(p.Results.datadictionary))
                datadictionary=[p.Results.modelname '.sldd'];
            else
                datadictionary=[p.Results.datadictionary '.sldd'];
            end
            
            % First checking for duplicates
            if(numel(obj.wrapperlist)>0)
                wrappernamelist={};
                wrapperddnamelist={};
                for ii=1:numel(obj.wrapperlist)
                    wrappernamelist{end+1}=obj.wrapperlist{ii}{4};
                    wrapperddnamelist{end+1}=obj.wrapperlist{ii}{5};
                end
                if(ismember(p.Results.modelname,wrappernamelist) || ismember(p.Results.datadictionary,wrapperddnamelist))
                  warning('SCDclass_expcode:addwrapper','wrapper ''%s'' already present, ignoring.',wrappername);
            
            %% update node info
            nodestr=sprintf('node%02d',node);
            obj.(nodestr).varalgo(cpu) = varalgo;
            obj.(nodestr).wrapper{cpu} = wrappername;
            obj.(nodestr).cpuactive(cpu) = 1;
            %% save in wrapper list
                
            tempwrapper=cell(10,1);
            tempwrapper{1}=p.Results.node;
            tempwrapper{2}=p.Results.cpu;
            tempwrapper{3}=p.Results.varalgo;
            tempwrapper{4}=p.Results.modelname;
            tempwrapper{5}=datadictionary;
            obj.wrapperlist{end+1}=tempwrapper;
            
        end     
            
        function obj = addalgorithm(obj, in_node, in_cpu, in_algo)
            
            % TODO: import the entrire object into a container class ??
            
            p=inputParser;
            checknodes = @(x) ismember(x,obj.activenodes );
            checkcpu = @(x) ismember(x,obj.activecpus{in_node});
          
            addRequired(p, 'node', checknodes); 
            addRequired(p, 'cpu', checkcpu); 
            addRequired(p, 'algo', @(x) isobject(x));
            
            parse(p, in_node, in_cpu, in_algo);

            node = p.Results.node;
            cpu = p.Results.cpu;
            algo = p.Results.algo;
            
            % Checking and importing algorithm name
            if(~ismember(algo.getname,obj.algonamelist))
                obj.algonamelist{end+1}=algo.getname;
            else
                warning('SCDclass_expcode:addalgorithm','algorithm ''%s'' already present in the expcode, skipping!',algo.getname);
                return;
            end
                
            % Importing algorithm MDS objects into the main mdscontainer,
            % filling base structure name
            algomdscontainer=algo.getmdscontainer;
            basewgstruct=sprintf('SCDsimdata.SCDnode%02d%02d_simdata.wavegen', node, cpu);
            algomdscontainer=algomdscontainer.setwavegenbasestruct(basewgstruct);
            obj.mdscontainer=obj.mdscontainer.importmdsobjects(algomdscontainer);
             
            % Importing exported tps
            algoexptps=algo.getexportedtps;
            if(numel(algoexptps)>0)
                for(ii=1:numel(algoexptps))
                    if(~ismember(algoexptps{ii},obj.exportedtps))
                        obj.exportedtps{end+1}=algoexptps{ii};
                    else
                        warning('SCDclass_expcode:addalgorithm','exported tunparams sctruct ''%s'' already present, ignoring',algoexptps{ii})
                    end
                end
            end
            
            % Importing algorithms data dictionary, only those with proper
            % name
            algodd=algo.getdatadictionary;
            if(strcmp(algodd(1:7),'SCDalgo'))
                if(~ismember(algodd,obj.algoddlist))
                    obj.algoddlist{end+1}=algodd;
                else
                    warning('SCDclass_expcode:addalgorithm','algorithm data dictionary ''%s'' already present, ignoring', algodd);
                end
            else
                % warning here ?
            end
           
            % Importing tasks 
            algotaskcontainer=algo.gettaskcontainer;
            obj.taskcontainer=obj.taskcontainer.importtaskobjects(algotaskcontainer);
            
            % Importing inits
            algoinits=algo.getinits;
            if(numel(algoinits)>0)
              toadd = ones(numel(algoinits),1);
              for ii=1:numel(algoinits)
                if(~isempty(obj.stdinits))
                  for jj=1:numel(obj.stdinits)
                    for kk=1:numel(obj.stdinits{jj}{2})
                      if(strcmp(char(obj.stdinits{jj}{2}{kk}),algoinits{ii}{2}))
                        warning('SCDclass_expcode:addalgorithm','An init driving the structure %s has already been added, ignoring this init.\d',algoinits{ii}{2})
                        toadd(ii)=0;
                      end
                  end
                end
                if toadd(ii)
                  temp=cell(10,1);
                  temp{1}=algoinits{ii}{1};
                  temp{2}=algoinits{ii}{2};
                  obj.stdinits{end+1}=temp;
              end
              if any(toadd) % if any inits from this algoobj were taken
                obj.algoobjlist{end+1}=algo; %% Add the full algorithm object here, to see if it is fine
              end
            end
        end     
            
        function out = getexportedtps(obj)
            out = obj.exportedtps;
        end
        
        function obj = importexpcode(obj, expcode)
           % This function imports settings of an existing expcode into another
           
           warning('Not yet supported!');
           return;
           
           % tunparamstruct import
           exportedtpstoadd = expcode.getexportedtps;
           for ii=1:numel(exportedtpstoadd)
               if ~sum(ismember(exportedtpstoadd{ii},obj.exportedtps))
                   obj.addtunparamstruct(exportedtpstoadd{ii});
               end
           end
            
           % parameters import
           obj.mdscontainer=obj.mdscontainer.importmdsobjects(expcode.mdscontainer);
        end
        
        
        function setup(obj)
           % This function sets up the TCV Simulink  model
           % to simulate this experimental code.
           % NOTE THAT it doesn't actualize tunable parameters
           % and wavegens, call actualizedata for that
           fprintf('Setting up expcode %d, ''%s'', configuring wrappers ...\n',obj.maincode,obj.name);
           obj=obj.setupwrappers;
           obj.setupvaralgo;
           fprintf('Setting up expcode %d, ''%s'', configuring data dictionaries ...\n',obj.maincode,obj.name);
           obj.setupwrapdd;
           obj.setupalgodd;
           fprintf('Setting up expcode %d, ''%s'', configuring global data ...\n',obj.maincode,obj.name);
           obj.setupmain;
           fprintf('Setting up expcode %d, ''%s'', configuring main workspace variables ...\n',obj.maincode,obj.name);           
           obj.buildworkspacesimstruct;
           obj.buildworkspacetpstruct;
           % Set cache and codegen folders
           SCDclass_expcode.setcachefolder(obj);
           SCDclass_expcode.setcodegenfolder(obj);
        function actualize(obj, shot, varargin)
            p=inputParser;
            % if a model name is given, operations will be performed
            % only on it, otherwise they will be performed on all
            % configured models
            addParameter(p,'model','',@(x) ischar(x));
            parse(p,varargin{:});
            
            if(isempty(p.Results.model))
                obj.modeltoactualize='all';
            else
                obj.modeltoactualize=p.Results.model;
            end
            
            obj.actualizedata(shot);
            fprintf('Actualizing expcode %d, ''%s'', performing tasks ...\n',obj.maincode,obj.name);
            obj.taskcontainer.modeltoexecute=obj.modeltoactualize;
            obj.taskcontainer.exectasksoninit(shot);
        end
        
        function actualizedata(obj, shot)
           % This function actualizes configured
           % tunable parameters and wavegens timeseries
           % according to the given shot
           
           currentexpcode=Simulink.data.evalinGlobal('tcv','scd.expcode');
           if(currentexpcode~=obj.maincode)
               error('SCDclass_expcode:wrongexpcodeloaded','Cannot perform data actualization, the loaded expcode is not matching, try to setup the expcode first');
           end
           fprintf('Actualizing expcode %d, ''%s'', configuring tunable parameters ...\n',obj.maincode,obj.name);
           obj.actualizeparameters(shot)
           fprintf('Actualizing expcode %d, ''%s'', configuring wavegens ...\n',obj.maincode,obj.name);
           obj.actualizewavegens(shot);
        end

        
        function printparameters(obj)
            obj.mdscontainer.printparameters;
        end

        function printwavegens(obj)
            obj.mdscontainer.printwavegens;
        end
        
        function printtasks(obj)
            obj.taskcontainer.printtasks;
        end
        
        function actualizeparameters(obj,shot)
            obj.mdscontainer.modeltoactualize=obj.modeltoactualize;
            obj.mdscontainer.actualizeparameters(shot);
        end
        
        function actualizewavegens(obj,shot)
            obj.mdscontainer.modeltoactualize=obj.modeltoactualize;
            obj.mdscontainer.actualizewavegens(shot);
        end
        
        
        function printinits(obj)
           if(~isempty(obj.stdinits))
               for ii=1:numel(obj.stdinits)
                   fprintf('%s -> %s\n',char(obj.stdinits{ii}{1}),char(obj.stdinits{ii}{2}));
               end
           end
        end
       
       
        function callinits(obj,shot)
          if(~isempty(obj.algoobjlist))
              for(ii=1:numel(obj.algoobjlist))
                 if nargin==1
                  obj.algoobjlist{ii}.callinits();
                 elseif nargin==2
                   obj.algoobjlist{ii}.callinits(shot);
                 else
                   error('invalid number of arguments for callinits');
                 end
        function printMARTe2taskconfig(obj, shot, varargin)   
            p=inputParser;
            % if a model name is given, operations will be performed
            % only on it, otherwise they will be performed on all
            % configured models
            addParameter(p,'model','',@(x) ischar(x));
            parse(p,varargin{:});
            
            if(isempty(p.Results.model))
                obj.taskcontainer.modeltogenerate='all';
            else
                obj.taskcontainer.modeltogenerate=p.Results.model;
            end
            obj.taskcontainer.printMARTe2taskconfig(shot);
        end
        
        function printMARTe2parconfig(obj, shot, varargin)   
            p=inputParser;
            % if a model name is given, operations will be performed
            % only on it, otherwise they will be performed on all
            % configured models
            addParameter(p,'model','',@(x) ischar(x));
            parse(p,varargin{:});
            
            if(isempty(p.Results.model))
                obj.mdscontainer.modeltogenerate='all';
            else
                obj.mdscontainer.modeltogenerate=p.Results.model;
            end
            obj.mdscontainer.printMARTe2parconfig(shot);
        function printMARTe2wgbusconfig(obj, shot, ddname, busname, frequency)
            fprintf("+MDSWavegen_%s = {\n", busname);
            fprintf(" Class = MDSWavegen\n");
            fprintf(" Shot = %d\n",shot);
            fprintf(" Frequency = %.2f\n",frequency);
            dim=obj.mdscontainer.printMARTe2wgbusconfig(shot, ddname, busname);       
            fprintf(" Signals = {\n");
            fprintf("   wavegen_%s = { Type = float32 NumberOfElements = %d }\n", busname, dim ); 
            fprintf(" }\n");
            fprintf("}\n");
        end
        function compile(~,varargin)
          myslx = SCDclass_expcode.getslx(varargin{:});
          fprintf('Compiling %s.slx\n',myslx)
            eval(sprintf('%s([],[],[],''compile'')',myslx));
            eval(sprintf('%s([],[],[],''term'')',myslx));
        function sim(~,varargin)
          SCDconf_setSIMconf
          myslx = SCDclass_expcode.getslx(varargin{:});
          fprintf('Simulating %s.slx\n',myslx)
          sim(myslx)
        function open(~,varargin)
          openslx = SCDclass_expcode.getslx(varargin{:});
          fprintf('Opening %s.slx\n',openslx)
Federico Felici's avatar
Federico Felici committed
          open(openslx);
        function build(obj,varargin)
          if numel(varargin)==0
            fprintf('\n=== Building all threads for %s ===\n',obj.name);
            % make list of nodes to build
            compileslx_list = cell(0);
            for inode=1:8
              nodeinfo=obj.(sprintf('node%02d',inode));
              for icpu = 1:nodeinfo.ncpu
                if nodeinfo.cpuactive(icpu)
                  compileslx_list = [compileslx_list,...
                    SCDclass_expcode.getthreadslx(node,cpu)]; %#ok<AGROW>
                end
              end
            end
            
            if isempty(compileslx_list)
              fprintf('No active nodes found, no .slx to compile. Done\n');
              return
            end
          else
            % user passed nodes,threads to compile
            myslx = SCDclass_expcode.getslx(varargin{:});
            fprintf('building %s.slx\n',myslx)
          end
           % set CodeGen folder for this expcode (allows fast rebuilding)
           SCDclass_expcode.setcodegenfolder(obj)
Federico Felici's avatar
Federico Felici committed
           % check env variable
           assert(~isempty(getenv('RTCCODE_LIBPATH')),'RTCCODE_LIBPATH environment variable needs to be defined to compile');
Federico Felici's avatar
Federico Felici committed
    
           % set configuration settings for compilation
           SCDconf_setCODEconf('configurationSettingsCODEicc')
Federico Felici's avatar
Federico Felici committed

           % Build
           try
             SCDclass_expcode.build_nodes(compileslx_list);
           catch ME
             % if fails on first attempt, clear build folder and retry
             fprintf(' **** FIRST ATTEMPT BUILDING %s FAILED **** \n',obj.name)
             fprintf('  Error message:\n %s\n',getReport(ME));
             fprintf('  Try again clearning build folder\n')
             
             system(sprintf('rm -rf %s/*',CodeGenFolder));
             SCDclass_expcode.build_nodes(compileslx_list);
           end           
    end
   
    methods (Access = private)
        
        function obj=printlog(obj,str)
            if obj.loadverbose==1
               fprintf('Expcode %d, %s\n', obj.maincode, str); 
            end
        end
                 
        function obj = buildworkspacetpstruct(obj)
            % this funtion builds a workspace structures containing
Federico Felici's avatar
Federico Felici committed
            % replicas of all tunable parameters structures in the data
            % dictionaries, this structure is the one actually used 
            % for loading simulation wavegen data
            % It is better not to use directly data dictionaries structures
            % to avoid flooding dds with big sim data sets (and
Federico Felici's avatar
Federico Felici committed
            % conseguently the rtccode GIT repo itself
           
            dd=SCDconf_getdatadict('tcv.sldd');
            
            for ii=1:numel(obj.exportedtps)
                simstructnamedd=sprintf('%s_tmpl',char(obj.exportedtps(ii)));
                simstructnamews=char(obj.exportedtps(ii));
                simstruct=dd.getEntry(simstructnamedd).getValue;
                assignstr=sprintf('%s=temp;',simstructnamews);
                assignin('base','temp',simstruct);
                evalin('base',assignstr);
            end
            
            evalin('base','clear temp;');            
        end
        
           
        function obj = setupwrapdd(obj)
            % Sets up the data dictionaries of the wrappers to be loaded
            % on the nodes inside the main tcv.sldd
            
            % For every node, given the current status finds its dictionary
            % and the requred data sources, find actions to do and setup
            % wrappers data sources accordingly
            
            % It is assumed that there is only 1 wrapper and 1 wrapper data
            % dictionary active at a given time for every CPU model
            
            % Looping through every active node
            for idx_nodedds=1:numel(obj.activenodes)
                
               % Getting data dictionary and required data sources 
               datadictname=eval(sprintf('obj.node%02d.datadict',obj.activenodes(idx_nodedds)));
               nodedd=Simulink.data.dictionary.open(datadictname);
               nodeddsources=nodedd.DataSources;
               reqsources=eval(sprintf('obj.node%02d.wrapdatadicts', obj.activenodes(idx_nodedds)));
               
               % Filtering out not pertinent data sources by name prefix
               nodeddsourcesok={};
               nodeddsourcesokitems=0;
               for ii=1:numel(nodeddsources)
                  if(strcmp(nodeddsources{ii}(1:7),'SCDwrap'))
                      temp={nodeddsources{ii}, 0};
                      nodeddsourcesok=[nodeddsourcesok; temp];
                      nodeddsourcesokitems=nodeddsourcesokitems+1;
                  end
               end
               
               reqsourcesok={};
               reqsourcesokitems=0;
               for ii=1:numel(reqsources)
                  if(strcmp(reqsources{ii}(1:7),'SCDwrap'))           
                      temp={reqsources{ii}, 1};
                      reqsourcesok=[reqsourcesok; temp];
                      reqsourcesokitems=reqsourcesokitems+1;
                  else
                      str=sprintf('Proposed wrapper data dictionary %s does not begin with SCDwrap, ignoring it.', reqsources{ii});
                      warning(str);
                      %obj.printlog(str);
                  end
                  
               end
               
               % Finding which data sources to eliminate and which to add
               if(nodeddsourcesokitems>0 && reqsourcesokitems>0)
                  for ii=1:nodeddsourcesokitems
                     todel=1;
                     for jj=1:reqsourcesokitems
                         if(strcmp(char(nodeddsourcesok{ii,1}),char(reqsourcesok{jj,1})))
                             todel=0;
                             break
                         end
                     end
                     nodeddsourcesok{ii,2}=todel;
                  end
                  
                  for ii=1:reqsourcesokitems
                     toadd=1;
                     for jj=1:nodeddsourcesokitems
                         if(strcmp(char(reqsourcesok{ii,1}),char(nodeddsourcesok{jj,1})))
                             toadd=0;
                             break
                         end
                     end
                     reqsourcesok{ii,2}=toadd;
                  end  
               end
               
               % Removing data sources
               if(nodeddsourcesokitems>0)
                  for ii=1:nodeddsourcesokitems
                    if(nodeddsourcesok{ii,2}==1)
                       str=sprintf('Removing wrapper data source %s from %s', char(nodeddsourcesok{ii,1}), datadictname);
                       obj.printlog(str);
                       removeDataSource(nodedd, char(nodeddsourcesok{ii,1}));
                    end
                  end
               end
               
               % Adding data sources
               if(reqsourcesokitems>0)
                  for ii=1:reqsourcesokitems
                      if(reqsourcesok{ii,2}==1)
                         str=sprintf('Adding wrapper data source %s to %s', char(reqsourcesok{ii,1}), datadictname); 
                         obj.printlog(str);
                         addDataSource(nodedd, char(reqsourcesok{ii,1}));
                      end
                  end
               end
                   
            end  
        end
        
        function obj = setupalgodd(obj)
            
               % Getting data dictionary and required data sources 
               tcvdd=Simulink.data.dictionary.open('tcv.sldd');
               tcvddsources=tcvdd.DataSources;
               reqsources=obj.algoddlist;
               
               % Filtering out not pertinent data sources by name prefix
               tcvddsourcesok={};
               tcvddsourcesokitems=0;
               for ii=1:numel(tcvddsources)
                  if(strcmp(tcvddsources{ii}(1:7),'SCDalgo'))
                      temp={tcvddsources{ii}, 1};
                      tcvddsourcesok=[tcvddsourcesok; temp];
                      tcvddsourcesokitems=tcvddsourcesokitems+1;
                  end
               end
               
               reqsourcesok={};
               reqsourcesokitems=0;
               for ii=1:numel(reqsources)
                  if(strcmp(reqsources{ii}(1:7),'SCDalgo'))           
                      temp={reqsources{ii}, 1};
                      reqsourcesok=[reqsourcesok; temp];
                      reqsourcesokitems=reqsourcesokitems+1;
                  else
                      warning('SCDexpcode:setupalgodd','Proposed algo data dictionary %s does not begin with SCDalgo, ignoring it.', reqsources{ii});
                  end
               end
               
               % Finding which data sources to eliminate and which to add
               if(tcvddsourcesokitems>0 && reqsourcesokitems>0)
                  for ii=1:tcvddsourcesokitems
                     todel=1;
                     for jj=1:reqsourcesokitems
                         if(strcmp(char(tcvddsourcesok{ii,1}),char(reqsourcesok{jj,1})))
                             todel=0;
                             break
                         end
                     end
                     tcvddsourcesok{ii,2}=todel;
                  end

                  for ii=1:reqsourcesokitems
                     toadd=1;
                     for jj=1:tcvddsourcesokitems
                         if(strcmp(char(reqsourcesok{ii,1}),char(tcvddsourcesok{jj,1})))
                             toadd=0;
                             break
                         end
                     end
                     reqsourcesok{ii,2}=toadd;
                  end  
               end
               
               % Removing data sources
               if(tcvddsourcesokitems>0)
                  for ii=1:tcvddsourcesokitems
                    if(tcvddsourcesok{ii,2}==1)
                       str=sprintf('Removing algorithm data source %s', char(tcvddsourcesok{ii,1}));
                       obj.printlog(str);
                       removeDataSource(tcvdd, char(tcvddsourcesok{ii,1}));
                    end
                  end
               end
               
               % Adding data sources
               if(reqsourcesokitems>0)
                  for ii=1:reqsourcesokitems
                      if(reqsourcesok{ii,2}==1)
                         str=sprintf('Adding algorithm data source %s', char(reqsourcesok{ii,1})); 
                         obj.printlog(str);
                         addDataSource(tcvdd, char(reqsourcesok{ii,1}));
                      end
                  end
               end
        end
        
        function buildworkspacesimstruct(obj)
            obj.mdscontainer.buildworkspacesimstruct;
        end    


        function obj = setupmain(obj)
            % sets up global configs for the expcode
            assigncmd=sprintf('scd.expcode=%d;',obj.maincode);
            Simulink.data.evalinGlobal('tcv',assigncmd);
        end
        
        function obj = setupwrappers(obj)
            
            for ii=1:numel(obj.wrapperlist)
                switch obj.wrapperlist{ii}{1}
                    case 1
                        if(obj.wrapperlist{ii}{2}==1)
                            obj.node01.varalgo=obj.wrapperlist{ii}{3};
                            obj.node01.wrapdatadicts{1}=obj.wrapperlist{ii}{5};
                        else
                            warning('SCDclass_expcode:setupwrappers','not supported node01 cpu');
                        end
                        
                    case 2
                        if(obj.wrapperlist{ii}{2}>=1 &&  obj.wrapperlist{ii}{2}<=4)
                            obj.node02.varalgo(obj.wrapperlist{ii}{2})=obj.wrapperlist{ii}{3};
                            obj.node02.wrapdatadicts{obj.wrapperlist{ii}{2}}=obj.wrapperlist{ii}{5};
                        else
                            warning('SCDclass_expcode:setupwrappers','not supported node02 cpu');
                        end
                        
                    case 3
                        if(obj.wrapperlist{ii}{2}>=1 &&  obj.wrapperlist{ii}{2}<=4)
                            obj.node03.varalgo(obj.wrapperlist{ii}{2})=obj.wrapperlist{ii}{3};
                            obj.node03.wrapdatadicts{obj.wrapperlist{ii}{2}}=obj.wrapperlist{ii}{5};
                        else
                            warning('SCDclass_expcode:setupwrappers','not supported node03 cpu');
                        end
                                             
                    case 6
                        if(obj.wrapperlist{ii}{2}>=1 &&  obj.wrapperlist{ii}{2}<=4)
                            obj.node06.varalgo(obj.wrapperlist{ii}{2})=obj.wrapperlist{ii}{3};
                            obj.node06.wrapdatadicts{obj.wrapperlist{ii}{2}}=obj.wrapperlist{ii}{5};
                        else
                            warning('SCDclass_expcode:setupwrappers','not supported node06 cpu');
                        end
                        
                    case 7
                        if(obj.wrapperlist{ii}{2}>=1 &&  obj.wrapperlist{ii}{2}<=4)
                            obj.node07.varalgo(obj.wrapperlist{ii}{2})=obj.wrapperlist{ii}{3};
                            obj.node07.wrapdatadicts{obj.wrapperlist{ii}{2}}=obj.wrapperlist{ii}{5};
                        else
                            warning('SCDclass_expcode:setupwrappers','not supported node07 cpu');
                        end
                        
                    case 8
                        if(obj.wrapperlist{ii}{2}==1)
                            obj.node08.varalgo=obj.wrapperlist{ii}{3};
                            obj.node08.wrapdatadicts{1}=obj.wrapperlist{ii}{5};
                        else
                            warning('SCDclass_expcode:setupwrappers','not supported node08 cpu');
                        end
                        
                    otherwise
                        warning('SCDclass_expcode:setupwrappers','not supported node');
                  
                end
                
            end
            
        end
        
        function obj = setupvaralgo(obj)
            % Sets up varalgo structure in main tcv data dictionary
            % according to varalgo info of the nodes

            % Getting data section of main tcv data dictionary
            d=Simulink.data.dictionary.open('tcv.sldd');
            dd=getSection(d, 'Design Data');
            varalgodd=dd.getEntry('SCDvaralgo');
            
            s=struct();
            
            % Looping through every active node
            for idx_nodedds=1:numel(obj.activenodes)
               varalgo=eval(sprintf('obj.node%02d.varalgo',obj.activenodes(idx_nodedds)));
               
               for ii=1:numel(varalgo)
                   str=sprintf('s.algo%02d%02d=%d;',obj.activenodes(idx_nodedds),ii,varalgo(ii));
                   eval(str);
               end
            end
            varalgodd.setValue(s);
        end

    end