Is there any plugin that allows automatic tracking of history of all workspace variables?

1 view (last 30 days)
Denis Chouvaev
Denis Chouvaev on 17 May 2022
Commented: Daniel on 19 May 2022
In RTL simulators (like Questasim, Modelsim, any) and in elecronic circuit simulators (like Cadence virtuoso) it is very easy to setup saving all transitions of all nodes / register values during simulation and them plot them as waveforms.
Has anybody tried to implement something similar for the Matlab workspace?
That is, a plugin that records all transitions of all workspace variables, and stores them as time series (where "time" is just a number in sequence), as a debug tool? Sure it is fairly easy to trace one variable in the code itself, but if you need many, all? Like when you need to inspect bit occupancy of all integers in a complicated loop...
  4 Comments
Denis Chouvaev
Denis Chouvaev on 18 May 2022
This last option makes a lot of sense. Could you quote a simple example of a class that monitors a variable?

Sign in to comment.

Accepted Answer

Rik
Rik on 19 May 2022
Below is my initial implementation of what you need. There are a lot of adaptations still to be made. It implements both a vector history storage and a simple scalar storage method.
classdef CappedNumber
%Store a scalar and emit a warning when setting the value to something larger than a threshold.
% Detailed explanation goes here
%
% The implementation below assumes you want obj1=sqrt(obj1);. If you don't want that, you can
% do this instead: obj2=CappedNumber(sqrt(obj1)); (which will refresh the flag and history).
%
% Syntax examples:
%
% % Create variables like this:
% a=CappedNumber(1,10,5)
% % For all functions you use, make sure to create a method that will handle the conversion
% a=a+1
% % You can extract the entire history of the variable like this:
% a.value
%
% % Some things even works for arrays out of the box:
% b=[a+2 a+3;a+4 a+11]
% b(1).flag,b(4).flag
properties
value
threshold
flag=false;
end
properties (Hidden = true)
index=1;
StoreAsVector=false;
init=true;
end
methods
function obj = CappedNumber(v,t,BufferSize)
% Constructor.
if isa(v,'CappedNumber')
oldObject=v;
v=getValue(oldObject);
t=oldObject.threshold;
if obj.StoreAsVector
BufferSize=numel(oldObject.value);
obj = CappedNumber(v,t,BufferSize);
else
obj = CappedNumber(v,t);
end
return
end
if nargin==3
% Store the value in a vector.
obj.value=NaN(1,BufferSize);
obj.index=0;
obj.threshold=t;
obj.StoreAsVector=true;
obj.value=v;
else
obj.threshold=t;
obj.StoreAsVector=false;
obj.value=v;
end
end
function v=getValue(obj)
% NB: this doesn't actually overload the get method.
if numel(obj)>1
error('this function wasn''t implemented for array inputs')
end
v=obj.value(obj.index);
end
function obj = set.value(obj,new_val)
% Overload the set method to emit a warning when the threshold is crossed and store the
% the value in a vector if that is enabled.
if obj.init %#ok<MCSUP>
obj.value=new_val;
obj.init=false; %#ok<MCSUP>
return
end
if obj.StoreAsVector,obj.index=obj.index+1;end %#ok<MCSUP>
if new_val>obj.threshold %#ok<MCSUP>
obj.value(obj.index)=obj.threshold; %#ok<MCSUP>
obj.flag=true; %#ok<MCSUP>
warning('CappedNumber:InvalidValue','threshold crossed')
else
obj.value(obj.index)=new_val; %#ok<MCSUP>
end
end
function disp(obj)
v=zeros(size(obj));
for n=1:numel(v),v(n)=obj(n).value(obj(n).index);end
disp(v)
end
% Implement all function interactions you want to use (there is probably a better way than
% this to get this behavior).
% For common operators, see this doc page:
%https://www.mathworks.com/help/matlab/matlab_oop/implementing-operators-for-your-class.html#br02znk-6
function obj=plus(op1,op2)
% Copy the threshold and the flag properties from the first operand.
if isa(op2,'CappedNumber'),obj=op2;op2=getValue(op2);end
if isa(op1,'CappedNumber'),obj=op1;op1=getValue(op1);end
obj.value=plus(op1,op2);
end
function obj=sqrt(obj)
% This syntax assumes obj1=sqrt(obj1);
% If you don't want that, you can also do
% obj2=CappedNumber(sqrt(obj1));
obj.value=sqrt(getValue(obj));
end
function varargout=min(varargin)
% Copy the threshold and the flag properties from the first operand.
varargout=cell(1,nargout);
error(['the min function has complex behavior and also handles arrays\n'...
'You will need to implement the array behavior.'])
end
end
end
  3 Comments
Daniel
Daniel on 19 May 2022
Rik, I like your solution a lot! Clean and simple. I just wanted to make a few extra comments.
  • Scopes: To log and visualize data as you go, have a look at all the scopes that MATLAB has. There are timescope, spectrumAnalyzer, dsp.LogicAnalyzer to name a few. Denis, for the usecase you are mentioning, dsp.LogicAnalyzer comes closest. Just define scope = dsp.LogicAnalyzer; and then put data through the scope by calling scope(data). This requires DSP System Toolbox.
  • Automatic instrumentation: buildInstrumentedMex will build in instrumentation into a function, that keeps track of all variables. This requires Fixed-Point Designer.
  • Fixed-point datatypes: If you use fi() datatypes, then you can turn on logging via P = fipref; P.LoggingMode = 'On'. Now, if you define a = fi(7,0,4,1); and calculate a(:)=a+1, then you get an immediate warning: 'Warning: 1 overflow(s) occurred in the fi assignment operation'. It also keeps track of the number of overflows/underflows that have occured. This requires Fixed-Point Designer.

Sign in to comment.

More Answers (0)

Products


Release

R2020b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!