Newer
Older
% Main methods:
% .open: Open baseline .slx model
% open(N): Open node N
% open(N,M): Open thread M of node N
% .build, build(N), build(N,M): Generate C code for node N, thread M
% .compile, compile(N), compile(N,M): Compile Simulink model for node N, thread M)
% .close_all: Close all Simulink block diagrams
%
% .printinfo: Print information about components of this expcode
% .printtasks: Print configured tasks
% .printwavegens: Print configured wavegen signals
%.
properties (Access = public)
% Main properties
maincode % Expcode numerical code
end
properties (Access = protected)
loadverbose % Verbosity level of the loading (currently 0 or 1)
end
properties (SetAccess = private)
name % Expcode main name
initobjlist % list of loaded algorithm objects with configured inits
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
modeltoactualize % name of the algorithm to actualize ('all' means all coonfigured)
algos % list of algorithms objects
nodes % array of node properties structs
ddname = 'tcv.sldd' % main expcode data dictionary name
%%
%% STATIC METHODS
%%
function help
help(mfilename)
end
function build_nodes(compileslx_list)
for mynodeslx = compileslx_list
fprintf(' *** Buiding Node %s ***\n',mynodeslx{1});
rtwbuild(mynodeslx{1});
end
end
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 close_all(saveflag)
if nargin==0
saveflag = 1;
end
assert(saveflag == 1 || saveflag == 0,'saveflag must be 1 or 0')
if saveflag==1
closemsg = 'Saving and Closing %s\n';
else
closemsg = 'Dicarding changes and closing %s\n';
end
while ~isempty(bdroot)
fprintf(closemsg,bdroot);
close_system(bdroot,saveflag)
%%
%% PUBLIC METHODS
%%
function obj=SCDclass_expcode(name)
if nargin==0; name = 'template'; end
obj.name = name;
obj.maincode = 1;
obj.status = 'debug';
obj.loadverbose = 1;
hardwarepath = fileparts(which(mainslx));
assert(~isempty(hardwarepath),'%s not found?',mainslx)
obj.ddpath = hardwarepath;
obj.definednodes = [1 2 6 7 8];
obj.algonamelist = {};
obj.algoddlist = {};
obj.exportedtps = [];
obj.mdscontainer = SCDclass_mdsobjcontainer;
obj.taskcontainer = SCDclass_taskcontainer;
obj.nodes{nodenr} = SCDclass_node(nodenr);
%% Main expcode handling methods
function open(~,varargin)
openslx = SCDclass_expcode.getslxname(varargin{:});
fprintf('Opening %s.slx\n',openslx)
open(openslx);
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 data dictionaries ...\n',obj.maincode,obj.name);
obj.setupnodedd;
obj.setupmaindd;
fprintf('Setting up expcode %d, ''%s'', configuring default tunable parameters ...\n',obj.maincode,obj.name);
obj.updatedefaulttp;
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
obj.setcachefolder;
obj.setcodegenfolder;
end
% create main data dictionary from scratch to ensure it exists
if contains(Simulink.data.dictionary.getOpenDictionaryPaths,obj.ddname)
Simulink.data.dictionary.closeAll(obj.ddname,'-discard');
% close if it exists and discard changes
delete(which(obj.ddname));
Simulink.data.dictionary.create(fullfile(obj.ddpath,obj.ddname));
end
% prepare main top-level SLDD
dd = Simulink.data.dictionary.open(obj.ddname);
% link data dictionaries for active nodes
mydatasource = obj.nodes{ii}.ddname;
fprintf('adding data source %s to %s\n',mydatasource,obj.ddname)
dd.addDataSource(mydatasource);
fprintf('Setting up variant model configuration')
obj.setupvaralgo;
dd.saveChanges;
function actualize(obj, shot, varargin)
% 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
% close all data dictionaries
Simulink.data.dictionary.closeAll('-discard')
% Set configuration settings sldd
SCDconf_setConf('SIM')
% carry out any init tasks of algorithms
for ii=1:numel(obj.initobjlist)
obj.initobjlist{ii}.init();
opendds = Simulink.data.dictionary.getOpenDictionaryPaths;
% check that tcv.sldd is not opened by some algorithm init
assert(~any(contains(opendds,obj.ddname)),...
'init for %s leaves %s open - this should be avoided',...
obj.initobjlist{ii}.getname,obj.ddname)
end
fprintf('\n** DONE WITH ALL SCDINITS **\n');
function updatemdsmodel(obj, algo)
obj.updatemds(algo, -1);
function compile(~,varargin)
myslx = SCDclass_expcode.getslxname(varargin{:});
fprintf('Compiling %s.slx\n',myslx)
try
eval(sprintf('%s([],[],[],''compile'')',myslx));
eval(sprintf('%s([],[],[],''term'')',myslx));
catch ME
rethrow(ME)
end
end
function sim(~,varargin)
SCDconf_setConf('SIM')
myslx = SCDclass_expcode.getslxname(varargin{:});
fprintf('Simulating %s.slx\n',myslx)
sim(myslx)
end
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
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.nodes(inode);
for icpu = 1:nodeinfo.ncpu
if nodeinfo.cpuactive(icpu)
compileslx_list = [compileslx_list,...
SCDclass_expcode.getslxname(inode,icpu)]; %#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.getslxname(varargin{:});
fprintf('building %s.slx\n',myslx)
compileslx_list{1} = myslx;
end
% set CodeGen folder for this expcode (allows fast rebuilding)
CodeGenFolder = obj.setcodegenfolder;
% check env variable
assert(~isempty(getenv('RTCCODE_LIBPATH')),'RTCCODE_LIBPATH environment variable needs to be defined to compile');
% set configuration settings for compilation
SCDconf_setConf('CODE');
% 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
%% Property access methods
function nodes = getnodes(obj)
nodes = obj.nodes;
end
function obj = setnode(obj,node,nodenr)
node = node.setactive(true);
assert(node.nodenr == nodenr,...
'set node number and node property do not match while setting node %s',nodenr)
obj.nodes{node.nodenr} = node;
% Make lists of data dictionaries, mds objects, init functions etc
% that come with this node.
% wrapper algorithms
for iwrap = 1:numel(node.wrappers)
wrapperObj = node.wrappers{iwrap}.wrapperobj;
for ialgo = 1:numel(wrapperObj.algos)
algoObj = wrapperObj.algos(ialgo);
obj = processalgorithm(obj,algoObj,node.nodenr,cpunr);
end
end
% node algorithms
for ialgo = 1:numel(node.algos)
algoObj = node.algos;
obj = processalgorithm(obj,algoObj,node.nodenr,1);
end
if nargin==3
% thread printinfo
obj.nodes{nodenr}.wrapper{cpunr}.wrapperObj.printinfo;
return
elseif nargin==2
if isempty(obj.nodes{nodenr}); fprintf('no node %d defined\n',nodenr); end
return
end
fprintf('*****************************************************\n');
fprintf('* SCD expcode: ''%s'', main code: %d\n',obj.name,obj.maincode);
fprintf('*****************************************************\n');
fprintf('* Configured nodes:\n')
for node = obj.nodes
if isempty(node{:}),continue; end
node{:}.printinfo;
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.initobjlist));
function printtasks(obj)
obj.taskcontainer.printtasks;
end
function printinits(obj)
% TODO: uniform the approach between stdinits and fpinits
% but only if fpinits will stay ...
fprintf('* Configured std init scripts:\n');
if(~isempty(obj.initobjlist))
for ii=1:numel(obj.initobjlist)
[stdinitstmp,~]=obj.initobjlist{ii}.getinits;
if ~isempty(stdinitstmp)
for jj=1:numel(stdinitstmp)
fprintf(' %s\n',char(stdinitstmp{jj}));
end
end
end
end
fprintf('* Configured fp init scripts:\n');
if(~isempty(obj.fpinits))
for ii=1:numel(obj.fpinits)
fprintf(' %s -> %s\n',char(obj.fpinits{ii}{1}),char(obj.fpinits{ii}{2}));
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);
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, busname, frequency, varargin)
% printMARTe2wgbusconfig(obj, shot, busname, frequency, varargin)
%
% prints cfg file for loading busname Simulink.Bus
% as a wavegen (or a set of them) in MARTe2
% shot can be -1 or a fixed shot (usually -1), but currently
% the Shot= entry is populated by a fixed macro
% frequency is the frequency of signal generation in MARTe2
% the optional parameter 'ddname' can be given to specify
% the data dictionary where the bus definition is, if omitted
% the default expcode level data dicationary is used
p=inputParser;
addParameter(p,'ddname',obj.ddname,@(x) ischar(x));
parse(p,varargin{:});
obj.mdscontainer.printMARTe2wgbusconfig(shot, myddname, busname, frequency);
end
function printparameters(obj)
obj.mdscontainer.printparameters;
end
function printwavegens(obj)
obj.mdscontainer.printwavegens;
end
%% Configuration methods
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
function obj = processalgorithm(obj,algoObj,node,cpu)
% Checking and importing algorithm name
if(~ismember(algoObj.getname,obj.algonamelist))
obj.algonamelist{end+1} = algoObj.getname;
obj.algos{end+1} = algoObj;
algoispresent = false;
else
fprintf('algorithm ''%s'' already present in the expcode, importing only wavegens',algoObj.getname);
algoispresent = true;
end
% Importing algorithm MDS objects into the main mdscontainer,
% filling base structure name
algomdscontainer = algoObj.getmdscontainer;
basewgstruct = sprintf('SCDsimdata.SCDnode%02d%02d_simdata.wavegen', node, cpu);
algomdscontainer = algomdscontainer.setwavegenbasestruct(basewgstruct);
obj.mdscontainer = obj.mdscontainer.importmdswavegens(algomdscontainer);
if algoispresent, return; end % return if algo is already present
% Importing exported tunable parameters
obj.mdscontainer=obj.mdscontainer.importmdsparams (algomdscontainer);
algoexptps=algoObj.getexportedtps;
if numel(algoexptps)>0
for ii=1:numel(algoexptps)
if ~ismember(algoexptps{ii},obj.exportedtps)
obj.exportedtps{end+1}=algoexptps{ii};
else
fprintf('exported tunparams sctruct ''%s'' already present, ignoring',algoexptps{ii})
end
end
% Importing algorithms data dictionary, only those with proper name
algodd=algoObj.getdatadictionary;
if(strcmp(algodd(1:7),'SCDalgo'))
if(~ismember(algodd,obj.algoddlist))
obj.algoddlist{end+1}=algodd;
warning('SCDclass_expcode:addalgorithm','algorithm data dictionary ''%s'' already present, ignoring', algodd);
else
error('attempting to add algorithm data dictionary not starting with ''SCDalgo''')
end
% Importing tasks
algotaskcontainer=algoObj.gettaskcontainer;
obj.taskcontainer=obj.taskcontainer.importtaskobjects(algotaskcontainer);
% Importing inits
[stdinitstmp,fpinitstmp]=algoObj.getinits;
if(numel(fpinitstmp)>0)
toadd = ones(numel(fpinitstmp),1);
for ii=1:numel(fpinitstmp)
if(~isempty(obj.fpinits))
for jj=1:numel(obj.fpinits)
for kk=1:numel(obj.fpinits{jj}{2})
if(strcmp(char(obj.fpinits{jj}{2}{kk}),fpinitstmp{ii}{2}))
warning('SCDclass_expcode:addalgorithm','An init driving the structure %s has already been added, ignoring this init',char(fpinitstmp{ii}{2}))
if toadd(ii)
temp=cell(10,1);
temp{1}=fpinitstmp{ii}{1};
temp{2}=fpinitstmp{ii}{2};
if any(toadd) % if any inits from this algoobj were taken
obj.initobjlist{end+1}=algoObj; %% Add the full algorithm object here, to see if it is fine
end
elseif(numel(stdinitstmp)>0)
obj.initobjlist{end+1}=algoObj;
end
end
function out = getexportedtps(obj)
out = obj.exportedtps;
end
function updatedefaulttp(obj)
% updatedefaulttp()
%
% updates _tmpl tunparams structures
% for every defined updating function
% To define an update function see SCDclass_algo.addtunparamstruct
for ii=1:numel(obj.nodes)
mynode = obj.nodes{ii};
if ~isempty(mynode)
mynode.updatetemplatetp();
%% PRIVATE METHODS
methods (Access = private)
%% Matlab environmental setup methods
function CacheFolder = 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);
function CodeGenFolder = 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);
function obj=printlog(obj,str,varargin)
% printlog, allows sprintf()-like expressions
fprintf(str,varargin{:}); fprintf('\n');
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
function add_remove_sources(obj,ddsources_to_add,ddname,prefix)
% add and remove data sources from data dictionary ddname
% ddsources_to_add is cell array with sources
% prefix is an optional filter to only remove those with the correct
% prefix.
ddObj = Simulink.data.dictionary.open(ddname);
prevsources = ddObj.DataSources;
prevsources_prefix = prevsources(startsWith(prefix,prevsources));
for ii=1:numel(prevsources_prefix)
myddsource = prevsources_prefix{ii};
if ~contains(ddsources_to_add,myddsource)
obj.printlog('Removing wrapper data source %s from %s', myddsource, ddname);
ddObj.removeDataSource(myddsource)
end
end
for ii=1:numel(ddsources_to_add)
myddsource = ddsources_to_add{ii};
if contains(prevsources_prefix,myddsource)
obj.printlog('Not Adding wrapper data source %s from %s - already there',...
myddsource, ddname);
else
obj.printlog('Adding wrapper data source %s to %s',...
myddsource, ddname);
ddObj.addDataSource(myddsource);
end
end
end
function obj = buildworkspacetpstruct(obj)
% this funtion builds a workspace structures containing
% 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
dict=Simulink.data.dictionary.open(obj.ddname);
for ii=1:numel(obj.exportedtps)
simstructnamedd=sprintf('%s_tmpl',char(obj.exportedtps(ii)));
simstructnamews=char(obj.exportedtps(ii));
if ~dd.exist(simstructnamedd)
warning('tunable params structure %s not found', simstructnamedd);
continue
assert(numel(Entry)<2,'multiple entries found for %s',simstructnamedd);
simstruct = dd.getEntry(simstructnamedd).getValue;
assignstr = sprintf('%s=temp;',simstructnamews);
assignin('base','temp',simstruct);
evalin('base',assignstr);
end
evalin('base','clear temp;');
end
function setupnodedd(obj)
% For every node, add required wrapper datadicationaries as
% sources for the main data dicationary
% Getting main data dictionary and required data sources
datadictname = obj.ddname;
fprintf('opening %s\n',datadictname)
% Looping through every active node
for idx_nodedds=1:numel(obj.definednodes)
inode = obj.definednodes(idx_nodedds);
mynode = obj.nodes{inode};
% Add all wrapper dictionaries as datasources for main dd
wrapperdd_to_add = cell(numel(mynode.wrappers),1); % init
for iwrap=1:numel(mynode.wrappers)
wrapperdd_to_add{iwrap} = mynode.wrappers{iwrap}.wrapperobj.ddname;
end
ddsources_to_add = wrapperdd_to_add;
% remove ones we don't need
obj.add_remove_sources(ddsources_to_add,datadictname,'SCDwrap')
%%
% Add also node algorithm dd to node dd directly
if ~isempty(mynode.algos)
algodd_to_add = {mynode.algos.getdatadictionary};
else
algodd_to_add = {};
end
obj.add_remove_sources(algodd_to_add,mynode.ddname,'SCDalgo')
function setupwrapperdd(obj)
% Set up the wrapper data dictionary links
for inode = 1:numel(obj.nodes)
mynode = obj.nodes{inode};
if isempty(mynode), continue; end
for ii=1:numel(mynode.wrappers)
wrapperObj = mynode.wrappers{ii}.wrapperobj;
% link to algorithms contained in the wrappers
wrapperObj.linkalgodd;
end
end
function buildworkspacesimstruct(obj)
% obj.mdscontainer.buildworkspacesimstructnode(obj,node)
% obj.mdscontainer.buildworkspacesimstruct; % old
dd=SCDconf_getdatadict(obj.ddname);
for ii = 1:numel(obj.definednodes)
inode = obj.definednodes(ii);
buildworkspacesimstructnode(obj,inode,dd);
end
evalin('base', 'SCDrefdata = SCDsimdata;');
end
function obj = setupmain(obj)
% sets up global configs for the expcode
scd.timing.dt = 25e-6; % hard code for now, determine later from slowest thread
Simulink.data.assigninGlobal(obj.getslxname,'scd',scd);
% add configurations.sldd as reference, contains simulation parameters
ddObj = Simulink.data.dictionary.open(obj.ddname);
ddObj.addDataSource('configurations.sldd');
function addRFMbus(obj,dd)
ddSection = dd.getSection('Design Data');
zeroElem = Simulink.BusElement;
zeroElem.Name = 'zero';
Elems = repmat(Simulink.BusElement,numel(obj.definednodes),1);
for ii = 1:numel(obj.definednodes)
inode = obj.definednodes(ii);
leafName = sprintf('Node%02d_RFM' ,inode);
subBusName = sprintf('Bus: RFMOUT%02dbus',inode);
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
% corresponding leaf element in main RFMIn bus
Elems(ii) = Simulink.BusElement;
Elems(ii).Name = leafName;
Elems(ii).Description = sprintf('Node %02d RFM output',inode);
Elems(ii).DataType = subBusName;
end
ii=ii+1;
% Extra bus and leaf for Externals_RFM (non-node entities writing to RFM)
[extBusObj,extBusName] = SCDconf_createRFMOUTextbus;
assignin(ddSection,extBusName,extBusObj);
Elems(ii) = Simulink.BusElement;
Elems(ii).Name = 'Externals_RFM';
Elems(ii).DataType = ['Bus: ',extBusName];
Elems(ii).Description = 'Bus for data from external nodes writing to RFM';
% Assemble RFM input bus
RFMINbus = Simulink.Bus;
RFMINbus.HeaderFile = '';
RFMINbus.Description = 'RFM input bus for all nodes';
RFMINbus.DataScope = 'Auto';
RFMINbus.Alignment = -1;
RFMINbus.Elements = Elems;
assignin(ddSection,'RFMINbus',RFMINbus);
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
fprintf('opening %s to setup variant model configurations\n',obj.ddname);
d=Simulink.data.dictionary.open(obj.ddname);
dd=getSection(d, 'Design Data');
s=struct();
% Looping through every active node
for ii=1:numel(obj.definednodes)
inode = obj.definednodes(ii);
for jj=1:numel(mynode.wrappers)
fieldname = sprintf('algo%02d%02d',inode,jj);
s.(fieldname) = mynode.wrappers{jj}.varalgo;
% save in data dictionary
if dd.exist('SCDvaralgo')
ee = dd.getEntry('SCDvaralgo'); ee.setValue(s);
else
dd.addEntry('SCDvaralgo',s);
end
function obj = buildworkspacesimstructnode(obj,inode,dd)
% build simulation data structure
if evalin('base','exist(''SCDsimdata'',''var'')')
SCDsimdata = evalin('base','SCDsimdata');
else
SCDsimdata = struct(); % assign here if empty
end
if node.haswavegen
for ithread = 1:node.ncpu
% get whatever is in data dictionary template in wrappers
simstructname = sprintf('SCDnode%02d%02d_simdata',inode,ithread);
wgbusname = sprintf('WG%02d%02dbus',inode,ithread);
fprintf(' setting up %s',simstructname);
if dd.exist(simstructname)
ddentry = dd.getEntry(simstructname);
assert(numel(ddentry)==1,'multiple entries found for %s',simstructname)
simstruct = ddentry.getValue;
mybus=dd.getEntry(wgbusname).getValue; % get from data dictionary
if ~isstruct(simstruct) || ~isfield(simstruct,'wavegen')
fprintf('.. loaded simstruct wavegen is not compatible');
regenerate = true;
elseif SCDconf_structbuscmp(simstruct.wavegen,mybus)
fprintf('... loaded WG from data dictionary\n');
regenerate=false;
else
fprintf('... loaded WG structure from dd does not match bus definition...');
regenerate=true;
end
else
fprintf('... could not find %s in data dictionary',simstructname);
end
if regenerate
simstruct.wavegen = SCDconf_createstructfrombus(dd,wgbusname); % structure to match
%ddsource = dd.find('Name',wgbusname).DataSource; % dd containing bus
%wrapdd=Simulink.data.dictionary.open(ddsource).getSection('Design Data');
%wrapdd.addEntry(simstructname,simstruct)
fprintf('... re-generated from bus %s\n',wgbusname')
end
SCDsimdata.(simstructname) = simstruct;
end
end
% Node-specific
simstructname = sprintf('SCDnode%02dsimdata',inode);
if node.hasadc
adcbusname = sprintf('ADC%02dbus',inode);
fprintf(' setting up %s.adc\n',simstructname);
SCDsimdata.(simstructname).adc = SCDconf_createstructfrombus(dd,adcbusname);
end
if node.hasethercat
assert(inode==2,'Ethercat not yet implemented for other node than 2');
ethercatbusname = 'ETHCAT1IN';
fprintf(' setting up %s.ethercat\n',simstructname);
SCDsimdata.(simstructname).ethercat = ...
SCDconf_createstructfrombus(dd,ethercatbusname);
end
% add also RFM
RFMbusname = 'RFMINbus';
SCDsimdata.rfm = SCDconf_createstructfrombus(dd,RFMbusname);
% assign result in base workspace
assignin('base','SCDsimdata',SCDsimdata);
end
%% Actualization methods
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 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
%% MDS update methods
function updatemds(obj, algo, shot)
if shot~=-1
error('SCDclass_expcode:updatemds','update permitted only on the model shot');
end
% % first update algorithm tunparams default locally
% for ii=1:numel(obj.algonamelist)
% if strcmp(algo, obj.algonamelist{ii})
% obj.algos{ii}.updatetemplatetp();
% end
% end
% % then update mds
obj.mdscontainer.modeltogenerate=algo;
obj.mdscontainer.autopopulateMDSparams(shot);
obj.mdscontainer.autopopulateMDSwavegens(shot);
end