classdef SCDclass_node < SCDclass_component % Wrapper class containing algos properties (SetAccess = private) nodenr active = false; % not active by default hasrfm = true; % all nodes have rfm haswavegen hasadc hasethercat ncpu % number of CPUs cputype timing = struct('t_start',-4.5,'t_stop',3,'dt',1e-4); thperiod buildcfg initscdbeforecomp cpuactive wrappers % info about thread wrappers contained in this node end properties type = 'node'; end methods function obj = SCDclass_node(nodenr) name = sprintf('SCD_rtc_%02d',nodenr); obj.nodenr = nodenr; obj.name = name; obj.algos = []; obj.ddname = [name,'.sldd']; obj.mdlname = [name,'.slx']; obj = defaultnodeconfig(obj,nodenr); end function obj = addwrapper(obj,wrapperObj,cpunr,varalgo,isactive) % by default, activate CPU when adding a wrapper if nargin==4, isactive=true; end assert(isa(wrapperObj,'SCDclass_wrapper')); for ii=1:numel(obj.wrappers) assert(~isequal(wrapperObj,obj.wrappers{ii}.wrapperobj),... 'wrapper %s is already present in node %d thread %d',... obj.wrappers{ii}.wrapperobj.name,obj.nodenr,cpunr) end mywrapper.wrapperobj = wrapperObj; mywrapper.cpunr = cpunr; mywrapper.varalgo = varalgo; obj.wrappers{cpunr} = mywrapper; obj.cpuactive(cpunr) = isactive; end function node = defaultnodeconfig(node,nodenr) % [general part] switch nodenr case 1 node.ncpu = 1; node.type = 'std1cpu2015a'; node.timing.t_start = -4.5; node.timing.t_stop = 3; node.timing.dt = 1e-4; node.thperiod = 1.0000e-03; node.buildcfg.conffile{1} = 'standard'; node.buildcfg.initscdbeforecomp = false; node.haswavegen = true; node.hasethercat = false; node.hasadc = true; case 2 node.ncpu = 6; node.type = 'std1cpu2015a'; node.timing.t_start = -4.5; node.timing.t_stop = 3; node.timing.dt = 1e-4; node.thperiod = [1.0000e-03 1.0000e-03 1.0000e-03 1.0000e-03 1.0e-3 1.0e-3]; node.buildcfg.conffile = cell(node.ncpu,1); node.buildcfg.conffile{1} = 'standard'; node.buildcfg.conffile{2} = 'standard'; node.buildcfg.conffile{3} = 'standard'; node.buildcfg.conffile{4} = 'standard'; node.buildcfg.conffile{5} = 'standard'; node.buildcfg.conffile{6} = 'standard'; node.buildcfg.initscdbeforecomp = false; node.haswavegen = true; node.hasadc = true; node.hasethercat = true; case 3 node.ncpu = 4; node.type = '4cpus2015a'; node.timing.t_start = -2.0; node.timing.t_stop = 2.75; node.timing.dt = 1e-3; node.thperiod = [1.0000e-03 1.0000e-03 1.0000e-03 1.0000e-03]; node.buildcfg.conffile = cell(node.ncpu,1); node.buildcfg.conffile{1} = 'standard'; node.buildcfg.conffile{2} = 'standard'; node.buildcfg.conffile{3} = 'standard'; node.buildcfg.conffile{4} = 'standard'; node.buildcfg.initscdbeforecomp = [0 0 0 0]; node.haswavegen = true; node.hasadc = false; node.hasethercat = false; case 4 node.ncpu = 4; node.type = 'std1cpu2015a'; node.timing.t_start = -4.5; node.timing.t_stop = 3; node.timing.dt = 1e-4; node.thperiod = 1.0000e-04; node.buildcfg.conffile{1} = 'standard'; node.buildcfg.initscdbeforecomp = false; node.haswavegen = true; node.hasadc = false; node.hasethercat = false; case 5 node.ncpu = 1; node.type = 'std1cpu2015a'; node.timing.t_start = -4.5; node.timing.t_stop = 3; node.timing.dt = 1e-4; node.thperiod = 1.0000e-04; node.buildcfg.conffile{1} = 'standard'; node.buildcfg.initscdbeforecomp = false; node.haswavegen = true; node.hasadc = false; node.hasethercat = false; case 6 node.ncpu = 4; node.type = '4cpus2015a'; node.timing.t_start = 0.0; node.timing.t_stop = 2.75; node.timing.dt = 1e-3; node.thperiod = [1.0000e-03 1.0000e-03 1.0000e-03 1.0000e-03]; node.buildcfg.conffile = cell(node.ncpu,1); node.buildcfg.conffile{1} = 'standard'; node.buildcfg.conffile{2} = 'standard'; node.buildcfg.conffile{3} = 'standard'; node.buildcfg.conffile{4} = 'standard'; node.buildcfg.initscdbeforecomp = [0 0 0 0]; node.haswavegen = true; node.hasadc = false; node.hasethercat = false; case 7 node.ncpu = 4; node.type = '4cpus2015a'; node.timing.t_start = -0.5; node.timing.t_stop = 2.5; node.timing.dt = 1e-3; node.thperiod = [1.0000e-03 1.0000e-03 1.0000e-03 1.0000e-03]; node.buildcfg.conffile = cell(node.ncpu,1); node.buildcfg.conffile{1} = 'standard'; node.buildcfg.conffile{2} = 'standard'; node.buildcfg.conffile{3} = 'standard'; node.buildcfg.conffile{4} = 'standard'; node.buildcfg.initscdbeforecomp = [0 0 0 0]; node.haswavegen = true; node.hasadc = true; node.hasethercat = false; case 8 node.ncpu = 1; node.type = '4cpus2015a'; node.timing.t_start = -0.5; node.timing.t_stop = 2.5; node.timing.dt = 1e-3; node.thperiod = [1.0000e-03 1.0000e-03 1.0000e-03 1.0000e-03]; node.buildcfg.conffile = cell(node.ncpu,1); node.buildcfg.conffile{1} = 'standard'; node.buildcfg.conffile{2} = 'standard'; node.buildcfg.conffile{3} = 'standard'; node.buildcfg.conffile{4} = 'standard'; node.buildcfg.initscdbeforecomp = [0 0 0 0]; node.haswavegen = true; node.hasadc = true; node.hasethercat = false; end node.cpuactive = zeros(1,node.ncpu); % add template node wrappers for icpu=1:node.ncpu wrappername = sprintf('SCDwrap_template%02d%02d',nodenr,icpu); mywrapper = SCDclass_wrapper(wrappername); varalgo = 1; % template value node = node.addwrapper(mywrapper,icpu,varalgo,false); end end function obj = setactive(obj,value) assert(islogical(value),'value must be boolean') obj.active = value; end function linknodedd(obj,node) % link node data dictionary to main expcode object data dicationary assert(isa(node,'SCDclass_node'),'node must be an SCDclass_node object') ddObj = Simulink.data.dictionary.open(obj.ddname); prefix = 'SCD_rtc'; % already linked sources prevsources = ddObj.DataSources; prevsources_nodes = prevsources(startsWith(prevsources,prefix)); % make algo data dictionary list list reqsources = node.ddname; % removing unnecessary ones for ii=1:numel(prevsources_nodes) mysource = prevsources_nodes{ii}; if ~contains(reqsources,mysource) obj.printlog('Removing algorithm data source %s from %s',mysource,obj.ddname); ddObj.removeDataSource(prevsources_nodes{ii}) end end % add new ones not yet present mysource = reqsources; assert(startsWith(mysource,prefix),... 'attempting to add algo dd: %s that does not start with ''%s''-aborting',prefix,mysource); if contains(prevsources,mysource) obj.printlog('Not adding node data source %s - already exists',mysource); else obj.printlog('Adding node data source %s to %s',mysource,obj.ddname); ddObj.addDataSource(mysource); end end function updatetemplatetp(obj) % update wrapper algos for ii=1:numel(obj.wrappers) obj.wrappers{ii}.wrapperobj.updatetemplatetp; end % update node algos for ii=1:numel(obj.algos) if ~isempty(obj.algos(ii)) obj.algos(ii).updatetemplatetp; end end end function printinfo(obj) % print wrapper and algo info fprintf('\nNode%02d, CPUs:%02d, nodename:%s\n',... obj.nodenr,obj.ncpu,obj.name) for wrapper = obj.wrappers fprintf(' CPU %d wrapper: ',wrapper{:}.cpunr); wrapper{:}.wrapperobj.printinfo; end if ~isempty(obj.algos) fprintf(' Node Algos:\n') for ii=1:numel(obj.algos) algo = obj.algos(ii); fprintf('%s',algo.getname); end end fprintf('\n'); end end end