diff --git a/+adi/+AD4030/Rx.m b/+adi/+AD4030/Rx.m new file mode 100644 index 0000000..86d8ae2 --- /dev/null +++ b/+adi/+AD4030/Rx.m @@ -0,0 +1,47 @@ +classdef Rx < adi.common.Rx ... + & adi.AD463x.Base + + % AD4030-24 Precision ADC Class + % adi.AD4030.Rx Receives data from the AD4030-24 ADC + % The adi.AD4030.Rx System object is a signal source that can receive + % data from the AD4030-24. + % + % rx = adi.AD4030.Rx; + % rx = adi.AD4030.Rx('uri','192.168.2.1'); + % + % AD4030-24 Datasheet + + properties (Nontunable, Hidden, Constant) + Type = 'Rx' + end + + properties (Hidden) + % Number of frames or buffers of data to capture + FrameCount = 1 + end + + properties (Nontunable, Hidden) + + % Channels present with default register settings - + channel_names = {'differential0', 'differential1'} + end + + properties (Hidden) + Timeout = Inf + kernelBuffersCount = 4 + dataTypeStr = 'int32' + phyDevName = 'ad4030-24' + devName = 'ad4030-24' + end + + methods + + %% Constructor + function obj = Rx(varargin) + coder.allowpcode('plain'); + obj = obj@adi.AD463x.Base(varargin{:}); + + end + + end +end diff --git a/+adi/+AD4630_16/Rx.m b/+adi/+AD4630_16/Rx.m new file mode 100644 index 0000000..f555eb6 --- /dev/null +++ b/+adi/+AD4630_16/Rx.m @@ -0,0 +1,47 @@ +classdef Rx < adi.common.Rx & adi.common.RxTx ... + & adi.AD463x.Base + + % AD4630-16 Precision ADC Class + % adi.AD4630_16.Rx Receive data from the AD4630-16 ADC + % The adi.AD4630_16.Rx System object is a signal source that can receive + % data from the AD4630-16. + % + % rx = adi.AD4630_16.Rx; + % rx = adi.AD4630_16.Rx('uri','192.168.2.1'); + % + % AD4630-16 Datasheet + + properties (Nontunable, Hidden, Constant) + Type = 'Rx' + end + + properties (Hidden) + % Number of frames or buffers of data to capture + FrameCount = 1 + end + + properties (Nontunable, Hidden) + + % Channels present with default register settings - + channel_names = {'differential0', 'differential1'} + end + + properties (Hidden) + Timeout = Inf + kernelBuffersCount = 4 + dataTypeStr = 'int32' + phyDevName = 'ad4630-16' + devName = 'ad4630-16' + end + + methods + %% Constructor + + function obj = Rx(varargin) + coder.allowpcode('plain'); + obj = obj@adi.AD463x.Base(varargin{:}); + + end + + end +end diff --git a/+adi/+AD4630_24/Rx.m b/+adi/+AD4630_24/Rx.m new file mode 100644 index 0000000..f63d9a5 --- /dev/null +++ b/+adi/+AD4630_24/Rx.m @@ -0,0 +1,46 @@ +classdef Rx < adi.common.Rx ... + & adi.AD463x.Base + + % AD4630-24 Precision ADC Class + % adi.AD4630_24.Rx Receive data from the AD4630-24 ADC + % The adi.AD4630_24.Rx System object is a signal source that can receive + % data from the AD4630-24. + % + % rx = adi.AD4630_24.Rx; + % rx = adi.AD4630_24.Rx('uri','192.168.2.1'); + % + % AD4630-24 Datasheet + + properties (Nontunable, Hidden, Constant) + Type = 'Rx' + end + + properties (Hidden) + % Number of frames or buffers of data to capture + FrameCount = 1 + end + + properties (Nontunable, Hidden) + % Channels present with default register settings - + channel_names = {'differential0', 'differential1'} + end + + properties (Hidden) + Timeout = Inf + kernelBuffersCount = 4 + dataTypeStr = 'int32' + phyDevName = 'ad4630-24' + devName = 'ad4630-24' + end + + methods + + %% Constructor + function obj = Rx(varargin) + coder.allowpcode('plain'); + obj = obj@adi.AD463x.Base(varargin{:}); + + end + + end +end diff --git a/+adi/+AD463x/Base.m b/+adi/+AD463x/Base.m new file mode 100644 index 0000000..2686242 --- /dev/null +++ b/+adi/+AD463x/Base.m @@ -0,0 +1,241 @@ +classdef Base < adi.common.Rx & adi.common.RxTx & ... + matlabshared.libiio.base & adi.common.Attribute & ... + adi.common.RegisterReadWrite & adi.common.Channel + % AD463x is a family of Precision ADC + % AD4630-16 is dual channel 16bit SAR ADC with max sampling frequency + % of 2MSPS + % AD4630-24 is dual channel 24bit SAR ADC with max sampling frequency 2MSPS + % AD4030-24 is single channel version of AD4630-24 + + properties (Nontunable) + % SampleRate Sample Rate + % Baseband sampling rate in Hz, specified as a scalar + % in samples per second. + SampleRate = '1000000' + % SamplesPerFrame Samples Per Frame + % Number of samples per frame, specified as an even positive + % integer. + SamplesPerFrame = 2^15 + + % SampleAveragingLength + % Block length of samples to be averaged. Applied in the + % Averaging Mode register only when OUT_DATA_MD is set + % to 30-bit averaged differential mode + SampleAveragingLength = '2' + end + + properties (Abstract, Nontunable, Hidden) + channel_names + end + + properties (Hidden, Nontunable, Access = protected) + isOutput = false + end + + properties (Abstract, Nontunable, Hidden) + Timeout + kernelBuffersCount + dataTypeStr + phyDevName + devName + end + + properties (Hidden, Constant, Abstract) + Type + end + + properties (Hidden, Constant) + ComplexData = false + SampleAveragingLengthSet = matlab.system.StringSet({ ... + '2', '4', '8', '16', '32', '64', '128', '256', ... + '512', '1024', '2048', '4096', '8192', '16384', ... + '32768', '65536'}) + end + + methods + + %% Constructor + function obj = Base(varargin) + obj = obj@matlabshared.libiio.base(varargin{:}); + obj.enableExplicitPolling = false; + obj.EnabledChannels = 1; + obj.BufferTypeConversionEnable = true; + + % Check if uri has been specified, else throw an error + uriFound = 0; + for i = 1:length(varargin) + if isequal(varargin{i}, 'uri') + if i == length(varargin) + break + else + uriArgIndex = find(contains([varargin{:}], 'uri')); + obj.uri = varargin{uriArgIndex + 1}; + uriFound = 1; + end + end + end + if uriFound == 0 + error("Error. \nUri was not supplied. Supply it in the" + ... + " following manner \n %s", ... + "adi.ADXXXX.Rx('uri', )"); + end + + % Connects to device temporarily and fetches the channel names + obj.setup(); + release(obj); + end + + function set.SamplesPerFrame(obj, value) + validateattributes(value, { 'double', 'single', 'uint32' }, ... + { 'real', 'positive', 'scalar', 'finite', ... + 'nonnan', 'nonempty', 'integer', '>', 0, ... + '<', 2^20 + 1}, ... + '', 'SamplesPerFrame'); + obj.SamplesPerFrame = value; + end + + function set.SampleAveragingLength(obj, value) + validateattributes(value, { 'char', 'string'}, ... + {}, ... + '', 'SampleAveragingLength'); + obj.SampleAveragingLength = value; + + end + + function flush(obj) + flushBuffers(obj); + end + + function delete(obj) + delete@adi.common.RxTx(obj); + end + + % Check SamplingRate + function set.SampleRate(obj, value) + obj.SampleRate = value; + if obj.ConnectedToDevice + obj.setDeviceAttributeRAW('sampling_frequency', value); + end + end + + end + + %% API Functions + methods (Hidden, Access = protected) + + function setupInit(obj) + % Write all attributes to device once connected through set + % methods + % Do writes directly to hardware without using set methods. + % This is required sine Simulink support doesn't support + % modification to nontunable variables at SetupImpl + obj.setDeviceAttributeRAW('sampling_frequency', ... + num2str(obj.SampleRate)); + if obj.getRegister('0x20') == 67 % Check if the + % current out-data-mode is 30bit averaging + obj.setDeviceAttributeRAW('sample_averaging', ... + obj.SampleAveragingLength); + end + + obj.set_channel_names(); + + end + + function set_channel_names(obj) + obj.channel_names = {}; + phydev = getDev(obj, obj.devName); + chanCount = obj.iio_device_get_channels_count(phydev); + for c = 1:chanCount + chanPtr = obj.iio_device_get_channel(phydev, c - 1); + obj.channel_names{end + 1} = obj.iio_channel_get_name(chanPtr); + end + end + + function [data, valid] = stepImpl(obj) + % [data,valid] = rx() returns data received from the radio + % hardware associated with the receiver System object, rx. + % The output 'valid' indicates whether the object has received + % data from the radio hardware. The first valid data frame can + % contain transient values, resulting in packets containing + % undefined data. + % + % The output 'data' will be an [NxM] vector where N is + % 'SamplesPerFrame' and M is the number of elements in + % 'EnabledChannels'. 'data' will be complex if the devices + % assumes complex data operations. + + capCount = obj.FrameCount; + + if obj.ComplexData + kd = 1; + ce = length(obj.EnabledChannels); + [dataRAW, valid] = getData(obj); + data = complex(zeros(obj.SamplesPerFrame, ce)); + for k = 1:ce + data(:, k) = complex(dataRAW(kd, :), dataRAW(kd + 1, :)).'; + kd = kd + 2; + end + else + if obj.BufferTypeConversionEnable + + dataRAW = zeros([length(obj.EnabledChannels) ... + obj.SamplesPerFrame * capCount]); + for count = 1:capCount + [data_i, valid] = getData(obj); + dataRAW(:, obj.SamplesPerFrame * (count - 1) + ... + 1:count * obj.SamplesPerFrame) = data_i; + end + disp("Finished grabbing data. Processing it now..."); + % Channels must be in columns or pointer math fails + dataRAW = dataRAW.'; + [D1, D2] = size(dataRAW); + data = coder.nullcopy(zeros(D1, D2, obj.dataTypeStr)); + dataPtr = libpointer(obj.ptrTypeStr, data); + dataRAWPtr = libpointer(obj.ptrTypeStr, dataRAW); + % Convert hardware format to human format channel by + % channel + for l = 0:D2 - 1 + chanPtr = getChan(obj, obj.iioDev, ... + obj.channel_names{obj.EnabledChannels(l + 1)}, false); + % Pull out column + tmpPtrSrc = dataRAWPtr + D1 * l; + tmpPtrDst = dataPtr + D1 * l; + setdatatype(tmpPtrSrc, obj.ptrTypeStr, D1, 1); + setdatatype(tmpPtrDst, obj.ptrTypeStr, D1, 1); + for k = 0:D1 - 1 + iio_channel_convert(obj, chanPtr, tmpPtrDst + k, tmpPtrSrc + k); + end + end + data = dataPtr.Value; + else + dataRAW = zeros([length(obj.EnabledChannels) obj.SamplesPerFrame * capCount]); + for count = 1:capCount + [data_i, valid] = getData(obj); + dataRAW(:, obj.SamplesPerFrame * (count - 1) + ... + 1:count * obj.SamplesPerFrame) = data_i; + end + data = dataRAW.'; + end + end + end + + end + + %% External Dependency Methods + methods (Hidden, Static) + + function tf = isSupportedContext(bldCfg) + tf = matlabshared.libiio.ExternalDependency.isSupportedContext(bldCfg); + end + + function updateBuildInfo(buildInfo, bldCfg) + % Call the matlabshared.libiio.method first + matlabshared.libiio.ExternalDependency.updateBuildInfo(buildInfo, bldCfg); + end + + function bName = getDescriptiveName(~) + bName = 'AD463x Precision ADC'; + end + + end +end diff --git a/+adi/+AD7380/Rx.m b/+adi/+AD7380/Rx.m new file mode 100644 index 0000000..e880f12 --- /dev/null +++ b/+adi/+AD7380/Rx.m @@ -0,0 +1,169 @@ +classdef Rx < adi.common.Rx & matlabshared.libiio.base & adi.common.Attribute + % AD7380 Precision ADC Class + % adi.AD7380.Rx Receives data from the AD7380 ADC + % The adi.AD7380.Rx System object is a signal source that can receive + % data from the AD7380. + % + % rx = adi.AD7380.Rx; + % rx = adi.AD7380.Rx('uri','192.168.2.1'); + % + % AD7380 Datasheet + + properties (Nontunable) + % SampleRate Sample Rate + % Baseband sampling rate in Hz, specified as a scalar + % in samples per second. Options are: + % '256000','128000','64000','32000','16000','8000','4000', + % '2000','1000' + SampleRate = '4000000' + SamplesPerFrame = 1024 + end + + properties (Hidden) + % Number of frames or buffers of data to capture + FrameCount = 1 + end + + % Channel names + properties (Nontunable, Hidden, Constant) + channel_names = { + 'voltage0' + 'voltage1' + } + Type = 'Rx' + end + + % isOutput + properties (Hidden, Nontunable, Access = protected) + isOutput = false + end + + properties (Constant, Hidden) + SampleRateSet = matlab.system.StringSet({'4000000', '256000', '128000', '64000', ... + '32000', '16000', '8000', '4000', '2000', '1000'}) + + end + + properties (Nontunable, Hidden) + Timeout = Inf + kernelBuffersCount = 2 + % dataTypeStr = 'int64'; + dataTypeStr = 'int16' + phyDevName = 'ad7380' + devName = 'ad7380' + end + + properties (Hidden, Constant) + ComplexData = false + end + + methods + + %% Constructor + function obj = Rx(varargin) + obj = obj@matlabshared.libiio.base(varargin{:}); + obj.enableExplicitPolling = false; + obj.EnabledChannels = 1; + obj.BufferTypeConversionEnable = true; + obj.uri = 'ip:analog.local'; + end + + function flush(obj) + flushBuffers(obj); + end + + % Check SamplingRate + function set.SampleRate(obj, value) + obj.SampleRate = value; + if obj.ConnectedToDevice + obj.setDeviceAttributeRAW('sampling_frequency', value); + end + end + + end + + %% API Functions + methods (Hidden, Access = protected) + + function setupInit(obj) + % Write all attributes to device once connected through set + % methods + % Do writes directly to hardware without using set methods. + % This is required since Simulink support doesn't support + % modification to nontunable variables at SetupImpl + + % obj.setDeviceAttributeRAW('sampling_frequency',num2str(obj.SampleRate)); + + end + + function [data, valid] = stepImpl(obj) + % [data,valid] = rx() returns data received from the radio + % hardware associated with the receiver System object, rx. + % The output 'valid' indicates whether the object has received + % data from the radio hardware. The first valid data frame can + % contain transient values, resulting in packets containing + % undefined data. + % + % The output 'data' will be an [NxM] vector where N is + % 'SamplesPerFrame' and M is the number of elements in + % 'EnabledChannels'. 'data' will be complex if the devices + % assumes complex data operations. + + capCount = obj.FrameCount; + + if obj.ComplexData + kd = 1; + ce = length(obj.EnabledChannels); + [dataRAW, valid] = getData(obj); + data = complex(zeros(obj.SamplesPerFrame, ce)); + for k = 1:ce + data(:, k) = complex(dataRAW(kd, :), dataRAW(kd + 1, :)).'; + kd = kd + 2; + end + else + if obj.BufferTypeConversionEnable + + dataRAW = zeros([length(obj.EnabledChannels) obj.SamplesPerFrame * capCount]); + for count = 1:capCount + [data_i, valid] = getData(obj); + dataRAW(:, obj.SamplesPerFrame * (count - 1) + ... + 1:count * obj.SamplesPerFrame) = data_i; + end + disp("Finished grabbing data. Processing it now..."); + % Channels must be in columns or pointer math fails + dataRAW = dataRAW.'; + [D1, D2] = size(dataRAW); + data = coder.nullcopy(zeros(D1, D2, obj.dataTypeStr)); + dataPtr = libpointer(obj.ptrTypeStr, data); + dataRAWPtr = libpointer(obj.ptrTypeStr, dataRAW); + % Convert hardware format to human format channel by + % channel + for l = 0:D2 - 1 + chanPtr = getChan(obj, obj.iioDev, ... + obj.channel_names{obj.EnabledChannels(l + 1)}, false); + % Pull out column + tmpPtrSrc = dataRAWPtr + D1 * l; + tmpPtrDst = dataPtr + D1 * l; + setdatatype(tmpPtrSrc, obj.ptrTypeStr, D1, 1); + setdatatype(tmpPtrDst, obj.ptrTypeStr, D1, 1); + for k = 0:D1 - 1 + iio_channel_convert(obj, chanPtr, tmpPtrDst + k, tmpPtrSrc + k); + end + end + data = dataPtr.Value; + else + dataRAW = zeros([length(obj.EnabledChannels) ... + obj.SamplesPerFrame * capCount]); + for count = 1:capCount + [data_i, valid] = getData(obj); + dataRAW(:, obj.SamplesPerFrame * (count - 1) + ... + 1 : count * obj.SamplesPerFrame) = data_i; + end + + data = dataRAW.'; + end + end + end + + end +end diff --git a/+adi/+AD7768/Base.m b/+adi/+AD7768/Base.m new file mode 100644 index 0000000..feb6e00 --- /dev/null +++ b/+adi/+AD7768/Base.m @@ -0,0 +1,162 @@ +classdef (Abstract, Hidden = true) Base < ... + adi.common.RxTx & ... + adi.common.Attribute & ... + adi.common.DebugAttribute & ... + matlabshared.libiio.base & ... + adi.common.Rx + + properties (Nontunable) + % SamplesPerFrame Samples Per Frame + % Number of samples per frame, specified as an even positive + % integer from 2 to 16,777,216. Using values less than 3660 can + % yield poor performance. + SamplesPerFrame = 2^15 + end + + properties (Abstract) + % SamplingRate Sampling Rate + % Baseband sampling rate in Hz, specified as a scalar + % from 65105 to 61.44e6 samples per second. + SampleRate + + end + + properties (Abstract, Nontunable, Hidden) + Timeout + kernelBuffersCount + dataTypeStr + phyDevName + devName + end + + properties (Hidden, Constant) + ComplexData = false + end + + methods + + %% Constructor + function obj = Base(varargin) + coder.allowpcode('plain'); + obj = obj@matlabshared.libiio.base(varargin{:}); + end + + % Destructor + function delete(obj) + delete@adi.common.RxTx(obj); + end + + % Check SamplesPerFrame + function set.SamplesPerFrame(obj, value) + validateattributes(value, { 'double', 'single', 'uint32'}, ... + { 'real', 'positive', 'scalar', 'finite', ... + 'nonnan', 'nonempty', 'integer', '>', 0, '<=', 2^20}, ... + '', 'SamplesPerFrame'); + obj.SamplesPerFrame = value; + end + + end + + %% API Functions + methods (Hidden, Access = protected) + + function icon = getIconImpl(obj) + icon = sprintf(['AD7768 ', obj.Type]); + end + + function [data, valid] = stepImpl(obj) + % [data,valid] = rx() returns data received from the radio + % hardware associated with the receiver System object, rx. + % The output 'valid' indicates whether the object has received + % data from the radio hardware. The first valid data frame can + % contain transient values, resulting in packets containing + % undefined data. + % + % The output 'data' will be an [NxM] vector where N is + % 'SamplesPerFrame' and M is the number of elements in + % 'EnabledChannels'. 'data' will be complex if the devices + % assumes complex data operations. + + % Get the data + + capCount = obj.FrameCount; + + if obj.ComplexData + kd = 1; + ce = length(obj.EnabledChannels); + [dataRAW, valid] = getData(obj); + data = complex(zeros(obj.SamplesPerFrame, ce)); + for k = 1:ce + data(:, k) = complex(dataRAW(kd, :), dataRAW(kd + 1, :)).'; + kd = kd + 2; + end + else + if obj.BufferTypeConversionEnable + + dataRAW = zeros([length(obj.EnabledChannels) ... + obj.SamplesPerFrame * capCount]); + for count = 1:capCount + [data_i, valid] = getData(obj); + % dataRAW = cat(2, dataRAW, data_i); + + dataRAW(:, obj.SamplesPerFrame * (count - 1) + ... + 1:count * obj.SamplesPerFrame) = data_i; + end + disp("Finished grabbing data. Processing it now..."); + % Channels must be in columns or pointer math fails + dataRAW = dataRAW.'; + [D1, D2] = size(dataRAW); + data = coder.nullcopy(zeros(D1, D2, obj.dataTypeStr)); + dataPtr = libpointer(obj.ptrTypeStr, data); + dataRAWPtr = libpointer(obj.ptrTypeStr, dataRAW); + % Convert hardware format to human format channel by + % channel + for l = 0:D2 - 1 + chanPtr = getChan(obj, obj.iioDev, ... + obj.channel_names{obj.EnabledChannels(l + 1)}, false); + % Pull out column + tmpPtrSrc = dataRAWPtr + D1 * l; + tmpPtrDst = dataPtr + D1 * l; + setdatatype(tmpPtrSrc, obj.ptrTypeStr, D1, 1); + setdatatype(tmpPtrDst, obj.ptrTypeStr, D1, 1); + for k = 0:D1 - 1 + iio_channel_convert(obj, chanPtr, tmpPtrDst + k, tmpPtrSrc + k); + end + end + data = dataPtr.Value; + else + dataRAW = zeros([length(obj.EnabledChannels) ... + obj.SamplesPerFrame * capCount]); + for count = 1:capCount + [data_i, valid] = getData(obj); + % dataRAW = cat(2, dataRAW, data_i); + + dataRAW(:, obj.SamplesPerFrame * (count - 1) + ... + 1:count * obj.SamplesPerFrame) = data_i; + end + + data = dataRAW.'; + end + end + end + + end + + %% External Dependency Methods + methods (Hidden, Static) + + function tf = isSupportedContext(bldCfg) + tf = matlabshared.libiio.ExternalDependency.isSupportedContext(bldCfg); + end + + function updateBuildInfo(buildInfo, bldCfg) + % Call the matlabshared.libiio.method first + matlabshared.libiio.ExternalDependency.updateBuildInfo(buildInfo, bldCfg); + end + + function bName = getDescriptiveName(~) + bName = 'AD7768'; + end + + end +end diff --git a/+adi/+AD7768/Rx.m b/+adi/+AD7768/Rx.m new file mode 100644 index 0000000..0869a22 --- /dev/null +++ b/+adi/+AD7768/Rx.m @@ -0,0 +1,124 @@ +classdef Rx < adi.AD7768.Base & matlabshared.libiio.base & adi.common.Attribute + % AD7768 Precision ADC Class + % adi.AD7768.Rx Receives data from the AD7768 ADC + % The adi.AD7768.Rx System object is a signal source that can receive + % data from the AD7768. + % + % rx = adi.AD7768.Rx; + % rx = adi.AD7768.Rx('uri','192.168.2.1'); + % + % AD7768 Datasheet + + properties (Nontunable) + % SampleRate Sample Rate + % Baseband sampling rate in Hz, specified as a scalar + % in samples per second. Options are: + % '256000','128000','64000','32000','16000','8000','4000', + % '2000','1000' + SampleRate = '256000' + + end + + properties (Hidden) + % Number of frames or buffers of data to capture + FrameCount = 1 + end + + properties (Nontunable, Hidden, Constant) + channel_names = { ... + 'voltage0', 'voltage1', 'voltage2', 'voltage3', ... + 'voltage4', 'voltage5', 'voltage6', 'voltage7'} + end + + properties (Hidden, Nontunable, Access = protected) + isOutput = false + end + + properties (Constant, Hidden) + SampleRateSet = matlab.system.StringSet({ ... + '256000', '128000', '64000', ... + '32000', '16000', '8000', '4000', ... + '2000', '1000'}) + + end + + properties (Nontunable, Hidden) + Timeout = Inf + kernelBuffersCount = 2 + dataTypeStr = 'int32' + phyDevName = 'ad7768' + devName = 'ad7768' + end + + properties (Nontunable, Hidden, Constant) + Type = 'Rx' + + end + + methods + + %% Constructor + function obj = Rx(varargin) + obj = obj@matlabshared.libiio.base(varargin{:}); + obj.enableExplicitPolling = false; + obj.EnabledChannels = 1; + obj.BufferTypeConversionEnable = true; + obj.uri = 'ip:analog.local'; + end + + function flush(obj) + flushBuffers(obj); + end + + % Check SamplingRate + function set.SampleRate(obj, value) + obj.SampleRate = value; + if obj.ConnectedToDevice + obj.setDeviceAttributeRAW('sampling_frequency', value); + end + end + + end + + methods (Access = protected) + + function numOut = getNumOutputsImpl(~) + numOut = 1; + end + + end + + %% API Functions + methods (Hidden, Access = protected) + + function setupInit(obj) + % Write all attributes to device once connected through set + % methods + % Do writes directly to hardware without using set methods. + % This is required since Simulink doesn't support + % modification to nontunable variables at SetupImpl + + obj.setDeviceAttributeRAW('sampling_frequency', num2str(obj.SampleRate)); + + end + + end + + %% External Dependency Methods + methods (Hidden, Static) + + function tf = isSupportedContext(bldCfg) + tf = matlabshared.libiio.ExternalDependency.isSupportedContext(bldCfg); + end + + function updateBuildInfo(buildInfo, bldCfg) + % Call the matlabshared.libiio.method first + matlabshared.libiio.ExternalDependency.updateBuildInfo(buildInfo, bldCfg); + end + + function bName = getDescriptiveName(~) + bName = 'AD7768 Precision ADC'; + end + + end +end diff --git a/+adi/+AD7768_1/Rx.m b/+adi/+AD7768_1/Rx.m new file mode 100644 index 0000000..8004a40 --- /dev/null +++ b/+adi/+AD7768_1/Rx.m @@ -0,0 +1,146 @@ +classdef Rx < adi.AD7768.Base & matlabshared.libiio.base & adi.common.Attribute + % AD7768-1 Precision ADC Class + % adi.AD7768_1.Rx Receives data from the AD7768-1 ADC + % The adi.AD7768_1.Rx System object is a signal source that can receive + % data from the AD7768-1. + % + % rx = adi.AD7768_1.Rx; + % rx = adi.AD7768_1.Rx('uri','192.168.2.1'); + % + % AD7768-1 Datasheet + + properties (Nontunable) + % SampleRate Sample Rate + % Baseband sampling rate in Hz, specified as a scalar + % in samples per second. Options are: + % '256000','128000','64000','32000','16000','8000','4000', + % '2000','1000' + SampleRate = '256000' + + % SCommonModeVolts Common Mode Voltage + % Common mode voltage in volts, specified as a string + % Options are: + % '(AVDD1-AVSS)/2','2V5','2V05','1V9','1V65','1V1','0V9','OFF' + CommonModeVolts = '(AVDD1-AVSS)/2' + + end + + properties (Hidden) + % Number of frames or buffers of data to capture + FrameCount = 1 + end + + properties (Nontunable, Hidden, Constant) + channel_names = { ... + 'voltage0'} + end + + properties (Hidden, Nontunable, Access = protected) + isOutput = false + end + + properties (Constant, Hidden) + SampleRateSet = matlab.system.StringSet({ ... + '256000', '128000', '64000', ... + '32000', '16000', '8000', '4000', ... + '2000', '1000'}) + + CommonModeVoltsSet = matlab.system.StringSet({ '(AVDD1-AVSS)/2', '2V5', ... + '2V05', '1V9', '1V65', '1V1', '0V9', 'OFF'}) + + end + + properties (Nontunable, Hidden) + Timeout = Inf + kernelBuffersCount = 2 + dataTypeStr = 'int32' + phyDevName = 'ad7768-1' + devName = 'ad7768-1' + end + + properties (Nontunable, Hidden, Constant) + Type = 'Rx' + + end + + methods + + %% Constructor + function obj = Rx(varargin) + obj = obj@matlabshared.libiio.base(varargin{:}); + obj.enableExplicitPolling = false; + obj.EnabledChannels = 1; + obj.BufferTypeConversionEnable = true; + obj.uri = 'ip:analog.local'; + end + + function flush(obj) + flushBuffers(obj); + end + + % Check SamplingRate + function set.SampleRate(obj, value) + obj.SampleRate = value; + if obj.ConnectedToDevice + obj.setDeviceAttributeRAW('sampling_frequency', value); + end + end + + % Check SamplesPerFrame + function set.CommonModeVolts(obj, value) + validateattributes(value, { 'char', 'string'}, ... + { 'nonempty'}, ... + '', 'CommonModeVolts'); + obj.CommonModeVolts = value; + end + + end + + methods (Access = protected) + + function numOut = getNumOutputsImpl(~) + % numOut = 1; + numOut = 2; + end + + end + + %% Sensor specific APIs + methods + end + + %% API Functions + methods (Hidden, Access = protected) + + function setupInit(obj) + % Write all attributes to device once connected through set + % methods + % Do writes directly to hardware without using set methods. + % This is required since Simulink doesn't support + % modification to nontunable variables at SetupImpl + + obj.setDeviceAttributeRAW('sampling_frequency', num2str(obj.SampleRate)); + obj.setDeviceAttributeRAW('common_mode_voltage', obj.CommonModeVolts); + + end + + end + + %% External Dependency Methods + methods (Hidden, Static) + + function tf = isSupportedContext(bldCfg) + tf = matlabshared.libiio.ExternalDependency.isSupportedContext(bldCfg); + end + + function updateBuildInfo(buildInfo, bldCfg) + % Call the matlabshared.libiio.method first + matlabshared.libiio.ExternalDependency.updateBuildInfo(buildInfo, bldCfg); + end + + function bName = getDescriptiveName(~) + bName = 'AD7768-1 Precision ADC'; + end + + end +end diff --git a/+adi/+common b/+adi/+common new file mode 160000 index 0000000..2463dfa --- /dev/null +++ b/+adi/+common @@ -0,0 +1 @@ +Subproject commit 2463dfa888d255f38054d22dcc31b535ea62cee6 diff --git a/+adi/Contents.m b/+adi/Contents.m new file mode 100644 index 0000000..5823d37 --- /dev/null +++ b/+adi/Contents.m @@ -0,0 +1,13 @@ +% Analog Devices, Inc. Precision Toolbox +% Version 21.2.1 (R2021b) +% +% ==== Table of Contents (TOC) ==== +% +% Parts +% ----------------------- +% AD7380 - ADC +% AD7768 - ADC +% AD7768-1 - ADC +% AD4030-24 - ADC +% AD4630-16 - ADC +% AD4630-24 - ADC diff --git a/+adi/Version.m b/+adi/Version.m new file mode 100644 index 0000000..cffb464 --- /dev/null +++ b/+adi/Version.m @@ -0,0 +1,16 @@ +classdef Version + % Version + % BSP Version information + properties (Constant) + MATLAB = 'R2021b' + Release = '21.2.1' + AppName = 'Analog Devices, Inc. Precision Toolbox' + ToolboxName = 'PrecisionToolbox' + ToolboxNameShort = 'pcx' + ExamplesDir = 'examples' + HasHDL = false + end + + methods + end +end diff --git a/.github/workflows/doc.yml b/.github/workflows/doc.yml new file mode 100644 index 0000000..8ef569d --- /dev/null +++ b/.github/workflows/doc.yml @@ -0,0 +1,29 @@ +name: Documentation + +on: [push, pull_request] + +jobs: + BuildDocs: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up Python 3.7 + uses: actions/setup-python@v2 + with: + python-version: 3.7 + + - name: Install dependencies + run: | + sudo apt install -y python3-numpy + pip install -r requirements_doc.txt + - name: Check doc build + run: | + make -C CI/gen_doc doc + - name: Publish master doc + if: github.ref == 'refs/heads/master' + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./doc + destination_dir: master \ No newline at end of file diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..12bf1fc --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "+adi/+common"] + path = +adi/+common + url = https://github.com/analogdevicesinc/ToolboxCommon.git diff --git a/CI/doc/ADITTBHome.m b/CI/doc/ADITTBHome.m new file mode 100644 index 0000000..f29a4cd --- /dev/null +++ b/CI/doc/ADITTBHome.m @@ -0,0 +1,59 @@ +%% ANALOG DEVICES INC. Precision Converter TOOLBOX SUPPORT PACKAGE +% Analog Devices Inc. Precision Converter Toolbox Support Package for Analog +% Devices Precision Converters enable the user in designing and prototyping +% practical wireless systems. Using MATLAB system objects provided with +% this support package, you can use ADI Precision Converter products to either +% capture streaming RF data and apply signal processing algorithms in +% MATLAB or utilize the provided HDL infrastructre to develop targetable +% designs that process RF data on the fly, thereby facilitating +% the design, development and testing of modem designs under real-world +% conditions. +% +% +%{ +Refer to existing documentation as much as possible. Only provide an +overview from a MATLAB perspective. +%} +% +% +%{ +Describe API in a unified manner to appeal to all users regardless of +whether Pluto, AD936x, AD937x, ADRV900x is being used to run code examples. +%} +% +% +%{ +What does HDL coder do? +IQ in IQ out +Valid in Valid out +Discussion on targeting from a non-AD9361 perspective since MATLAB +documentation has AD9361 perspective on HDL. Point to wiki page on +Precision Converter toolbox. But, update it first. +%} +% +% +%{ +Streaming Examples +Targeting Examples (Workflow from MATLAB Algorithm implementation to FPGA +targeting) - point to the donut diagram +Show examples the way MATLAB doc shows - demos.xml, similarly, see if there is an apps.xml +published examples, +%} +% +% +% +%{ +State Management +- When you change an attribute, when does it take effect? +- What happens when you run the system object operator? +- CenterFrequency gets written to hardware immediately in ADITB, not so in +MWTB. Illustrate by sine wave, FFT plot or iio_attr commands. +Attributes +Debug Attributes +Fast lock/frequency hopping +... +... +AGC Tuning (For AD936x) +%} +% +% \ No newline at end of file diff --git a/CI/doc/ADI_Logo_AWP_Large.png b/CI/doc/ADI_Logo_AWP_Large.png new file mode 100644 index 0000000..7a11a0c Binary files /dev/null and b/CI/doc/ADI_Logo_AWP_Large.png differ diff --git a/CI/doc/Buffers.mlx b/CI/doc/Buffers.mlx new file mode 100644 index 0000000..ad4d554 Binary files /dev/null and b/CI/doc/Buffers.mlx differ diff --git a/CI/doc/CodeExamples.mlx b/CI/doc/CodeExamples.mlx new file mode 100644 index 0000000..bc17764 Binary files /dev/null and b/CI/doc/CodeExamples.mlx differ diff --git a/CI/doc/Examples.mlx b/CI/doc/Examples.mlx new file mode 100644 index 0000000..72ddc63 Binary files /dev/null and b/CI/doc/Examples.mlx differ diff --git a/CI/doc/ForDevs.mlx b/CI/doc/ForDevs.mlx new file mode 100644 index 0000000..9046205 Binary files /dev/null and b/CI/doc/ForDevs.mlx differ diff --git a/CI/doc/StateMgmt.mlx b/CI/doc/StateMgmt.mlx new file mode 100644 index 0000000..1595116 Binary files /dev/null and b/CI/doc/StateMgmt.mlx differ diff --git a/CI/doc/Support.mlx b/CI/doc/Support.mlx new file mode 100644 index 0000000..1f27e8c Binary files /dev/null and b/CI/doc/Support.mlx differ diff --git a/CI/doc/SupportedHardware.mlx b/CI/doc/SupportedHardware.mlx new file mode 100644 index 0000000..fbdb86a Binary files /dev/null and b/CI/doc/SupportedHardware.mlx differ diff --git a/CI/doc/SysObjsProps.m b/CI/doc/SysObjsProps.m new file mode 100644 index 0000000..32da009 --- /dev/null +++ b/CI/doc/SysObjsProps.m @@ -0,0 +1,9 @@ +%% System Object Properties +% This section lists the system object properties for devices and +% evaluation boards supported by Precision Converter Toolbox. +%%% Devices +% * AD4630 +% * AD4030 +% * AD463x +% * AD7768 + diff --git a/CI/doc/SystemObjects.mlx b/CI/doc/SystemObjects.mlx new file mode 100644 index 0000000..e554404 Binary files /dev/null and b/CI/doc/SystemObjects.mlx differ diff --git a/CI/doc/adi_bsp.mlx b/CI/doc/adi_bsp.mlx new file mode 100644 index 0000000..e7d7cad Binary files /dev/null and b/CI/doc/adi_bsp.mlx differ diff --git a/CI/doc/customDoc.m b/CI/doc/customDoc.m new file mode 100644 index 0000000..6d9071c --- /dev/null +++ b/CI/doc/customDoc.m @@ -0,0 +1,163 @@ +function html = customDoc(str) + % Make sure that we can support the doc command on this platform. + if ~usejava('mwt') + error(message('MATLAB:doc:UnsupportedPlatform', upper(mfilename))); + end + + % Examine the inputs to see what options are selected. + [showClassicDoc, topic, search, isVariable] = examineInputs(str); + if isVariable + varName = inputname(isVariable); + elseif ~isempty(topic) && nargin == 1 + wsVariables = evalin('caller', 'whos'); + [topic, isVariable, varName] = matlab.internal.help.getClassNameFromWS(topic, wsVariables, true); + end + if search + docsearch(topic); + return; + end + % Check this before checking docroot, the -classic option is used to show doc not under docroot. + if showClassicDoc + com.mathworks.mlservices.MLHelpServices.invokeClassicHelpBrowser(); + return; + end + + % Make sure docroot is valid. + if ~matlab.internal.help.isDocInstalled + % If m-file help is available for this topic, call helpwin. + if ~isempty(topic) + if showHelpwin(topic) + return; + end + end + + % Otherwise show the appropriate error page. + htmlFile = fullfile(matlabroot,'toolbox','local','helperr.html'); + + if exist(htmlFile, 'file') ~= 2 + error(message('MATLAB:doc:HelpErrorPageNotFound', htmlFile)); + end + displayFile(htmlFile); + return; + end + + % Case no topic specified. + if isempty(topic) + % Just open the help browser and display the default startup page. + com.mathworks.mlservices.MLHelpServices.invoke(); + return; + end + + if strncmpi(topic, 'mupad/', 6) + if ~mupaddoc(topic) + showNoReferencePageFound; + end + return; + end + + [operator,topic] = matlab.internal.language.introspective.isOperator(topic); + if ~operator + if topic(end) == '/' + topic = topic(1:end-1); + end + + if showProductPage(topic) + return; + end + + [possibleTopics, isPrimitive] = matlab.internal.help.resolveDocTopic(topic, isVariable); + + if isPrimitive + disp(matlab.internal.help.getInstanceIsa(varName, topic)); + return; + end + else + [~,possibleTopics.topic] = fileparts(topic); + possibleTopics.isElement = false; + end + + [foundTopic, html] = showHelpwin(topic); + if ~displayDocPage(possibleTopics) && ~foundTopic + docsearch(topic); + end +end + +function [showClassicDoc, topic, search, varIndex] = examineInputs(str) + showClassicDoc = 0; + topic = []; + search = 0; + varIndex = 0; + + % for i = 1:numel(str) + argName = str; % str{i}; + if isstring(argName) + if ~isscalar(argName) + MException(message('MATLAB:doc:MustBeSingleString')).throwAsCaller; + end + argName = char(strip(argName)); + elseif ischar(argName) + argName = strtrim(argName); + else + argName = class(argName); + % varIndex = i; + end + + if strcmp(argName, '-classic') + showClassicDoc = 1; + else + % assume this is the location. + if ~isempty(topic) + topic = sprintf('%s %s', topic, argName); + search = 1; + else + topic = argName; + end + end + % end +end + +function success = showProductPage(topic) + success = com.mathworks.mlservices.MLHelpServices.showProductPage(topic); +end + +function success = displayDocPage(possibleTopics) + success = false; + for topic = possibleTopics + if com.mathworks.mlservices.MLHelpServices.showReferencePage(topic.topic, topic.isElement) + success = true; + return; + end + end + + for topic = possibleTopics + if matlab.internal.doc.isLiveCodeAndHasDocumentation(topic.topic) + internal.help.livecodedoc.mlxdoc(topic.topic); + success = true; + return; + end + end +end + +function [foundTopic, html] = showHelpwin(topic) + % turn off the warning message about helpwin being removed in a future + % release + s = warning('off', 'MATLAB:helpwin:FunctionToBeRemoved'); + [foundTopic, html] = customHelpwin(topic, '', '', '-doc'); + + % turn the warning message back on if it was on to begin with + warning(s.state, 'MATLAB:helpwin:FunctionToBeRemoved'); +end + +function showNoReferencePageFound(topic) + noFuncPage = matlab.internal.help.underDocroot('nofunc.html'); + if ~isempty(noFuncPage) + displayFile(noFuncPage); + else + error(message('MATLAB:doc:InvalidTopic', topic)); + end +end + +function displayFile(htmlFile) + % Display the file inside the help browser. + web(htmlFile, '-helpbrowser'); +end diff --git a/CI/doc/customHelpwin.m b/CI/doc/customHelpwin.m new file mode 100644 index 0000000..d9e1a74 --- /dev/null +++ b/CI/doc/customHelpwin.m @@ -0,0 +1,188 @@ +function [success, html] = customHelpwin(topic,pagetitle,helptitle,varargin) +%HELPWIN MATLAB file help displayed in a window +% HELPWIN TOPIC displays the help text for the specified TOPIC inside a +% window. Links are created to functions referenced in the 'See Also' +% line of the help text. +% +% HELPWIN(HELP_STR,TITLE) displays the string HELP_STR in the help +% window. HELP_STR may be passed in as a string with each line separated +% by carriage returns, a column vector cell array of strings with each cell +% (row) representing a line or as a string matrix with each row representing +% a line. The optional string TITLE will appear in the title banner. +% +% HELPWIN({TITLE1 HELP_STR1;TITLE2 HELP_STR2;...},PAGE) displays one page +% of multi-page help text. Note: this calling sequence is deprecated and +% is provided only for compatibility with previous versions of HELPWIN. +% The multi-page help text is passed in as a +% cell array of strings or cells containing TITLE and HELP_STR pairs. +% Each row of the multi-page help text cell array (dimensioned number of +% pages by 2) consists of a title string paired with a string, cell array +% or string matrix of help text. The second argument PAGE is a string +% which must match one of the TITLE entries in the multi-page help text. +% The matching TITLE represents the page that is to be displayed first. +% If no second argument is given, the first page is displayed. +% +% HELPWIN displays the default topic list in a window. +% +% HELPWIN will be removed in a future release. Use DOC instead. +% +% See also HELP, DOC. + +% Copyright 1984-2020 The MathWorks, Inc. + +if nargout + success = true; +end + +% Make sure that we can support the helpwin command on this platform. +if ~usejava('mwt') + error(message('MATLAB:doc:UnsupportedPlatform',upper(mfilename))); +end + +% This function has to support the old helpwin syntax, which +% provides for three disparate cases. +% Case 1: HELPWIN TOPIC, to display function or topic help (same as HELP function). +% Case 2: HELPWIN(HELP_STR,TITLE), to display an arbitrary help string. +% Case 3: HELPWIN({TITLE1 HELP_STR1;TITLE2 HELP_STR2;...},PAGE) +% to display multi-page help. + +% Is this multi-page help text? (case 3 above) +if nargin>0 && (iscell(topic) || isstring(topic)) && (size(topic,2) > 1) + if nargin < 2 + pagetitle = ''; + helptitle = ''; + elseif nargin < 3 + helptitle = pagetitle; + end + if nargin > 3 + displayOption = varargin{1}; + else + displayOption = ''; + end + handle_multipage_help(topic,pagetitle,helptitle,displayOption) + return; +end + +if (nargin == 0) + doc; + return; +elseif (nargin == 1) + html = help2html(topic); +elseif (nargin > 1) + if nargin > 3 + helpCommandOption = varargin{1}; + else + helpCommandOption = '-helpwin'; + end + html = help2html(topic,pagetitle,helpCommandOption); +end + +if isempty(html) && nargout + success = false; + %{ +else + displayFile(['text://' html]); + %} +end + +function handle_multipage_help(topic,pagetitle,helptitle,displayOption) +if (iscell(topic) || isstring(topic)) && numel(topic) == 2 + % This isn't really multipage help. Use a different helpwin syntax. + helpwin(topic{2},topic{1}); + return; +end + +pagetitle = char(pagetitle); +helptitle = char(helptitle); + +% Alternate between multiple temp files (starting with matlabTemp1.html). +% Multiple files are needed because a single file won't refresh properly, +% and to allow for a certain level of "Back" operations in the browser. +% You have to pass the browser a new file name each time to get it to reload. +dirName = char(com.mathworks.services.Prefs.getPropertyDirectory); +currFile = char(com.mathworks.mlservices.MLHelpServices.getCurrentLocation); +tempNum = regexp(currFile,'matlabTemp(\d).html','tokens','once'); +if ~isempty(tempNum) + tempNum = rem(str2double(tempNum),5) + 1; +else + tempNum = 1; +end +fileName = fullfile(dirName,['matlabTemp' num2str(tempNum) '.html']); + +% Workaround for ICE bug involving named anchors +fnPos = strfind(fileName, 'matlabTemp'); +shortName = fileName(fnPos:length(fileName)); + +% Starting building HTML output, beginning with optional title banner. +% At top put header with links to each page. +% Only show header if more than one page. +dom = com.mathworks.xml.XMLUtils.createDocument('help-info'); +dom.getDomConfig.setParameter('cdata-sections',true); +addTextNode(dom,dom.getDocumentElement,'title',helptitle); +addTextNode(dom,dom.getDocumentElement,'filename',shortName); + +helpdir = fileparts(mfilename('fullpath')); +helpdir = ['file:///' strrep(helpdir,'\','/')]; +addTextNode(dom,dom.getDocumentElement,'helptools-dir',helpdir); + +if ~strcmp(helptitle,pagetitle) + addTextNode(dom,dom.getDocumentElement,'pagetitle',pagetitle); +end +numpages = size(topic,1); +for x = 1:numpages + pgtitle = char(topic(x,1)); + helpNode = help2xml(dom,pgtitle,pgtitle,'-helpwin'); + addAttribute(dom,helpNode,'id',num2str(x)); +end + +addTextNode(dom,dom.getDocumentElement,'default-topics-text',getString(message('MATLAB:helpwin:sprintf_DefaultTopics'))); +addTextNode(dom,dom.getDocumentElement,'help-command-option','helpwin'); +xslfile = fullfile(fileparts(mfilename('fullpath')),'private','helpwin.xsl'); +html = xslt(dom,xslfile,'-tostring'); + +for x = 1:numpages + helpstr = char(topic(x,2)); + if (size(helpstr,1) > 1) + % Convert a 2-D char array to 1-D. + c = cellstr(helpstr); + helpstr = sprintf('%s\n',c{:}); + end + + html = regexprep(html,['\s*'], sprintf('\n\n%s',regexptranslate('escape',helpstr))); +end + +if strcmp(displayOption,'-nofile') + displayFile(['text://' html]); +else + fid = fopen(fileName,'w'); + fprintf(fid,'%s', html); + fclose(fid); + + % Get the index for the requested page from the cell array. + % Display the appropriate page. + ind = strmatch(pagetitle,topic(:,1),'exact'); + if isempty(ind), ind = 1; end + if ind == 1 + displayFile(fileName); + else + namedAnchor = sprintf('#topic%u',ind); + displayFile([fileName namedAnchor ]); + end +end + +function addTextNode(dom,parent,name,text) +child = dom.createElement(name); +child.appendChild(dom.createTextNode(text)); +parent.appendChild(child); + +function addAttribute(dom,elt,name,text) +att = dom.createAttribute(name); +att.appendChild(dom.createTextNode(text)); +elt.getAttributes.setNamedItem(att); + + +%------------------------------------------ +% Helper function that displays the HTML file in the web browser. +function displayFile(htmlFile) +web(htmlFile, '-helpbrowser'); + diff --git a/CI/doc/genhtml.m b/CI/doc/genhtml.m new file mode 100644 index 0000000..76c34bd --- /dev/null +++ b/CI/doc/genhtml.m @@ -0,0 +1,43 @@ +mfiledir = '..\..\+adi\'; +docdir = '..\..\doc\'; +parts = {'AD4630','AD4030','AD463x','AD7768'}; +trx_files = {'Rx','Base','Tx'}; +for ii = 1:numel(parts) + for jj = 1:numel(trx_files) + dotmfilename = strcat(mfiledir, '+', parts{ii}, '\', trx_files{jj}, '.m'); + if isfile(dotmfilename) + htmlfilename = strcat(docdir, parts{ii}, '_', trx_files{jj}, '.html'); + html = customDoc(dotmfilename); + dlmwrite(htmlfilename, html, 'delimiter', ''); + use_local_css(htmlfilename) + disp(htmlfilename); + end + end +end +publish('SysObjsProps.m','outputDir','..\..\doc'); +publish('ADITTBHome.m','outputDir','..\..\doc'); + +%{ +[filepath,name,ext] = fileparts(mfilename('fullpath')); +cd(filepath); +files = dir(filepath); + +target = '../../doc/'; + +skip = {'NA'}; + +for f = {files.name} + if strfind(f{:},'.mlx')>=0 + filename = f{:}; + if contains(filename,skip) + continue; + end + htmlFilename = [filename(1:end-4),'.html']; + disp(htmlFilename); + matlab.internal.liveeditor.openAndConvert(filename,htmlFilename); + movefile(htmlFilename,target); + end +end +%} + + diff --git a/CI/doc/use_local_css.m b/CI/doc/use_local_css.m new file mode 100644 index 0000000..364780e --- /dev/null +++ b/CI/doc/use_local_css.m @@ -0,0 +1,10 @@ +function use_local_css(html_file) + url_str = 'https://localhost:31515/static/help/includes/product/css/'; + contents = fileread(html_file); + str_loc = strfind(contents, url_str); + contents(str_loc:str_loc+numel(url_str)-1) = []; + + fid = fopen(html_file,'w'); + fprintf(fid, '%s', contents); + fclose(fid); +end \ No newline at end of file diff --git a/CI/gen_doc/Makefile b/CI/gen_doc/Makefile new file mode 100644 index 0000000..7ea2811 --- /dev/null +++ b/CI/gen_doc/Makefile @@ -0,0 +1,65 @@ +# Usage: +# make MLRELEASE= HDLBRANCH= +# Example +# make build MLRELEASE=R2018b HDLBRANCH=hdl_2018_r1 + +SHELL := /bin/bash + +MLFLAGS := -nodisplay -nodesktop -nosplash + +ifeq ($(MLRELEASE),) +MLRELEASE := R2021a +endif + +ifeq ($(HDLBRANCH),) +HDLBRANCH := hdl_2018_r2 +endif + +ifeq ($(OS),Windows_NT) +MLPATH := /cygdrive/c/Program\ Files/MATLAB +MLFLAGS := $(MLFLAGS) -wait +else +UNAME_S := $(shell uname -s) +ifeq ($(UNAME_S),Linux) +MLPATH := /usr/local/MATLAB +endif +ifeq ($(UNAME_S),Darwin) +MLPATH := /Applications +MLRELEASE := MATLAB_${MLRELEASE}.app +endif +endif + +ifeq ($(BOARD),) +BOARD := +endif + +ifeq ($(INCLUDE_EXAMPLES),) +INCLUDE_EXAMPLES := 1 +endif + +GITTAG := $(shell git describe --tags HEAD) + +.PHONY: doc + +.ONESHELL: + +doc_ml: + cd ../.. ; \ + cd docs ; \ + cp ../../scripts/ports.json . ; \ + cp ../../scripts/read_ports_json.py . ; \ + python3 read_ports_json.py ; \ + MATLAB=ON python3 gen_all_doc.py ; \ + cd .. ; \ + mkdocs build -d doc + +doc: + cd docs ; \ + # cp ../../scripts/ports.json . ; \ + # cp ../../scripts/read_ports_json.py . ; \ + python3 read_ports_json.py ; \ + python3 gen_all_doc.py ; \ + cd .. ; \ + mkdocs build -d doc ; \ + mkdir -p ../../doc ; \ + cp -r doc/* ../../doc/ ; \ diff --git a/CI/gen_doc/docs/_pages/examples.md b/CI/gen_doc/docs/_pages/examples.md new file mode 100644 index 0000000..80daac3 --- /dev/null +++ b/CI/gen_doc/docs/_pages/examples.md @@ -0,0 +1,13 @@ +{% include 'header.tmpl' %} +# Examples + +Examples for streaming data are listed within the Toolbox documentation itself. To view run the following with MATLAB: + +``` +doc adi +``` + +They can also be viewed on GitHub: + + - [Streaming examples](https://github.com/analogdevicesinc/PrecisionToolbox/tree/master/examples) + diff --git a/CI/gen_doc/docs/_pages/header.tmpl b/CI/gen_doc/docs/_pages/header.tmpl new file mode 100644 index 0000000..1ded747 --- /dev/null +++ b/CI/gen_doc/docs/_pages/header.tmpl @@ -0,0 +1,7 @@ +{%- if disable_nav -%} +--- +hide: + - navigation + - toc +--- +{%- endif -%} \ No newline at end of file diff --git a/CI/gen_doc/docs/_pages/index.md b/CI/gen_doc/docs/_pages/index.md new file mode 100644 index 0000000..b35e436 --- /dev/null +++ b/CI/gen_doc/docs/_pages/index.md @@ -0,0 +1,35 @@ +{% include 'header.tmpl' %} + + + + +
+ + +
+ + +ADI maintains a set of tools to interface with ADI precision converters within MATLAB and Simulink. These are combined into a single toolbox. The list of supported parts is provided below. + +The following have device-specific implementations in MATLAB and Simulink. If a device has an IIO driver, MATLAB support is possible, but a device-specific MATLAB or Simulink interface may not exist yet. + +| Evaluation Card | FPGA Board | Streaming Support | Targeting | Variants and Minimum Supported Release | +| --------- | --------- | --------- | --------- | --------- | +| AD7380 | Zedboard | Yes | No | ADI (2021b) | +| AD7768 | Zedboard | Yes | No | ADI (2021b) | +| AD7768-1 | Zedboard | Yes | No | ADI (2021b) | +| AD4030-24 | Zedboard | Yes | No | ADI (2021b) | +| AD4630-16 | Zedboard | Yes | No | ADI (2021b) | +| AD4630-24 | Zedboard | Yes | No | ADI (2021b) | diff --git a/CI/gen_doc/docs/_pages/install.md b/CI/gen_doc/docs/_pages/install.md new file mode 100644 index 0000000..3b08137 --- /dev/null +++ b/CI/gen_doc/docs/_pages/install.md @@ -0,0 +1,43 @@ +{% include 'header.tmpl' %} +# Installation + +## Dependencies + +The toolbox has different dependencies based on the features required. The base dependencies for streaming data are listed below. + + +### Data Streaming with Hardware + +The base dependencies for the toolbox requires libiio and the libiio MATLAB bindings. There are three options for this install with different required MathWorks Toolboxes: + +- [Communications Toolbox Support Package for Xilinx Zynq-Based Radio](https://www.mathworks.com/help/supportpkg/xilinxzynqbasedradio/index.html) + - Communications Toolbox + - Signal Processing ToolboxTM + - DSP System ToolboxTM +- [Communications Toolbox Support Package for Analog Devices ADALM-Pluto Radio](https://www.mathworks.com/help/supportpkg/plutoradio/index.html) + - Communications Toolbox + - Signal Processing ToolboxTM + - DSP System ToolboxTM +- [libiio MATLAB Binding Standalone Installer (R2021b+)](https://github.com/mathworks/buildroot/releases/download/mathworks_zynq_R21.2.0/libiio.mlpkginstall) + - Signal Processing ToolboxTM + + +## Precision Toolbox Install + +The Precision Toolbox itself can be installed either from: + +- [MATLAB's Add-On Explorer](https://www.mathworks.com/products/matlab/add-on-explorer.html) +- [GitHub Releases page](https://github.com/analogdevicesinc/PrecisionToolbox/releases). + +!!! warning "MATLAB Versions" + Before installing Precision Toolbox check the [Release Page](https://github.com/analogdevicesinc/PrecisionToolbox/releases) to check for the latest supported version of MATLAB. The latest version is the one which is available in [Add-on Explorer](https://www.mathworks.com/products/matlab/add-on-explorer.html), since Add-On Explorer does not currently support hosting multiple versions. If you have an older release of MATLAB, download the MLTBX installer from matching release on the [Release Page](https://github.com/analogdevicesinc/PrecisionToolbox/releases). + + +### Add-On Explorer Walkthrough + +To install the toolbox from within MATLAB using the Add-On Explorer: + + - Launch the Add-Ons Explorer from MATLAB's Home tab + - Search for 'Precision Toolbox' + - Select Precision Toolbox from Analog Devices, Inc. from the results: + - Install the toolbox diff --git a/CI/gen_doc/docs/_pages/limitations.md b/CI/gen_doc/docs/_pages/limitations.md new file mode 100644 index 0000000..c70441f --- /dev/null +++ b/CI/gen_doc/docs/_pages/limitations.md @@ -0,0 +1,27 @@ +{% include 'header.tmpl' %} +# Known Limitations, Bugs and Quirks + +Some limitations and bugs are known to be present in the support for the ADCs relevant to the Precision Toolbox. They have been summarized below. + +## Libiio backend + +Currently only ethernet/IP backends are supported for all the parts in the toolbox. For AD4030-24, AD4630-16 and AD4630-24 the usb backend can also be used. Serial backends are not supported. + +## AD7380 + +Trigger setup needs to be done before running any of the toolbox scripts that interact with the AD7380. Refer to the [Trigger Management section on the AD738x Linux IIO driver wiki page](https://wiki.analog.com/resources/tools-software/linux-drivers/iio-adc/ad738x#trigger_management) + +## AD7768 + +The Linux IIO driver for the AD7768 returns data for all the channels whenever a data capture is requested. So, in order to get sensible outputs, ensure that the EnabledChannels array consists of indices for all the channels. + +## AD4030-24. AD4630-16, AD4630-24 + +The Linux IIO driver for the three parts (there's a common Linux driver that addresses all three parts) returns data for all the channels whenever a data capture is requested. In order to have sensible outputs, ensure that the EnabledChannels array consists of indices for all the channels. + +Another known issue here has to do with the case where the ADC sends out common mode voltage data along with the differential voltage data. The EnabledChannel property values that consist of more than two indices (even when there are 4 IIO channels), are not 'valid'. Of the possible groupings with two channel indices, the ones that correspond to {differential0, common_voltage0} and {differential1, common_voltage1} are also not 'valid' + +It is possible to get data (common-mode and differential) for all the ADC channels, by using a 'valid' channel grouping, setting the BufferTypeConversionEnable property to 'false' in the Base class for the AD463x family, and adding custom parsing logic to extract the data for all IIO channels, from the 32-bit raw words you get from the data capture. + + + diff --git a/CI/gen_doc/docs/_pages/models.md b/CI/gen_doc/docs/_pages/models.md new file mode 100644 index 0000000..3af312e --- /dev/null +++ b/CI/gen_doc/docs/_pages/models.md @@ -0,0 +1,8 @@ +{% include 'header.tmpl' %} +# Behavioral Models + + +The toolbox contains behavioral simulation models of different data converters that can be used in MATLAB and Simulink. These are designed to help users understand device limitations and advanced feature sets. As well as to test their algorithms and signal processing against. +The currently supported behavioral models are: + +- [AD9081 MxFE Quad, 16-Bit, 12GSPS RFDAC and Quad, 12-Bit, 4GSPS RFADC](/models/ad9081/top_level.tex/) \ No newline at end of file diff --git a/CI/gen_doc/docs/_pages/streaming.md b/CI/gen_doc/docs/_pages/streaming.md new file mode 100644 index 0000000..41a6bb9 --- /dev/null +++ b/CI/gen_doc/docs/_pages/streaming.md @@ -0,0 +1,90 @@ +{% include 'header.tmpl' %} +# Receiving and Sending Data + +Remote data streaming to and from hardware is made available through [system object interfaces](https://www.mathworks.com/help/matlab/matlab_prog/what-are-system-objects.html), which are unique for each component or platform. The hardware interfacing system objects provide a since class to both configure a given platform and move data back and forth from the device. + +Command and control of hardware from MATLAB is accomplished by leveraging the [IIO drivers](https://wiki.analog.com/software/linux/docs/iio/iio) built into the target platform's kernel and [libiio](https://wiki.analog.com/resources/tools-software/linux-software/libiio) which provides remote backends to control drivers across different backends. Backends can be Ethernet/IP/USB based. Below is a diagram of the different components in the stack for a setup targeting the evaluation of the AD7380, but the setup will be nearly similar for other ADCs as well. + +![MATLAB libiio Stack](assets/PCXEvalStack.PNG) + +Since libiio is cross-platform it can be used from Windows, Linux, or macOS based systems. It is also a lower level library independent of MATLAB, so when moving toward production or untethered systems similar APIs that are used in MATLAB can be used in C,C++,Python, or other languages. + +## Connecting and Configuration + +Connecting to hardware is done by setting the **uri** property of the system object interface. The **uri** for libiio always has the convention "*< backend >:< address >*", where *backend* can be ethernet, ip or usb. *address* will be specific to the backend. This is documented in the [libiio API](https://analogdevicesinc.github.io/libiio/master/libiio/group__Context.html#gafdcee40508700fa395370b6c636e16fe). + +Below is a basic example of setting up a generic ADC using an Ethernet/IP backend: +```linenums="1" +rx = adi.ADxxxx.Rx; +rx.uri = 'ip:analog.local'; +data = rx(); +``` +With the code above, the hardware is not contacted until the operator or step method is called on line 3. Therefore, any properties that are set or defined before line 3 are not applied or updated on the hardware until after line 3. However, after line 3 has completed the object will become locked and certain configuration changes cannot be applied after this point. These will primarily sample rates and buffer sizes. + +The state of the object follows the flow of the diagram below triggered by line 3 above. + +``` mermaid +graph LR + Z[Operator Called] -->A; + A[Connect To Board] --> B[Update Properties]; + B --> C[Initialize Buffers]; + C --> D[Send or Receive Data]; + D --> E[Lock Object]; +``` +Once the object becomes locked it must be released if the sample rate or buffers need to be modified. This will disconnect from the hardware: +``` +rx.release(); % Release object +``` + +To provide a complete example we can do more advanced configuration like so to demonstrate property changes: +```linenums="1" +rx = adi.ADxxxx.Rx; +rx.uri = 'ip:analog.local'; +rx.SamplesPerFrame = 1024; +rx.SampleRate = 256000; +data1 = rx(); + +% Update tunable property +rx.SampleRate = 128000; +data2 = rx(); + +% Update non-tunable property +rx.release(); +rx.SamplesPerFrame = 4096; +dataLargerBuffer = rx(); +``` + +## Receiving Data + +To receive or capture data from a given device first you must instantiate that device's interface class. For a generic ADC, this would be as follows: + +``` +rx = adi.ADxxxx.Rx; +``` + +Once instantiated you can configure the number of samples to be captured by setting the property **SamplesPerFrame.** + +``` +rx.SamplesPerFrame = 1e6; +``` + +**SamplesPerFrame** is the number of samples per channel which will be captured. If your device produces complex data (I and Q) this is the number of complex samples. There will be a limit to the maximum samples which can be collected. By default this is set to 2^20, but it may be possible to make it larger depending on hardware. Once the operator methods are used for a give instantiation, the object will become locked and the **SamplesPerFrame** property cannot be changed. This is known as a non-tunable property. + +To actually collect the samples or perform the capture, the operator of the system object should be used or the **step** method as so: + +``` +data = rx(); % Operator method +data = rx.step(); % Step method +``` + +Both method calls are equivalent, and the produced matrix **data** will be of size [SamplesPerFrame x length(EnabledChannels)]. **EnabledChannels** determines the channels which data will be collected from. **EnabledChannels** is a [1xN] vector with indexes starting at 1 of the desired channels. + +## Continuous Data Acquisition + +If you are capturing multiple frames or buffers of data, then there might arise situations where discontinuities appear in the samples, when plotted. + +Some detail and tips are discussed in this wiki page on [IIO System Considerations, Tips and Tricks](https://wiki.analog.com/resources/tools-software/linux-software/libiio_tips_tricks) + +The IIO buffer size is governed by the SamplesPerFrame property of the System Object classes. The kernelBuffersCount is also a property defined for the classes, and can be modified. + + diff --git a/CI/gen_doc/docs/_pages/support.md b/CI/gen_doc/docs/_pages/support.md new file mode 100644 index 0000000..6982a8f --- /dev/null +++ b/CI/gen_doc/docs/_pages/support.md @@ -0,0 +1,9 @@ +{% include 'header.tmpl' %} +# Support + +Support is provided online through the EngineerZone forums. If you have questions related to the hardware itself outside of this BSP, contact your local FAE or ask on the forums. + +Question regarding specific aspect of the BSP should be asked in the following places: + +- [**Software Interface Tools**](https://ez.analog.com/sw-interface-tools/f/q-a) for questions on the BSP itself +- [**Linux Software Drivers**](https://ez.analog.com/linux-software-drivers/f/q-a) for libiio and iio driver questions \ No newline at end of file diff --git a/CI/gen_doc/docs/_pages/targeting.md b/CI/gen_doc/docs/_pages/targeting.md new file mode 100644 index 0000000..eaa4c80 --- /dev/null +++ b/CI/gen_doc/docs/_pages/targeting.md @@ -0,0 +1,57 @@ + +# HDL Targeting with HDL-Coder + +High-Speed Converter Toolbox supports the IP Core generation flow from MathWorks which allows for automated integration of DSP into HDL reference designs from Analog Devices. This workflow will take Simulink subsystems, run HDL-Coder to generate source Verilog, and then integrate that into a larger reference design. The figure below is a simplified block diagram of a SoC (Fabric+ARM) device, where specialized IP are inserted into the receive and transmit datapaths. This is supported on specific FPGA families and high-speed based reference designs. This support is based on the Zynq HDL-Coder and support + + + +## Recommended Review + +- [Getting started with Zynq](https://www.mathworks.com/support/search.html/videos/getting-started-with-zynq-80338.html?fq%5B%5D=asset_type_name:video&fq%5B%5D=category:hdlcoder/index&page=1) + +## Getting Started + +To perform targeting will require FPGA vendor tools for the FPGA system. For Xilinx this will be Vivado and the toolbox will require specific versions for each release. For the current release this is Vivado 2019.1. Using other versions are not supported. To build the necessary BOOT.BIN files will require the Xilinx SDK as well. + +Once you have the installed the necessary 3rd party tools MATLAB needs to be told where they are installed by use of the [hdlsetuptoolpath](https://www.mathworks.com/help/hdlcoder/ref/hdlsetuptoolpath.html) command. For Windows the following MATLAB command can be used: + +```matlab +hdlsetuptoolpath('ToolName', 'Xilinx Vivado', 'ToolPath', 'C:\Xilinx\Vivado\2019.1\bin\vivado.bat'); +``` + +or Linux: + +```matlab +hdlsetuptoolpath('ToolName', 'Xilinx Vivado', 'ToolPath', '/opt/Xilinx/Vivado/2019.1/bin/vivado'); +``` + +Please change the tool path if it is different on your system. + +### Checking For Supported Designs + +To verify that the ADI reference designs are available to [HDL Workflow Advisor](https://www.mathworks.com/help/hdlcoder/ug/overview-of-workflows-in-hdl-workflow-advisor.html) a Simulink model needs to be opened. To do so launch Simulink with the following command: + +```matlab +simulink +``` + +After it launches open a "Blank DUT" model from the "HDL Coder" dropdown of the Simulink Start Page. + + + + +After the model opens, click on the green subsystem to select it. Then open the "Apps" tap, open the apps menu and +scroll down to HDL-Coder. + + + + +This will open the HDL-Coder menu, from here the Workflow Advisor is selectable. Click on it to launch the advisor. + + + + +Once launch go to Step 1.1 on the left side column. Then on the right side of the window select "IP Core Generation" for "Target workflow". Then the ADI reference designs should be available in the "Target platform" menu as so: + + + \ No newline at end of file diff --git a/CI/gen_doc/docs/_pages/toc.tmpl b/CI/gen_doc/docs/_pages/toc.tmpl new file mode 100644 index 0000000..78e9a19 --- /dev/null +++ b/CI/gen_doc/docs/_pages/toc.tmpl @@ -0,0 +1,14 @@ + + + Analog Devices, Inc Precision Toolbox +{%- for page in pages %} + {{ page|capitalize }} +{%- endfor %} + + Hardware Interface APIs +{%- for obj in devices %} + {{ obj }} +{%- endfor %} + + + diff --git a/CI/gen_doc/docs/_templates/allsysobjs.tmpl b/CI/gen_doc/docs/_templates/allsysobjs.tmpl new file mode 100644 index 0000000..c21ef46 --- /dev/null +++ b/CI/gen_doc/docs/_templates/allsysobjs.tmpl @@ -0,0 +1,12 @@ +{% include 'header.tmpl' %} +# Hardware Interface APIs + +Available hardware streaming interfaces in PCX Toolbox: + +{%- for obj in devices %} +- {{ obj }} +{%- endfor %} + +Click on left table of contents for individual component pages. \ No newline at end of file diff --git a/CI/gen_doc/docs/_templates/header.tmpl b/CI/gen_doc/docs/_templates/header.tmpl new file mode 100644 index 0000000..1ded747 --- /dev/null +++ b/CI/gen_doc/docs/_templates/header.tmpl @@ -0,0 +1,7 @@ +{%- if disable_nav -%} +--- +hide: + - navigation + - toc +--- +{%- endif -%} \ No newline at end of file diff --git a/CI/gen_doc/docs/_templates/mkdocs.tmpl b/CI/gen_doc/docs/_templates/mkdocs.tmpl new file mode 100644 index 0000000..43d3ba5 --- /dev/null +++ b/CI/gen_doc/docs/_templates/mkdocs.tmpl @@ -0,0 +1,62 @@ +site_name: Analog Devices, Inc. Precision Toolbox + +theme: + logo: assets/matlab_white_icon.svg + name: material + palette: + - scheme: default + primary: blue + + - scheme: slate + primary: blue + toggle: + icon: material/toggle-switch + name: Switch to light mode + +nav: + - Overview: index.md + - Installation: install.md + - Data Streaming: streaming.md + - Examples: examples.md + - Support: support.md +{%- if matlab %} + - Hardware Interface APIs: objects.md +{%- endif %} + - Reference API: + - Device Interfaces: +{%- for dev in devices %} + - {{ dev }}: {{ devices[dev] }} +{%- endfor %} + + +extra_css: + - stylesheets/style.css + - stylesheets/rd_style.css +{%- if matlab %} + - stylesheets/ml_style.css +{%- endif %} + +extra_javascript: + - js/sys_objects.js + +plugins: + - search + - awesome-pages + - mermaid2 + - inline-svg + +markdown_extensions: + - attr_list + - md_in_html + - admonition + - pymdownx.details + - pymdownx.highlight: + anchor_linenums: true + - pymdownx.inlinehilite + - pymdownx.snippets + - pymdownx.superfences: + # make exceptions to highlighting of code: + custom_fences: + - name: mermaid + class: mermaid + format: !!python/name:mermaid2.fence_mermaid \ No newline at end of file diff --git a/CI/gen_doc/docs/_templates/refdesign.html b/CI/gen_doc/docs/_templates/refdesign.html new file mode 100644 index 0000000..05e225d --- /dev/null +++ b/CI/gen_doc/docs/_templates/refdesign.html @@ -0,0 +1,47 @@ +{% include 'header.tmpl' %} +{% block content %} + +# {{ obj.name }} Reference Design Integration + +This page outlines the HDL reference design integration for the *{{ obj.name }}* reference design for the Analog Devices +{{ obj.chip }} component. The IP-Core Generation follow is available on the based on the following base HDL reference design for the following board and design variants: + +- [Base reference design documentation]({{ obj.hdl_rd_doc }}) +- Supported FPGA carriers: +{%- for carrier in obj.fpga %} + - {{ carrier.upper() }} +{%- endfor %} +- Supported design variants: +{%- for supported_rd in obj.supported_rd %} + - {{ supported_rd.upper() }} +{%- endfor %} + +## Reference Design + +
+ {% if obj.rd_image == "ad9361" %} + ![Reference Design](../assets/rd_ad9361_custom.svg) + {% elif obj.rd_image == "adrv9001" %} + ![Reference Design](../assets/rd_adrv9001_custom.svg) + {% elif obj.rd_image == "jesd" %} + ![Reference Design](../assets/rd_jesd_custom.svg) + {% endif %} +
HDL Reference Design with Custom IP from HDL-Coder. Click on sub-blocks for more documentation.
+
+The IP-Core generation flow will integrate IP generated from Simulink subsystem into an ADI authored reference design. Depending on the FPGA carrier and FMC card or SoM, this will support different IP locations based on the diagram above. + +## HDL Worflow Advisor Port Mappings + +When using the HDL Worflow Advisor, the following port mappings are used to connect the reference design to the HDL-Coder generated IP-Core: + +| Type | Target Platform Interface (MATLAB) | Reference Design Connection (Vivado) | Width | Reference Design Variant | +| ---- | ------------------------ | --------------------------- | ----- | ----------- | +{%- for rds in obj.ports[0] %} + +{%- for rd in obj.ports[0][rds] %} +| {{ rd['type'].upper() }}-{% if rd['input'] == "true" %}IN{% else %}OUT{% endif %} | {{ rd['m_name'] }} | {{ rd['name'] }} | {{ rd['width'] }} | {{ rds.upper() }} | +{%- endfor %} + +{%- endfor %} + +{% endblock %} diff --git a/CI/gen_doc/docs/_templates/sysobj.html b/CI/gen_doc/docs/_templates/sysobj.html new file mode 100644 index 0000000..19c8120 --- /dev/null +++ b/CI/gen_doc/docs/_templates/sysobj.html @@ -0,0 +1,94 @@ +{% include 'header.tmpl' %} +{% block content %} + + + + + + +
+ +{{ obj.dec }} + + +
+ +
Creation
+ +The class can be instantiated in the following way with and without property name value pairs. + +```matlab +dev = {{ obj.name }} +dev = {{ obj.name }}(Name, Value) +``` + +
Properties
+ +
+ +Unless otherwise indicated, properties are non-tunable, which means you cannot change their values after calling the object. Objects lock when you call them, and the release function unlocks them. +

+If a property is tunable, you can change its value at any time. +

+For more information on changing property values, see System Design in MATLAB Using System Objects. +
+
+ +{%- for prop in obj.props %} +
+ + +
+{%- endfor -%} + +{% endblock %} + +
Example Usage
+ +``` +{% if obj.type == "Tx" %} +%% Configure device +tx = {{ obj.name }}; +tx.uri = "ip:analog.local"; +tx.DataSource = 'DMA'; +tx.EnableCyclicBuffers = true; +tx.EnabledChannels = 1; + +%% Generate tone +amplitude = 2^15; frequency = 0.12e6; +swv1 = dsp.SineWave(amplitude, frequency); +{% if obj.name == "adi.AD9081.Tx" or obj.name == "adi.AD9081.Rx" -%} +swv1.ComplexOutput = true; +{% endif -%} +swv1.SamplesPerFrame = 2^14; +{% if (obj.name == "adi.AD9081.Tx") or (obj.name == "adi.AD9081.Rx") -%} +swv1.SampleRate = 250e6; +{% else %} +swv1.SampleRate = tx.SamplingRate; +{% endif -%} +y = swv1(); + +%% Send +tx(y); +{% else %} +%% Rx set up +rx = {{ obj.name }}('uri','ip:analog.local'); +rx.SamplesPerFrame = 2^14; +rx.EnabledChannels = 1; + +%% Run +for k=1:10 + valid = false; + while ~valid + [out, valid] = rx(); + end +end + +%% Cleanup +release(rx) +{% endif %} +``` \ No newline at end of file diff --git a/CI/gen_doc/docs/assets/MATLAB_HDL_Ref_Design.png b/CI/gen_doc/docs/assets/MATLAB_HDL_Ref_Design.png new file mode 100644 index 0000000..e146e59 Binary files /dev/null and b/CI/gen_doc/docs/assets/MATLAB_HDL_Ref_Design.png differ diff --git a/CI/gen_doc/docs/assets/MATLAB_libiio_Stack.png b/CI/gen_doc/docs/assets/MATLAB_libiio_Stack.png new file mode 100644 index 0000000..1788194 Binary files /dev/null and b/CI/gen_doc/docs/assets/MATLAB_libiio_Stack.png differ diff --git a/CI/gen_doc/docs/assets/PCXEvalStack.PNG b/CI/gen_doc/docs/assets/PCXEvalStack.PNG new file mode 100644 index 0000000..bfa091d Binary files /dev/null and b/CI/gen_doc/docs/assets/PCXEvalStack.PNG differ diff --git a/CI/gen_doc/docs/assets/PCXTlbx_Image.PNG b/CI/gen_doc/docs/assets/PCXTlbx_Image.PNG new file mode 100644 index 0000000..6a1884f Binary files /dev/null and b/CI/gen_doc/docs/assets/PCXTlbx_Image.PNG differ diff --git a/CI/gen_doc/docs/assets/PcxToolboxLogo.png b/CI/gen_doc/docs/assets/PcxToolboxLogo.png new file mode 100644 index 0000000..5aa1c09 Binary files /dev/null and b/CI/gen_doc/docs/assets/PcxToolboxLogo.png differ diff --git a/CI/gen_doc/docs/assets/Reference_Designs.fig b/CI/gen_doc/docs/assets/Reference_Designs.fig new file mode 100644 index 0000000..a66e4f9 Binary files /dev/null and b/CI/gen_doc/docs/assets/Reference_Designs.fig differ diff --git a/CI/gen_doc/docs/assets/add_ex.png b/CI/gen_doc/docs/assets/add_ex.png new file mode 100644 index 0000000..6a3fa66 Binary files /dev/null and b/CI/gen_doc/docs/assets/add_ex.png differ diff --git a/CI/gen_doc/docs/assets/addons_page.png b/CI/gen_doc/docs/assets/addons_page.png new file mode 100644 index 0000000..8059a08 Binary files /dev/null and b/CI/gen_doc/docs/assets/addons_page.png differ diff --git a/CI/gen_doc/docs/assets/addons_page_wbox.png b/CI/gen_doc/docs/assets/addons_page_wbox.png new file mode 100644 index 0000000..8809e04 Binary files /dev/null and b/CI/gen_doc/docs/assets/addons_page_wbox.png differ diff --git a/CI/gen_doc/docs/assets/hwa_11.png b/CI/gen_doc/docs/assets/hwa_11.png new file mode 100644 index 0000000..2a133ed Binary files /dev/null and b/CI/gen_doc/docs/assets/hwa_11.png differ diff --git a/CI/gen_doc/docs/assets/hwa_11_crop.png b/CI/gen_doc/docs/assets/hwa_11_crop.png new file mode 100644 index 0000000..7e9ab89 Binary files /dev/null and b/CI/gen_doc/docs/assets/hwa_11_crop.png differ diff --git a/CI/gen_doc/docs/assets/matlab_white_icon.svg b/CI/gen_doc/docs/assets/matlab_white_icon.svg new file mode 100644 index 0000000..354bad1 --- /dev/null +++ b/CI/gen_doc/docs/assets/matlab_white_icon.svg @@ -0,0 +1,16 @@ + + + + + + + + + diff --git a/CI/gen_doc/docs/assets/rd_ad9361.svg b/CI/gen_doc/docs/assets/rd_ad9361.svg new file mode 100644 index 0000000..d34a544 --- /dev/null +++ b/CI/gen_doc/docs/assets/rd_ad9361.svg @@ -0,0 +1,284 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CI/gen_doc/docs/assets/rd_ad9361_custom.svg b/CI/gen_doc/docs/assets/rd_ad9361_custom.svg new file mode 100644 index 0000000..e964b9f --- /dev/null +++ b/CI/gen_doc/docs/assets/rd_ad9361_custom.svg @@ -0,0 +1,284 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CI/gen_doc/docs/assets/rd_adrv9001.svg b/CI/gen_doc/docs/assets/rd_adrv9001.svg new file mode 100644 index 0000000..f8a0ebd --- /dev/null +++ b/CI/gen_doc/docs/assets/rd_adrv9001.svg @@ -0,0 +1,254 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CI/gen_doc/docs/assets/rd_adrv9001_custom.svg b/CI/gen_doc/docs/assets/rd_adrv9001_custom.svg new file mode 100644 index 0000000..094b236 --- /dev/null +++ b/CI/gen_doc/docs/assets/rd_adrv9001_custom.svg @@ -0,0 +1,254 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CI/gen_doc/docs/assets/rd_jesd.svg b/CI/gen_doc/docs/assets/rd_jesd.svg new file mode 100644 index 0000000..8beb0e2 --- /dev/null +++ b/CI/gen_doc/docs/assets/rd_jesd.svg @@ -0,0 +1,328 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CI/gen_doc/docs/assets/rd_jesd_custom.svg b/CI/gen_doc/docs/assets/rd_jesd_custom.svg new file mode 100644 index 0000000..f33e590 --- /dev/null +++ b/CI/gen_doc/docs/assets/rd_jesd_custom.svg @@ -0,0 +1,328 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CI/gen_doc/docs/assets/simulink_blank_dut.png b/CI/gen_doc/docs/assets/simulink_blank_dut.png new file mode 100644 index 0000000..35a9f7d Binary files /dev/null and b/CI/gen_doc/docs/assets/simulink_blank_dut.png differ diff --git a/CI/gen_doc/docs/assets/simulink_hdl_coder.png b/CI/gen_doc/docs/assets/simulink_hdl_coder.png new file mode 100644 index 0000000..fabfba5 Binary files /dev/null and b/CI/gen_doc/docs/assets/simulink_hdl_coder.png differ diff --git a/CI/gen_doc/docs/assets/simulink_new_model.png b/CI/gen_doc/docs/assets/simulink_new_model.png new file mode 100644 index 0000000..8dc6059 Binary files /dev/null and b/CI/gen_doc/docs/assets/simulink_new_model.png differ diff --git a/CI/gen_doc/docs/assets/simulink_wa.png b/CI/gen_doc/docs/assets/simulink_wa.png new file mode 100644 index 0000000..1b4c44d Binary files /dev/null and b/CI/gen_doc/docs/assets/simulink_wa.png differ diff --git a/CI/gen_doc/docs/assets/trx_search.png b/CI/gen_doc/docs/assets/trx_search.png new file mode 100644 index 0000000..53ae4cf Binary files /dev/null and b/CI/gen_doc/docs/assets/trx_search.png differ diff --git a/CI/gen_doc/docs/assets/trx_search_find.png b/CI/gen_doc/docs/assets/trx_search_find.png new file mode 100644 index 0000000..5d17a84 Binary files /dev/null and b/CI/gen_doc/docs/assets/trx_search_find.png differ diff --git a/CI/gen_doc/docs/assets/trx_search_find_wbox.png b/CI/gen_doc/docs/assets/trx_search_find_wbox.png new file mode 100644 index 0000000..722ff1c Binary files /dev/null and b/CI/gen_doc/docs/assets/trx_search_find_wbox.png differ diff --git a/CI/gen_doc/docs/assets/trx_search_wbox.png b/CI/gen_doc/docs/assets/trx_search_wbox.png new file mode 100644 index 0000000..0290229 Binary files /dev/null and b/CI/gen_doc/docs/assets/trx_search_wbox.png differ diff --git a/CI/gen_doc/docs/gen_all_doc.py b/CI/gen_doc/docs/gen_all_doc.py new file mode 100644 index 0000000..0ff1be8 --- /dev/null +++ b/CI/gen_doc/docs/gen_all_doc.py @@ -0,0 +1,10 @@ +from gen_md_pages import gen_pages_and_toc +from gen_sysobj_pages import gen_sys_obj_pages +from gen_rd_svg import gen_rd_svg +import os + +if __name__ == "__main__": + gen_rd_svg() + matlab = bool(os.environ.get("MATLAB")) + devices, designs = gen_sys_obj_pages(matlab) + gen_pages_and_toc(matlab, devices, designs) diff --git a/CI/gen_doc/docs/gen_hdl_refdesigns.py b/CI/gen_doc/docs/gen_hdl_refdesigns.py new file mode 100644 index 0000000..74f8c07 --- /dev/null +++ b/CI/gen_doc/docs/gen_hdl_refdesigns.py @@ -0,0 +1,55 @@ +from jinja2 import Environment, FileSystemLoader +import os +import json +import numpy as np + + +def update_hdl_refdesigns(): + + template_filename = "refdesign.html" + + # Data for template + f = open("ports.json") + objs = json.load(f) + f.close() + + # Import template + loc = os.path.dirname(__file__) + loc = os.path.join(loc, "_templates") + file_loader = FileSystemLoader(loc) + env = Environment(loader=file_loader) + + loc = os.path.join(template_filename) + template = env.get_template(loc) + + designs = {} + + for obj in objs: + # Render template + objs[obj]["name"] = obj + + if objs[obj]["name"] in ["fmcomms2", "adrv9361z7035", "adrv9364z7020", "pluto"]: + objs[obj]["rd_image"] = "ad9361" + elif objs[obj]["name"] in ["adrv9002"]: + objs[obj]["rd_image"] = "adrv9001" + else: + objs[obj]["rd_image"] = "jesd" + + output = template.render(obj=objs[obj]) + # Write output + output_filename = f"hdlrefdesigns/{obj}.md" + loc = os.path.join(output_filename) + f = open(loc, "w") + f.write(output) + f.close() + designs[obj] = output_filename + + # # Update mkdocs.yml + # loc = os.path.join("mkdocs.tmpl") + # template = env.get_template(loc) + # output = template.render(designs=designs) + + # loc = os.path.join("..", "mkdocs.yml") + # with open(loc, "w") as f: + # f.write(output) + return designs diff --git a/CI/gen_doc/docs/gen_md_pages.py b/CI/gen_doc/docs/gen_md_pages.py new file mode 100644 index 0000000..9c72301 --- /dev/null +++ b/CI/gen_doc/docs/gen_md_pages.py @@ -0,0 +1,68 @@ +from jinja2 import Environment, FileSystemLoader +import os +from os import listdir + +# output_folder = "output" + +# if not os.path.exists(output_folder): +# os.makedirs(output_folder) + + +def gen_page(template_filename, disable_nav): + # Import template + loc = os.path.dirname(__file__) + loc = os.path.join(loc, "_pages") + print(loc) + file_loader = FileSystemLoader(loc) + env = Environment(loader=file_loader) + + template = env.get_template(template_filename) + + output = template.render(disable_nav=disable_nav) + + with open(template_filename, "w") as f: + f.write(output) + + +def gen_toc(pages, devices, designs): + + # Ensure that install.md is the first item here + pages.remove("install") + pages.insert(0, "install") + + # Import template + loc = os.path.dirname(__file__) + loc = os.path.join(loc, "_pages") + file_loader = FileSystemLoader(loc) + env = Environment(loader=file_loader) + + template = env.get_template("toc.tmpl") + + # Remove index from the list of pages -- otherwise it'll get added twice in the helptoc + pages.remove("index") + pages.remove("targeting") + pages.remove("models") + output = template.render(pages=pages, devices=devices, designs=designs) + + loc = os.path.dirname(__file__) + loc = os.path.join(loc, "helptoc.xml") + + with open(loc, "w") as f: + f.write(output) + + +def gen_pages_and_toc(matlab, devices, designs): + + template_filenames = listdir("_pages") + + pages = [] + for template_filename in template_filenames: + if matlab and template_filename == "models.md": + continue + if template_filename in ["header.tmpl", "toc.tmpl"]: + continue + gen_page(template_filename, matlab) + template_filename = template_filename.replace(".md", "") + pages.append(template_filename) + + gen_toc(pages, devices, designs) diff --git a/CI/gen_doc/docs/gen_rd_svg.py b/CI/gen_doc/docs/gen_rd_svg.py new file mode 100644 index 0000000..8cb6f6b --- /dev/null +++ b/CI/gen_doc/docs/gen_rd_svg.py @@ -0,0 +1,94 @@ +import os + +def gen_rd_svg(): + refs = ["rd_ad9361","rd_adrv9001","rd_jesd"] + css_out = "" + + for ref in refs: + + with open(f"assets/{ref}.svg", "r") as f: + svg = f.read() + + selectable_boxes = { + "AXIAD9361Box": {"link": "https://wiki.analog.com/resources/fpga/docs/axi_ad9361"}, + "AXIADRV9002Box": {"link": "https://wiki.analog.com/resources/eval/user-guides/adrv9002/axi_adrv9002"}, + "TxDMAEngineBox": {"link": "https://wiki.analog.com/resources/fpga/docs/axi_dmac"}, + "TxUPACKBox": {"link": "https://wiki.analog.com/resources/fpga/docs/util_upack"}, + "TxFIFOBox": {"link": "https://wiki.analog.com/resources/fpga/docs/util_rfifo"}, + "RxDMAEngineBox": {"link": "https://wiki.analog.com/resources/fpga/docs/axi_dmac"}, + "CPACKBox": {"link": "https://wiki.analog.com/resources/fpga/docs/util_cpack"}, + "RxFIFOBox": {"link": "https://wiki.analog.com/resources/fpga/docs/util_rfifo"}, + "RxJESDTPL": {"link": "https://wiki.analog.com/resources/fpga/peripherals/jesd204/jesd204_tpl_adc"}, + "TxJESDTPL": {"link": "https://wiki.analog.com/resources/fpga/peripherals/jesd204/jesd204_tpl_dac"}, + "RxJESDLink": {"link": "https://wiki.analog.com/resources/fpga/peripherals/jesd204/axi_jesd204_rx"}, + "TxJESDLink": {"link": "https://wiki.analog.com/resources/fpga/peripherals/jesd204/axi_jesd204_tx"}, + "RxJESDPHY": {"link": "https://wiki.analog.com/resources/fpga/docs/axi_adxcvr"}, + "TxJESDPHY": {"link": "https://wiki.analog.com/resources/fpga/docs/axi_adxcvr"}, + } + + + # "TxCustomIPBox", + # CarrierBox + # AXIInterconnectBox + # ZynqBox + # DDRxBox + # InterruptsBox + # UARTBox + # EthernetBox + # RxCustomIPBox + # CustomIPOutline + + + # Parse each g tag + output = "" + for i, sec in enumerate(svg.split("") + 4 + gtag = o[:loc] + post_gtag = o[loc:] + # print(gtag) + loc = gtag.find("id=") + 4 + id = gtag[loc : gtag.find('"', loc)] + if id == "CarrierBox": + css_out += ( + f"\n#{id} > rect {{\n" + + " fill: var(--md-default-fg-color--light);\n" + + "}\n" + ) + + + if not id or id not in selectable_boxes: + output += o + continue + # Add link wrapper + output += f'{gtag}{post_gtag}' + # output += o + # print(sec) + # Add css to change fill color + css_out += f"#{id} > rect {{\n" + " stroke: white;\n" + "}\n" + css_out += f"\n#{id}:hover > rect {{\n" + " fill: rgb(0, 174, 255);\n" + "}\n" + + + + with open(f"assets/{ref}_custom.svg", "w") as f: + f.write(output) + + css_out += "\n#FPGACarrierText {\n" + " fill: var(--rd-title-color);\n" + "}\n" + css_out += "\n#CarrierBox > rect {\n" + " fill: none;\n stroke: black\n" + "}\n" + css_out += ( + "\n#CustomIPOutline > rect {\n" + " stroke: var(--rd-title-color);\n" + "}\n" + ) + css_out += ("\n#CustomIPIntegrationText {\n" + " fill: var(--rd-title-color);\n" + "}\n") + + with open("stylesheets/rd_style.css", "w") as f: + f.write(css_out) diff --git a/CI/gen_doc/docs/gen_sysobj_doc.m b/CI/gen_doc/docs/gen_sysobj_doc.m new file mode 100644 index 0000000..480832e --- /dev/null +++ b/CI/gen_doc/docs/gen_sysobj_doc.m @@ -0,0 +1,73 @@ +[filepath,name,ext] = fileparts(mfilename('fullpath')); +cd(filepath); +cd('..'); +files = dir(filepath); + +mfiledir = fullfile('adi'); +docdir = fullfile('doc'); + +rootClasses = {... + {'AD7380',{'Rx'}}... + , {'AD7768', {'Rx'}}... + , {'AD7768_1', {'Rx'}}... + , {'AD4030', {'Rx'}}... + , {'AD4630_16', {'Rx'}}... + , {'AD4630_24', {'Rx'}}... + %{'QuadMxFE',{'Rx','Tx'}}... + }; + +all_devs = []; +for ii = 1:numel(rootClasses) + for jj = 1:numel(rootClasses{ii}{2}) + part = rootClasses{ii}{1}; + tmp = rootClasses{ii}{2}; + trx_file = tmp{jj}; + all_props = []; + dotmfilename = strcat(mfiledir, '.', part, '.', trx_file); + props = unique(properties(dotmfilename)); + for prop = 1:length(props) + + if props{prop} == "enIO" + continue; + end + pdoc = help(strcat(dotmfilename,'.',props{prop})); + + pdocs = strsplit(pdoc,'\n'); + prop_title = pdocs{1}; + prop_description = strip(replace(strjoin(pdocs(2:end),'\n'),'\n','')); + prop_description = int32(prop_description); + prop_description(prop_description==10) = []; + prop_description(prop_description==13) = []; + prop_description = char(prop_description); + prop_description = replace(prop_description,' ',' '); + prop_description = replace(prop_description,' ',' '); + + s = struct('prop_name',props{prop},... + 'prop_title',prop_title,... + 'prop_description',prop_description); + all_props = [all_props,s]; + end + top_doc = help(dotmfilename); + top_doc = strsplit(top_doc,'\n'); + top_doc = replace(top_doc,'\n','
'); + top_doc = strjoin(top_doc(2:end),'
'); + +% top_doc = strip(replace(top_doc,'\n','')); +% top_doc = int32(top_doc); +% top_doc(top_doc==10) = []; +% top_doc(top_doc==13) = []; +% top_doc = char(top_doc); +% top_doc = replace(top_doc,' ',' '); +% top_doc = replace(top_doc,' ',' '); + + + oname = struct('name',dotmfilename, 'dec',top_doc, 'props',all_props); + all_devs = [all_devs, oname]; + end +end +%% +jsonText = jsonencode(all_devs,'PrettyPrint',true); +fid = fopen('docs/sysobjs.json', 'w'); +fprintf(fid, '%s', jsonText); +fclose(fid); + diff --git a/CI/gen_doc/docs/gen_sysobj_pages.py b/CI/gen_doc/docs/gen_sysobj_pages.py new file mode 100644 index 0000000..0a6f96b --- /dev/null +++ b/CI/gen_doc/docs/gen_sysobj_pages.py @@ -0,0 +1,89 @@ +from jinja2 import Environment, FileSystemLoader +import os +import json + + +def gen_sys_obj_pages(matlab): + + template_filename = "sysobj.html" + + # Data for template + f = open("sysobjs.json") + objs = json.load(f) + f.close() + + # Import template + loc = os.path.dirname(__file__) + loc = os.path.join(loc, "_templates") + file_loader = FileSystemLoader(loc) + env = Environment(loader=file_loader) + + loc = os.path.join(template_filename) + template = env.get_template(loc) + + devices = {} + + def cleanup(obj): + + # obj["dec"] = obj["dec"].replace("192.168.2.1", "ip:192.168.2.1") + d = obj["dec"] + ol = [] + for d in obj["dec"].split("
"): + + if "See also" in d: + continue + if "Documentation for" in d: + continue + if "doc adi." in d: + continue + + ol.append(d) + + obj["dec"] = "
".join(ol) + if ".Rx" in obj["name"]: + obj["type"] = "Rx" + else: + obj["type"] = "Tx" + + return obj + + for obj in objs: + # Render template + obj = cleanup(obj) + output = template.render(obj=obj, disable_nav=matlab) + # Write output + output_filename = f"sysobjects/{obj['name']}.md" + loc = os.path.join(output_filename) + f = open(loc, "w") + f.write(output) + f.close() + devices[obj["name"]] = output_filename + + #if matlab: + if True: + # Generate index for objs + loc = os.path.join("allsysobjs.tmpl") + template = env.get_template(loc) + output = template.render(devices=devices, disable_nav=matlab) + + loc = os.path.join("objects.md") + with open(loc, "w") as f: + f.write(output) + + ############################################################################### + # HDL Refdesigns + ############################################################################### + from gen_hdl_refdesigns import update_hdl_refdesigns + + designs = update_hdl_refdesigns() + + # Update mkdocs.yml + loc = os.path.join("mkdocs.tmpl") + template = env.get_template(loc) + output = template.render(devices=devices, designs=designs, matlab=matlab) + + loc = os.path.join("..", "mkdocs.yml") + with open(loc, "w") as f: + f.write(output) + + return devices, designs diff --git a/CI/gen_doc/docs/hdlrefdesigns/adrv9002.md b/CI/gen_doc/docs/hdlrefdesigns/adrv9002.md new file mode 100644 index 0000000..1db2989 --- /dev/null +++ b/CI/gen_doc/docs/hdlrefdesigns/adrv9002.md @@ -0,0 +1,52 @@ + + +# adrv9002 Reference Design Integration + +This page outlines the HDL reference design integration for the *adrv9002* reference design for the Analog Devices +ADRV9002 component. The IP-Core Generation follow is available on the based on the following base HDL reference design for the following board and design variants: + +- [Base reference design documentation](https://wiki.analog.com/resources/eval/user-guides/adrv9001/reference_hdl) +- Supported FPGA carriers: + - ZCU102 +- Supported design variants: + - RX + - TX + - RX & TX + +## Reference Design + +
+ + ![Reference Design](../assets/rd_adrv9001_custom.svg) + +
HDL Reference Design with Custom IP from HDL-Coder. Click on sub-blocks for more documentation.
+
+The IP-Core generation flow will integrate IP generated from Simulink subsystem into an ADI authored reference design. Depending on the FPGA carrier and FMC card or SoM, this will support different IP locations based on the diagram above. + +## HDL Worflow Advisor Port Mappings + +When using the HDL Worflow Advisor, the following port mappings are used to connect the reference design to the HDL-Coder generated IP-Core: + +| Type | Target Platform Interface (MATLAB) | Reference Design Connection (Vivado) | Width | Reference Design Variant | +| ---- | ------------------------ | --------------------------- | ----- | ----------- | +| VALID-OUT | IP Data Valid OUT | util_adc_1_pack/fifo_wr_en | 1 | RX | +| VALID-IN | IP Valid Rx Data IN | axi_adrv9001/adc_1_valid_i0 | 1 | RX | +| DATA-OUT | IP Data 0 OUT | util_adc_1_pack/fifo_wr_data_0 | 16 | RX | +| DATA-OUT | IP Data 1 OUT | util_adc_1_pack/fifo_wr_data_1 | 16 | RX | +| DATA-OUT | IP Data 2 OUT | util_adc_1_pack/fifo_wr_data_2 | 16 | RX | +| DATA-OUT | IP Data 3 OUT | util_adc_1_pack/fifo_wr_data_3 | 16 | RX | +| DATA-IN | ADRV9002 ADC Data Q0 | axi_adrv9001/adc_1_data_i0 | 16 | RX | +| DATA-IN | ADRV9002 ADC Data I0 | axi_adrv9001/adc_1_data_i1 | 16 | RX | +| DATA-IN | ADRV9002 ADC Data Q0 | axi_adrv9001/adc_1_data_q0 | 16 | RX | +| DATA-IN | ADRV9002 ADC Data I0 | axi_adrv9001/adc_1_data_q1 | 16 | RX | +| VALID-IN | IP Valid Tx Data IN | util_dac_1_upack/fifo_rd_valid | 1 | TX | +| VALID-OUT | IP Load Tx Data OUT | util_dac_1_upack/fifo_rd_en | 1 | TX | +| DATA-OUT | ADRV9002 DAC Data Q0 | axi_adrv9001/dac_1_data_i0 | 16 | TX | +| DATA-OUT | ADRV9002 DAC Data I0 | axi_adrv9001/dac_1_data_i1 | 16 | TX | +| DATA-OUT | ADRV9002 DAC Data Q0 | axi_adrv9001/dac_1_data_q0 | 16 | TX | +| DATA-OUT | ADRV9002 DAC Data I0 | axi_adrv9001/dac_1_data_q1 | 16 | TX | +| DATA-IN | IP Data 0 IN | util_dac_1_upack/fifo_rd_data_0 | 16 | TX | +| DATA-IN | IP Data 1 IN | util_dac_1_upack/fifo_rd_data_1 | 16 | TX | +| DATA-IN | IP Data 2 IN | util_dac_1_upack/fifo_rd_data_2 | 16 | TX | +| DATA-IN | IP Data 3 IN | util_dac_1_upack/fifo_rd_data_3 | 16 | TX | + diff --git a/CI/gen_doc/docs/hdlrefdesigns/adrv9009.md b/CI/gen_doc/docs/hdlrefdesigns/adrv9009.md new file mode 100644 index 0000000..a71e8f0 --- /dev/null +++ b/CI/gen_doc/docs/hdlrefdesigns/adrv9009.md @@ -0,0 +1,52 @@ + + +# adrv9009 Reference Design Integration + +This page outlines the HDL reference design integration for the *adrv9009* reference design for the Analog Devices +ADRV9009 component. The IP-Core Generation follow is available on the based on the following base HDL reference design for the following board and design variants: + +- [Base reference design documentation](https://wiki.analog.com/resources/eval/user-guides/adrv9009/reference_hdl) +- Supported FPGA carriers: + - ZCU102 +- Supported design variants: + - RX + - TX + - RX & TX + +## Reference Design + +
+ + ![Reference Design](../assets/rd_jesd_custom.svg) + +
HDL Reference Design with Custom IP from HDL-Coder. Click on sub-blocks for more documentation.
+
+The IP-Core generation flow will integrate IP generated from Simulink subsystem into an ADI authored reference design. Depending on the FPGA carrier and FMC card or SoM, this will support different IP locations based on the diagram above. + +## HDL Worflow Advisor Port Mappings + +When using the HDL Worflow Advisor, the following port mappings are used to connect the reference design to the HDL-Coder generated IP-Core: + +| Type | Target Platform Interface (MATLAB) | Reference Design Connection (Vivado) | Width | Reference Design Variant | +| ---- | ------------------------ | --------------------------- | ----- | ----------- | +| VALID-OUT | IP Data Valid OUT | util_adrv9009_rx_cpack/fifo_wr_en | 1 | RX | +| VALID-IN | IP Valid Rx Data IN | rx_adrv9009_tpl_core/adc_valid_0 | 1 | RX | +| DATA-OUT | IP Data 0 OUT | util_adrv9009_rx_cpack/fifo_wr_data_0 | 16 | RX | +| DATA-OUT | IP Data 1 OUT | util_adrv9009_rx_cpack/fifo_wr_data_1 | 16 | RX | +| DATA-OUT | IP Data 2 OUT | util_adrv9009_rx_cpack/fifo_wr_data_2 | 16 | RX | +| DATA-OUT | IP Data 3 OUT | util_adrv9009_rx_cpack/fifo_wr_data_3 | 16 | RX | +| DATA-IN | ADRV9009 ADC Data Q0 | rx_adrv9009_tpl_core/adc_data_0 | 16 | RX | +| DATA-IN | ADRV9009 ADC Data I0 | rx_adrv9009_tpl_core/adc_data_1 | 16 | RX | +| DATA-IN | ADRV9009 ADC Data Q1 | rx_adrv9009_tpl_core/adc_data_2 | 16 | RX | +| DATA-IN | ADRV9009 ADC Data I1 | rx_adrv9009_tpl_core/adc_data_3 | 16 | RX | +| VALID-IN | IP Valid Tx Data IN | util_adrv9009_tx_upack/fifo_rd_valid | 1 | TX | +| VALID-OUT | IP Load Tx Data OUT | util_adrv9009_tx_upack/fifo_rd_en | 1 | TX | +| DATA-OUT | ADRV9009 DAC Data Q0 | tx_adrv9009_tpl_core/dac_data_0 | 16 | TX | +| DATA-OUT | ADRV9009 DAC Data I0 | tx_adrv9009_tpl_core/dac_data_1 | 16 | TX | +| DATA-OUT | ADRV9009 DAC Data Q1 | tx_adrv9009_tpl_core/dac_data_2 | 16 | TX | +| DATA-OUT | ADRV9009 DAC Data I1 | tx_adrv9009_tpl_core/dac_data_3 | 16 | TX | +| DATA-IN | IP Data 0 IN | util_adrv9009_tx_upack/fifo_rd_data_0 | 16 | TX | +| DATA-IN | IP Data 1 IN | util_adrv9009_tx_upack/fifo_rd_data_1 | 16 | TX | +| DATA-IN | IP Data 2 IN | util_adrv9009_tx_upack/fifo_rd_data_2 | 16 | TX | +| DATA-IN | IP Data 3 IN | util_adrv9009_tx_upack/fifo_rd_data_3 | 16 | TX | + diff --git a/CI/gen_doc/docs/hdlrefdesigns/adrv9361z7035.md b/CI/gen_doc/docs/hdlrefdesigns/adrv9361z7035.md new file mode 100644 index 0000000..45d0773 --- /dev/null +++ b/CI/gen_doc/docs/hdlrefdesigns/adrv9361z7035.md @@ -0,0 +1,56 @@ + + +# adrv9361z7035 Reference Design Integration + +This page outlines the HDL reference design integration for the *adrv9361z7035* reference design for the Analog Devices +AD9361 component. The IP-Core Generation follow is available on the based on the following base HDL reference design for the following board and design variants: + +- [Base reference design documentation](https://wiki.analog.com/resources/eval/user-guides/ad-fmcomms2-ebz/reference_hdl) +- Supported FPGA carriers: + - CCBOB_CMOS + - CCBOB_LVDS + - CCBOX_LVDS + - CCFMC_LVDS + - CCPACKRF_LVDS +- Supported design variants: + - RX + - TX + - RX & TX + +## Reference Design + +
+ + ![Reference Design](../assets/rd_ad9361_custom.svg) + +
HDL Reference Design with Custom IP from HDL-Coder. Click on sub-blocks for more documentation.
+
+The IP-Core generation flow will integrate IP generated from Simulink subsystem into an ADI authored reference design. Depending on the FPGA carrier and FMC card or SoM, this will support different IP locations based on the diagram above. + +## HDL Worflow Advisor Port Mappings + +When using the HDL Worflow Advisor, the following port mappings are used to connect the reference design to the HDL-Coder generated IP-Core: + +| Type | Target Platform Interface (MATLAB) | Reference Design Connection (Vivado) | Width | Reference Design Variant | +| ---- | ------------------------ | --------------------------- | ----- | ----------- | +| VALID-OUT | IP Data Valid OUT | util_ad9361_adc_pack/fifo_wr_en | 1 | RX | +| VALID-IN | IP Valid Rx Data IN | util_ad9361_adc_fifo/dout_valid_0 | 1 | RX | +| DATA-OUT | IP Data 0 OUT | util_ad9361_adc_pack/fifo_wr_data_0 | 16 | RX | +| DATA-OUT | IP Data 1 OUT | util_ad9361_adc_pack/fifo_wr_data_1 | 16 | RX | +| DATA-OUT | IP Data 2 OUT | util_ad9361_adc_pack/fifo_wr_data_2 | 16 | RX | +| DATA-OUT | IP Data 3 OUT | util_ad9361_adc_pack/fifo_wr_data_3 | 16 | RX | +| DATA-IN | AD9361 ADC Data Q0 | util_ad9361_adc_fifo/dout_data_0 | 16 | RX | +| DATA-IN | AD9361 ADC Data I0 | util_ad9361_adc_fifo/dout_data_1 | 16 | RX | +| DATA-IN | AD9361 ADC Data Q1 | util_ad9361_adc_fifo/dout_data_2 | 16 | RX | +| DATA-IN | AD9361 ADC Data I1 | util_ad9361_adc_fifo/dout_data_3 | 16 | RX | +| VALID-IN | IP Valid Tx Data IN | util_ad9361_dac_upack/fifo_rd_valid | 1 | TX | +| VALID-OUT | IP Load Tx Data OUT | axi_ad9361_dac_fifo/din_valid_in_0 | 1 | TX | +| DATA-OUT | AD9361 DAC Data Q0 | axi_ad9361_dac_fifo/din_data_0 | 16 | TX | +| DATA-OUT | AD9361 DAC Data I0 | axi_ad9361_dac_fifo/din_data_1 | 16 | TX | +| DATA-OUT | AD9361 DAC Data Q1 | axi_ad9361_dac_fifo/din_data_2 | 16 | TX | +| DATA-OUT | AD9361 DAC Data I1 | axi_ad9361_dac_fifo/din_data_3 | 16 | TX | +| DATA-IN | IP Data 0 IN | util_ad9361_dac_upack/fifo_rd_data_0 | 16 | TX | +| DATA-IN | IP Data 1 IN | util_ad9361_dac_upack/fifo_rd_data_1 | 16 | TX | +| DATA-IN | IP Data 2 IN | util_ad9361_dac_upack/fifo_rd_data_2 | 16 | TX | +| DATA-IN | IP Data 3 IN | util_ad9361_dac_upack/fifo_rd_data_3 | 16 | TX | + diff --git a/CI/gen_doc/docs/hdlrefdesigns/adrv9364z7020.md b/CI/gen_doc/docs/hdlrefdesigns/adrv9364z7020.md new file mode 100644 index 0000000..7faf6b7 --- /dev/null +++ b/CI/gen_doc/docs/hdlrefdesigns/adrv9364z7020.md @@ -0,0 +1,54 @@ + + +# adrv9364z7020 Reference Design Integration + +This page outlines the HDL reference design integration for the *adrv9364z7020* reference design for the Analog Devices +AD9364 component. The IP-Core Generation follow is available on the based on the following base HDL reference design for the following board and design variants: + +- [Base reference design documentation](https://wiki.analog.com/resources/eval/user-guides/ad-fmcomms2-ebz/reference_hdl) +- Supported FPGA carriers: + - CCBOB_CMOS + - CCBOB_LVDS + - CCBOX_LVDS +- Supported design variants: + - RX + - TX + - RX & TX + +## Reference Design + +
+ + ![Reference Design](../assets/rd_ad9361_custom.svg) + +
HDL Reference Design with Custom IP from HDL-Coder. Click on sub-blocks for more documentation.
+
+The IP-Core generation flow will integrate IP generated from Simulink subsystem into an ADI authored reference design. Depending on the FPGA carrier and FMC card or SoM, this will support different IP locations based on the diagram above. + +## HDL Worflow Advisor Port Mappings + +When using the HDL Worflow Advisor, the following port mappings are used to connect the reference design to the HDL-Coder generated IP-Core: + +| Type | Target Platform Interface (MATLAB) | Reference Design Connection (Vivado) | Width | Reference Design Variant | +| ---- | ------------------------ | --------------------------- | ----- | ----------- | +| VALID-OUT | IP Data Valid OUT | util_ad9361_adc_pack/fifo_wr_en | 1 | RX | +| VALID-IN | IP Valid Rx Data IN | util_ad9361_adc_fifo/dout_valid_0 | 1 | RX | +| DATA-OUT | IP Data 0 OUT | util_ad9361_adc_pack/fifo_wr_data_0 | 16 | RX | +| DATA-OUT | IP Data 1 OUT | util_ad9361_adc_pack/fifo_wr_data_1 | 16 | RX | +| DATA-OUT | IP Data 2 OUT | util_ad9361_adc_pack/fifo_wr_data_2 | 16 | RX | +| DATA-OUT | IP Data 3 OUT | util_ad9361_adc_pack/fifo_wr_data_3 | 16 | RX | +| DATA-IN | AD9364 ADC Data Q0 | util_ad9361_adc_fifo/dout_data_0 | 16 | RX | +| DATA-IN | AD9364 ADC Data I0 | util_ad9361_adc_fifo/dout_data_1 | 16 | RX | +| DATA-IN | AD9364 ADC Data Q1 | util_ad9361_adc_fifo/dout_data_2 | 16 | RX | +| DATA-IN | AD9364 ADC Data I1 | util_ad9361_adc_fifo/dout_data_3 | 16 | RX | +| VALID-IN | IP Valid Tx Data IN | util_ad9361_dac_upack/fifo_rd_valid | 1 | TX | +| VALID-OUT | IP Load Tx Data OUT | axi_ad9361_dac_fifo/din_valid_in_0 | 1 | TX | +| DATA-OUT | AD9364 DAC Data Q0 | axi_ad9361_dac_fifo/din_data_0 | 16 | TX | +| DATA-OUT | AD9364 DAC Data I0 | axi_ad9361_dac_fifo/din_data_1 | 16 | TX | +| DATA-OUT | AD9364 DAC Data Q1 | axi_ad9361_dac_fifo/din_data_2 | 16 | TX | +| DATA-OUT | AD9364 DAC Data I1 | axi_ad9361_dac_fifo/din_data_3 | 16 | TX | +| DATA-IN | IP Data 0 IN | util_ad9361_dac_upack/fifo_rd_data_0 | 16 | TX | +| DATA-IN | IP Data 1 IN | util_ad9361_dac_upack/fifo_rd_data_1 | 16 | TX | +| DATA-IN | IP Data 2 IN | util_ad9361_dac_upack/fifo_rd_data_2 | 16 | TX | +| DATA-IN | IP Data 3 IN | util_ad9361_dac_upack/fifo_rd_data_3 | 16 | TX | + diff --git a/CI/gen_doc/docs/hdlrefdesigns/adrv9371.md b/CI/gen_doc/docs/hdlrefdesigns/adrv9371.md new file mode 100644 index 0000000..dd6fe5e --- /dev/null +++ b/CI/gen_doc/docs/hdlrefdesigns/adrv9371.md @@ -0,0 +1,52 @@ + + +# adrv9371 Reference Design Integration + +This page outlines the HDL reference design integration for the *adrv9371* reference design for the Analog Devices +AD9371 component. The IP-Core Generation follow is available on the based on the following base HDL reference design for the following board and design variants: + +- [Base reference design documentation](https://wiki.analog.com/resources/eval/user-guides/mykonos/reference_hdl) +- Supported FPGA carriers: + - ZC706 + - ZCU102 +- Supported design variants: + - RX + - TX + +## Reference Design + +
+ + ![Reference Design](../assets/rd_jesd_custom.svg) + +
HDL Reference Design with Custom IP from HDL-Coder. Click on sub-blocks for more documentation.
+
+The IP-Core generation flow will integrate IP generated from Simulink subsystem into an ADI authored reference design. Depending on the FPGA carrier and FMC card or SoM, this will support different IP locations based on the diagram above. + +## HDL Worflow Advisor Port Mappings + +When using the HDL Worflow Advisor, the following port mappings are used to connect the reference design to the HDL-Coder generated IP-Core: + +| Type | Target Platform Interface (MATLAB) | Reference Design Connection (Vivado) | Width | Reference Design Variant | +| ---- | ------------------------ | --------------------------- | ----- | ----------- | +| VALID-OUT | IP Data Valid OUT | util_ad9371_rx_cpack/fifo_wr_en | 1 | RX | +| VALID-IN | IP Valid Rx Data IN | rx_ad9371_tpl_core/adc_valid_0 | 1 | RX | +| DATA-OUT | IP Data 0 OUT | util_ad9361_adc_pack/fifo_wr_data_0 | 16 | RX | +| DATA-OUT | IP Data 1 OUT | util_ad9361_adc_pack/fifo_wr_data_1 | 16 | RX | +| DATA-OUT | IP Data 2 OUT | util_ad9361_adc_pack/fifo_wr_data_2 | 16 | RX | +| DATA-OUT | IP Data 3 OUT | util_ad9361_adc_pack/fifo_wr_data_3 | 16 | RX | +| DATA-IN | AD9371 ADC Data Q0 | rx_ad9371_tpl_core/adc_data_0 | 16 | RX | +| DATA-IN | AD9371 ADC Data I0 | rx_ad9371_tpl_core/adc_data_1 | 16 | RX | +| DATA-IN | AD9371 ADC Data Q1 | rx_ad9371_tpl_core/adc_data_2 | 16 | RX | +| DATA-IN | AD9371 ADC Data I1 | rx_ad9371_tpl_core/adc_data_3 | 16 | RX | +| VALID-IN | IP Valid Tx Data IN | util_ad9371_tx_upack/fifo_rd_valid | 1 | TX | +| VALID-OUT | IP Load Tx Data OUT | util_ad9371_tx_upack/fifo_rd_en | 1 | TX | +| DATA-OUT | AD9371 DAC Data Q0 | tx_ad9371_tpl_core/dac_data_0 | 32 | TX | +| DATA-OUT | AD9371 DAC Data I0 | tx_ad9371_tpl_core/dac_data_1 | 32 | TX | +| DATA-OUT | AD9371 DAC Data Q1 | tx_ad9371_tpl_core/dac_data_2 | 32 | TX | +| DATA-OUT | AD9371 DAC Data I1 | tx_ad9371_tpl_core/dac_data_3 | 32 | TX | +| DATA-IN | IP Data 0 IN | util_ad9371_tx_upack/fifo_rd_data_0 | 32 | TX | +| DATA-IN | IP Data 1 IN | util_ad9371_tx_upack/fifo_rd_data_1 | 32 | TX | +| DATA-IN | IP Data 2 IN | util_ad9371_tx_upack/fifo_rd_data_2 | 32 | TX | +| DATA-IN | IP Data 3 IN | util_ad9371_tx_upack/fifo_rd_data_3 | 32 | TX | + diff --git a/CI/gen_doc/docs/hdlrefdesigns/daq2.md b/CI/gen_doc/docs/hdlrefdesigns/daq2.md new file mode 100644 index 0000000..eeb0075 --- /dev/null +++ b/CI/gen_doc/docs/hdlrefdesigns/daq2.md @@ -0,0 +1,54 @@ + + + +# daq2 Reference Design Integration + +This page outlines the HDL reference design integration for the *daq2* reference design for the Analog Devices +AD9680 and AD9144 component. The IP-Core Generation follow is available on the based on the following base HDL reference design for the following board and design variants: + +- [Base reference design documentation](https://wiki.analog.com/resources/eval/user-guides/daq2/reference_hdl) +- Supported FPGA carriers: + - ZC706 + - ZCU102 +- Supported design variants: + - RX + - TX + - RX & TX + +## Reference Design + +
+ + ![Reference Design](../assets/rd_jesd_custom.svg) + +
HDL Reference Design with Custom IP from HDL-Coder. Click on sub-blocks for more documentation.
+
+The IP-Core generation flow will integrate IP generated from Simulink subsystem into an ADI authored reference design. Depending on the FPGA carrier and FMC card or SoM, this will support different IP locations based on the diagram above. + +## HDL Worflow Advisor Port Mappings + +When using the HDL Worflow Advisor, the following port mappings are used to connect the reference design to the HDL-Coder generated IP-Core: + +| Type | Target Platform Interface (MATLAB) | Reference Design Connection (Vivado) | Width | Reference Design Variant | +| ---- | ------------------------ | --------------------------- | ----- | ----------- | +| VALID-OUT | IP Data Valid OUT | util_ad9680_cpack/fifo_wr_en | 1 | RX | +| VALID-IN | IP Valid Rx Data IN | rx_ad9680_tpl_core/adc_valid_0 | 1 | RX | +| DATA-OUT | IP Data 0 OUT | util_ad9680_cpack/fifo_wr_data_0 | 16 | RX | +| DATA-OUT | IP Data 1 OUT | util_ad9680_cpack/fifo_wr_data_1 | 16 | RX | +| DATA-OUT | IP Data 2 OUT | util_ad9680_cpack/fifo_wr_data_2 | 16 | RX | +| DATA-OUT | IP Data 3 OUT | util_ad9680_cpack/fifo_wr_data_3 | 16 | RX | +| DATA-IN | AD9680 and AD9144 ADC Data Q0 | rx_ad9680_tpl_core/adc_data_0 | 16 | RX | +| DATA-IN | AD9680 and AD9144 ADC Data I0 | rx_ad9680_tpl_core/adc_data_1 | 16 | RX | +| DATA-IN | AD9680 and AD9144 ADC Data Q1 | rx_ad9680_tpl_core/adc_data_2 | 16 | RX | +| DATA-IN | AD9680 and AD9144 ADC Data I1 | rx_ad9680_tpl_core/adc_data_3 | 16 | RX | +| VALID-IN | IP Valid Tx Data IN | util_ad9144_upack/fifo_rd_valid | 1 | TX | +| VALID-OUT | IP Load Tx Data OUT | util_ad9144_upack/fifo_rd_en | 1 | TX | +| DATA-OUT | AD9680 and AD9144 DAC Data Q0 | ad9144_tpl_core/dac_data_0 | 16 | TX | +| DATA-OUT | AD9680 and AD9144 DAC Data I0 | ad9144_tpl_core/dac_data_1 | 16 | TX | +| DATA-OUT | AD9680 and AD9144 DAC Data Q1 | ad9144_tpl_core/dac_data_2 | 16 | TX | +| DATA-OUT | AD9680 and AD9144 DAC Data I1 | ad9144_tpl_core/dac_data_3 | 16 | TX | +| DATA-IN | IP Data 0 IN | util_ad9144_upack/fifo_rd_data_0 | 16 | TX | +| DATA-IN | IP Data 1 IN | util_ad9144_upack/fifo_rd_data_1 | 16 | TX | +| DATA-IN | IP Data 2 IN | util_ad9144_upack/fifo_rd_data_2 | 16 | TX | +| DATA-IN | IP Data 3 IN | util_ad9144_upack/fifo_rd_data_3 | 16 | TX | + diff --git a/CI/gen_doc/docs/hdlrefdesigns/fmcomms2.md b/CI/gen_doc/docs/hdlrefdesigns/fmcomms2.md new file mode 100644 index 0000000..fc2772f --- /dev/null +++ b/CI/gen_doc/docs/hdlrefdesigns/fmcomms2.md @@ -0,0 +1,54 @@ + + +# fmcomms2 Reference Design Integration + +This page outlines the HDL reference design integration for the *fmcomms2* reference design for the Analog Devices +AD9361 component. The IP-Core Generation follow is available on the based on the following base HDL reference design for the following board and design variants: + +- [Base reference design documentation](https://wiki.analog.com/resources/eval/user-guides/ad-fmcomms2-ebz/reference_hdl) +- Supported FPGA carriers: + - ZED + - ZC706 + - ZC702 +- Supported design variants: + - RX + - TX + - RX & TX + +## Reference Design + +
+ + ![Reference Design](../assets/rd_ad9361_custom.svg) + +
HDL Reference Design with Custom IP from HDL-Coder. Click on sub-blocks for more documentation.
+
+The IP-Core generation flow will integrate IP generated from Simulink subsystem into an ADI authored reference design. Depending on the FPGA carrier and FMC card or SoM, this will support different IP locations based on the diagram above. + +## HDL Worflow Advisor Port Mappings + +When using the HDL Worflow Advisor, the following port mappings are used to connect the reference design to the HDL-Coder generated IP-Core: + +| Type | Target Platform Interface (MATLAB) | Reference Design Connection (Vivado) | Width | Reference Design Variant | +| ---- | ------------------------ | --------------------------- | ----- | ----------- | +| VALID-OUT | IP Data Valid OUT | util_ad9361_adc_pack/fifo_wr_en | 1 | RX | +| VALID-IN | IP Valid Rx Data IN | util_ad9361_adc_fifo/dout_valid_0 | 1 | RX | +| DATA-OUT | IP Data 0 OUT | util_ad9361_adc_pack/fifo_wr_data_0 | 16 | RX | +| DATA-OUT | IP Data 1 OUT | util_ad9361_adc_pack/fifo_wr_data_1 | 16 | RX | +| DATA-OUT | IP Data 2 OUT | util_ad9361_adc_pack/fifo_wr_data_2 | 16 | RX | +| DATA-OUT | IP Data 3 OUT | util_ad9361_adc_pack/fifo_wr_data_3 | 16 | RX | +| DATA-IN | AD9361 ADC Data Q0 | util_ad9361_adc_fifo/dout_data_0 | 16 | RX | +| DATA-IN | AD9361 ADC Data I0 | util_ad9361_adc_fifo/dout_data_1 | 16 | RX | +| DATA-IN | AD9361 ADC Data Q1 | util_ad9361_adc_fifo/dout_data_2 | 16 | RX | +| DATA-IN | AD9361 ADC Data I1 | util_ad9361_adc_fifo/dout_data_3 | 16 | RX | +| VALID-IN | IP Valid Tx Data IN | util_ad9361_dac_upack/fifo_rd_valid | 1 | TX | +| VALID-OUT | IP Load Tx Data OUT | axi_ad9361_dac_fifo/din_valid_in_0 | 1 | TX | +| DATA-OUT | AD9361 DAC Data Q0 | axi_ad9361_dac_fifo/din_data_0 | 16 | TX | +| DATA-OUT | AD9361 DAC Data I0 | axi_ad9361_dac_fifo/din_data_1 | 16 | TX | +| DATA-OUT | AD9361 DAC Data Q1 | axi_ad9361_dac_fifo/din_data_2 | 16 | TX | +| DATA-OUT | AD9361 DAC Data I1 | axi_ad9361_dac_fifo/din_data_3 | 16 | TX | +| DATA-IN | IP Data 0 IN | util_ad9361_dac_upack/fifo_rd_data_0 | 16 | TX | +| DATA-IN | IP Data 1 IN | util_ad9361_dac_upack/fifo_rd_data_1 | 16 | TX | +| DATA-IN | IP Data 2 IN | util_ad9361_dac_upack/fifo_rd_data_2 | 16 | TX | +| DATA-IN | IP Data 3 IN | util_ad9361_dac_upack/fifo_rd_data_3 | 16 | TX | + diff --git a/CI/gen_doc/docs/hdlrefdesigns/pluto.md b/CI/gen_doc/docs/hdlrefdesigns/pluto.md new file mode 100644 index 0000000..f1b308a --- /dev/null +++ b/CI/gen_doc/docs/hdlrefdesigns/pluto.md @@ -0,0 +1,42 @@ + + +# pluto Reference Design Integration + +This page outlines the HDL reference design integration for the *pluto* reference design for the Analog Devices +AD9361 component. The IP-Core Generation follow is available on the based on the following base HDL reference design for the following board and design variants: + +- [Base reference design documentation](https://wiki.analog.com/resources/eval/user-guides/ad-fmcomms2-ebz/reference_hdl) +- Supported FPGA carriers: +- Supported design variants: + - RX + - TX + +## Reference Design + +
+ + ![Reference Design](../assets/rd_ad9361_custom.svg) + +
HDL Reference Design with Custom IP from HDL-Coder. Click on sub-blocks for more documentation.
+
+The IP-Core generation flow will integrate IP generated from Simulink subsystem into an ADI authored reference design. Depending on the FPGA carrier and FMC card or SoM, this will support different IP locations based on the diagram above. + +## HDL Worflow Advisor Port Mappings + +When using the HDL Worflow Advisor, the following port mappings are used to connect the reference design to the HDL-Coder generated IP-Core: + +| Type | Target Platform Interface (MATLAB) | Reference Design Connection (Vivado) | Width | Reference Design Variant | +| ---- | ------------------------ | --------------------------- | ----- | ----------- | +| VALID-OUT | IP Data Valid OUT | cpack/fifo_wr_en | 1 | RX | +| VALID-IN | IP Valid Rx Data IN | axi_ad9361/adc_valid_i0 | 1 | RX | +| DATA-OUT | IP Data 0 OUT | cpack/fifo_wr_data_0 | 16 | RX | +| DATA-OUT | IP Data 1 OUT | cpack/fifo_wr_data_1 | 16 | RX | +| DATA-IN | AD9361 ADC Data Q0 | axi_ad9361/adc_data_i0 | 16 | RX | +| DATA-IN | AD9361 ADC Data Q0 | axi_ad9361/adc_data_q0 | 16 | RX | +| VALID-IN | IP Valid Tx Data IN | tx_upack/fifo_rd_valid | 1 | TX | +| VALID-OUT | IP Load Tx Data OUT | logic_or/Op1 | 1 | TX | +| DATA-OUT | AD9361 DAC Data Q0 | axi_ad9361/dac_data_i0 | 16 | TX | +| DATA-OUT | AD9361 DAC Data Q0 | axi_ad9361/dac_data_q0 | 16 | TX | +| DATA-IN | IP Data 0 IN | util_ad9361_dac_upack/fifo_rd_data_0 | 16 | TX | +| DATA-IN | IP Data 1 IN | util_ad9361_dac_upack/fifo_rd_data_1 | 16 | TX | + diff --git a/CI/gen_doc/docs/helptoc.xml b/CI/gen_doc/docs/helptoc.xml new file mode 100644 index 0000000..aa53e2d --- /dev/null +++ b/CI/gen_doc/docs/helptoc.xml @@ -0,0 +1,28 @@ + + + Analog Devices, Inc High-Speed Converter Toolbox + Install + Support + Examples + Models + Streaming + Index + Targeting + Behavioral Models + AD9081: MxFE + ADC + DAC + DDC + DUC + PFILT + + + Hardware Interface APIs + adi.AD9081.Rx + adi.AD9081.Tx + adi.AD9467.Rx + adi.DAQ2.Rx + adi.DAQ2.Tx + + + \ No newline at end of file diff --git a/CI/gen_doc/docs/js/sys_objects.js b/CI/gen_doc/docs/js/sys_objects.js new file mode 100644 index 0000000..44bcd99 --- /dev/null +++ b/CI/gen_doc/docs/js/sys_objects.js @@ -0,0 +1,43 @@ +function collapse(id) { + console.log(id); + var el = document.getElementsByClassName('collapsible-property-' + id); + el[0].classList.toggle("active"); + var elb = el[0]; + + el = document.getElementsByClassName('content-'+id); + // console.log(el); + if (el.length > 0) { + el0 = el[0]; + console.log(el0.style); + console.log("Updating style") + // console.log(el0.style.display) + el0.style.display = (el0.style.display == 'none' ? 'block' : 'none'); + + console.log(elb.style.borderBottomLeftRadius) + elb.style.borderBottomLeftRadius = (el0.style.display == 'none' ? '5px' : '0px'); + // elb.style.borderBottomLeftRadius = (el0.style.display == 'none' ? '0px' : '25px'); + console.log(elb.style.borderBottomLeftRadius) + + el = document.getElementsByClassName('plus-'+id); + el[0].innerHTML = (el0.style.display == 'none' ? '+' : '-'); + + } +} + + +// var coll = document.getElementsByClassName("collapsible-property"); +// var i; + +// for (i = 0; i < coll.length; i++) { +// coll[i].addEventListener("click", function() { +// console.log("CALLED"); +// this.classList.toggle("active"); +// var content = this.nextElementSibling; +// console.log(content); +// if (content.style.display === "block") { +// content.style.display = "none"; +// } else { +// content.style.display = "block"; +// } +// }); +// } \ No newline at end of file diff --git a/CI/gen_doc/docs/models/ad9081/adc.tex.md b/CI/gen_doc/docs/models/ad9081/adc.tex.md new file mode 100644 index 0000000..c67a734 --- /dev/null +++ b/CI/gen_doc/docs/models/ad9081/adc.tex.md @@ -0,0 +1,80 @@ +# AD9081 ADC and ADC Mux + + +The pipelined ADC models are simplified behavioral implementations that are based on the currently estimated specifications of the data converters. They are designed to be similar to the noise spectral density (NSD) of the converters. Note that since physical hardware does not exist these are estimated values and will likely change. There will be other distortions introduce by physical hardware as well, relating to front-end matches, internal chip structures, baluns, and gains stages among others. The ADC model should be considered similar but not exact. + + +# Top-Level Control + + +There are two control properties related to ADC control: **SampleRate** and **Crossbar4x4Mux0**. + + + + +**SampleRate** is the data rate of the converters themselves. Therefore, the output datarate of the model will be this SampleRate divided by the different decimations used. + + + +```python +help adi.sim.AD9081.Rx.SampleRate +``` + + +``` + SampleRate Sample Rate of ADCs + Scalar in Hz. Currently this is fixed since NSD will change + with this number, which would make the model invalid +``` + + + +**Crossbar4x4Mux0** is a full crossbar mux connecting the ADCs to the rest of the system. + + + +```python +help adi.sim.AD9081.Rx.Crossbar4x4Mux0 +``` + + +``` + Crossbar4x4Mux0 Crossbar 4x4 Mux0 + Array of input and output mapping. Index is the output and the + value is the selected input +``` + +# Example Configuration + + +Here is a basic example were we want to map ADC0, ADC1, and ADC2 out only. + + + +```python +rx = adi.sim.AD9081.Rx; +rx.SampleRate = 4e9; +rx.Crossbar4x4Mux0 = [1,1,3,4]; +% Pass noise through model at 10% and 1% fullscale +noiseVolts1 = 1.4/2*0.1*randn(1000,1); +noiseVolts2 = 1.4/2*0.01*randn(1000,1); +[o1,o2,~,~,o3,o4] = rx(noiseVolts1,noiseVolts2,noiseVolts1,noiseVolts1); +outs = [o1,o2,o3,o4]; +fprintf('Mapped values identical %d\n',isequal(outs(:,1),outs(:,2))) +``` + + +``` +Mapped values identical 1 +``` + + +```python +fprintf('Mapped values identical %d\n',isequal(outs(:,3),outs(:,4))) +``` + + +``` +Mapped values identical 0 +``` + diff --git a/CI/gen_doc/docs/models/ad9081/dac.tex.md b/CI/gen_doc/docs/models/ad9081/dac.tex.md new file mode 100644 index 0000000..479c13d --- /dev/null +++ b/CI/gen_doc/docs/models/ad9081/dac.tex.md @@ -0,0 +1,32 @@ +# AD9081 DAC + + +The DAC models are simplified behavioral implementations that are based on the currently estimated specifications of the data converters. They are designed to match the noise spectral density (NSD). Note that since physical hardware does not exist these are estimated values and will likely change by a few dB. + + +# Top-Level Control + + +There are one control properties related to the DACs: **SampleRate**. + + + + +**SampleRate** is the data rate of the converters themselves. Therefore, the input datarate of the model will be this **SampleRate** divided by the different interpolations used. + + + +```python +help adi.sim.AD9081.Tx.SampleRate +``` + + +``` + SampleRate Sample Rate of DACs + Scalar in Hz + InverseSincGainAdjustDB Inverse Gain Adjust DB + Add gain to the output signal filter. Gain is in dB and can + only be >=0 but <=8.7040. This will be internally quantized + based on the 8-bit allowed values with steps of 0.034dB. +``` + diff --git a/CI/gen_doc/docs/models/ad9081/ddc2.tex.md b/CI/gen_doc/docs/models/ad9081/ddc2.tex.md new file mode 100644 index 0000000..7bfc204 --- /dev/null +++ b/CI/gen_doc/docs/models/ad9081/ddc2.tex.md @@ -0,0 +1,158 @@ +# AD9081 Digital Down Converters + + +The AD9081 has two sets of digital down converters (DDC), the coarse (CDDC) and fine (FDDC), both following the ADC and PFILTs. These are used to both decimate and move signals using the NCOs. They also can be used to phase shift and apply gain to the input signal. + + + + +The CDDCs and FDDC are almost identical except for their available decimations, allowable rates, and count. There are two CDDCs per ADC pair and four FDDCs per ADC pair. In the data pipeline, data from the ADCs will be passed through the CDDCs, or bypass the CDDCs, then routed through a mux into the FDDCs, which can also be bypassed. + + +# Top-Level Control + + +The CDDC and FDDC decimations are controlled by **MainDataPathDecimation** and **ChannelizerPathDecimation** respectively. + + + +```python +help adi.sim.AD9081.Rx.MainDataPathDecimation +``` + + +``` + MainDataPathDecimation Main Data Path Decimation + Specify the decimation in the main data path which can be + [1,2,3,4,6] +``` + + +```python +help adi.sim.AD9081.Rx.ChannelizerPathDecimation +``` + + +``` + ChannelizerPathDecimation Channelizer Path Decimation + Specify the decimation in the channelizer path which can be + [1,2,3,4,6,8,12,16,24] +``` + +## Muxing + + +The CDDC pairs share a common full crossbar to the four downstream FDDCs connected to them. This is represented by a single crossbar that limits routes to the halves of AD9081. This crossbar or mux is controlled by the **Crossbar4x8Mux2** and will constrain all the mappings. + + + +```python +help adi.sim.AD9081.Rx.Crossbar4x8Mux2 +``` + + +``` + Crossbar4x8Mux2 Crossbar 4x8 Mux2 + Array of input and output mapping. Index is the output and the + value is the selected input (values should not exceed 4) +``` + +## NCO Mixer Enable and Modes + + +If the NCOs need to be used they must be individually enabled through the **CDDCNCOEnable** and **FDDCNCOEnable** properties, which are both arrays of booleans. + + + +```python +help adi.sim.AD9081.Rx.CDDCNCOEnable +``` + + +``` + CDDCNCOEnable CDDC NCO Enable + 1x4 Array of booleans to enable NCOs in main data path +``` + + +```python +help adi.sim.AD9081.Rx.FDDCNCOEnable +``` + + +``` + FDDCNCOEnable FDDC NCO Enable + 1x4 Array of booleans to enable NCOs in channelizer path +``` + +## NCO Frequency and Phase + + +Once the NCOs are enabled the frequencies and phases of the NCOs can be controlled individually. This is done through the **CDDCNCOFrequencies, FDDCNCOFrequencies**, **CDDCNCOPhases**, and **FDDCNCOPhases**. The frequencies will be limited based on the rate going into the NCO at that stage. Note that both the frequency and phase values are internally quantized to 48-bits based on the effective range of the NCO based on the sample rate into a given stage. + + + +```python +help adi.sim.AD9081.Rx.CDDCNCOFrequencies +``` + + +``` + CDDCNCOFrequencies CDDC NCO Frequencies + 1x4 Array of frequencies of NCOs in main data path +``` + + +```python +help adi.sim.AD9081.Rx.FDDCNCOFrequencies +``` + + +``` + FDDCNCOFrequencies FDDC NCO Frequencies + 1x8 Array of frequencies of NCOs in channelizer path +``` + +# Example Configuration + + +The example below take a single input tone and shifts it into separate channels using the CDDC NCOs. + + + +```python +rx = adi.sim.AD9081.Rx; +% Enable 3 NCOs to shift single into different bands +rx.MainDataPathDecimation = 4; +rx.CDDCNCOEnable = [true,true,true,false]; +rx.CDDCNCOFrequencies = [5e7,-3e7,1e8,0]; +rx.Crossbar4x8Mux2 = [1,2,1,2,3,4,3,4]; +% Create sinewave input +sw = dsp.SineWave; +sw.Amplitude = 1.4*0.5; +sw.Frequency = 100e6; +sw.SampleRate = rx.SampleRate; +sw.SamplesPerFrame = 4e4; +data = sw(); +[o1,o2,~,~,o5,o6] = rx(data,data,data,data); +outputCodes = [o1,o2,o5,o6]; +% Plot spectrum +Nfft = length(outputCodes); +fullscale = 2^15; fs = rx.SampleRate/4; +win = kaiser(Nfft,100); +win = win/sum(win); +win = win*Nfft; +outputCodes = double(outputCodes).*win; +spec = fft(outputCodes) / Nfft; +spec_db = 20*log10(abs(spec)/fullscale+10^-20); +df = fs/Nfft; freqRangeRx = (-fs/2:df:fs/2-df).'; +plot(freqRangeRx,fftshift(spec_db)); +legend('CDDC0','CDDC1','CDDC2','CDDC3') +xlabel('Frequency (Hz)');ylabel('Magnitude (dBFS)'); +``` + + +![/tmp/HighSpeedConverterToolbox/CI/doc/ad9081/ddc2_images/figure_0.png +](ddc2_images/figure_0.png +) + diff --git a/CI/gen_doc/docs/models/ad9081/ddc2_images/figure_0.png b/CI/gen_doc/docs/models/ad9081/ddc2_images/figure_0.png new file mode 100644 index 0000000..6f02b37 Binary files /dev/null and b/CI/gen_doc/docs/models/ad9081/ddc2_images/figure_0.png differ diff --git a/CI/gen_doc/docs/models/ad9081/duc.tex.md b/CI/gen_doc/docs/models/ad9081/duc.tex.md new file mode 100644 index 0000000..5c1f0f7 --- /dev/null +++ b/CI/gen_doc/docs/models/ad9081/duc.tex.md @@ -0,0 +1,104 @@ +# AD9081 Digital Up Converters + + +The AD9081 has two sets of digital up converters (DUC), the coarse (CDUC) and fine (FDUC). These are used to both interpolate and move signals using the NCOs. They also can be used to phase shift and apply gain to the input signal. + + + + +The CDUCs and FDUC are almost identical except for their available interpolations, allowable rates, and count. There are two CDUCs per DAC pair and four FDUCs per DAC pair. In the data pipeline, data from the input will be passed through the FDUCs, or bypass the FDUCs, then routed through a mux into the CDUCs, which can also be bypassed. + + +# Top-Level Control + + +The CDUC and FDUC interpolations are controlled by **MainDataPathInterpolation** and **ChannelizerPathInterpolation** respectively. + + + +```python +help adi.sim.AD9081.Tx.MainDataPathInterpolation +``` + + +``` + MainDataPathInterpolation Main Data Path Interpolation + Specify the decimation in the main data path which can be + [1,2,3,4,6] +``` + + +```python +help adi.sim.AD9081.Tx.ChannelizerPathInterpolation +``` + + +``` + ChannelizerPathInterpolation Channelizer Path Interpolation + Specify the decimation in the channelizer path which can be + [1,2,3,4,6,8,12,16,24] +``` + +## Muxing + + +The FDUC quads share a common full crossbar to the pairs of upstream CDUCs connected to them. This is represented by a single summing crossbar that limits routes to the halves of AD9081. This crossbar or mux is controlled by the **Crossbar8x8Mux** and will constrain all the mappings. + + + +```python +help adi.sim.AD9081.Tx.Crossbar8x8Mux +``` + + +``` + Crossbar8x8Mux Crossbar 8x8 Mux + Logical 4x8 array of for MainDataPath input summers. Each row + corresponds to each summmer [1-4] and each column corresponds + to an input Channelizer path 1-8]. Set indexes to true to + enable a given path to be added into summer's output. +``` + + + +The 8x8 summing crossbar can sum any channels within the FDUC quads (FDUC0->FDUC3 and FDUC4->FDUC7). This is controlled by the columns of **Crossbar8x8Mux**, where each true row in a given column is feed into the individual summers feeding the inputs to the CDUCs. Below is an example of summing FDUC0,FDUC1,FDUC3 to CDDC0 and FDUC4,FDUC5 to CDDC2: + + + +```python +tx = adi.sim.AD9081.Tx; +tx.Crossbar8x8Mux = [... + 1,0,0,0,0,0,0,0;...FDUC0->CDUC0 + 0,1,0,0,0,0,0,0;...FDUC1->CDUC1 + 0,0,1,0,0,0,0,0;...FDUC2->CDUC2 + 0,0,0,1,0,0,0,0]; %FDUC3->CDUC3 +``` + +## NCO Frequency and Phase + + +Once the NCOs are enabled the frequencies and phases of the NCOs can be controlled individually. This is done through the **CDUCNCOFrequencies, FDUCNCOFrequencies**, **CDUCNCOPhases**, and **FDUCNCOPhases**. The frequencies will be limited based on the rate going into the NCO at that stage. + + + +```python +help adi.sim.AD9081.Tx.CDUCNCOFrequencies +``` + + +``` + CDUCNCOFrequencies CDUC NCO Frequencies + 1x4 Array of frequencies of NCOs in main data path +``` + + +```python +help adi.sim.AD9081.Tx.FDUCNCOFrequencies +``` + + +``` + FDUCNCOFrequencies FDUC NCO Frequencies + 1x8 Array of frequencies of NCOs in channelizer path +``` + diff --git a/CI/gen_doc/docs/models/ad9081/pfilt.tex.md b/CI/gen_doc/docs/models/ad9081/pfilt.tex.md new file mode 100644 index 0000000..b8c435f --- /dev/null +++ b/CI/gen_doc/docs/models/ad9081/pfilt.tex.md @@ -0,0 +1,91 @@ +# AD9081 Programmable FIR Filters (PFILT) + + +Following the ADCs are the Programmable FIRs (PFILTs) that can operate at maximum rates of the RX paths. The PFILTs are useful for channel equalization, image rejection, and generic filtering. The PFILTs also act as muxes into the CDDCs connected downstream on the RX path. + + + + +There are two PFILT blocks per AD9081 which operate on pairs of ADCs. The ADC pairs can be individually muxed based on requirements with Mux0 + + +# **Top-Level Control** + + +RX has a pair of PFILT each which are denoted by PFilterX, where X is 1 or 2 in the property listing. Therefore RX will have properties: **PFilterXMode**, **PFilterXTaps**, and **PFilterXGains**. + + +## Operational Modes and Features + + +Each PFILT block is fundamentally a large 192 tap filter which can be split into: + + + + - 1 192 tap filter + - 2 96 tap filters + - 3 64 tap filters (Matrix filter only) + - 4 48 tap filters + + + +The filters are individually mapped to pairs of ADCs on the RX side based on the mode used. The PFILTs have eight configuration modes and the following notation will be used to describe the filtering modes: + + + + - x1: first input + - x2: second input + - y1: first output + - y2: second output + - F1: filter 1 + - F2: filter 2 + - F3: filter 3 + - F4: filter 4 + - p: length of filters (individually) + + + +The different operational modes selectable through the **PFilterXMode** property are: + + + + - **NoFilter**: y1 = x1, y2 = x2, y3 = x2, y4 = x2 + - **SingleInphase**: y1 = F1(x1), y2 = x2 + - **SingleQuadrature**: y1 = x1, y2 = F1(x2) + - **DualReal**: y1 = F1(x1), y2 = F2(x2) + - **HalfComplexSumInphase**: y1 = F1(x1)+F2(x1), y2 = x2*z^-p + - **HalfComplexSumQuadrature**: y2 = F1(x1)+F2(x1), y1 = x1*z^-p + - **FullComplex**: y1 = F1(x1)-F3(x2), y2 = F1(x1)+F3(x2)-F2(x1+x2) + - **Matrix**: y1 = F1(x1) - F3(x2), y2 = F2(x1) - F4(x2) + +# Example Configuration + + +Here is a basic example of a moving average filter applied on the RX path on one of the four ADCs. + + + +```python +rx = adi.sim.AD9081.Rx; +rx.PFIREnable = 1; +rx.PFilter1Mode = 'SingleInphase'; +rx.PFilter2Mode = 'NoFilter'; +N = 48; rx.PFilter1Taps = [ones(1,N)./2^3,zeros(1,192-N)]; +rx.PFilter1TapsWidthsPerQuad = [... +16,16,16,16,16,16,16,16,16,16,16,16,... +12,12,12,12,12,12,12,12,12,12,12,12,... +6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6];... +rampVolts = 1.0*[(1./1e3.*(1:1e3)).';(1./1e3.*(1e3:-1:1)).']; +rampVolts = randn(size(rampVolts))./16+rampVolts; +[out1,out2,~,~,out3,out4] = rx(rampVolts,rampVolts,rampVolts,rampVolts); +outs = [out1,out2,out3,out4]; +n = 1:2e3; +subplot(2,1,1);plot(n,real(outs(:,1)));title("Moving Average Filter") +subplot(2,1,2);plot(n,real(outs(:,2)));title("No Filter") +``` + + +![/tmp/HighSpeedConverterToolbox/CI/doc/ad9081/pfilt_images/figure_0.png +](pfilt_images/figure_0.png +) + diff --git a/CI/gen_doc/docs/models/ad9081/pfilt_images/figure_0.png b/CI/gen_doc/docs/models/ad9081/pfilt_images/figure_0.png new file mode 100644 index 0000000..b4cc5aa Binary files /dev/null and b/CI/gen_doc/docs/models/ad9081/pfilt_images/figure_0.png differ diff --git a/CI/gen_doc/docs/models/ad9081/top_level.tex.md b/CI/gen_doc/docs/models/ad9081/top_level.tex.md new file mode 100644 index 0000000..40f804b --- /dev/null +++ b/CI/gen_doc/docs/models/ad9081/top_level.tex.md @@ -0,0 +1,183 @@ +# AD9081 Behavioral Model Introduction + + +The AD9081 is a highly integrated RF mixed-signal front-end (MxFE) that features four 16-bit, 12 GSPS DAC cores and four 12-bit, 4 GSPS ADC cores, as shown below: + + + + +![ad9081/top_level_images/image_0.png +](top_level_images/image_0.png +) + + + + +The device includes an optional on-chip clock multiplier (up to 12GHz) for DAC and ADC sampling clock generation as well as broadband ADC and DAC cores. + + + + +The transmit and receive digital datapaths are highly configurable and support a wide range of single-band and multiband applications with varying RF bandwidth requirements. The AD9081 transmit and receive datapaths consist of four main datapaths in support of wideband signals and eight channelizers in support of narrower band signals. For multiband applications with wide separation between RF bands, the channelizers can be used to process the individual RF bands to reduce the overall complex data rate needed to represent each narrower band. Both the main and channelizer datapath stages offer flexible interpolating and decimation factors to allow a more manageable data interface rate aligned to the actual signal bandwidth requirements. The numerically controlled oscillator of each stage can be independently tuned for maximum flexibility. + + + + +The models available in the High-Speed Converter Toolbox are designed to educate users on the configuration, features, and limitations of the AD9081. However, it should not be expected to match hardware exactly, but be similar in behavior. It should not be used for exact performance measurements. + + + + +The device model is split into two components, one modeling the transmit path and one for the receive path. Both are [System Objects](https://www.mathworks.com/help/matlab/matlab_prog/what-are-system-objects.html) and have methods and properties to allow configuration and passing of data into the models. For details on the different features select from the links below. For a basic overview of the models go to the \hyperref{H_C9E8316D}{Quick Start} section below. + + + + - [ADC and ADC Mux](../adc.tex) + - [DAC](../dac.tex) + - [Programmable FIR Filters (PFILT)](../pfilt.tex) + - [Digital Down Converters](../ddc2.tex) + - [Digital Up Converters](../duc.tex) + +# Model Limitations + + +The models are primarily designed to expose the DSP features of AD9081 and the different configurations possible. This does not include the JESD interfaces or highly detailed implementation of the ADCs or DACs within the device. However, the converter models will have similar NSD performance of the device. + + +# Quick Start + + +Each TX and RX model instance can be instantiated like any other System Object in MATLAB through the constructor call. The constructor can be used to parameterize the model but it is typically more understandable to do this separately from the constructor as below: + + + +```python +rx = adi.sim.AD9081.Rx; % Call constructor of Receiver model +rx.MainDataPathDecimation = 4; % Set CDDC decimation to 4 + +% Call constructor with arguments +rx = adi.sim.AD9081.Rx('MainDataPathDecimation',4); +``` + + + +The receiver model has dozens of properties and are set in a similar way to the above **MainDataPathDecimation**. These properties are validated when update and at runtime so the model will not run in an undefined mode. + + + + +On receive, the input data is assumed to be in *volts* and the output of the model will be in *codes*. Note that these are not strictly ADC codes depending on what processing is enable inside. + + + + +We can demonstrate a typical usage flow of the receiver through a few examples. In the below example feeds a 50% fullscale and 110% fullscale signal into the four ADCs in the form of a matrix. The input to the RX model must always be a 4 real Nx1 arrays of type double, representing the input to each ADC. N must be a multiple of the total decimation enable and should be relatively large for performance reasons. + + + +```python +rx = adi.sim.AD9081.Rx; +% Create sinewave at 50% FSR +sw = dsp.SineWave; +sw.Amplitude = 0.125; % volts +sw.Frequency = 10e6; +sw.SampleRate = rx.SampleRate; +sw.SamplesPerFrame = 4e4; +data = sw(); +outputCodes = rx(data.*0.5,data.*0.5,data.*0.5,data.*1.1); +% Plots +plot(real(outputCodes));xlabel('Sample');ylabel('Code'); +``` + + +![/tmp/HighSpeedConverterToolbox/CI/doc/ad9081/top_level_images/figure_0.png +](top_level_images/figure_0.png +) + + + +On the TX side the usage model is the same, but we are instead passing integers to be transmitted from the DACs and the outputs are codes to the relative fullscale of the DAC which is 16-bits. + + + +```python +tx = adi.sim.AD9081.Tx; +tx.MainDataPathInterpolation = 2; +tx.ModeSelectMux = 0; % Set DAC inputs to real data from CDUCs. + +% Create sinewave at 50% and 25% FSR +sw = dsp.SineWave; +sw.Amplitude = 2^15*0.5; % codes +sw.Frequency = 10e6; +sw.SampleRate = rx.SampleRate; +sw.SamplesPerFrame = 4e4; +dataS = sw(); +data = int16(dataS);dataHalf = int16(dataS.*0.5); +[outputCodes0,~,~,outputCodes3] = tx(data,data,data,dataHalf,data,data,data,data); +% Plots +plot(real(outputCodes0)); hold on; +plot(real(outputCodes3)); hold off; +xlabel('Sample');ylabel('Code'); +``` + + +![/tmp/HighSpeedConverterToolbox/CI/doc/ad9081/top_level_images/figure_1.png +](top_level_images/figure_1.png +) + +## Inspecting Properties + + +When using the model individual properties can be inspected for their functionality. Leveraging the **help** command will print out useful information on each setting. Follow the patterns below to perform lookups: + + + +```python +help adi.sim.AD9081.Rx.MainDataPathDecimation +``` + + +``` + MainDataPathDecimation Main Data Path Decimation + Specify the decimation in the main data path which can be + [1,2,3,4,6] +``` + + +```python +rx = adi.sim.AD9081.Rx +``` + + +``` +rx = + adi.sim.AD9081.Rx with properties: + + CDDCNCOFrequencies: [1000000 1000000 1000000 1000000] + CDDCNCOEnable: [0 0 0 0] + FDDCNCOFrequencies: [1000000 1000000 1000000 1000000 1000000 1000000 1000000 1000000] + FDDCNCOEnable: [0 0 0 0 0 0 0 0] + MainDataPathDecimation: 1 + ChannelizerPathDecimation: 1 + Crossbar4x4Mux0: [1 2 3 4] + Crossbar4x8Mux2: [1 2 1 2 3 4 3 4] + PFIREnable: false + ModeSelectMux1: false + SampleRate: 4.0000e+09 + +``` + + +```python +help rx.MainDataPathDecimation +``` + + +``` +--- help for adi.sim.AD9081.Rx/MainDataPathDecimation --- + + MainDataPathDecimation Main Data Path Decimation + Specify the decimation in the main data path which can be + [1,2,3,4,6] +``` + diff --git a/CI/gen_doc/docs/models/ad9081/top_level_images/figure_0.png b/CI/gen_doc/docs/models/ad9081/top_level_images/figure_0.png new file mode 100644 index 0000000..141fd95 Binary files /dev/null and b/CI/gen_doc/docs/models/ad9081/top_level_images/figure_0.png differ diff --git a/CI/gen_doc/docs/models/ad9081/top_level_images/figure_1.png b/CI/gen_doc/docs/models/ad9081/top_level_images/figure_1.png new file mode 100644 index 0000000..9ba3c2e Binary files /dev/null and b/CI/gen_doc/docs/models/ad9081/top_level_images/figure_1.png differ diff --git a/CI/gen_doc/docs/models/ad9081/top_level_images/image_0.png b/CI/gen_doc/docs/models/ad9081/top_level_images/image_0.png new file mode 100644 index 0000000..dfafe74 Binary files /dev/null and b/CI/gen_doc/docs/models/ad9081/top_level_images/image_0.png differ diff --git a/CI/gen_doc/docs/ports.json b/CI/gen_doc/docs/ports.json new file mode 100644 index 0000000..278ae32 --- /dev/null +++ b/CI/gen_doc/docs/ports.json @@ -0,0 +1,178 @@ +{ + "ad7380": { + "chip": "AD7380", + "complex": "false", + "fpga": [ + "zcu102" + ], + "supported_rd": [ + "rx" + ], + "ports": [ + { + "rx": [ + { + "input": "false", + "width": 1, + "name": "axi_ad9680_cpack/fifo_wr_en", + "type": "valid" + }, + { + "input": "true", + "width": 1, + "name": "axi_ad9680_tpl/adc_valid_0", + "type": "valid" + }, + { + "input": "false", + "width": 64, + "name": "axi_ad9680_cpack/fifo_wr_data_0", + "type": "data" + }, + { + "input": "false", + "width": 64, + "name": "axi_ad9680_cpack/fifo_wr_data_1", + "type": "data" + }, + { + "input": "true", + "width": 64, + "name": "axi_ad9680_tpl/adc_data_0", + "type": "data" + }, + { + "input": "true", + "width": 64, + "name": "axi_ad9680_tpl/adc_data_1", + "type": "data" + } + ] + } + ] + }, + "ad7768": { + "chip": "AD7768", + "complex": "false", + "fpga": [ + "zcu102" + ], + "supported_rd": [ + "rx" + ], + "ports": [ + { + "rx": [ + { + "input": "false", + "width": 1, + "name": "util_mxfe_cpack/fifo_wr_en", + "type": "valid" + }, + { + "input": "true", + "width": 1, + "name": "rx_mxfe_tpl_core/adc_valid_0", + "type": "valid" + }, + { + "input": "false", + "width": 16, + "name": "util_mxfe_cpack/fifo_wr_data_0", + "type": "data" + }, + { + "input": "false", + "width": 16, + "name": "util_mxfe_cpack/fifo_wr_data_1", + "type": "data" + }, + { + "input": "false", + "width": 16, + "name": "util_mxfe_cpack/fifo_wr_data_2", + "type": "data" + }, + { + "input": "false", + "width": 16, + "name": "util_mxfe_cpack/fifo_wr_data_3", + "type": "data" + }, + { + "input": "false", + "width": 16, + "name": "util_mxfe_cpack/fifo_wr_data_4", + "type": "data" + }, + { + "input": "false", + "width": 16, + "name": "util_mxfe_cpack/fifo_wr_data_5", + "type": "data" + }, + { + "input": "false", + "width": 16, + "name": "util_mxfe_cpack/fifo_wr_data_6", + "type": "data" + }, + { + "input": "false", + "width": 16, + "name": "util_mxfe_cpack/fifo_wr_data_7", + "type": "data" + }, + { + "input": "true", + "width": 16, + "name": "rx_mxfe_tpl_core/adc_data_0", + "type": "data" + }, + { + "input": "true", + "width": 16, + "name": "rx_mxfe_tpl_core/adc_data_1", + "type": "data" + }, + { + "input": "true", + "width": 16, + "name": "rx_mxfe_tpl_core/adc_data_2", + "type": "data" + }, + { + "input": "true", + "width": 16, + "name": "rx_mxfe_tpl_core/adc_data_3", + "type": "data" + }, + { + "input": "true", + "width": 16, + "name": "rx_mxfe_tpl_core/adc_data_4", + "type": "data" + }, + { + "input": "true", + "width": 16, + "name": "rx_mxfe_tpl_core/adc_data_5", + "type": "data" + }, + { + "input": "true", + "width": 16, + "name": "rx_mxfe_tpl_core/adc_data_6", + "type": "data" + }, + { + "input": "true", + "width": 16, + "name": "rx_mxfe_tpl_core/adc_data_7", + "type": "data" + } + ] + } + ] + } +} diff --git a/CI/gen_doc/docs/read_ports_json.py b/CI/gen_doc/docs/read_ports_json.py new file mode 100644 index 0000000..7d6a695 --- /dev/null +++ b/CI/gen_doc/docs/read_ports_json.py @@ -0,0 +1,59 @@ +import json + +# open ports.json file and parse +ports_json_file = 'ports.json' +with open(ports_json_file) as json_file: + ports = json.load(json_file) + + tmp_key = "m_name" + for key0 in ports.keys(): + for key1 in ports[key0]['ports'][0].keys(): + if (key1 == "rx"): + for ii in range(0, len(ports[key0]['ports'][0][key1])): + tmp_dict = ports[key0]['ports'][0][key1][ii] + if (tmp_dict['type'].lower() == "data"): + if (tmp_dict['input'] == "true"): + if tmp_key not in tmp_dict: + tmp_list = tmp_dict['name'].split("_") + last_ele = tmp_list[-1] + if (len(last_ele) == 1): + tmp_dict[tmp_key] = f"{ports[key0]['chip']} ADC Data {last_ele} IN" + elif (len(last_ele) == 2): + tmp_dict[tmp_key] = f"{ports[key0]['chip']} ADC Data {last_ele.upper()}" + elif (tmp_dict['input'] == "false"): + if tmp_key not in tmp_dict: + tmp_list = tmp_dict['name'].split("_") + last_ele = tmp_list[-1] + tmp_dict[tmp_key] = f"IP Data {last_ele.upper()} OUT" + elif (tmp_dict['type'].lower() == "valid"): + if (tmp_dict['input'] == "true"): + tmp_dict[tmp_key] = f"IP Valid Rx Data IN" + elif (tmp_dict['input'] == "false"): + tmp_dict[tmp_key] = f"IP Data Valid OUT" + ports[key0]['ports'][0][key1][ii] = tmp_dict + elif (key1 == "tx"): + for ii in range(0, len(ports[key0]['ports'][0][key1])): + tmp_dict = ports[key0]['ports'][0][key1][ii] + if (tmp_dict['type'].lower() == "data"): + if (tmp_dict['input'] == "false"): + if tmp_key not in tmp_dict: + tmp_list = tmp_dict['name'].split("_") + last_ele = tmp_list[-1] + if (len(last_ele) == 1): + tmp_dict[tmp_key] = f"{ports[key0]['chip']} DAC Data {last_ele} OUT" + elif (len(last_ele) == 2): + tmp_dict[tmp_key] = f"{ports[key0]['chip']} DAC Data {last_ele.upper()}" + elif (tmp_dict['input'] == "true"): + if tmp_key not in tmp_dict: + tmp_list = tmp_dict['name'].split("_") + last_ele = tmp_list[-1] + tmp_dict[tmp_key] = f"IP Data {last_ele.upper()} IN" + elif (tmp_dict['type'].lower() == "valid"): + if (tmp_dict['input'] == "true"): + tmp_dict[tmp_key] = f"IP Valid Tx Data IN" + elif (tmp_dict['input'] == "false"): + tmp_dict[tmp_key] = f"IP Load Tx Data OUT" + ports[key0]['ports'][0][key1][ii] = tmp_dict + +with open(ports_json_file, 'w') as json_file: + json.dump(ports, json_file, indent = 4) \ No newline at end of file diff --git a/CI/gen_doc/docs/stylesheets/ml_style.css b/CI/gen_doc/docs/stylesheets/ml_style.css new file mode 100644 index 0000000..fcb16d6 --- /dev/null +++ b/CI/gen_doc/docs/stylesheets/ml_style.css @@ -0,0 +1,7 @@ +.md-header { + display: none; +} + +.md-footer { + display: none; +} \ No newline at end of file diff --git a/CI/gen_doc/docs/stylesheets/rd_style.css b/CI/gen_doc/docs/stylesheets/rd_style.css new file mode 100644 index 0000000..a147ed4 --- /dev/null +++ b/CI/gen_doc/docs/stylesheets/rd_style.css @@ -0,0 +1,217 @@ + +#CarrierBox > rect { + fill: var(--md-default-fg-color--light); +} +#AXIAD9361Box > rect { + stroke: white; +} + +#AXIAD9361Box:hover > rect { + fill: rgb(0, 174, 255); +} +#TxDMAEngineBox > rect { + stroke: white; +} + +#TxDMAEngineBox:hover > rect { + fill: rgb(0, 174, 255); +} +#TxUPACKBox > rect { + stroke: white; +} + +#TxUPACKBox:hover > rect { + fill: rgb(0, 174, 255); +} +#TxFIFOBox > rect { + stroke: white; +} + +#TxFIFOBox:hover > rect { + fill: rgb(0, 174, 255); +} +#RxDMAEngineBox > rect { + stroke: white; +} + +#RxDMAEngineBox:hover > rect { + fill: rgb(0, 174, 255); +} +#CPACKBox > rect { + stroke: white; +} + +#CPACKBox:hover > rect { + fill: rgb(0, 174, 255); +} +#RxFIFOBox > rect { + stroke: white; +} + +#RxFIFOBox:hover > rect { + fill: rgb(0, 174, 255); +} + +#FPGACarrierText { + fill: var(--rd-title-color); +} + +#CarrierBox > rect { + fill: none; + stroke: black +} + +#CustomIPOutline > rect { + stroke: var(--rd-title-color); +} + +#CustomIPIntegrationText { + fill: var(--rd-title-color); +} + +#CarrierBox > rect { + fill: var(--md-default-fg-color--light); +} +#TxDMAEngineBox > rect { + stroke: white; +} + +#TxDMAEngineBox:hover > rect { + fill: rgb(0, 174, 255); +} +#TxUPACKBox > rect { + stroke: white; +} + +#TxUPACKBox:hover > rect { + fill: rgb(0, 174, 255); +} +#RxDMAEngineBox > rect { + stroke: white; +} + +#RxDMAEngineBox:hover > rect { + fill: rgb(0, 174, 255); +} +#CPACKBox > rect { + stroke: white; +} + +#CPACKBox:hover > rect { + fill: rgb(0, 174, 255); +} +#AXIADRV9002Box > rect { + stroke: white; +} + +#AXIADRV9002Box:hover > rect { + fill: rgb(0, 174, 255); +} + +#FPGACarrierText { + fill: var(--rd-title-color); +} + +#CarrierBox > rect { + fill: none; + stroke: black +} + +#CustomIPOutline > rect { + stroke: var(--rd-title-color); +} + +#CustomIPIntegrationText { + fill: var(--rd-title-color); +} + +#CarrierBox > rect { + fill: var(--md-default-fg-color--light); +} +#TxDMAEngineBox > rect { + stroke: white; +} + +#TxDMAEngineBox:hover > rect { + fill: rgb(0, 174, 255); +} +#TxUPACKBox > rect { + stroke: white; +} + +#TxUPACKBox:hover > rect { + fill: rgb(0, 174, 255); +} +#RxDMAEngineBox > rect { + stroke: white; +} + +#RxDMAEngineBox:hover > rect { + fill: rgb(0, 174, 255); +} +#CPACKBox > rect { + stroke: white; +} + +#CPACKBox:hover > rect { + fill: rgb(0, 174, 255); +} +#RxJESDTPL > rect { + stroke: white; +} + +#RxJESDTPL:hover > rect { + fill: rgb(0, 174, 255); +} +#RxJESDLink > rect { + stroke: white; +} + +#RxJESDLink:hover > rect { + fill: rgb(0, 174, 255); +} +#RxJESDPHY > rect { + stroke: white; +} + +#RxJESDPHY:hover > rect { + fill: rgb(0, 174, 255); +} +#TxJESDTPL > rect { + stroke: white; +} + +#TxJESDTPL:hover > rect { + fill: rgb(0, 174, 255); +} +#TxJESDLink > rect { + stroke: white; +} + +#TxJESDLink:hover > rect { + fill: rgb(0, 174, 255); +} +#TxJESDPHY > rect { + stroke: white; +} + +#TxJESDPHY:hover > rect { + fill: rgb(0, 174, 255); +} + +#FPGACarrierText { + fill: var(--rd-title-color); +} + +#CarrierBox > rect { + fill: none; + stroke: black +} + +#CustomIPOutline > rect { + stroke: var(--rd-title-color); +} + +#CustomIPIntegrationText { + fill: var(--rd-title-color); +} diff --git a/CI/gen_doc/docs/stylesheets/style.css b/CI/gen_doc/docs/stylesheets/style.css new file mode 100644 index 0000000..86b7539 --- /dev/null +++ b/CI/gen_doc/docs/stylesheets/style.css @@ -0,0 +1,88 @@ +:root > * { + --md-primary-fg-color: #0370B8; + --md-primary-fg-color--light: #0370B8; + --md-primary-fg-color--dark: #0370B8; +} + +[data-md-color-scheme="slate"] { + --prop-box-color: var(--md-code-bg-color); + --logo-light-mode: none; + --logo-dark-mode: block; + --rd-title-color: white; +} + +[data-md-color-scheme="default"] { + --prop-box-color: #f1f1f1; + --prop-box-color: var(--md-default-fg-color--dark); + --logo-light-mode: block; + --logo-dark-mode: none; + --rd-title-color: black; +} + + +.sysobj_desc_title { + border-bottom: 1px solid rgb(153, 153, 153); + margin-bottom: 10px; +} + +.property { + margin: 16px; +} + +/* Style the button that is used to open and close the collapsible content */ +.collapsible-property { + background-color: #eee; + color: #444; + cursor: pointer; + padding: 18px; + width: 100%; + border: rgb(153, 153, 153) 1px solid; + text-align: left; + outline: none; + font-size: 15px; + border-radius: 3px; +} + +/* Add a background color to the button if it is clicked on (add the .active class with JS), and when you move the mouse over it (hover) */ +.active, +.collapsible-property:hover { + background-color: #ccc; +} + +/* Style the collapsible content. Note: hidden by default */ +.content { + padding: 0 18px; + display: none; + overflow: hidden; + background-color: var(--prop-box-color); + border-radius: 0px; + border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; + border: rgb(153, 153, 153) 1px solid; +} + +.screenshot { + box-shadow: 0px 6px 5px #ccc; + width: 80%; +} + +/* Logo dark/light */ +.dark-logo { + display: var(--logo-light-mode); +} + +.light-logo { + display: var(--logo-dark-mode); +} + +:root { + --md-primary-fg-color: #1E68D8; + --md-primary-fg-color--light: #1E68D8; + --md-primary-fg-color--dark: #1E68D8; +} + +[data-md-color-scheme="blue"] { + --md-primary-fg-color: #1E68D8; + --md-primary-fg-color--light: #1E68D8; + --md-primary-fg-color--dark: #1E68D8; +} diff --git a/CI/gen_doc/docs/sysobjects/.pages b/CI/gen_doc/docs/sysobjects/.pages new file mode 100644 index 0000000..7835617 --- /dev/null +++ b/CI/gen_doc/docs/sysobjects/.pages @@ -0,0 +1 @@ +title: Device Interfaces diff --git a/CI/gen_doc/docs/sysobjects/adi.AD9081.Rx.md b/CI/gen_doc/docs/sysobjects/adi.AD9081.Rx.md new file mode 100644 index 0000000..d0eb6ed --- /dev/null +++ b/CI/gen_doc/docs/sysobjects/adi.AD9081.Rx.md @@ -0,0 +1,125 @@ +--- +hide: + - navigation + - toc +--- + + + + + + + +
+ + The adi.AD9081.Rx System object is a signal source that can receive
complex data from the AD9081.

rx = adi.AD9081.Rx;
rx = adi.AD9081.Rx('uri','ip:192.168.2.1');

AD9081 Datasheet

+
+ +
+ +
Creation
+ +The class can be instantiated in the following way with and without property name value pairs. + +```matlab +dev = adi.AD9081.Rx +dev = adi.AD9081.Rx(Name, Value) +``` + +
Properties
+ +
+ +Unless otherwise indicated, properties are non-tunable, which means you cannot change their values after calling the object. Objects lock when you call them, and the release function unlocks them. +

+If a property is tunable, you can change its value at any time. +

+For more information on changing property values, see System Design in MATLAB Using System Objects. +
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
Example Usage
+ +``` + +%% Rx set up +rx = adi.adi.AD9081.Rx.Rx('uri','ip:analog.local'); +rx.CenterFrequency = 1e9; +rx.EnabledChannels = 1; +%% Run +for k=1:10 + valid = false; + while ~valid + [out, valid] = rx(); + end +end + +``` \ No newline at end of file diff --git a/CI/gen_doc/docs/sysobjects/adi.AD9081.Tx.md b/CI/gen_doc/docs/sysobjects/adi.AD9081.Tx.md new file mode 100644 index 0000000..6b61fdf --- /dev/null +++ b/CI/gen_doc/docs/sysobjects/adi.AD9081.Tx.md @@ -0,0 +1,148 @@ +--- +hide: + - navigation + - toc +--- + + + + + + + +
+ + The adi.AD9081.Tx System object is a signal sink that can tranmsit
complex data from the AD9081.

tx = adi.AD9081.Tx;
tx = adi.AD9081.Tx('uri','ip:ip:192.168.2.1');

AD9081 Datasheet
+
+ +
+ +
Creation
+ +The class can be instantiated in the following way with and without property name value pairs. + +```matlab +dev = adi.AD9081.Tx +dev = adi.AD9081.Tx(Name, Value) +``` + +
Properties
+ +
+ +Unless otherwise indicated, properties are non-tunable, which means you cannot change their values after calling the object. Objects lock when you call them, and the release function unlocks them. +

+If a property is tunable, you can change its value at any time. +

+For more information on changing property values, see System Design in MATLAB Using System Objects. +
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
Example Usage
+ +``` + +%% Configure device +tx = adi.adi.AD9081.Tx; +tx.uri = "ip:analog.local"; +tx.CenterFrequency = 1e9; +tx.DataSource = 'DMA'; +tx.EnableCyclicBuffers = true; +tx.EnabledChannels = 1; +%% Generate tone +amplitude = 2^15; frequency = 0.12e6; +swv1 = dsp.SineWave(amplitude, frequency); +swv1.ComplexOutput = true; +swv1.SamplesPerFrame = 2^14; +swv1.SampleRate = tx.SamplingRate; +y = swv1(); +% Send +tx(y); + +``` \ No newline at end of file diff --git a/CI/gen_doc/docs/sysobjects/adi.AD9467.Rx.md b/CI/gen_doc/docs/sysobjects/adi.AD9467.Rx.md new file mode 100644 index 0000000..16a8d23 --- /dev/null +++ b/CI/gen_doc/docs/sysobjects/adi.AD9467.Rx.md @@ -0,0 +1,101 @@ +--- +hide: + - navigation + - toc +--- + + + + + + + +
+ + The adi.AD9467.Rx System object is a signal source that can receive
complex data from the AD9467.

rx = adi.AD9467.Rx;
rx = adi.AD9467.Rx('uri','ip:192.168.2.1');

AD9467 Datasheet
+
+ +
+ +
Creation
+ +The class can be instantiated in the following way with and without property name value pairs. + +```matlab +dev = adi.AD9467.Rx +dev = adi.AD9467.Rx(Name, Value) +``` + +
Properties
+ +
+ +Unless otherwise indicated, properties are non-tunable, which means you cannot change their values after calling the object. Objects lock when you call them, and the release function unlocks them. +

+If a property is tunable, you can change its value at any time. +

+For more information on changing property values, see System Design in MATLAB Using System Objects. +
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
Example Usage
+ +``` + +%% Rx set up +rx = adi.adi.AD9467.Rx.Rx('uri','ip:analog.local'); +rx.CenterFrequency = 1e9; +rx.EnabledChannels = 1; +%% Run +for k=1:10 + valid = false; + while ~valid + [out, valid] = rx(); + end +end + +``` \ No newline at end of file diff --git a/CI/gen_doc/docs/sysobjects/adi.DAQ2.Rx.md b/CI/gen_doc/docs/sysobjects/adi.DAQ2.Rx.md new file mode 100644 index 0000000..0d4422f --- /dev/null +++ b/CI/gen_doc/docs/sysobjects/adi.DAQ2.Rx.md @@ -0,0 +1,101 @@ +--- +hide: + - navigation + - toc +--- + + + + + + + +
+ + The adi.DAQ2.Rx System object is a signal source that can
receive complex data from the DAQ2.

rx = adi.DAQ2.Rx;
rx = adi.DAQ2.Rx('uri','ip:192.168.2.1');

User Guide

+
+ +
+ +
Creation
+ +The class can be instantiated in the following way with and without property name value pairs. + +```matlab +dev = adi.DAQ2.Rx +dev = adi.DAQ2.Rx(Name, Value) +``` + +
Properties
+ +
+ +Unless otherwise indicated, properties are non-tunable, which means you cannot change their values after calling the object. Objects lock when you call them, and the release function unlocks them. +

+If a property is tunable, you can change its value at any time. +

+For more information on changing property values, see System Design in MATLAB Using System Objects. +
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
Example Usage
+ +``` + +%% Rx set up +rx = adi.adi.DAQ2.Rx.Rx('uri','ip:analog.local'); +rx.CenterFrequency = 1e9; +rx.EnabledChannels = 1; +%% Run +for k=1:10 + valid = false; + while ~valid + [out, valid] = rx(); + end +end + +``` \ No newline at end of file diff --git a/CI/gen_doc/docs/sysobjects/adi.DAQ2.Tx.md b/CI/gen_doc/docs/sysobjects/adi.DAQ2.Tx.md new file mode 100644 index 0000000..932412e --- /dev/null +++ b/CI/gen_doc/docs/sysobjects/adi.DAQ2.Tx.md @@ -0,0 +1,136 @@ +--- +hide: + - navigation + - toc +--- + + + + + + + +
+ + The adi.DAQ2.Tx System object is a signal source that can
send complex data to the DAQ2.

tx = adi.DAQ2.Tx;
tx = adi.DAQ2.Tx('uri','ip:192.168.2.1');

User Guide

+
+ +
+ +
Creation
+ +The class can be instantiated in the following way with and without property name value pairs. + +```matlab +dev = adi.DAQ2.Tx +dev = adi.DAQ2.Tx(Name, Value) +``` + +
Properties
+ +
+ +Unless otherwise indicated, properties are non-tunable, which means you cannot change their values after calling the object. Objects lock when you call them, and the release function unlocks them. +

+If a property is tunable, you can change its value at any time. +

+For more information on changing property values, see System Design in MATLAB Using System Objects. +
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
Example Usage
+ +``` + +%% Configure device +tx = adi.adi.DAQ2.Tx; +tx.uri = "ip:analog.local"; +tx.CenterFrequency = 1e9; +tx.DataSource = 'DMA'; +tx.EnableCyclicBuffers = true; +tx.EnabledChannels = 1; +%% Generate tone +amplitude = 2^15; frequency = 0.12e6; +swv1 = dsp.SineWave(amplitude, frequency); +swv1.ComplexOutput = true; +swv1.SamplesPerFrame = 2^14; +swv1.SampleRate = tx.SamplingRate; +y = swv1(); +% Send +tx(y); + +``` \ No newline at end of file diff --git a/CI/gen_doc/docs/sysobjects/output1.md b/CI/gen_doc/docs/sysobjects/output1.md new file mode 100644 index 0000000..7d992e5 --- /dev/null +++ b/CI/gen_doc/docs/sysobjects/output1.md @@ -0,0 +1,308 @@ +
+ + +
+ + + +
adi.Pluto.Rx
+ +
+Receive data from Analog Devices AD9361 transceiver +
+ +
Description
+ +
+The comm.SDRRxPluto System object™ is a signal source that receives data from an Analog Devices® ADALM-PLUTO radio. This connection enables you to simulate and develop various software-defined radio applications. + +The following diagram shows the interaction between MATLAB®, the comm.SDRRxPluto System object, and the radio hardware. + +
+ +
Creation
+ +Syntax + + +
Properties
+ +
+Unless otherwise indicated, properties are nontunable, which means you cannot change their values after calling the object. Objects lock when you call them, and the release function unlocks them. + +If a property is tunable, you can change its value at any time. + +For more information on changing property values, see System Design in MATLAB Using System Objects. + +
+
+
+

+ +

+
+
+ RF center frequency, specified in Hz as a scalar. The default is 2.4e9. This property is tunable.Help for adi.Pluto.Rx/CenterFrequency is inherited from superclass ADI.AD9361.RX +
+
+
+
+ +
+
+

+ +

+
+
+ Baseband sampling rate in Hz, specified as a scalar from 65105 to 61.44e6 samples per second.Help for adi.Pluto.Rx/SamplingRate is inherited from superclass ADI.AD9361.RX +
+
+
+
+ +
+
+

+ +

+
+
+ RF Bandwidth of front-end analog filter in Hz, specified as a scalar from 200 kHz to 56 MHz.Help for adi.Pluto.Rx/RFBandwidth is inherited from superclass ADI.AD9361.RX +
+
+
+
+ +
+
+

+ +

+
+
+ specified as one of the following: 'slow_attack' — For signals with slowly changing power levels 'fast_attack' — For signals with rapidly changing power levels 'manual' — For setting the gain manually with the Gain property 'hybrid' — For configuring hybrid AGC modeHelp for adi.Pluto.Rx/GainControlModeChannel0 is inherited from superclass ADI.AD9361.RX +
+
+
+
+ +
+
+

+ +

+
+
+ Channel 0 gain, specified as a scalar from -3 dB to 71 dB. The acceptable minimum and maximum gain setting depends on the center frequency.Help for adi.Pluto.Rx/GainChannel0 is inherited from superclass ADI.AD9361.RX +
+
+
+
+ +
+
+

+ +

+
+
+ specified as one of the following: 'slow_attack' — For signals with slowly changing power levels 'fast_attack' — For signals with rapidly changing power levels 'manual' — For setting the gain manually with the Gain property 'hybrid' — For configuring hybrid AGC modeHelp for adi.Pluto.Rx/GainControlModeChannel1 is inherited from superclass ADI.AD9361.RX +
+
+
+
+ +
+
+

+ +

+
+
+ Channel 1 gain, specified as a scalar from -3 dB to 71 dB. The acceptable minimum and maximum gain setting depends on the center frequency.Help for adi.Pluto.Rx/GainChannel1 is inherited from superclass ADI.AD9361.RX +
+
+
+
+ +
+
+

+ +

+
+
+ Option to set digital loopback mode, specified as 0, 1 or 2. Allows either to digitally loopback TX data into the RX path or vice versa. Value | Mode --------------------------- 0 | Disable 1 | Digital TX -> Digital RX 2 | RF RX -> RF TX Help for adi.Pluto.Rx/LoopbackMode is inherited from superclass ADI.AD9361.RX +
+
+
+
+ +
+
+

+ +

+
+
+ Option to enable quadrature tracking, specified as true or false. When this property is true, IQ imbalance compensation is applied to the input signal.Help for adi.Pluto.Rx/EnableQuadratureTracking is inherited from superclass ADI.AD9361.RX +
+
+
+
+ +
+
+

+ +

+
+
+ Option to enable RF DC tracking, specified as true or false. When this property is true, an RF DC blocking filter is applied to the input signal.Help for adi.Pluto.Rx/EnableRFDCTracking is inherited from superclass ADI.AD9361.RX +
+
+
+
+ +
+
+

+ +

+
+
+ Option to enable baseband DC tracking, specified as true or false. When this property is true, a baseband DC blocking filter is applied to the input signal.Help for adi.Pluto.Rx/EnableBasebandDCTracking is inherited from superclass ADI.AD9361.RX +
+
+
+
+ +
+
+

+ +

+
+
+ 'A_BALANCED' 'B_BALANCED' 'C_BALANCED' 'A_N' 'A_P' 'B_N' 'B_P' 'C_N' 'C_P' 'TX_MONITOR1' 'TX_MONITOR2' 'TX_MONITOR1_2'Help for adi.Pluto.Rx/RFPortSelect is inherited from superclass ADI.AD9361.RX +
+
+
+
+ +
+
+

+ +

+
+
+ Number of samples per frame, specified as an even positive integer from 2 to 16,777,216. Using values less than 3660 can yield poor performance. +
+
+
+
+ +
+
+

+ +

+
+
+ Enable use of custom filter file to set SamplingRate, RFBandwidth, and FIR in datapaths +
+
+
+
+ +
+
+

+ +

+
+
+ Path to custom filter file created from filter wizard +
+
+
+
+ +
+
+

+ +

+
+
+ Indexs of channels to be enabled. Input should be a [1xN] vector with the indexes of channels to be enabled. Order is irrelevant +
+
+
+
+ +
+
+

+ +

+
+
+ Hostname or IP address of remote libIIO deviceHelp for adi.Pluto.Rx/uri is inherited from superclass MATLABSHARED.LIBIIO.BASE +
+
+
+
+ +
+
+

+ +

+
+
+ If true, connects to libIIO device during simulationHelp for adi.Pluto.Rx/enIO is inherited from superclass MATLABSHARED.LIBIIO.BASE +
+
+
+
+ + diff --git a/CI/gen_doc/docs/sysobjs.json b/CI/gen_doc/docs/sysobjs.json new file mode 100644 index 0000000..7524757 --- /dev/null +++ b/CI/gen_doc/docs/sysobjs.json @@ -0,0 +1,178 @@ +[ + { + "name": "adi.AD7380.Rx", + "dec": " adi.AD7380.Rx Receives data from the AD7380 ADC
The adi.AD7380.Rx System object is a signal source that can receive
data from the AD7380.

rx = adi.AD7380.Rx;
rx = adi.AD7380.Rx('uri','192.168.2.1');

AD7380 Datasheet
Documentation for adi.AD7380.Rx
doc adi.AD7380.Rx
", + "props": [ + { + "prop_name": "EnabledChannels", + "prop_title": " EnabledChannels Enabled Channels", + "prop_description": "Indexs of channels to be enabled. Input should be a [1xN] vector with the indexes of channels to be enabled. Order is irrelevant" + }, + { + "prop_name": "SampleRate", + "prop_title": " SampleRate Sample Rate", + "prop_description": "Baseband sampling rate in Hz, specified as a scalar in samples per second. Options are: '256000','128000','64000','32000','16000','8000','4000', '2000','1000'" + }, + { + "prop_name": "SamplesPerFrame", + "prop_title": " Frame size", + "prop_description": "Size of the frame in samplesHelp for adi.AD7380.Rx/SamplesPerFrame is inherited from superclass matlabshared.libiio.base" + }, + { + "prop_name": "uri", + "prop_title": " URI - remote host URI", + "prop_description": "Hostname or IP address of remote libIIO deviceHelp for adi.AD7380.Rx/uri is inherited from superclass matlabshared.libiio.base" + } + ] + }, + { + "name": "adi.AD7768.Rx", + "dec": " adi.AD7768.Rx Receives data from the AD7768 ADC
The adi.AD7768.Rx System object is a signal source that can receive
data from the AD7768.

rx = adi.AD7768.Rx;
rx = adi.AD7768.Rx('uri','192.168.2.1');

AD7768 Datasheet
Documentation for adi.AD7768.Rx
doc adi.AD7768.Rx
", + "props": [ + { + "prop_name": "EnabledChannels", + "prop_title": " EnabledChannels Enabled Channels", + "prop_description": "Indexs of channels to be enabled. Input should be a [1xN] vector with the indexes of channels to be enabled. Order is irrelevant" + }, + { + "prop_name": "SampleRate", + "prop_title": " SampleRate Sample Rate", + "prop_description": "Baseband sampling rate in Hz, specified as a scalar in samples per second. Options are: '256000','128000','64000','32000','16000','8000','4000', '2000','1000'" + }, + { + "prop_name": "SamplesPerFrame", + "prop_title": " SamplesPerFrame Samples Per Frame", + "prop_description": "Number of samples per frame, specified as an even positive integer from 2 to 16,777,216. Using values less than 3660 can yield poor performance." + }, + { + "prop_name": "uri", + "prop_title": " URI - remote host URI", + "prop_description": "Hostname or IP address of remote libIIO deviceHelp for adi.AD7768.Rx/uri is inherited from superclass matlabshared.libiio.base" + } + ] + }, + { + "name": "adi.AD7768_1.Rx", + "dec": " adi.AD7768_1.Rx Receives data from the AD7768-1 ADC
The adi.AD7768_1.Rx System object is a signal source that can receive
data from the AD7768-1.

rx = adi.AD7768_1.Rx;
rx = adi.AD7768_1.Rx('uri','192.168.2.1');

AD7768-1 Datasheet
Documentation for adi.AD7768_1.Rx
doc adi.AD7768_1.Rx
", + "props": [ + { + "prop_name": "CommonModeVolts", + "prop_title": " SCommonModeVolts Common Mode Voltage", + "prop_description": "Common mode voltage in volts, specified as a string Options are: '(AVDD1-AVSS)/2','2V5','2V05','1V9','1V65','1V1','0V9','OFF'" + }, + { + "prop_name": "EnabledChannels", + "prop_title": " EnabledChannels Enabled Channels", + "prop_description": "Indexs of channels to be enabled. Input should be a [1xN] vector with the indexes of channels to be enabled. Order is irrelevant" + }, + { + "prop_name": "SampleRate", + "prop_title": " SampleRate Sample Rate", + "prop_description": "Baseband sampling rate in Hz, specified as a scalar in samples per second. Options are: '256000','128000','64000','32000','16000','8000','4000', '2000','1000'" + }, + { + "prop_name": "SamplesPerFrame", + "prop_title": " SamplesPerFrame Samples Per Frame", + "prop_description": "Number of samples per frame, specified as an even positive integer from 2 to 16,777,216. Using values less than 3660 can yield poor performance." + }, + { + "prop_name": "uri", + "prop_title": " URI - remote host URI", + "prop_description": "Hostname or IP address of remote libIIO deviceHelp for adi.AD7768_1.Rx/uri is inherited from superclass matlabshared.libiio.base" + } + ] + }, + { + "name": "adi.AD4030.Rx", + "dec": " adi.AD4030.Rx Receives data from the AD4030-24 ADC
The adi.AD4030.Rx System object is a signal source that can receive
data from the AD4030-24.

rx = adi.AD4030.Rx;
rx = adi.AD4030.Rx('uri','192.168.2.1');

AD4030-24 Datasheet
Documentation for adi.AD4030.Rx
doc adi.AD4030.Rx
", + "props": [ + { + "prop_name": "EnabledChannels", + "prop_title": " EnabledChannels Enabled Channels", + "prop_description": "Indexs of channels to be enabled. Input should be a [1xN] vector with the indexes of channels to be enabled. Order is irrelevant" + }, + { + "prop_name": "SampleAveragingLength", + "prop_title": " SampleAveragingLength", + "prop_description": "Block length of samples to be averaged. Applied in the Averaging Mode register only when OUT_DATA_MD is set to 30-bit averaged differential modeHelp for adi.AD4030.Rx/SampleAveragingLength is inherited from superclass adi.AD463x.Base" + }, + { + "prop_name": "SampleRate", + "prop_title": " SampleRate Sample Rate", + "prop_description": "Baseband sampling rate in Hz, specified as a scalar in samples per second.Help for adi.AD4030.Rx/SampleRate is inherited from superclass adi.AD463x.Base" + }, + { + "prop_name": "SamplesPerFrame", + "prop_title": " SamplesPerFrame Samples Per Frame", + "prop_description": "Number of samples per frame, specified as an even positive integer.Help for adi.AD4030.Rx/SamplesPerFrame is inherited from superclass adi.AD463x.Base" + }, + { + "prop_name": "uri", + "prop_title": " URI - remote host URI", + "prop_description": "Hostname or IP address of remote libIIO deviceHelp for adi.AD4030.Rx/uri is inherited from superclass matlabshared.libiio.base" + } + ] + }, + { + "name": "adi.AD4630_16.Rx", + "dec": " adi.AD4630_16.Rx Receive data from the AD4630-16 ADC
The adi.AD4630_16.Rx System object is a signal source that can receive
data from the AD4630-16.

rx = adi.AD4630_16.Rx;
rx = adi.AD4630_16.Rx('uri','192.168.2.1');

AD4630-16 Datasheet
Documentation for adi.AD4630_16.Rx
doc adi.AD4630_16.Rx
", + "props": [ + { + "prop_name": "EnabledChannels", + "prop_title": " EnabledChannels Enabled Channels", + "prop_description": "Indexs of channels to be enabled. Input should be a [1xN] vector with the indexes of channels to be enabled. Order is irrelevant" + }, + { + "prop_name": "SampleAveragingLength", + "prop_title": " SampleAveragingLength", + "prop_description": "Block length of samples to be averaged. Applied in the Averaging Mode register only when OUT_DATA_MD is set to 30-bit averaged differential modeHelp for adi.AD4630_16.Rx/SampleAveragingLength is inherited from superclass adi.AD463x.Base" + }, + { + "prop_name": "SampleRate", + "prop_title": " SampleRate Sample Rate", + "prop_description": "Baseband sampling rate in Hz, specified as a scalar in samples per second.Help for adi.AD4630_16.Rx/SampleRate is inherited from superclass adi.AD463x.Base" + }, + { + "prop_name": "SamplesPerFrame", + "prop_title": " SamplesPerFrame Samples Per Frame", + "prop_description": "Number of samples per frame, specified as an even positive integer.Help for adi.AD4630_16.Rx/SamplesPerFrame is inherited from superclass adi.AD463x.Base" + }, + { + "prop_name": "uri", + "prop_title": " URI - remote host URI", + "prop_description": "Hostname or IP address of remote libIIO deviceHelp for adi.AD4630_16.Rx/uri is inherited from superclass matlabshared.libiio.base" + } + ] + }, + { + "name": "adi.AD4630_24.Rx", + "dec": " adi.AD4630_24.Rx Receive data from the AD4630-24 ADC
The adi.AD4630_24.Rx System object is a signal source that can receive
data from the AD4630-24.

rx = adi.AD4630_24.Rx;
rx = adi.AD4630_24.Rx('uri','192.168.2.1');

AD4630-24 Datasheet
Documentation for adi.AD4630_24.Rx
doc adi.AD4630_24.Rx
", + "props": [ + { + "prop_name": "EnabledChannels", + "prop_title": " EnabledChannels Enabled Channels", + "prop_description": "Indexs of channels to be enabled. Input should be a [1xN] vector with the indexes of channels to be enabled. Order is irrelevant" + }, + { + "prop_name": "SampleAveragingLength", + "prop_title": " SampleAveragingLength", + "prop_description": "Block length of samples to be averaged. Applied in the Averaging Mode register only when OUT_DATA_MD is set to 30-bit averaged differential modeHelp for adi.AD4630_24.Rx/SampleAveragingLength is inherited from superclass adi.AD463x.Base" + }, + { + "prop_name": "SampleRate", + "prop_title": " SampleRate Sample Rate", + "prop_description": "Baseband sampling rate in Hz, specified as a scalar in samples per second.Help for adi.AD4630_24.Rx/SampleRate is inherited from superclass adi.AD463x.Base" + }, + { + "prop_name": "SamplesPerFrame", + "prop_title": " SamplesPerFrame Samples Per Frame", + "prop_description": "Number of samples per frame, specified as an even positive integer.Help for adi.AD4630_24.Rx/SamplesPerFrame is inherited from superclass adi.AD463x.Base" + }, + { + "prop_name": "uri", + "prop_title": " URI - remote host URI", + "prop_description": "Hostname or IP address of remote libIIO deviceHelp for adi.AD4630_24.Rx/uri is inherited from superclass matlabshared.libiio.base" + } + ] + } +] \ No newline at end of file diff --git a/CI/gen_doc/gen_pages.py b/CI/gen_doc/gen_pages.py new file mode 100644 index 0000000..7d13e86 --- /dev/null +++ b/CI/gen_doc/gen_pages.py @@ -0,0 +1,64 @@ +import glob + +# Get list of HTML files +root = "source/_mlpages" +target = "source" + + +files = glob.glob(root + "**/**/**/**/doc/*.html", recursive=True) +files = sorted(files) + +titles = { + "SysObjsProps": "System Objects and Properties", + "SystemObjects": "System Objects", + "StateMgmt": "State Management", + "ForDevs": "For Developers", +} + +for f in files: + filename = f.split("/")[-1] + rstfile = filename[:-5] + ".rst" + + # Skip + if filename in ["adi_bsp.html", "adi_ttb_home.html"]: + continue + + # Handle devices + if f.split("/")[-2] == "devices": + # Create RST + with open(target + "/" + rstfile, "w") as file: + title = filename[:-4] + "\n" + l = "*" * len(title) + "\n" + file.write(title) + file.write(l) + file.write(".. raw:: html\n") + file.write(f" :file: _mlpages/devices/{filename}\n") + with open(target + "/devices.rst", "a") as file: + file.write(f" {title[:-2]} <{rstfile}>\n") + continue + + # Handle other pages + with open(target + "/" + rstfile, "w") as file: + sfile = filename.split(".")[0] + if sfile in titles.keys(): + title = titles[sfile] + "\n" + else: + title = sfile + "\n" + l = "*" * len(title) + "\n" + file.write(title) + file.write(l) + file.write(".. raw:: html\n") + file.write(f" :file: _mlpages/{filename}\n") + if rstfile in ["ForDevs.rst"]: + continue + with open(target + "/index.rst", "a") as file: + file.write(f" {title[:-1]} <{rstfile}>\n") + +# Add to end +with open(target + "/index.rst", "a") as file: + file.write(f" Devices \n") + +with open(target + "/index.rst", "a") as file: + file.write(f" Developers \n") + + diff --git a/CI/gen_doc/gen_pages.sh b/CI/gen_doc/gen_pages.sh new file mode 100644 index 0000000..c2ccf2b --- /dev/null +++ b/CI/gen_doc/gen_pages.sh @@ -0,0 +1,14 @@ + + +cp source/devices.tmpl source/devices.rst +cp source/index.tmpl source/index.rst + +mkdir -p source/_mlpages/devices +cp ../../doc/*.html source/_mlpages/ +mv source/_mlpages/AD*.html source/_mlpages/devices/ +mv source/_mlpages/FMComms*.html source/_mlpages/devices/ +mv source/_mlpages/Pluto*.html source/_mlpages/devices/ +mv source/_mlpages/Pack*.html source/_mlpages/devices/ + +python3 gen_pages.py +make html diff --git a/CI/gen_doc/make.bat b/CI/gen_doc/make.bat new file mode 100644 index 0000000..061f32f --- /dev/null +++ b/CI/gen_doc/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=build + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.https://www.sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/CI/scripts/Docker b/CI/scripts/Docker new file mode 100644 index 0000000..6c95c6f --- /dev/null +++ b/CI/scripts/Docker @@ -0,0 +1,10 @@ +FROM ubuntu:16.04 + +MAINTAINER Travis Collins +RUN DEBIAN_FRONTEND=noninteractive apt update +RUN DEBIAN_FRONTEND=noninteractive apt-get install -y libpng-dev libfreetype6-dev libblas-dev liblapack-dev gfortran build-essential xorg +RUN DEBIAN_FRONTEND=noninteractive apt-get install -y openjdk-8-jre openjdk-8-jdk libgtk2.0-0 libxss1 libxt6 zip unzip curl wget tar git xvfb +RUN DEBIAN_FRONTEND=noninteractive apt-get install -y fakeroot libncurses5-dev libssl-dev ccache dfu-util u-boot-tools device-tree-compiler +RUN DEBIAN_FRONTEND=noninteractive apt-get install -y libssl-dev mtools bc python cpio zip unzip rsync file wget +RUN DEBIAN_FRONTEND=noninteractive dpkg --add-architecture i386 +RUN DEBIAN_FRONTEND=noninteractive apt-get install -y lib32stdc++6 diff --git a/CI/scripts/Makefile b/CI/scripts/Makefile new file mode 100644 index 0000000..4e91c39 --- /dev/null +++ b/CI/scripts/Makefile @@ -0,0 +1,124 @@ +# Usage: +# make MLRELEASE= HDLBRANCH= +# Example +# make build MLRELEASE=R2018b HDLBRANCH=hdl_2018_r1 + +SHELL := /bin/bash + +MLFLAGS := -nodisplay -nodesktop -nosplash + +ifeq ($(MLRELEASE),) +MLRELEASE := R2021b +endif + +ifeq ($(HDLBRANCH),) +HDLBRANCH := hdl_2019_r1 +endif + +ifeq ($(OS),Windows_NT) +MLPATH := /cygdrive/c/Program\ Files/MATLAB +MLFLAGS := $(MLFLAGS) -wait +else +UNAME_S := $(shell uname -s) +ifeq ($(UNAME_S),Linux) +MLPATH := /usr/local/MATLAB +endif +ifeq ($(UNAME_S),Darwin) +MLPATH := /Applications +MLRELEASE := MATLAB_${MLRELEASE}.app +endif +endif + +ifeq ($(BOARD),) +BOARD := +endif + +ifeq ($(INCLUDE_EXAMPLES),) +INCLUDE_EXAMPLES := 1 +endif + +GITTAG := $(shell git describe --tags HEAD) + +.ONESHELL: +build: + # Uses the HDLBRANCH variable + bash build_bsp.sh + +add_libad9361: + cd ../.. ; \ + mkdir deps ; \ + cd deps ; \ + mkdir linux ; \ + cd linux ; \ + wget http://swdownloads.analog.com/cse/travis_builds/master_latest_libad9361-iio-trusty.tar.gz ; \ + tar xvf *.tar.gz ; \ + mv usr/local/lib/* . ; \ + mv usr/local/include ../ ; \ + rm -rf usr ; \ + rm *.tar.gz ; \ + cd .. ; \ + mkdir osx ; \ + cd osx ; \ + wget http://swdownloads.analog.com/cse/travis_builds/master_latest_libad9361-iio-osx_10.12.tar.gz ; \ + tar xvf *.tar.gz ; \ + cd ad9361* ; \ + mv usr/local/lib/ad9361.framework/Versions/Current/ad9361 ../libad9361.dylib ; \ + cd .. ; \ + rm -rf ad9361-*-Darwin ; \ + rm *.tar.gz ; \ + cd .. ; \ + mkdir win ; \ + cd win ; \ + wget "https://github.com/analogdevicesinc/libad9361-iio/releases/download/v0.2/libad9361-0.2-win64.zip" -O lib.zip ; \ + unzip lib.zip ; \ + mv libad9361-win64/* . ; \ + rm -rf libad9361-win64 ; \ + rm *.h ; \ + rm lib.zip + +test_installer: + cd ../.. ; \ + cp *.mltbx test/ ; \ + cp hdl/vendor/AnalogDevices/hdlcoder_board_customization.m test/hdlcoder_board_customization_local.m ; \ + sed -i "s/hdlcoder_board_customization/hdlcoder_board_customization_local/g" test/hdlcoder_board_customization_local.m ; \ + ${MLPATH}/$(MLRELEASE)/bin/matlab $(MLFLAGS) -r "cd('test');runInstallerTests('$(BOARD)');" + +test: + cd ../.. ; \ + ${MLPATH}/$(MLRELEASE)/bin/matlab $(MLFLAGS) -r "cd('test');runTests('$(BOARD)');" + +test_streaming: + cd ../.. ; \ + ${MLPATH}/$(MLRELEASE)/bin/matlab $(MLFLAGS) -r "addpath(genpath('test'));addpath(genpath('deps'));runHWTests;" + +test_evm: + cd ../.. ; \ + ${MLPATH}/$(MLRELEASE)/bin/matlab $(MLFLAGS) -r "addpath(genpath('test'));addpath(genpath('deps'));hwTestRunner;" + +test_modem: + cd ../.. ; \ + ${MLPATH}/$(MLRELEASE)/bin/matlab $(MLFLAGS) -r "addpath(genpath('hdl'));cd('targeting');addpath(genpath('modem-qpsk'))" + +test_synth: + bash synth_designs.sh $(BOARD) + +test_targeting_demos: + bash targeting_designs.sh + +lte_pa_app: + cd ../../trx_examples/streaming/LTE_PA_App/ ; \ + bash genInstaller.sh $(MLPATH) $(MLRELEASE) $(MLFLAGS) + +gen_tlbx: + ${MLPATH}/$(MLRELEASE)/bin/matlab $(MLFLAGS) -r "genTlbx($(INCLUDE_EXAMPLES));exit();" + +linter: + ${MLPATH}/$(MLRELEASE)/bin/matlab $(MLFLAGS) -r "linter;exit();" + +doc: + ${MLPATH}/$(MLRELEASE)/bin/matlab $(MLFLAGS) -r "cd('../doc');genhtml();exit();" + +zip: + cd ../.. ; \ + mkdir zip ; \ + zip -r zip/AnalogDevicesBSP_$(GITTAG).zip deps doc hdl hil_models targeting info.xml LICENSE README.md test/*.log diff --git a/CI/scripts/Makefile2 b/CI/scripts/Makefile2 new file mode 100644 index 0000000..cc2d2d9 --- /dev/null +++ b/CI/scripts/Makefile2 @@ -0,0 +1,128 @@ +# Usage: +# make MLRELEASE= HDLBRANCH= +# Example +# make build MLRELEASE=R2018b HDLBRANCH=hdl_2018_r1 + +SHELL := /bin/bash + +MLFLAGS := -nodisplay -nodesktop -nosplash + +ifeq ($(MLRELEASE),) +MLRELEASE := R2021a +endif + +ifeq ($(HDLBRANCH),) +HDLBRANCH := hdl_2019_r1 +endif + +ifeq ($(OS),Windows_NT) +MLPATH := /cygdrive/c/Program\ Files/MATLAB +MLFLAGS := $(MLFLAGS) -wait +else +UNAME_S := $(shell uname -s) +ifeq ($(UNAME_S),Linux) +MLPATH := /usr/local/MATLAB +endif +ifeq ($(UNAME_S),Darwin) +MLPATH := /Applications +MLRELEASE := MATLAB_${MLRELEASE}.app +endif +endif + +ifeq ($(BOARD),) +BOARD := +endif + +ifeq ($(INCLUDE_EXAMPLES),) +INCLUDE_EXAMPLES := 1 +endif + +GITTAG := $(shell git describe --tags HEAD) + +.ONESHELL: +build: + # Uses the HDLBRANCH variable + bash build_bsp.sh + +add_libad9361: + cd ../.. ; \ + mkdir deps ; \ + cd deps ; \ + mkdir linux ; \ + cd linux ; \ + wget http://swdownloads.analog.com/cse/travis_builds/master_latest_libad9361-iio-trusty.tar.gz ; \ + tar xvf *.tar.gz ; \ + mv usr/local/lib/* . ; \ + mv usr/local/include ../ ; \ + rm -rf usr ; \ + rm *.tar.gz ; \ + cd .. ; \ + mkdir osx ; \ + cd osx ; \ + wget http://swdownloads.analog.com/cse/travis_builds/master_latest_libad9361-iio-osx_10.12.tar.gz ; \ + tar xvf *.tar.gz ; \ + cd ad9361* ; \ + mv usr/local/lib/ad9361.framework/Versions/Current/ad9361 ../libad9361.dylib ; \ + cd .. ; \ + rm -rf ad9361-*-Darwin ; \ + rm *.tar.gz ; \ + cd .. ; \ + mkdir win ; \ + cd win ; \ + wget "https://github.com/analogdevicesinc/libad9361-iio/releases/download/v0.2/libad9361-0.2-win64.zip" -O lib.zip ; \ + unzip lib.zip ; \ + mv libad9361-win64/* . ; \ + rm -rf libad9361-win64 ; \ + rm *.h ; \ + rm lib.zip + +test_installer: + cd ../.. ; \ + cp *.mltbx test/ ; \ + cp hdl/vendor/AnalogDevices/hdlcoder_board_customization.m test/hdlcoder_board_customization_local.m ; \ + sed -i "s/hdlcoder_board_customization/hdlcoder_board_customization_local/g" test/hdlcoder_board_customization_local.m ; \ + ${MLPATH}/$(MLRELEASE)/bin/matlab $(MLFLAGS) -r "cd('test');runInstallerTests('$(BOARD)');" + +test: + cd ../.. ; \ + ${MLPATH}/$(MLRELEASE)/bin/matlab $(MLFLAGS) -r "cd('test');runTests('$(BOARD)');" + +test_ad4130: + cd ../.. ; \ + ${MLPATH}/$(MLRELEASE)/bin/matlab $(MLFLAGS) -r "cd('test');runAD4130Tests('$(BOARD)');" + +test_streaming: + cd ../.. ; \ + ${MLPATH}/$(MLRELEASE)/bin/matlab $(MLFLAGS) -r "addpath(genpath('test'));addpath(genpath('deps'));runHWTests;" + +test_evm: + cd ../.. ; \ + ${MLPATH}/$(MLRELEASE)/bin/matlab $(MLFLAGS) -r "addpath(genpath('test'));addpath(genpath('deps'));hwTestRunner;" + +test_modem: + cd ../.. ; \ + ${MLPATH}/$(MLRELEASE)/bin/matlab $(MLFLAGS) -r "addpath(genpath('hdl'));cd('targeting');addpath(genpath('modem-qpsk'))" + +test_synth: + bash synth_designs.sh $(BOARD) + +test_targeting_demos: + bash targeting_designs.sh + +lte_pa_app: + cd ../../trx_examples/streaming/LTE_PA_App/ ; \ + bash genInstaller.sh $(MLPATH) $(MLRELEASE) $(MLFLAGS) + +gen_tlbx: + ${MLPATH}/$(MLRELEASE)/bin/matlab $(MLFLAGS) -r "genTlbx($(INCLUDE_EXAMPLES));exit();" + +linter: + ${MLPATH}/$(MLRELEASE)/bin/matlab $(MLFLAGS) -r "linter;exit();" + +doc: + ${MLPATH}/$(MLRELEASE)/bin/matlab $(MLFLAGS) -r "cd('../doc');genhtml();exit();" + +zip: + cd ../.. ; \ + mkdir zip ; \ + zip -r zip/AnalogDevicesBSP_$(GITTAG).zip deps doc hdl hil_models targeting info.xml LICENSE README.md test/*.log \ No newline at end of file diff --git a/CI/scripts/adi_build.tcl b/CI/scripts/adi_build.tcl new file mode 100644 index 0000000..f85bf7c --- /dev/null +++ b/CI/scripts/adi_build.tcl @@ -0,0 +1,78 @@ +global fpga_board + +if {[info exists fpga_board]} { + puts "===========" + puts $fpga_board + puts "===========" +} else { + # Set to something not ZCU102 + set fpga_board "ZYNQ" +} + +# Build the project +update_compile_order -fileset sources_1 +reset_run impl_1 +reset_run synth_1 +launch_runs synth_1 +wait_on_run synth_1 +launch_runs impl_1 -to_step write_bitstream +wait_on_run impl_1 + +# Define local variables +set cdir [pwd] +set sdk_loc vivado_prj.sdk + +# Export the hdf +file delete -force $sdk_loc +file mkdir $sdk_loc +file copy -force vivado_prj.runs/impl_1/system_top.sysdef $sdk_loc/system_top.hdf + +# Close the Vivado project +close_project + +# Create the BOOT.bin +#exec xsdk -batch -source $cdir/projects/scripts/fsbl_build.tcl -tclargs $fpga_board -wait + +if {$fpga_board eq "ZCU102"} { + exec hsi -source $cdir/projects/scripts/pmufw_zynqmp.tcl + file copy -force $cdir/projects/scripts/fixmake.sh $cdir/fixmake.sh + exec chmod +x fixmake.sh + + #exec ./fixmake.sh + #cd pmufw + #exec make + #cd .. + if [catch "exec -ignorestderr ./fixmake.sh" ret opt] { + set makeRet [lindex [dict get $opt -errorcode] end] + puts "make returned with $makeRet" + } + if {[file exist pmufw/executable.elf] eq 0} { + puts "ERROR: pmufw not built" + return -code error 10 + } else { + puts "pmufw built correctly!" + } + + exec xsdk -batch -source $cdir/projects/scripts/fsbl_build_zynqmp.tcl + if {[file exist boot/BOOT.BIN] eq 0} { + puts "ERROR: BOOT.BIN not built" + return -code error 11 + } else { + puts "BOOT.BIN built correctly!" + } + +} else { + exec xsdk -batch -source $cdir/projects/scripts/fsbl_build_zynq.tcl + if {[file exist boot/BOOT.BIN] eq 0} { + puts "ERROR: BOOT.BIN not built" + return -code error 11 + } else { + puts "BOOT.BIN built correctly!" + } +} + +puts "------------------------------------" +puts "Embedded system build completed." +puts "You may close this shell." +puts "------------------------------------" +exit diff --git a/CI/scripts/adi_env.tcl b/CI/scripts/adi_env.tcl new file mode 100644 index 0000000..4e48bd9 --- /dev/null +++ b/CI/scripts/adi_env.tcl @@ -0,0 +1,25 @@ + +# environment related stuff + +set ad_hdl_dir [file normalize [file join [file dirname [info script]] "../.."]] + + +if [info exists ::env(ADI_HDL_DIR)] { + set ad_hdl_dir [file normalize $::env(ADI_HDL_DIR)] +} + + +# This helper pocedure retrieves the value of varible from environment if exists, +# other case returns the provided default value +# name - name of the environment variable +# default_value - returned vale in case environment variable does not exists +proc get_env_param {name default_value} { + if [info exists ::env($name)] { + puts "Getting from environment the parameter: $name=$::env($name) " + return $::env($name) + } else { + return $default_value + } +} + + diff --git a/CI/scripts/adi_ip.tcl b/CI/scripts/adi_ip.tcl new file mode 100644 index 0000000..301af4e --- /dev/null +++ b/CI/scripts/adi_ip.tcl @@ -0,0 +1,660 @@ + +source hdl/library/scripts/adi_xilinx_device_info_enc.tcl + +# check tool version + +if {![info exists REQUIRED_VIVADO_VERSION]} { + set REQUIRED_VIVADO_VERSION "2019.1" +} + +if {[info exists ::env(ADI_IGNORE_VERSION_CHECK)]} { + set IGNORE_VERSION_CHECK 1 +} elseif {![info exists IGNORE_VERSION_CHECK]} { + set IGNORE_VERSION_CHECK 0 +} + +## Add a ttcl file to the project. XDC does not support if statements +# in constraint definitions, this file can be used to add parameter dependent +# constraints to the IP. +# +# \param[ip_name] - IP name +# \param[ip_constr_files] - .ttcl file name (full path) +# +proc adi_ip_ttcl {ip_name ip_constr_files} { + + set cdir [pwd] + set m_file "" + set ip_constr_files_clean "" + foreach m_file $ip_constr_files { + file copy -force $m_file $cdir + set m_file [file tail $m_file] + lappend ip_constr_files_clean $m_file + } + set ip_constr_files $ip_constr_files_clean + + set proj_filegroup [ipx::get_file_groups -of_objects [ipx::current_core] -filter {NAME =~ *synthesis*}] + set f [ipx::add_file $ip_constr_files $proj_filegroup] + set_property -dict [list \ + type ttcl \ + ] $f + ipx::reorder_files -front $ip_constr_files $proj_filegroup +} + +## Add ttcl file to generate simulation files for System Verilog environments. +# +# \param[ip_name] - IP name +# \param[ip_constr_files] - .ttcl file name (full path) +# +proc adi_ip_sim_ttcl {ip_name ip_files} { + + set proj_filegroup [ipx::get_file_groups -of_objects [ipx::current_core] -filter {NAME =~ *simulation*}] + set f [ipx::add_file $ip_files $proj_filegroup] + set_property -dict [list \ + type ttcl \ + ] $f + ipx::reorder_files -front $ip_files $proj_filegroup +} + +## Add a block design, defined by a tcl source, to the IP. +# +# \param[ip_name] - IP name +# \param[ip_bd_files] - Tcl source file +# +proc adi_ip_bd {ip_name ip_bd_files} { + set proj_filegroup [ipx::get_file_groups xilinx_blockdiagram -of_objects [ipx::current_core]] + if {$proj_filegroup == {}} { + set proj_filegroup [ipx::add_file_group -type xilinx_blockdiagram "" [ipx::current_core]] + } + + foreach file $ip_bd_files { + set f [ipx::add_file $file $proj_filegroup] + set_property -dict [list \ + type tclSource \ + ] $f + } +} + +## Infers an AXI Streaming interface. Note that the interface has to exist. +# +# \param[ip_name] - IP name +# +proc adi_ip_infer_streaming_interfaces {ip_name} { + + ipx::infer_bus_interfaces xilinx.com:interface:axis_rtl:1.0 [ipx::current_core] + +} + +## Infers an AXI Memory Mapped interface. Note that the interface has to exist. +# +# \param[ip_name] - IP name +# +proc adi_ip_infer_mm_interfaces {ip_name} { + + ipx::infer_bus_interfaces xilinx.com:interface:aximm_rtl:1.0 [ipx::current_core] + +} + +## Defines a dependency for a port. +# +# \param[port_prefix] - Port prefix, which defines an interface. All ports of an +# interface must have the same prefix. If it's a single port, the whole name +# shall be defined. +# \param[dependency] - Dependency (e.g "PARAMETER_NAME == 1") ??? {spirit:decode(id('MODELPARAM_VALUE.PARAM_NAME')) == CONST} +# \param[driver_value] - Driver value is optional. It defines the default driver +# value of the port. +# +proc adi_set_ports_dependency {port_prefix dependency {driver_value {}}} { + foreach port [ipx::get_ports [format "%s%s" $port_prefix "*"]] { + set_property ENABLEMENT_DEPENDENCY $dependency $port + if {$driver_value != {}} { + set_property DRIVER_VALUE $driver_value $port + } + } +} + +## Defines a dependency for a bus. +# +# \param[bus] - Name of the bus +# \param[prefix] - Port prefix, in general same as the name of the bus +# \param[dependency] - Dependency (e.g "PARAMETER_NAME == 1") ??? {spirit:decode(id('MODELPARAM_VALUE.PARAM_NAME')) == CONST} +# +proc adi_set_bus_dependency {bus prefix dependency} { + set_property ENABLEMENT_DEPENDENCY $dependency [ipx::get_bus_interfaces $bus -of_objects [ipx::current_core]] + adi_set_ports_dependency $prefix $dependency 0 +} + +## Add a new port map definition to a bus interface. +# +# \param[bus] - Name of the bus interface +# \param[phys] - Physical name of the port +# \param[logic] - Logic name of the port (defined by the interface) +# +proc adi_add_port_map {bus phys logic} { + set map [ipx::add_port_map $phys $bus] + set_property "PHYSICAL_NAME" $phys $map + set_property "LOGICAL_NAME" $logic $map +} + +## Infers a new bus interface to an IP. +# +# \param[bus_name] - Bus name +# \param[mode] - Interface mode (master/slave) +# \param[abs_type] - Abstraction type, example: "xilinx.com:interface:axis_rtl:1.0" +# \param[bus_type] - Bus type, example: "xilinx.com:interface:axis:1.0" +# \param[port_maps] - Port map +# +# Port map example:\n +# [list \n +# {"m_axis_ready" "TREADY"}\n +# {"m_axis_valid" "TVALID"}\n +# {"m_axis_data" "TDATA"} ]\n + +proc adi_add_bus {bus_name mode abs_type bus_type port_maps} { + set bus [ipx::add_bus_interface $bus_name [ipx::current_core]] + + set_property "ABSTRACTION_TYPE_VLNV" $abs_type $bus + set_property "BUS_TYPE_VLNV" $bus_type $bus + set_property "INTERFACE_MODE" $mode $bus + + foreach port_map $port_maps { + adi_add_port_map $bus {*}$port_map + } +} + +## Add multiple bus interfaces of the same type to an IP. +# +# \param[num] - Number of interfaces +# \param[bus_name_prefix] - Prefix of the name of the interface +# \param[mode] - Interface mode (master/slave) +# \param[abs_type] - Abstraction type, example: "xilinx.com:interface:axis_rtl:1.0" +# \param[bus_type] - Bus type, example: "xilinx.com:interface:axis:1.0" +# \param[port_maps] - Port map, example: [list \n +# {"m_axis_ready" "TREADY"}\n +# {"m_axis_valid" "TVALID"}\n: +# {"m_axis_data" "TDATA"} ]\n +# \param[dependency] - Dependency (e.g "PARAMETER_NAME == 1") ??? {spirit:decode(id('MODELPARAM_VALUE.PARAM_NAME')) == CONST} +# +proc adi_add_multi_bus {num bus_name_prefix mode abs_type bus_type port_maps dependency} { + for {set i 0} {$i < $num} {incr i} { + set bus_name [format "%s%d" $bus_name_prefix $i] + set bus [ipx::add_bus_interface $bus_name [ipx::current_core]] + + set_property "ABSTRACTION_TYPE_VLNV" $abs_type $bus + set_property "BUS_TYPE_VLNV" $bus_type $bus + set_property "INTERFACE_MODE" $mode $bus + + if {$dependency ne ""} { + set bus_dependency [string map [list "{i}" $i] $dependency] + set_property ENABLEMENT_DEPENDENCY $bus_dependency $bus + } + + foreach port_map $port_maps { + lassign $port_map phys logic width + set map [ipx::add_port_map $phys $bus] + set_property "PHYSICAL_NAME" $phys $map + set_property "LOGICAL_NAME" $logic $map + set_property "PHYSICAL_RIGHT" [expr $i*$width] $map + set_property "PHYSICAL_LEFT" [expr ($i+1)*$width-1] $map + } + } +} + +## Assign clock and reset to an interface bus. +# +# \param[clock_signal_name] - Clock name +# \param[bus_inf_name] - Interface bus name. Note: If multiple interfaces uses +# the same clock, all shall be defined here. (e.g. "s_axis:m_axis") +# \param[reset_signal_name] - Reset signal name +# \param[reset_signal_mode] - Reset mode (master/slave) +# +proc adi_add_bus_clock {clock_signal_name bus_inf_name {reset_signal_name ""} {reset_signal_mode "slave"}} { + set bus_inf_name_clean [string map {":" "_"} $bus_inf_name] + set clock_inf_name [format "%s%s" $bus_inf_name_clean "_signal_clock"] + set clock_inf [ipx::add_bus_interface $clock_inf_name [ipx::current_core]] + set_property abstraction_type_vlnv "xilinx.com:signal:clock_rtl:1.0" $clock_inf + set_property bus_type_vlnv "xilinx.com:signal:clock:1.0" $clock_inf + set_property display_name $clock_inf_name $clock_inf + set clock_map [ipx::add_port_map "CLK" $clock_inf] + set_property physical_name $clock_signal_name $clock_map + + set assoc_busif [ipx::add_bus_parameter "ASSOCIATED_BUSIF" $clock_inf] + set_property value $bus_inf_name $assoc_busif + + if { $reset_signal_name != "" } { + set assoc_reset [ipx::add_bus_parameter "ASSOCIATED_RESET" $clock_inf] + set_property value $reset_signal_name $assoc_reset + + set reset_inf_name [format "%s%s" $bus_inf_name_clean "_signal_reset"] + set reset_inf [ipx::add_bus_interface $reset_inf_name [ipx::current_core]] + set_property abstraction_type_vlnv "xilinx.com:signal:reset_rtl:1.0" $reset_inf + set_property bus_type_vlnv "xilinx.com:signal:reset:1.0" $reset_inf + set_property display_name $reset_inf_name $reset_inf + set_property interface_mode $reset_signal_mode $reset_inf + set reset_map [ipx::add_port_map "RST" $reset_inf] + set_property physical_name $reset_signal_name $reset_map + + set reset_polarity [ipx::add_bus_parameter "POLARITY" $reset_inf] + if {[string match {*[Nn]} $reset_signal_name] == 1} { + set_property value "ACTIVE_LOW" $reset_polarity + } else { + set_property value "ACTIVE_HIGH" $reset_polarity + } + } +} + +## Defines an IP as the current IP's dependency. +# +# \param[vlnvs] - VLNVs of the instantiated IPs (e.g. "analog.com:user:util_cdc:1.0") +# +proc adi_ip_add_core_dependencies {vlnvs} { + foreach file_group [ipx::get_file_groups * -of_objects [ipx::current_core]] { + foreach vlnv $vlnvs { + ipx::add_subcore $vlnv $file_group + } + } +} + +## List of all constraint files +# +set ip_constr_files "" + +## Create a project which will be packed as an IP. +# +# \param[ip_name] - IP name +# +proc adi_ip_create {ip_name} { + + global ad_hdl_dir + global ad_ghdl_dir + global ip_constr_files + global REQUIRED_VIVADO_VERSION + global IGNORE_VERSION_CHECK + + set VIVADO_VERSION [version -short] + if {[string compare $VIVADO_VERSION $REQUIRED_VIVADO_VERSION] != 0} { + puts -nonewline "CRITICAL WARNING: vivado version mismatch; " + puts -nonewline "expected $REQUIRED_VIVADO_VERSION, " + puts -nonewline "got $VIVADO_VERSION.\n" + } + + create_project $ip_name . -force + + ## Load custom message severity definitions + source $ad_hdl_dir/projects/scripts/adi_xilinx_msg.tcl + + set ip_constr_files "" + set lib_dirs $ad_hdl_dir/library + if {$ad_hdl_dir ne $ad_ghdl_dir} { + lappend lib_dirs $ad_ghdl_dir/library + } + + set_property ip_repo_paths $lib_dirs [current_fileset] + update_ip_catalog +} + +## Add all source files to the IP's project. +# +# \param[ip_name] - The ip name +# \param[ip_files] - IP files (*.v *.vhd *.xdc) +# +proc adi_ip_files {ip_name ip_files} { + + global ip_constr_files + + set cdir [pwd] + set ip_constr_files "" + set ip_files_clean "" + foreach m_file $ip_files { + file copy -force $m_file $cdir + set m_file [file tail $m_file] + puts $m_file + if {[file extension $m_file] eq ".xdc"} { + lappend ip_constr_files $m_file + } + lappend ip_files_clean $m_file + } + + set ip_files $ip_files_clean + + set proj_fileset [get_filesets sources_1] + add_files -norecurse -scan_for_includes -fileset $proj_fileset $ip_files + add_files -norecurse -copy_to $cdir -force -fileset $proj_fileset $ip_files + set_property "top" "$ip_name" $proj_fileset +} + +## Pack the IP and set its proprieties. +# +# \param[ip_name] - The ip name +# +proc adi_ip_properties_lite {ip_name} { + + global ip_constr_files + + ipx::package_project -root_dir . -vendor analog.com -library user -taxonomy /Analog_Devices + set_property name $ip_name [ipx::current_core] + set_property vendor_display_name {Analog Devices} [ipx::current_core] + set_property company_url {http://www.analog.com} [ipx::current_core] + + set i_families "" + foreach i_part [get_parts] { + lappend i_families [get_property FAMILY $i_part] + } + set i_families [lsort -unique $i_families] + set s_families [get_property supported_families [ipx::current_core]] + foreach i_family $i_families { + set s_families "$s_families $i_family Production" + set s_families "$s_families $i_family Beta" + } + set_property supported_families $s_families [ipx::current_core] + ipx::save_core + + ipx::remove_all_bus_interface [ipx::current_core] + set memory_maps [ipx::get_memory_maps * -of_objects [ipx::current_core]] + foreach map $memory_maps { + ipx::remove_memory_map [lindex $map 2] [ipx::current_core ] + } + ipx::save_core + + set i_filegroup [ipx::get_file_groups -of_objects [ipx::current_core] -filter {NAME =~ *synthesis*}] + foreach i_file $ip_constr_files { + set i_module [file tail $i_file] + regsub {_constr\.xdc} $i_module {} i_module + ipx::add_file $i_file $i_filegroup + ipx::reorder_files -front $i_file $i_filegroup + set_property SCOPED_TO_REF $i_module [ipx::get_files $i_file -of_objects $i_filegroup] + } + ipx::save_core +} + +## Set AXI interface IP proprieties. +# +# \param[ip_name] - The ip name +# +proc adi_ip_properties {ip_name} { + + adi_ip_properties_lite $ip_name + + ipx::infer_bus_interface {\ + s_axi_awvalid \ + s_axi_awaddr \ + s_axi_awprot \ + s_axi_awready \ + s_axi_wvalid \ + s_axi_wdata \ + s_axi_wstrb \ + s_axi_wready \ + s_axi_bvalid \ + s_axi_bresp \ + + s_axi_bready \ + s_axi_arvalid \ + s_axi_araddr \ + s_axi_arprot \ + s_axi_arready \ + s_axi_rvalid \ + s_axi_rdata \ + s_axi_rresp \ + s_axi_rready} \ + xilinx.com:interface:aximm_rtl:1.0 [ipx::current_core] + + ipx::infer_bus_interface s_axi_aclk xilinx.com:signal:clock_rtl:1.0 [ipx::current_core] + ipx::infer_bus_interface s_axi_aresetn xilinx.com:signal:reset_rtl:1.0 [ipx::current_core] + + set raddr_width [expr [get_property SIZE_LEFT [ipx::get_ports -nocase true s_axi_araddr -of_objects [ipx::current_core]]] + 1] + set waddr_width [expr [get_property SIZE_LEFT [ipx::get_ports -nocase true s_axi_awaddr -of_objects [ipx::current_core]]] + 1] + + if {$raddr_width != $waddr_width} { + puts [format "WARNING: AXI address width mismatch for %s (r=%d, w=%d)" $ip_name $raddr_width, $waddr_width] + set range 65536 + } else { + if {$raddr_width >= 16} { + set range 65536 + } else { + set range [expr 1 << $raddr_width] + } + } + + ipx::add_memory_map {s_axi} [ipx::current_core] + set_property slave_memory_map_ref {s_axi} [ipx::get_bus_interfaces s_axi -of_objects [ipx::current_core]] + ipx::add_address_block {axi_lite} [ipx::get_memory_maps s_axi -of_objects [ipx::current_core]] + set_property range $range [ipx::get_address_blocks axi_lite \ + -of_objects [ipx::get_memory_maps s_axi -of_objects [ipx::current_core]]] + ipx::associate_bus_interfaces -clock s_axi_aclk -reset s_axi_aresetn [ipx::current_core] + ipx::save_core +} + +## Create/overwrite temporary files containing particular build case dependencies. +# +# DO NOT USE FOR: axi_dmac/jesd204/axi_clkgen +# +proc adi_init_bd_tcl {} { + + global auto_set_param_list + global auto_set_param_list_overwritable + set cc [ipx::current_core] + + if { [file exists bd] } { + file delete -force bd + } + file mkdir bd + + set bd_tcl [open "bd/bd.tcl" w] + + puts $bd_tcl "# SCRIPT AUTO-GENERATED AT BUILD, DO NOT MODIFY!" + puts $bd_tcl "proc init {cellpath otherInfo} {" + puts $bd_tcl " set ip \[get_bd_cells \$cellpath\]" + puts $bd_tcl "" + set auto_set_param "" + foreach i $auto_set_param_list { + if { [ipx::get_user_parameters $i -of_objects $cc -quiet] ne "" } { + append auto_set_param " $i \\\n" + } + } + if { $auto_set_param ne "" } { + puts $bd_tcl " bd::mark_propagate_only \$ip \" \\" + regsub "${i} \\\\" $auto_set_param "$i\"" auto_set_param + puts $bd_tcl $auto_set_param + } + + set auto_set_overwritable_param "" + foreach i $auto_set_param_list_overwritable { + if { [ipx::get_user_parameters $i -of_objects $cc -quiet] ne "" } { + append auto_set_overwritable_param " $i \\\n" + } + } + if { $auto_set_overwritable_param ne "" } { + puts $bd_tcl " bd::mark_propagate_override \$ip \" \\" + regsub "${i} \\\\" $auto_set_overwritable_param "$i\"" auto_set_overwritable_param + puts $bd_tcl $auto_set_overwritable_param + } + puts $bd_tcl " adi_auto_assign_device_spec \$cellpath" + puts $bd_tcl "}" + puts $bd_tcl "" + puts $bd_tcl "# auto set parameters defined in auto_set_param_list (adi_xilinx_device_info_enc.tcl)" + puts $bd_tcl "proc adi_auto_assign_device_spec {cellpath} {" + puts $bd_tcl "" + puts $bd_tcl " set ip \[get_bd_cells \$cellpath\]" + puts $bd_tcl " set ip_param_list \[list_property \$ip\]" + puts $bd_tcl " set ip_path \[bd::get_vlnv_dir \[get_property VLNV \$ip\]\]" + puts $bd_tcl "" + puts $bd_tcl " set parent_dir \"../\"" + puts $bd_tcl " for {set x 1} {\$x<=4} {incr x} {" + puts $bd_tcl " set linkname \${ip_path}\${parent_dir}scripts/adi_xilinx_device_info_enc.tcl" + puts $bd_tcl " if { \[file exists \$linkname\] } {" + puts $bd_tcl " source \${ip_path}\${parent_dir}/scripts/adi_xilinx_device_info_enc.tcl" + puts $bd_tcl " break" + puts $bd_tcl " }" + puts $bd_tcl " append parent_dir \"../\"" + puts $bd_tcl " }" + puts $bd_tcl "" + puts $bd_tcl " # Find predefindes auto assignable parameters" + puts $bd_tcl " foreach i \$auto_set_param_list {" + puts $bd_tcl " if { \[lsearch \$ip_param_list \"CONFIG.\$i\"\] > 0 } {" + puts $bd_tcl " set val \[adi_device_spec \$cellpath \$i\]" + puts $bd_tcl " set_property CONFIG.\$i \$val \$ip" + puts $bd_tcl " }" + puts $bd_tcl " }" + puts $bd_tcl "" + puts $bd_tcl " # Find predefindes auto assignable/overwritable parameters" + puts $bd_tcl " foreach i \$auto_set_param_list_overwritable {" + puts $bd_tcl " if { \[lsearch \$ip_param_list \"CONFIG.\$i\"\] > 0 } {" + puts $bd_tcl " set val \[adi_device_spec \$cellpath \$i\]" + puts $bd_tcl " set_property CONFIG.\$i \$val \$ip" + puts $bd_tcl " }" + puts $bd_tcl " }" + puts $bd_tcl "}" + puts $bd_tcl "" + close $bd_tcl + + set proj_fileset [get_filesets sources_1] + add_files -norecurse -scan_for_includes -fileset $proj_fileset "bd/bd.tcl" + + set local_mk [open "temporary_case_dependencies.mk" w] + seek $local_mk 0 start + puts $local_mk "CLEAN_TARGET += bd" + puts $local_mk "CLEAN_TARGET += temporary_case_dependencies.mk" + close $local_mk +} + +## Search after device specific parameters and call the adi_add_device_spec_param +# process with the result. The list of these parameters are defined in +# library/scripts/adi_xilinx_device_info_enc.tcl +# +proc adi_add_auto_fpga_spec_params {} { + + global auto_set_param_list + global auto_set_param_list_overwritable + set cc [ipx::current_core] + + foreach i $auto_set_param_list { + if { [ipx::get_user_parameters $i -of_objects $cc -quiet] ne ""} { + adi_add_device_spec_param $i + } + } + foreach i $auto_set_param_list_overwritable { + if { [ipx::get_user_parameters $i -of_objects $cc -quiet] ne ""} { + adi_add_device_spec_param $i + } + } +} + +## Generate validation properties for a parameter, using predefined ranges or +# set of values (the definition of the ranges can be found in +# library/scripts/adi_xilinx_device_info_enc.tcl). +# +# \param[ip_parameter] - name of the HDL parameter +# +proc adi_add_device_spec_param {ip_param} { + + set cc [ipx::current_core] + + set list_pointer [string tolower $ip_param] + set list_pointer [append list_pointer "_list"] + + global $list_pointer + + # set j 1D list from the original list + foreach i [subst $$list_pointer] {lappend j [lindex $i 0] [lindex $i 1]} + + # set ranges or validation pairs (show x in GUI assign the corresponding y to HDL) + if { [llength [subst $$list_pointer]] == 2 && [llength $j] == 4} { + set_property -dict [list \ + "value_validation_type" "range" \ + "value_validation_range_minimum" [lindex [subst $$list_pointer] 0] \ + "value_validation_range_maximum" [lindex [subst $$list_pointer] 1] ] \ + [ipx::get_user_parameters $ip_param -of_objects $cc] + } else { + set_property -dict [list \ + "value_validation_type" "pairs" \ + "value_validation_pairs" $j ] \ + [ipx::get_user_parameters $ip_param -of_objects $cc] + } + + # FPGA info grup + set info_group_name "FPGA info" + set info_group [ipgui::get_groupspec -name $info_group_name -component $cc -quiet] + if { [string trim $info_group] eq "" } { + set page0 [ipgui::get_pagespec -name "Page 0" -component $cc] + set info_group [ipgui::add_group -name $info_group_name -component $cc \ + -parent $page0 -display_name $info_group_name] + } + + set p [ipgui::get_guiparamspec -name $ip_param -component $cc] + set_property -dict [list "widget" "comboBox" ] $p + ipgui::move_param -component $cc -order 0 $p -parent $info_group +} + +## Define a custom interface bus. +# +# \param[name] - Interface name +# +proc adi_if_define {name} { + + ipx::create_abstraction_definition analog.com interface ${name}_rtl 1.0 + ipx::create_bus_definition analog.com interface $name 1.0 + + set_property xml_file_name ${name}_rtl.xml [ipx::current_busabs] + set_property xml_file_name ${name}.xml [ipx::current_busdef] + set_property bus_type_vlnv analog.com:interface:${name}:1.0 [ipx::current_busabs] + + ipx::save_abstraction_definition [ipx::current_busabs] + ipx::save_bus_definition [ipx::current_busdef] +} + +## Add ports to a custom interface bus. +# +# \param[dir] - Port direction +# \param[width] - Port width +# \param[name] - Port logical name +# \param[type] - Type of the port (default "none") +# +proc adi_if_ports {dir width name {type none}} { + + ipx::add_bus_abstraction_port $name [ipx::current_busabs] + set m_intf [ipx::get_bus_abstraction_ports $name -of_objects [ipx::current_busabs]] + set_property master_presence required $m_intf + set_property slave_presence required $m_intf + set_property master_width $width $m_intf + set_property slave_width $width $m_intf + + set m_dir "in" + set s_dir "out" + if {$dir eq "output"} { + set m_dir "out" + set s_dir "in" + } + + set_property master_direction $m_dir $m_intf + set_property slave_direction $s_dir $m_intf + + if {$type ne "none"} { + set_property is_${type} true $m_intf + } + + ipx::save_bus_definition [ipx::current_busdef] + ipx::save_abstraction_definition [ipx::current_busabs] +} + +## Infers a new bus interface to an IP. +# +# \param[if_name] - Interface bus name +# \param[mode] - Type of the interface bus (master/slave) +# \param[name] - Interface bus instance name +# \param[maps] - Mapping of the physical ports +# +proc adi_if_infer_bus {if_name mode name maps} { + + ipx::add_bus_interface $name [ipx::current_core] + set m_bus_if [ipx::get_bus_interfaces $name -of_objects [ipx::current_core]] + set_property abstraction_type_vlnv ${if_name}_rtl:1.0 $m_bus_if + set_property bus_type_vlnv ${if_name}:1.0 $m_bus_if + set_property interface_mode $mode $m_bus_if + + foreach map $maps { + set m_maps [regexp -all -inline {\S+} $map] + lassign $m_maps p_name p_map + ipx::add_port_map $p_name $m_bus_if + set_property physical_name $p_map [ipx::get_port_maps $p_name -of_objects $m_bus_if] + } +} + diff --git a/CI/scripts/adi_ip_xilinx.tcl b/CI/scripts/adi_ip_xilinx.tcl new file mode 100644 index 0000000..45fdadb --- /dev/null +++ b/CI/scripts/adi_ip_xilinx.tcl @@ -0,0 +1,657 @@ + +source $ad_hdl_dir/library/scripts/adi_xilinx_device_info_enc.tcl + +# check tool version + +if {![info exists REQUIRED_VIVADO_VERSION]} { + set REQUIRED_VIVADO_VERSION "2019.1" +} + +if {[info exists ::env(ADI_IGNORE_VERSION_CHECK)]} { + set IGNORE_VERSION_CHECK 1 +} elseif {![info exists IGNORE_VERSION_CHECK]} { + set IGNORE_VERSION_CHECK 0 +} + +## Add a ttcl file to the project. XDC does not support if statements +# in constraint definitions, this file can be used to add parameter dependent +# constraints to the IP. +# +# \param[ip_name] - IP name +# \param[ip_constr_files] - .ttcl file name (full path) +# +proc adi_ip_ttcl {ip_name ip_constr_files} { + + set cdir [pwd] + set m_file "" + set ip_constr_files_clean "" + foreach m_file $ip_constr_files { + file copy -force $m_file $cdir + set m_file [file tail $m_file] + lappend ip_constr_files_clean $m_file + } + set ip_constr_files $ip_constr_files_clean + + set proj_filegroup [ipx::get_file_groups -of_objects [ipx::current_core] -filter {NAME =~ *synthesis*}] + set f [ipx::add_file $ip_constr_files $proj_filegroup] + set_property -dict [list \ + type ttcl \ + ] $f + ipx::reorder_files -front $ip_constr_files $proj_filegroup +} + +## Add ttcl file to generate simulation files for System Verilog environments. +# +# \param[ip_name] - IP name +# \param[ip_constr_files] - .ttcl file name (full path) +# +proc adi_ip_sim_ttcl {ip_name ip_files} { + + set proj_filegroup [ipx::get_file_groups -of_objects [ipx::current_core] -filter {NAME =~ *simulation*}] + set f [ipx::add_file $ip_files $proj_filegroup] + set_property -dict [list \ + type ttcl \ + ] $f + ipx::reorder_files -front $ip_files $proj_filegroup +} + +## Add a block design, defined by a tcl source, to the IP. +# +# \param[ip_name] - IP name +# \param[ip_bd_files] - Tcl source file +# +proc adi_ip_bd {ip_name ip_bd_files} { + set proj_filegroup [ipx::get_file_groups xilinx_blockdiagram -of_objects [ipx::current_core]] + if {$proj_filegroup == {}} { + set proj_filegroup [ipx::add_file_group -type xilinx_blockdiagram "" [ipx::current_core]] + } + + foreach file $ip_bd_files { + set f [ipx::add_file $file $proj_filegroup] + set_property -dict [list \ + type tclSource \ + ] $f + } +} + +## Infers an AXI Streaming interface. Note that the interface has to exist. +# +# \param[ip_name] - IP name +# +proc adi_ip_infer_streaming_interfaces {ip_name} { + + ipx::infer_bus_interfaces xilinx.com:interface:axis_rtl:1.0 [ipx::current_core] + +} + +## Infers an AXI Memory Mapped interface. Note that the interface has to exist. +# +# \param[ip_name] - IP name +# +proc adi_ip_infer_mm_interfaces {ip_name} { + + ipx::infer_bus_interfaces xilinx.com:interface:aximm_rtl:1.0 [ipx::current_core] + +} + +## Defines a dependency for a port. +# +# \param[port_prefix] - Port prefix, which defines an interface. All ports of an +# interface must have the same prefix. If it's a single port, the whole name +# shall be defined. +# \param[dependency] - Dependency (e.g "PARAMETER_NAME == 1") ??? {spirit:decode(id('MODELPARAM_VALUE.PARAM_NAME')) == CONST} +# \param[driver_value] - Driver value is optional. It defines the default driver +# value of the port. +# +proc adi_set_ports_dependency {port_prefix dependency {driver_value {}}} { + foreach port [ipx::get_ports [format "%s%s" $port_prefix "*"]] { + set_property ENABLEMENT_DEPENDENCY $dependency $port + if {$driver_value != {}} { + set_property DRIVER_VALUE $driver_value $port + } + } +} + +## Defines a dependency for a bus. +# +# \param[bus] - Name of the bus +# \param[prefix] - Port prefix, in general same as the name of the bus +# \param[dependency] - Dependency (e.g "PARAMETER_NAME == 1") ??? {spirit:decode(id('MODELPARAM_VALUE.PARAM_NAME')) == CONST} +# +proc adi_set_bus_dependency {bus prefix dependency} { + set_property ENABLEMENT_DEPENDENCY $dependency [ipx::get_bus_interfaces $bus -of_objects [ipx::current_core]] + adi_set_ports_dependency $prefix $dependency 0 +} + +## Add a new port map definition to a bus interface. +# +# \param[bus] - Name of the bus interface +# \param[phys] - Physical name of the port +# \param[logic] - Logic name of the port (defined by the interface) +# +proc adi_add_port_map {bus phys logic} { + set map [ipx::add_port_map $phys $bus] + set_property "PHYSICAL_NAME" $phys $map + set_property "LOGICAL_NAME" $logic $map +} + +## Infers a new bus interface to an IP. +# +# \param[bus_name] - Bus name +# \param[mode] - Interface mode (master/slave) +# \param[abs_type] - Abstraction type, example: "xilinx.com:interface:axis_rtl:1.0" +# \param[bus_type] - Bus type, example: "xilinx.com:interface:axis:1.0" +# \param[port_maps] - Port map +# +# Port map example:\n +# [list \n +# {"m_axis_ready" "TREADY"}\n +# {"m_axis_valid" "TVALID"}\n +# {"m_axis_data" "TDATA"} ]\n + +proc adi_add_bus {bus_name mode abs_type bus_type port_maps} { + set bus [ipx::add_bus_interface $bus_name [ipx::current_core]] + + set_property "ABSTRACTION_TYPE_VLNV" $abs_type $bus + set_property "BUS_TYPE_VLNV" $bus_type $bus + set_property "INTERFACE_MODE" $mode $bus + + foreach port_map $port_maps { + adi_add_port_map $bus {*}$port_map + } +} + +## Add multiple bus interfaces of the same type to an IP. +# +# \param[num] - Number of interfaces +# \param[bus_name_prefix] - Prefix of the name of the interface +# \param[mode] - Interface mode (master/slave) +# \param[abs_type] - Abstraction type, example: "xilinx.com:interface:axis_rtl:1.0" +# \param[bus_type] - Bus type, example: "xilinx.com:interface:axis:1.0" +# \param[port_maps] - Port map, example: [list \n +# {"m_axis_ready" "TREADY"}\n +# {"m_axis_valid" "TVALID"}\n: +# {"m_axis_data" "TDATA"} ]\n +# \param[dependency] - Dependency (e.g "PARAMETER_NAME == 1") ??? {spirit:decode(id('MODELPARAM_VALUE.PARAM_NAME')) == CONST} +# +proc adi_add_multi_bus {num bus_name_prefix mode abs_type bus_type port_maps dependency} { + for {set i 0} {$i < $num} {incr i} { + set bus_name [format "%s%d" $bus_name_prefix $i] + set bus [ipx::add_bus_interface $bus_name [ipx::current_core]] + + set_property "ABSTRACTION_TYPE_VLNV" $abs_type $bus + set_property "BUS_TYPE_VLNV" $bus_type $bus + set_property "INTERFACE_MODE" $mode $bus + + if {$dependency ne ""} { + set bus_dependency [string map [list "{i}" $i] $dependency] + set_property ENABLEMENT_DEPENDENCY $bus_dependency $bus + } + + foreach port_map $port_maps { + lassign $port_map phys logic width width_dep + set map [ipx::add_port_map $phys $bus] + set_property "PHYSICAL_NAME" $phys $map + set_property "LOGICAL_NAME" $logic $map + set_property "PHYSICAL_RIGHT" [expr $i*$width] $map + set_property "PHYSICAL_LEFT" [expr ($i+1)*$width-1] $map + if {$width_dep ne ""} { + set_property "PHYSICAL_RIGHT_RESOLVE_TYPE" "dependent" $map + set_property "PHYSICAL_LEFT_RESOLVE_TYPE" "dependent" $map + set width_dep_r "(($width_dep) * $i)" + set width_dep_l "(($width_dep) * ($i + 1)-1)" + set_property "PHYSICAL_RIGHT_DEPENDENCY" $width_dep_r $map + set_property "PHYSICAL_LEFT_DEPENDENCY" $width_dep_l $map + } + } + } +} + +## Assign clock and reset to an interface bus. +# +# \param[clock_signal_name] - Clock name +# \param[bus_inf_name] - Interface bus name. Note: If multiple interfaces uses +# the same clock, all shall be defined here. (e.g. "s_axis:m_axis") +# \param[reset_signal_name] - Reset signal name +# \param[reset_signal_mode] - Reset mode (master/slave) +# +proc adi_add_bus_clock {clock_signal_name bus_inf_name {reset_signal_name ""} {reset_signal_mode "slave"}} { + set bus_inf_name_clean [string map {":" "_"} $bus_inf_name] + set clock_inf_name [format "%s%s" $bus_inf_name_clean "_signal_clock"] + set clock_inf [ipx::add_bus_interface $clock_inf_name [ipx::current_core]] + set_property abstraction_type_vlnv "xilinx.com:signal:clock_rtl:1.0" $clock_inf + set_property bus_type_vlnv "xilinx.com:signal:clock:1.0" $clock_inf + set_property display_name $clock_inf_name $clock_inf + set clock_map [ipx::add_port_map "CLK" $clock_inf] + set_property physical_name $clock_signal_name $clock_map + + set assoc_busif [ipx::add_bus_parameter "ASSOCIATED_BUSIF" $clock_inf] + set_property value $bus_inf_name $assoc_busif + + if { $reset_signal_name != "" } { + set assoc_reset [ipx::add_bus_parameter "ASSOCIATED_RESET" $clock_inf] + set_property value $reset_signal_name $assoc_reset + + set reset_inf_name [format "%s%s" $bus_inf_name_clean "_signal_reset"] + set reset_inf [ipx::add_bus_interface $reset_inf_name [ipx::current_core]] + set_property abstraction_type_vlnv "xilinx.com:signal:reset_rtl:1.0" $reset_inf + set_property bus_type_vlnv "xilinx.com:signal:reset:1.0" $reset_inf + set_property display_name $reset_inf_name $reset_inf + set_property interface_mode $reset_signal_mode $reset_inf + set reset_map [ipx::add_port_map "RST" $reset_inf] + set_property physical_name $reset_signal_name $reset_map + + set reset_polarity [ipx::add_bus_parameter "POLARITY" $reset_inf] + if {[string match {*[Nn]} $reset_signal_name] == 1} { + set_property value "ACTIVE_LOW" $reset_polarity + } else { + set_property value "ACTIVE_HIGH" $reset_polarity + } + } +} + +## Defines an IP as the current IP's dependency. +# +# \param[vlnvs] - VLNVs of the instantiated IPs (e.g. "analog.com:user:util_cdc:1.0") +# +proc adi_ip_add_core_dependencies {vlnvs} { + foreach file_group [ipx::get_file_groups * -of_objects [ipx::current_core]] { + foreach vlnv $vlnvs { + ipx::add_subcore $vlnv $file_group + } + } +} + +## List of all constraint files +# +set ip_constr_files "" + +## Create a project which will be packed as an IP. +# +# \param[ip_name] - IP name +# +proc adi_ip_create {ip_name} { + + global ad_hdl_dir + global ip_constr_files + global REQUIRED_VIVADO_VERSION + global IGNORE_VERSION_CHECK + + set VIVADO_VERSION [version -short] + if {[string compare $VIVADO_VERSION $REQUIRED_VIVADO_VERSION] != 0} { + puts -nonewline "CRITICAL WARNING: vivado version mismatch; " + puts -nonewline "expected $REQUIRED_VIVADO_VERSION, " + puts -nonewline "got $VIVADO_VERSION.\n" + } + + create_project $ip_name . -force + + ## Load custom message severity definitions + source $ad_hdl_dir/projects/scripts/adi_xilinx_msg.tcl + + set ip_constr_files "" + set lib_dirs $ad_hdl_dir/library + + set_property ip_repo_paths $lib_dirs [current_fileset] + update_ip_catalog +} + +## Add all source files to the IP's project. +# +# \param[ip_name] - The ip name +# \param[ip_files] - IP files (*.v *.vhd *.xdc) +# +proc adi_ip_files {ip_name ip_files} { + + global ip_constr_files + + set cdir [pwd] + set ip_constr_files "" + set ip_files_clean "" + foreach m_file $ip_files { + file copy -force $m_file $cdir + set m_file [file tail $m_file] + puts $m_file + if {[file extension $m_file] eq ".xdc"} { + lappend ip_constr_files $m_file + } + lappend ip_files_clean $m_file + } + + set ip_files $ip_files_clean + + set proj_fileset [get_filesets sources_1] + add_files -norecurse -scan_for_includes -fileset $proj_fileset $ip_files + add_files -norecurse -copy_to $cdir -force -fileset $proj_fileset $ip_files + set_property "top" "$ip_name" $proj_fileset +} + +## Pack the IP and set its proprieties. +# +# \param[ip_name] - The ip name +# +proc adi_ip_properties_lite {ip_name} { + + global ip_constr_files + + ipx::package_project -root_dir . -vendor analog.com -library user -taxonomy /Analog_Devices + set_property name $ip_name [ipx::current_core] + set_property vendor_display_name {Analog Devices} [ipx::current_core] + set_property company_url {http://www.analog.com} [ipx::current_core] + + set i_families "" + foreach i_part [get_parts] { + lappend i_families [get_property FAMILY $i_part] + } + set i_families [lsort -unique $i_families] + set s_families [get_property supported_families [ipx::current_core]] + foreach i_family $i_families { + set s_families "$s_families $i_family Production" + set s_families "$s_families $i_family Beta" + } + set_property supported_families $s_families [ipx::current_core] + + ipx::save_core [ipx::current_core] + + ipx::remove_all_bus_interface [ipx::current_core] + set memory_maps [ipx::get_memory_maps * -of_objects [ipx::current_core]] + foreach map $memory_maps { + ipx::remove_memory_map [lindex $map 2] [ipx::current_core] + } + + ipx::update_checksums [ipx::current_core] + ipx::save_core [ipx::current_core] +} + +## Set AXI interface IP proprieties. +# +# \param[ip_name] - The ip name +# +proc adi_ip_properties {ip_name} { + + adi_ip_properties_lite $ip_name + + ipx::infer_bus_interface {\ + s_axi_awvalid \ + s_axi_awaddr \ + s_axi_awprot \ + s_axi_awready \ + s_axi_wvalid \ + s_axi_wdata \ + s_axi_wstrb \ + s_axi_wready \ + s_axi_bvalid \ + s_axi_bresp \ + + s_axi_bready \ + s_axi_arvalid \ + s_axi_araddr \ + s_axi_arprot \ + s_axi_arready \ + s_axi_rvalid \ + s_axi_rdata \ + s_axi_rresp \ + s_axi_rready} \ + xilinx.com:interface:aximm_rtl:1.0 [ipx::current_core] + + ipx::infer_bus_interface s_axi_aclk xilinx.com:signal:clock_rtl:1.0 [ipx::current_core] + ipx::infer_bus_interface s_axi_aresetn xilinx.com:signal:reset_rtl:1.0 [ipx::current_core] + + set raddr_width [expr [get_property SIZE_LEFT [ipx::get_ports -nocase true s_axi_araddr -of_objects [ipx::current_core]]] + 1] + set waddr_width [expr [get_property SIZE_LEFT [ipx::get_ports -nocase true s_axi_awaddr -of_objects [ipx::current_core]]] + 1] + + if {$raddr_width != $waddr_width} { + puts [format "WARNING: AXI address width mismatch for %s (r=%d, w=%d)" $ip_name $raddr_width, $waddr_width] + set range 65536 + } else { + if {$raddr_width >= 16} { + set range 65536 + } else { + set range [expr 1 << $raddr_width] + } + } + + ipx::add_memory_map {s_axi} [ipx::current_core] + set_property slave_memory_map_ref {s_axi} [ipx::get_bus_interfaces s_axi -of_objects [ipx::current_core]] + ipx::add_address_block {axi_lite} [ipx::get_memory_maps s_axi -of_objects [ipx::current_core]] + set_property range $range [ipx::get_address_blocks axi_lite \ + -of_objects [ipx::get_memory_maps s_axi -of_objects [ipx::current_core]]] + ipx::associate_bus_interfaces -clock s_axi_aclk -reset s_axi_aresetn [ipx::current_core] + ipx::save_core +} + +## Create/overwrite temporary files containing particular build case dependencies. +# +# DO NOT USE FOR: axi_dmac/jesd204/axi_clkgen +# +proc adi_init_bd_tcl {} { + + global auto_set_param_list + global auto_set_param_list_overwritable + set cc [ipx::current_core] + + if { [file exists bd] } { + file delete -force bd + } + file mkdir bd + + set bd_tcl [open "bd/bd.tcl" w] + + puts $bd_tcl "# SCRIPT AUTO-GENERATED AT BUILD, DO NOT MODIFY!" + puts $bd_tcl "proc init {cellpath otherInfo} {" + puts $bd_tcl " set ip \[get_bd_cells \$cellpath\]" + puts $bd_tcl "" + set auto_set_param "" + foreach i $auto_set_param_list { + if { [ipx::get_user_parameters $i -of_objects $cc -quiet] ne "" } { + append auto_set_param " $i \\\n" + } + } + if { $auto_set_param ne "" } { + puts $bd_tcl " bd::mark_propagate_only \$ip \" \\" + regsub "${i} \\\\" $auto_set_param "$i\"" auto_set_param + puts $bd_tcl $auto_set_param + } + + set auto_set_overwritable_param "" + foreach i $auto_set_param_list_overwritable { + if { [ipx::get_user_parameters $i -of_objects $cc -quiet] ne "" } { + append auto_set_overwritable_param " $i \\\n" + } + } + if { $auto_set_overwritable_param ne "" } { + puts $bd_tcl " bd::mark_propagate_override \$ip \" \\" + regsub "${i} \\\\" $auto_set_overwritable_param "$i\"" auto_set_overwritable_param + puts $bd_tcl $auto_set_overwritable_param + } + puts $bd_tcl " adi_auto_assign_device_spec \$cellpath" + puts $bd_tcl "}" + puts $bd_tcl "" + puts $bd_tcl "# auto set parameters defined in auto_set_param_list (adi_xilinx_device_info_enc.tcl)" + puts $bd_tcl "proc adi_auto_assign_device_spec {cellpath} {" + puts $bd_tcl "" + puts $bd_tcl " set ip \[get_bd_cells \$cellpath\]" + puts $bd_tcl " set ip_param_list \[list_property \$ip\]" + puts $bd_tcl " set ip_path \[bd::get_vlnv_dir \[get_property VLNV \$ip\]\]" + puts $bd_tcl "" + puts $bd_tcl " set parent_dir \"../\"" + puts $bd_tcl " for {set x 1} {\$x<=4} {incr x} {" + puts $bd_tcl " set linkname \${ip_path}\${parent_dir}scripts/adi_xilinx_device_info_enc.tcl" + puts $bd_tcl " if { \[file exists \$linkname\] } {" + puts $bd_tcl " source \${ip_path}\${parent_dir}/scripts/adi_xilinx_device_info_enc.tcl" + puts $bd_tcl " break" + puts $bd_tcl " }" + puts $bd_tcl " append parent_dir \"../\"" + puts $bd_tcl " }" + puts $bd_tcl "" + puts $bd_tcl " # Find predefindes auto assignable parameters" + puts $bd_tcl " foreach i \$auto_set_param_list {" + puts $bd_tcl " if { \[lsearch \$ip_param_list \"CONFIG.\$i\"\] > 0 } {" + puts $bd_tcl " set val \[adi_device_spec \$cellpath \$i\]" + puts $bd_tcl " set_property CONFIG.\$i \$val \$ip" + puts $bd_tcl " }" + puts $bd_tcl " }" + puts $bd_tcl "" + puts $bd_tcl " # Find predefindes auto assignable/overwritable parameters" + puts $bd_tcl " foreach i \$auto_set_param_list_overwritable {" + puts $bd_tcl " if { \[lsearch \$ip_param_list \"CONFIG.\$i\"\] > 0 } {" + puts $bd_tcl " set val \[adi_device_spec \$cellpath \$i\]" + puts $bd_tcl " set_property CONFIG.\$i \$val \$ip" + puts $bd_tcl " }" + puts $bd_tcl " }" + puts $bd_tcl "}" + puts $bd_tcl "" + close $bd_tcl + + set proj_fileset [get_filesets sources_1] + add_files -norecurse -scan_for_includes -fileset $proj_fileset "bd/bd.tcl" + + set local_mk [open "temporary_case_dependencies.mk" w] + seek $local_mk 0 start + puts $local_mk "CLEAN_TARGET += bd" + puts $local_mk "CLEAN_TARGET += temporary_case_dependencies.mk" + close $local_mk +} + +## Search after device specific parameters and call the adi_add_device_spec_param +# process with the result. The list of these parameters are defined in +# library/scripts/adi_xilinx_device_info_enc.tcl +# +proc adi_add_auto_fpga_spec_params {} { + + global auto_set_param_list + global auto_set_param_list_overwritable + set cc [ipx::current_core] + + foreach i $auto_set_param_list { + if { [ipx::get_user_parameters $i -of_objects $cc -quiet] ne ""} { + adi_add_device_spec_param $i + } + } + foreach i $auto_set_param_list_overwritable { + if { [ipx::get_user_parameters $i -of_objects $cc -quiet] ne ""} { + adi_add_device_spec_param $i + } + } +} + +## Generate validation properties for a parameter, using predefined ranges or +# set of values (the definition of the ranges can be found in +# library/scripts/adi_xilinx_device_info_enc.tcl). +# +# \param[ip_parameter] - name of the HDL parameter +# +proc adi_add_device_spec_param {ip_param} { + + set cc [ipx::current_core] + + set list_pointer [string tolower $ip_param] + set list_pointer [append list_pointer "_list"] + + global $list_pointer + + # set j 1D list from the original list + foreach i [subst $$list_pointer] {lappend j [lindex $i 0] [lindex $i 1]} + + # set ranges or validation pairs (show x in GUI assign the corresponding y to HDL) + if { [llength [subst $$list_pointer]] == 2 && [llength $j] == 4} { + set_property -dict [list \ + "value_validation_type" "range_long" \ + "value_validation_range_minimum" [lindex [subst $$list_pointer] 0] \ + "value_validation_range_maximum" [lindex [subst $$list_pointer] 1] ] \ + [ipx::get_user_parameters $ip_param -of_objects $cc] + } else { + set_property -dict [list \ + "value_validation_type" "pairs" \ + "value_validation_pairs" $j ] \ + [ipx::get_user_parameters $ip_param -of_objects $cc] + } + + # FPGA info grup + set info_group_name "FPGA info" + set info_group [ipgui::get_groupspec -name $info_group_name -component $cc -quiet] + if { [string trim $info_group] eq "" } { + set page0 [ipgui::get_pagespec -name "Page 0" -component $cc] + set info_group [ipgui::add_group -name $info_group_name -component $cc \ + -parent $page0 -display_name $info_group_name] + } + + set p [ipgui::get_guiparamspec -name $ip_param -component $cc] + set_property -dict [list "widget" "comboBox" ] $p + ipgui::move_param -component $cc -order 0 $p -parent $info_group +} + +## Define a custom interface bus. +# +# \param[name] - Interface name +# +proc adi_if_define {name} { + + ipx::create_abstraction_definition analog.com interface ${name}_rtl 1.0 + ipx::create_bus_definition analog.com interface $name 1.0 + + set_property xml_file_name ${name}_rtl.xml [ipx::current_busabs] + set_property xml_file_name ${name}.xml [ipx::current_busdef] + set_property bus_type_vlnv analog.com:interface:${name}:1.0 [ipx::current_busabs] + + ipx::save_abstraction_definition [ipx::current_busabs] + ipx::save_bus_definition [ipx::current_busdef] +} + +## Add ports to a custom interface bus. +# +# \param[dir] - Port direction +# \param[width] - Port width +# \param[name] - Port logical name +# \param[type] - Type of the port (default "none") +# +proc adi_if_ports {dir width name {type none}} { + + ipx::add_bus_abstraction_port $name [ipx::current_busabs] + set m_intf [ipx::get_bus_abstraction_ports $name -of_objects [ipx::current_busabs]] + set_property master_presence required $m_intf + set_property slave_presence required $m_intf + set_property master_width $width $m_intf + set_property slave_width $width $m_intf + + set m_dir "in" + set s_dir "out" + if {$dir eq "output"} { + set m_dir "out" + set s_dir "in" + } + + set_property master_direction $m_dir $m_intf + set_property slave_direction $s_dir $m_intf + + if {$type ne "none"} { + set_property is_${type} true $m_intf + } + + ipx::save_bus_definition [ipx::current_busdef] + ipx::save_abstraction_definition [ipx::current_busabs] +} + +## Infers a new bus interface to an IP. +# +# \param[if_name] - Interface bus name +# \param[mode] - Type of the interface bus (master/slave) +# \param[name] - Interface bus instance name +# \param[maps] - Mapping of the physical ports +# +proc adi_if_infer_bus {if_name mode name maps} { + + ipx::add_bus_interface $name [ipx::current_core] + set m_bus_if [ipx::get_bus_interfaces $name -of_objects [ipx::current_core]] + set_property abstraction_type_vlnv ${if_name}_rtl:1.0 $m_bus_if + set_property bus_type_vlnv ${if_name}:1.0 $m_bus_if + set_property interface_mode $mode $m_bus_if + + foreach map $maps { + set m_maps [regexp -all -inline {\S+} $map] + lassign $m_maps p_name p_map + ipx::add_port_map $p_name $m_bus_if + set_property physical_name $p_map [ipx::get_port_maps $p_name -of_objects $m_bus_if] + } +} + diff --git a/CI/scripts/adi_project.tcl b/CI/scripts/adi_project.tcl new file mode 100644 index 0000000..2173764 --- /dev/null +++ b/CI/scripts/adi_project.tcl @@ -0,0 +1,215 @@ + +variable p_board +variable p_device +variable sys_zynq +variable p_prcfg_init +variable p_prcfg_list +variable p_prcfg_status + +if {![info exists REQUIRED_VIVADO_VERSION]} { + set REQUIRED_VIVADO_VERSION "2019.1" +} + +if {[info exists ::env(ADI_IGNORE_VERSION_CHECK)]} { + set IGNORE_VERSION_CHECK 1 +} elseif {![info exists IGNORE_VERSION_CHECK]} { + set IGNORE_VERSION_CHECK 0 +} + +set p_board "not-applicable" +set p_device "none" +set sys_zynq 1 +set ADI_POWER_OPTIMIZATION 0 + +proc adi_project_xilinx {project_name project_dir update_tcl {mode 0} {parameter_list ""}} { + + global ad_hdl_dir + global ad_phdl_dir + global p_board + global p_device + global sys_zynq + global REQUIRED_VIVADO_VERSION + global IGNORE_VERSION_CHECK + + if [regexp "_ac701$" $project_name] { + set p_device "xc7a200tfbg676-2" + set p_board "xilinx.com:ac701:part0:1.0" + set sys_zynq 0 + } + if [regexp "_kc705$" $project_name] { + set p_device "xc7k325tffg900-2" + set p_board "xilinx.com:kc705:part0:1.1" + set sys_zynq 0 + } + if [regexp "_vc707$" $project_name] { + set p_device "xc7vx485tffg1761-2" + set p_board "xilinx.com:vc707:part0:1.1" + set sys_zynq 0 + } + if [regexp "_kcu105$" $project_name] { + set p_device "xcku040-ffva1156-2-e" + set p_board "xilinx.com:kcu105:part0:1.1" + set sys_zynq 0 + } + if [regexp "_zed$" $project_name] { + set p_device "xc7z020clg484-1" + set p_board "em.avnet.com:zed:part0:1.3" + set sys_zynq 1 + } + if [regexp "_microzed$" $project_name] { + set p_device "xc7z010clg400-1" + set p_board "not-applicable" + set sys_zynq 1 + } + if [regexp "_zc702$" $project_name] { + set p_device "xc7z020clg484-1" + set p_board "xilinx.com:zc702:part0:1.2" + set sys_zynq 1 + } + if [regexp "_zc706$" $project_name] { + set p_device "xc7z045ffg900-2" + set p_board "xilinx.com:zc706:part0:1.2" + set sys_zynq 1 + } + if [regexp "_mitx045$" $project_name] { + set p_device "xc7z045ffg900-2" + set p_board "not-applicable" + set sys_zynq 1 + } + if [regexp "_zcu102$" $project_name] { + set p_device "xczu9eg-ffvb1156-2-e" + set p_board "xilinx.com:zcu102:part0:3.1" + set sys_zynq 2 + } + + #Added + set project_name_org $project_name + set project_name vivado_prj + + set VIVADO_VERSION [version -short] + if {[string compare $VIVADO_VERSION $REQUIRED_VIVADO_VERSION] != 0} { + puts -nonewline "CRITICAL WARNING: vivado version mismatch; " + puts -nonewline "expected $REQUIRED_VIVADO_VERSION, " + puts -nonewline "got $VIVADO_VERSION.\n" + } + + #Added + adi_setup_libs + + if {$mode == 0} { + set project_system_dir "./$project_name.srcs/sources_1/bd/system" + #Removed + #create_project $project_name . -part $p_device -force + } else { + set project_system_dir ".srcs/sources_1/bd/system" + #Removed + #create_project -in_memory -part $p_device + } + + if {$mode == 1} { + file mkdir $project_name.data + } + + if {$p_board ne "not-applicable"} { + set_property board_part $p_board [current_project] + } + + #Removed + #set lib_dirs $ad_hdl_dir/library + #if {$ad_hdl_dir ne $ad_phdl_dir} { + # lappend lib_dirs $ad_phdl_dir/library + #} + + #set_property ip_repo_paths $lib_dirs [current_fileset] + #update_ip_catalog + + set_msg_config -id {BD 41-1348} -new_severity info + set_msg_config -id {BD 41-1343} -new_severity info + set_msg_config -id {BD 41-1306} -new_severity info + set_msg_config -id {IP_Flow 19-1687} -new_severity info + set_msg_config -id {filemgmt 20-1763} -new_severity info + set_msg_config -severity {CRITICAL WARNING} -quiet -id {BD 41-1276} -new_severity error + + + #Added from adi_project_xilinx R2021a + # Set parameters of the top level file + # Make the same parameters available to system_bd.tcl + set proj_params [get_property generic [current_fileset]] + foreach {param value} $parameter_list { + lappend proj_params $param=$value + set ad_project_params($param) $value + } + + #Added + create_bd_design "system" + source $project_dir/system_bd.tcl + if {$project_name_org != "adrv9361z7035_ccbox_lvds_modem"} { + source $project_dir/$update_tcl + } + + set_property generic $proj_params [current_fileset] + regenerate_bd_layout + save_bd_design + validate_bd_design + + set_property synth_checkpoint_mode None [get_files $project_system_dir/system.bd] + generate_target {synthesis implementation} [get_files $project_system_dir/system.bd] + make_wrapper -files [get_files $project_system_dir/system.bd] -top + + if {$mode == 0} { + import_files -force -norecurse -fileset sources_1 $project_system_dir/hdl/system_wrapper.v + } else { + write_hwdef -file "$project_name.data/$project_name.hwdef" + } +} + +#Added +proc adi_setup_libs {} { + global ad_hdl_dir + global ad_phdl_dir + + set lib_dirs [get_property ip_repo_paths [current_fileset]] + + lappend lib_dirs $ad_hdl_dir/library + if {$ad_hdl_dir ne $ad_phdl_dir} { + lappend lib_dirs $ad_phdl_dir/library + } + + set_property ip_repo_paths $lib_dirs [current_fileset] + update_ip_catalog + adi_add_archive_ip $lib_dirs +} + +#Added +proc adi_add_archive_ip {lib_dirs} { + global ad_hdl_dir + global ad_phdl_dir + foreach libDir $lib_dirs { + set ipList [glob -nocomplain -directory $libDir *.zip] + foreach ipCore $ipList { + catch {update_ip_catalog -add_ip $ipCore -repo_path $libDir} + file delete -force $ipCore + } + } +} + +proc adi_project_files {project_name project_files} { + + global ad_hdl_dir + global ad_phdl_dir + global proj_dir + + #Added + cd $proj_dir + + add_files -norecurse -fileset sources_1 $project_files + set_property top system_top [current_fileset] + + #Added + cd $ad_hdl_dir +} + +proc adi_project_run {project_name} { + #Removed +} + diff --git a/CI/scripts/adi_project_xilinx.tcl b/CI/scripts/adi_project_xilinx.tcl new file mode 100644 index 0000000..6f49244 --- /dev/null +++ b/CI/scripts/adi_project_xilinx.tcl @@ -0,0 +1,435 @@ + +## Define the supported tool version +if {![info exists REQUIRED_VIVADO_VERSION]} { + set REQUIRED_VIVADO_VERSION "2019.1" +} + +## Define the ADI_IGNORE_VERSION_CHECK environment variable to skip version check +if {[info exists ::env(ADI_IGNORE_VERSION_CHECK)]} { + set IGNORE_VERSION_CHECK 1 +} elseif {![info exists IGNORE_VERSION_CHECK]} { + set IGNORE_VERSION_CHECK 0 +} + +## Define the ADI_USE_OOC_SYNTHESIS environment variable to enable out of context +# synthesis +if {[info exists ::env(ADI_USE_OOC_SYNTHESIS)]} { + set ADI_USE_OOC_SYNTHESIS 1 +} elseif {![info exists ADI_USE_OOC_SYNTHESIS]} { + set ADI_USE_OOC_SYNTHESIS 0 +} + +## Set to enable incremental compilation +set ADI_USE_INCR_COMP 1 + +## Set to enable power optimization +set ADI_POWER_OPTIMIZATION 0 + +## Initialize global variables +set p_board "not-applicable" +set p_device "none" +set sys_zynq 1 + +set p_prcfg_init "" +set p_prcfg_list "" +set p_prcfg_status "" + +## Creates a Xilinx project. +# +# \param[project_name] - name of the project +# \param[mode] - if set non-project mode will be used, otherwise project mode +# flow, see UG892 for more information +# \param[parameter_list] - a list of global parameters (parameters of the +# system_top module) +# +# Supported carrier names are: ac701, kc705, vc707, vcu118, kcu105, zed, +# microzed, zc702, zc706, mitx405, zcu102. +# +proc adi_project {project_name {mode 0} {parameter_list {}} } { + + global ad_hdl_dir + global p_board + global p_device + global sys_zynq + global REQUIRED_VIVADO_VERSION + global IGNORE_VERSION_CHECK + global ADI_USE_OOC_SYNTHESIS + global ADI_USE_INCR_COMP + + if [regexp "_ac701$" $project_name] { + set p_device "xc7a200tfbg676-2" + set p_board "xilinx.com:ac701:part0:1.0" + set sys_zynq 0 + } + if [regexp "_kc705$" $project_name] { + set p_device "xc7k325tffg900-2" + set p_board "xilinx.com:kc705:part0:1.1" + set sys_zynq 0 + } + if [regexp "_vc707$" $project_name] { + set p_device "xc7vx485tffg1761-2" + set p_board "xilinx.com:vc707:part0:1.1" + set sys_zynq 0 + } + if [regexp "_vcu118$" $project_name] { + set p_device "xcvu9p-flga2104-2L-e" + set p_board "xilinx.com:vcu118:part0:2.0" + set sys_zynq 0 + } + if [regexp "_kcu105$" $project_name] { + set p_device "xcku040-ffva1156-2-e" + set p_board "xilinx.com:kcu105:part0:1.1" + set sys_zynq 0 + } + if [regexp "_zed$" $project_name] { + set p_device "xc7z020clg484-1" + set p_board "em.avnet.com:zed:part0:1.3" + set sys_zynq 1 + } + if [regexp "_coraz7s$" $project_name] { + set p_device "xc7z007sclg400-1" + set p_board "not-applicable" + set sys_zynq 1 + } + if [regexp "_microzed$" $project_name] { + set p_device "xc7z010clg400-1" + set p_board "not-applicable" + set sys_zynq 1 + } + if [regexp "_zc702$" $project_name] { + set p_device "xc7z020clg484-1" + set p_board "xilinx.com:zc702:part0:1.2" + set sys_zynq 1 + } + if [regexp "_zc706$" $project_name] { + set p_device "xc7z045ffg900-2" + set p_board "xilinx.com:zc706:part0:1.2" + set sys_zynq 1 + } + if [regexp "_mitx045$" $project_name] { + set p_device "xc7z045ffg900-2" + set p_board "not-applicable" + set sys_zynq 1 + } + if [regexp "_zcu102$" $project_name] { + set p_device "xczu9eg-ffvb1156-2-e" + set p_board "xilinx.com:zcu102:part0:3.2" + set sys_zynq 2 + } + + set VIVADO_VERSION [version -short] + if {[string compare $VIVADO_VERSION $REQUIRED_VIVADO_VERSION] != 0} { + puts -nonewline "CRITICAL WARNING: vivado version mismatch; " + puts -nonewline "expected $REQUIRED_VIVADO_VERSION, " + puts -nonewline "got $VIVADO_VERSION.\n" + } + + if {$mode == 0} { + set project_system_dir "./$project_name.srcs/sources_1/bd/system" + create_project $project_name . -part $p_device -force + } else { + set project_system_dir ".srcs/sources_1/bd/system" + create_project -in_memory -part $p_device + } + + if {$mode == 1} { + file mkdir $project_name.data + } + + if {$p_board ne "not-applicable"} { + set_property board_part $p_board [current_project] + } + + set lib_dirs $ad_hdl_dir/library + + # Set a common IP cache for all projects + if {$ADI_USE_OOC_SYNTHESIS == 1} { + if {[file exists $ad_hdl_dir/ipcache] == 0} { + file mkdir $ad_hdl_dir/ipcache + } + config_ip_cache -import_from_project -use_cache_location $ad_hdl_dir/ipcache + } + + set_property ip_repo_paths $lib_dirs [current_fileset] + update_ip_catalog + + ## Load custom message severity definitions + source $ad_hdl_dir/projects/scripts/adi_xilinx_msg.tcl + + ## In Vivado there is a limit for the number of warnings and errors which are + ## displayed by the tool for a particular error or warning; the default value + ## of this limit is 100. + ## Overrides the default limit to 2000. + set_param messaging.defaultLimit 2000 + + # Set parameters of the top level file + # Make the same parameters available to system_bd.tcl + set proj_params [get_property generic [current_fileset]] + foreach {param value} $parameter_list { + lappend proj_params $param=$value + set ad_project_params($param) $value + } + set_property generic $proj_params [current_fileset] + + create_bd_design "system" + source system_bd.tcl + + save_bd_design + validate_bd_design + + if {$ADI_USE_OOC_SYNTHESIS == 1} { + set_property synth_checkpoint_mode Hierarchical [get_files $project_system_dir/system.bd] + } else { + set_property synth_checkpoint_mode None [get_files $project_system_dir/system.bd] + } + generate_target {synthesis implementation} [get_files $project_system_dir/system.bd] + if {$ADI_USE_OOC_SYNTHESIS == 1} { + export_ip_user_files -of_objects [get_files $project_system_dir/system.bd] -no_script -sync -force -quiet + create_ip_run [get_files $project_system_dir/system.bd] + } + make_wrapper -files [get_files $project_system_dir/system.bd] -top + + if {$mode == 0} { + import_files -force -norecurse -fileset sources_1 $project_system_dir/hdl/system_wrapper.v + } else { + write_hwdef -file "$project_name.data/$project_name.hwdef" + } + + if {$ADI_USE_INCR_COMP == 1} { + if {[file exists ./reference.dcp]} { + set_property incremental_checkpoint ./reference.dcp [get_runs impl_1] + } + } + +} + +## Add source files to an exiting project. +# +# \param[project_name] - name of the project +# \param[project_files] - list of project files +# +proc adi_project_files {project_name project_files} { + + foreach pfile $project_files { + if {[string range $pfile [expr 1 + [string last . $pfile]] end] == "xdc"} { + add_files -norecurse -fileset constrs_1 $pfile + } else { + add_files -norecurse -fileset sources_1 $pfile + } + } + + # NOTE: top file name is always system_top + set_property top system_top [current_fileset] +} + +## Run an existing project (generate bit stream). +# +# \param[project_name] - name of the project +# +proc adi_project_run {project_name} { + + global ADI_POWER_OPTIMIZATION + global ADI_USE_OOC_SYNTHESIS + + if {$ADI_USE_OOC_SYNTHESIS == 1} { + launch_runs -jobs 4 system_*_synth_1 synth_1 + } else { + launch_runs synth_1 + } + wait_on_run synth_1 + open_run synth_1 + report_timing_summary -file timing_synth.log + + if {![info exists ::env(ADI_NO_BITSTREAM_COMPRESSION)] && ![info exists ADI_NO_BITSTREAM_COMPRESSION]} { + set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design] + } + + if {$ADI_POWER_OPTIMIZATION == 1} { + set_property STEPS.POWER_OPT_DESIGN.IS_ENABLED true [get_runs impl_1] + set_property STEPS.POST_PLACE_POWER_OPT_DESIGN.IS_ENABLED true [get_runs impl_1] + } + + launch_runs impl_1 -to_step write_bitstream + wait_on_run impl_1 + open_run impl_1 + report_timing_summary -file timing_impl.log + + if {[info exists ::env(ADI_GENERATE_UTILIZATION)]} { + set csv_file resource_utilization.csv + if {[ catch { + xilinx::designutils::report_failfast -csv -file $csv_file -transpose -no_header -ignore_pr -quiet + set MMCM [llength [get_cells -hierarchical -filter { PRIMITIVE_TYPE =~ *MMCM* }]] + set PLL [llength [get_cells -hierarchical -filter { PRIMITIVE_TYPE =~ *PLL* }]] + set worst_slack_setup [get_property SLACK [get_timing_paths -setup]] + set worst_slack_hold [get_property SLACK [get_timing_paths -hold]] + + set fileRead [open $csv_file r] + set lines [split [read $fileRead] "\n"] + set names_line [lindex $lines end-3] + set values_line [lindex $lines end-2] + close $fileRead + + set fileWrite [open $csv_file w] + puts $fileWrite "$names_line,MMCM*,PLL*,Worst_Setup_Slack,Worst_Hold_Slack" + puts $fileWrite "$values_line,$MMCM,$PLL,$worst_slack_setup,$worst_slack_hold" + close $fileWrite + } issue ] != 0 } { + puts "GENERATE_REPORTS: tclapp::xilinx::designutils not installed" + } + } else { + puts "GENERATE_REPORTS: Resource utilization files won't be generated because ADI_GENERATE_UTILIZATION env var is not set" + } + + # Look for undefined clocks which do not show up in the timing summary + set timing_check [check_timing -override_defaults no_clock -no_header -return_string] + if {[regexp { (\d+) register} $timing_check -> num_regs]} { + + if {[info exist num_regs]} { + if {$num_regs > 0} { + puts "CRITICAL WARNING: There are $num_regs registers with no clocks !!! See no_clock.log for details." + check_timing -override_defaults no_clock -verbose -file no_clock.log + } + } + + } else { + puts "CRITICAL WARNING: The search for undefined clocks failed !!!" + } + + file mkdir $project_name.sdk + + if [expr [string match *VIOLATED* $[report_timing_summary -return_string]] == 1] { + file copy -force $project_name.runs/impl_1/system_top.sysdef $project_name.sdk/system_top_bad_timing.hdf + return -code error [format "ERROR: Timing Constraints NOT met!"] + } else { + file copy -force $project_name.runs/impl_1/system_top.sysdef $project_name.sdk/system_top.hdf + } +} + +## Run synthesis on an partial design; use it in Partial Reconfiguration flow. +# +# \param[project_name] - project name +# \param[prcfg_name] - name of the partial design +# \param[hdl_files] - hdl source of the partial design +# \param[xdc_files] - XDC constraint source of the partial design +# +proc adi_project_synth {project_name prcfg_name hdl_files {xdc_files ""}} { + + global p_device + + set p_prefix "$project_name.data/$project_name" + + if {$prcfg_name eq ""} { + + read_verilog .srcs/sources_1/bd/system/hdl/system_wrapper.v + read_verilog $hdl_files + read_xdc $xdc_files + + synth_design -mode default -top system_top -part $p_device > $p_prefix.synth.rds + write_checkpoint -force $p_prefix.synth.dcp + close_project + + } else { + + create_project -in_memory -part $p_device + read_verilog $hdl_files + synth_design -mode out_of_context -top "prcfg" -part $p_device > $p_prefix.${prcfg_name}_synth.rds + write_checkpoint -force $p_prefix.${prcfg_name}_synth.dcp + close_project + } +} + +## Run implementation on an partial design; use it in Partial Reconfiguration +# flow. +# +# \param[project_name] - project name +# \param[prcfg_name] - name of the partial design +# \param[xdc_files] - XDC constraint source of the partial design +# +proc adi_project_impl {project_name prcfg_name {xdc_files ""}} { + + global p_device + global p_prcfg_init + global p_prcfg_list + global p_prcfg_status + + set p_prefix "$project_name.data/$project_name" + + if {$prcfg_name eq "default"} { + set p_prcfg_status 0 + set p_prcfg_list "" + set p_prcfg_init "$p_prefix.${prcfg_name}_impl.dcp" + file mkdir $project_name.sdk + } + + if {$prcfg_name eq "default"} { + + open_checkpoint $p_prefix.synth.dcp -part $p_device + read_xdc $xdc_files + read_checkpoint -cell i_prcfg $p_prefix.${prcfg_name}_synth.dcp + set_property HD.RECONFIGURABLE 1 [get_cells i_prcfg] + opt_design > $p_prefix.${prcfg_name}_opt.rds + write_debug_probes -force $p_prefix.${prcfg_name}_debug_nets.ltx + place_design > $p_prefix.${prcfg_name}_place.rds + route_design > $p_prefix.${prcfg_name}_route.rds + + } else { + + open_checkpoint $p_prefix.default_impl_bb.dcp -part $p_device + lock_design -level routing + read_checkpoint -cell i_prcfg $p_prefix.${prcfg_name}_synth.dcp + read_xdc $xdc_files + opt_design > $p_prefix.${prcfg_name}_opt.rds + place_design > $p_prefix.${prcfg_name}_place.rds + route_design > $p_prefix.${prcfg_name}_route.rds + } + + write_checkpoint -force $p_prefix.${prcfg_name}_impl.dcp + report_utilization -pblocks pb_prcfg -file $p_prefix.${prcfg_name}_utilization.rpt + report_timing_summary -file $p_prefix.${prcfg_name}_timing_summary.rpt + + if [expr [get_property SLACK [get_timing_paths]] < 0] { + set p_prcfg_status 1 + puts "CRITICAL WARNING: Timing Constraints NOT met ($prcfg_name)!" + } + + write_checkpoint -force -cell i_prcfg $p_prefix.${prcfg_name}_prcfg_impl.dcp + update_design -cell i_prcfg -black_box + write_checkpoint -force $p_prefix.${prcfg_name}_impl_bb.dcp + open_checkpoint $p_prefix.${prcfg_name}_impl.dcp -part $p_device + write_bitstream -force -bin_file -file $p_prefix.${prcfg_name}.bit + write_sysdef -hwdef $p_prefix.hwdef -bitfile $p_prefix.${prcfg_name}.bit -file $p_prefix.${prcfg_name}.hdf + file copy -force $p_prefix.${prcfg_name}.hdf $project_name.sdk/system_top.${prcfg_name}.hdf + + if {$prcfg_name ne "default"} { + lappend p_prcfg_list "$p_prefix.${prcfg_name}_impl.dcp" + } + + if {$prcfg_name eq "default"} { + file copy -force $p_prefix.${prcfg_name}.hdf $project_name.sdk/system_top.hdf + } +} + +## Verify an implemented partial reconfiguration design, checks if all the +# partial design are compatible with the base design. +# +# \param[project_name] - project name +# +proc adi_project_verify {project_name} { + + # checkpoint for the default design + global p_prcfg_init + # list of checkpoints with all the PRs integrated into the default design + global p_prcfg_list + global p_prcfg_status + + set p_prefix "$project_name.data/$project_name" + + pr_verify -full_check -initial $p_prcfg_init \ + -additional $p_prcfg_list \ + -file $p_prefix.prcfg_verify.log + + if {$p_prcfg_status == 1} { + return -code error [format "ERROR: Timing Constraints NOT met!"] + } +} + diff --git a/CI/scripts/adi_xilinx_device_info_enc.tcl b/CI/scripts/adi_xilinx_device_info_enc.tcl new file mode 100644 index 0000000..af8b840 --- /dev/null +++ b/CI/scripts/adi_xilinx_device_info_enc.tcl @@ -0,0 +1,193 @@ +## *************************************************************************** +## *************************************************************************** +## Copyright 2014 - 2018 (c) Analog Devices, Inc. All rights reserved. +## +## In this HDL repository, there are many different and unique modules, consisting +## of various HDL (Verilog or VHDL) components. The individual modules are +## developed independently, and may be accompanied by separate and unique license +## terms. +## +## The user should read each of these license terms, and understand the +## freedoms and responsibilities that he or she has by using this source/core. +## +## This core is distributed in the hope that it will be useful, but WITHOUT ANY +## WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +## A PARTICULAR PURPOSE. +## +## Redistribution and use of source or resulting binaries, with or without modification +## of this file, are permitted under one of the following two license terms: +## +## 1. The GNU General Public License version 2 as published by the +## Free Software Foundation, which can be found in the top level directory +## of this repository (LICENSE_GPL2), and also online at: +## +## +## OR +## +## 2. An ADI specific BSD license, which can be found in the top level directory +## of this repository (LICENSE_ADIBSD), and also on-line at: +## https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +## This will allow to generate bit files and not release the source code, +## as long as it attaches to an ADI device. +## +## *************************************************************************** +## *************************************************************************** + +# adi_xilinx_device_info_enc.tcl + +variable auto_set_param_list +variable auto_set_param_list_overwritable +variable fpga_series_list +variable fpga_family_list +variable speed_grade_list +variable dev_package_list +variable xcvr_type_list +variable fpga_voltage_list + +# Parameter list for automatic assignament +set auto_set_param_list { \ + DEV_PACKAGE \ + SPEED_GRADE \ + FPGA_FAMILY \ + FPGA_TECHNOLOGY } + +set auto_set_param_list_overwritable { \ + FPGA_VOLTAGE \ + XCVR_TYPE } + +# List for automatically assigned parameter values and encoded values +# The list name must be the parameter name (lowercase), appending "_list" to it +set fpga_technology_list { \ + { Unknown 0 } \ + { 7series 1 } \ + { ultrascale 2 } \ + { ultrascale+ 3 }} + +set fpga_family_list { \ + { Unknown 0 } \ + { artix 1 } \ + { kintex 2 } \ + { virtex 3 } \ + { zynq 4 }} + +set speed_grade_list { \ + { Unknown 0 } \ + { -1 10 } \ + { -1L 11 } \ + { -1H 12 } \ + { -1HV 13 } \ + { -1LV 14 } \ + { -2 20 } \ + { -2L 21 } \ + { -2LV 22 } \ + { -3 30 }} + +set dev_package_list { \ + { Unknown 0 } \ + { rf 1 } \ + { fl 2 } \ + { ff 3 } \ + { fb 4 } \ + { hc 5 } \ + { fh 6 } \ + { cs 7 } \ + { cp 8 } \ + { ft 9 } \ + { fg 10 } \ + { sb 11 } \ + { rb 12 } \ + { rs 13 } \ + { cl 14 } \ + { sf 15 } \ + { ba 16 } \ + { fa 17 }} + +set xcvr_type_list { \ + { Unknown 0 } \ + { GTPE2_NOT_SUPPORTED 1 } \ + { GTXE2 2 } \ + { GTHE2_NOT_SUPPORTED 3 } \ + { GTZE2_NOT_SUPPORTED 4 } \ + { GTHE3 5 } \ + { GTYE3_NOT_SUPPORTED 6 } \ + { GTRE4_NOT_SUPPORTED 7 } \ + { GTHE4 8 } \ + { GTYE4 9 } \ + { GTME4_NOT_SUPPORTED 10}} + +set fpga_voltage_list {0 5000} ;# 0 to 5000mV + + +## *************************************************************************** + +proc adi_device_spec {cellpath param} { + + set list_pointer [string tolower $param] + set list_pointer [append list_pointer "_list"] + + upvar 1 $list_pointer $list_pointer + + set ip [get_bd_cells $cellpath] + set part [get_property PART [current_project]] + + switch -regexp -- $param { + FPGA_TECHNOLOGY { + switch -regexp -- $part { + ^xc7 {set series_name 7series} + ^xczu {set series_name ultrascale+} + ^xc.u.p {set series_name ultrascale+} + ^xc.u {set series_name ultrascale } + default { + puts "Undefined fpga technology for \"$part\"!" + exit -1 + } + } + return "$series_name" + } + FPGA_FAMILY { + set fpga_family [get_property FAMILY $part] + foreach i $fpga_family_list { + regexp ^[lindex $i 0] $fpga_family matched + } + return "$matched" + } + SPEED_GRADE { + set speed_grade [get_property SPEED $part] + return "$speed_grade" + } + DEV_PACKAGE { + set dev_package [get_property PACKAGE $part] + foreach i $dev_package_list { + regexp ^[lindex $i 0] $dev_package matched + } + return "$matched" + } + XCVR_TYPE { + set matched "" + set dev_transcivers "none" + foreach x [list_property $part] { + regexp ^GT..._TRANSCEIVERS $x dev_transcivers + } + foreach i $xcvr_type_list { + regexp ^[lindex $i 0] $dev_transcivers matched + } + if { $matched eq "" } { + puts "CRITICAL WARNING: \"$dev_transcivers\" TYPE IS NOT SUPPORTED BY ADI!" + } + return "$matched" + } + FPGA_VOLTAGE { + set fpga_voltage [get_property REF_OPERATING_VOLTAGE $part] + set fpga_voltage [expr int([expr $fpga_voltage * 1000])] ;# // V to mV conversion(integer val) + + return "$fpga_voltage" + } + default { + puts "WARNING: UNDEFINED PARAMETER \"$param\" (adi_device_spec)!" + } + } +} + + +## *************************************************************************** +## *************************************************************************** diff --git a/CI/scripts/bsp.tmpl b/CI/scripts/bsp.tmpl new file mode 100644 index 0000000..6dac3cf --- /dev/null +++ b/CI/scripts/bsp.tmpl @@ -0,0 +1,158 @@ + + + Analog Devices, Inc. Precision Toolbox + Analog Devices, Inc + + Analog Devices, Inc + Board support package for control and data streaming from Analog Devices Precision products. + Scripts and tools created by ADI to be used with MATLAB and Simulink with ADI Precision products +Documentation: https://wiki.analog.com/resources/tools-software/pcx-toolbox +Support: https://ez.analog.com/ + __REPO-ROOT__/CI/doc/ADI_Logo_AWP_Large.png + __VERSION__ + ${PROJECT_ROOT}/Analog Devices Board Support Packages.mltbx + + MATLAB + Simulink + Communications Toolbox + DSP System Toolbox + Signal Processing Toolbox + + + 1 + 2 + 36 + 24 + 101 + 8 + 14 + + + 9.5 + 9.2 + 7.0 + 9.7 + 3.13 + 8.1 + 9.0 + + + __UUID__ + % +CI/* +hdl_prj/* +slprj/* +.git/* +test/* +itests/* +mltbx/* +*~ +.Xil/* + true + + + + + ${PROJECT_ROOT}/info.xml + + + + false + __ML-RELEASE__ + __ML-RELEASE__ + true + true + false + true + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + __REPO-ROOT__ + + + ${PROJECT_ROOT}/LICENSE + ${PROJECT_ROOT}/README.md + ${PROJECT_ROOT}/doc + ${PROJECT_ROOT}/info.xml + ${PROJECT_ROOT}/rfm_examples + + + + + + + __REPO-ROOT__/AnalogDevicesPrecision.mltbx + + + + /usr/local/MATLAB/__ML-RELEASE__ + + + + + + + + + true + + + + + true + + + + + true + + + + + true + + + + + true + false + false + false + false + false + true + false + 4.15.0-34-generic + false + true + glnxa64 + true + + + diff --git a/CI/scripts/bsp_noexamples.tmpl b/CI/scripts/bsp_noexamples.tmpl new file mode 100644 index 0000000..15aac74 --- /dev/null +++ b/CI/scripts/bsp_noexamples.tmpl @@ -0,0 +1,162 @@ + + + Analog Devices, Inc. Transceiver Toolbox + Travis Collins + travis.collins@analog.com + Analog Devices, Inc + Board support package for HDL targeting and data streaming from Analog Devices transceivers. + Scripts and tools created by ADI to be used with MATLAB and Simulink with ADI transceivers +Documentation: https://wiki.analog.com/resources/eval/user-guides/ad-fmcomms2-ebz/software/matlab_bsp +Support: https://ez.analog.com/ + __REPO-ROOT__/CI/doc/ADI_Logo_AWP_Large.png + __VERSION__ + ${PROJECT_ROOT}/AnalogDevicesTransceiverToolbox.mltbx + + MATLAB + Simulink + Communications Toolbox + DSP System Toolbox + HDL Coder + Signal Processing Toolbox + Simulink Coder + + + 1 + 2 + 36 + 24 + 101 + 8 + 14 + + + 9.5 + 9.2 + 7.0 + 9.7 + 3.13 + 8.1 + 9.0 + + + __UUID__ + % +CI/* +deps/* +hdl_prj/* +slprj/* +.git/* +test/* +itests/* +mltbx/* +trx_examples/* +*~ +.Xil/* + true + + + + + ${PROJECT_ROOT}/info.xml + + + + false + __ML-RELEASE__ + __ML-RELEASE__ + true + true + false + true + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + __REPO-ROOT__ + + + ${PROJECT_ROOT}/LICENSE + ${PROJECT_ROOT}/README.md + ${PROJECT_ROOT}/doc + ${PROJECT_ROOT}/hdl + ${PROJECT_ROOT}/info.xml + + + + + + + __REPO-ROOT__/AnalogDevicesTransceiverToolbox.mltbx + + + + /usr/local/MATLAB/__ML-RELEASE__ + + + + + + + + + true + + + + + true + + + + + true + + + + + true + + + + + true + false + false + false + false + false + true + false + 4.15.0-34-generic + false + true + glnxa64 + true + + + diff --git a/CI/scripts/build_bsp.m b/CI/scripts/build_bsp.m new file mode 100644 index 0000000..6acdc33 --- /dev/null +++ b/CI/scripts/build_bsp.m @@ -0,0 +1,68 @@ +%% Move to correct location +p = mfilename('fullpath'); +p = strsplit(p,'/'); +p = p(1:end-1); +p = strjoin(p,'/'); +cd(p); +cd .. + +%% Setup HDL repo +system('git clone --single-branch -b hdl_2018_r1 https://github.com/analogdevicesinc/hdl.git') +system('source /opt/Xilinx/Vivado/2017.4/settings64.sh'); + +%% Update adi_ip script to make sure archive are built in a portable way +copyfile('scripts/adi_ip.tcl', 'hdl/library/scripts/') + +%% Pack all cores +system('/opt/Xilinx/Vivado/2017.4/bin/vivado -mode batch -source scripts/pack_all_ips.tcl && echo "success" || echo "failed"') + +%% Repack i2s core to include xml files +cd hdl/library/axi_i2s_adi/ +unzip('analog.com_user_axi_i2s_adi_1.0.zip','tmp') +delete('analog.com_user_axi_i2s_adi_1.0.zip') +copyfile('*.xml','tmp') +zip('analog.com_user_axi_i2s_adi_1.0.zip',{'*'},'tmp'); +cd ../../.. + +cd hdl/library/util_i2c_mixer/ +unzip('analog.com_user_util_i2c_mixer_1.0.zip','tmp') +delete('analog.com_user_util_i2c_mixer_1.0.zip') +copyfile('*.xml','tmp') +zip('analog.com_user_util_i2c_mixer_1.0.zip',{'*'},'tmp'); +cd ../../.. + +%% Move all cores +system('/opt/Xilinx/Vivado/2017.4/bin/vivado -mode batch -source scripts/copy_all_packed_ips.tcl && echo "success" || echo "failed"') +!cp -r hdl/library/jesd204/*.zip hdl/library/ +!cp -r hdl/library/xilinx/*.zip hdl/library/ +!rm -rf hdl/projects +!cp -r projects hdl/ + +%% Remove unused projects in BSP +% cd hdl/projects +% whitelist = {'..','.','scripts','fmcomms5','fmcomms2','common','adrv9361z7035','adrv9364z7020','adrv9009'}; +% files = dir('.'); +% files = {files.name}; +% for file = files +% if ~ismember(file{:},whitelist) +% disp(file{:}) +% if isfile(file{:}) +% delete(file{:}); +% elseif isfolder(file{:}) +% rmdir(file{:},'s'); +% end +% end +% end +% cd ../.. + +%% Update tcl scripts and additional IP cores (MUX) +copyfile('scripts/adi_project.tcl', 'hdl/projects/scripts/') +copyfile('scripts/adi_build.tcl', 'hdl/projects/scripts/') +copyfile('ip/*.zip', 'hdl/library/') +movefile('hdl','../../hdl_wa_bsp/vendor/AnalogDevices/vivado') + +%% Cleanup +delete('vivado_*') +delete('vivado.jou') +delete('vivado.log') + diff --git a/CI/scripts/build_bsp.sh b/CI/scripts/build_bsp.sh new file mode 100644 index 0000000..5a7d1a8 --- /dev/null +++ b/CI/scripts/build_bsp.sh @@ -0,0 +1,273 @@ +#!/bin/bash +set -x + +if [ -z "${HDLBRANCH}" ]; then +HDLBRANCH='hdl_2019_r2' +fi + + +# Script is designed to run from specific location +scriptdir=`dirname "$BASH_SOURCE"` +cd $scriptdir +cd .. + +# Get HDL +if [ -d "hdl" ]; then + rm -rf "hdl" +fi +for i in {1..5} +do + if git clone --single-branch -b $HDLBRANCH https://github.com/analogdevicesinc/hdl.git + then + break + fi + if [ -d "hdl" ]; then + break + fi +done +if [ ! -d "hdl" ]; then + echo "HDL clone failed" + exit 1 +fi + + +# Get required vivado version needed for HDL +if [ -f "hdl/library/scripts/adi_ip.tcl" ]; then + TARGET="hdl/library/scripts/adi_ip.tcl" +else + TARGET="hdl/library/scripts/adi_ip_xilinx.tcl" +fi +VER=$(awk '/set REQUIRED_VIVADO_VERSION/ {print $3}' $TARGET | sed 's/"//g') +echo "Required Vivado version ${VER}" +VIVADOFULL=${VER} +if [ ${#VER} = 8 ] +then +VER=${VER:0:6} +fi +VIVADO=${VER} + +# Setup +source /opt/Xilinx/Vivado/$VIVADO/settings64.sh + +# Update build scripts and force vivado versions +cp scripts/adi_ip.tcl hdl/library/scripts/ +VERTMP=$(awk '/set REQUIRED_VIVADO_VERSION/ {print $3}' hdl/library/scripts/adi_ip.tcl | sed 's/"//g') +grep -rl ${VERTMP} hdl/library/scripts | xargs sed -i -e "s/${VERTMP}/${VIVADOFULL}/g" + +# Update relative paths +FILES=$(grep -lrnw hdl/projects -e "\.\.\/common" | grep -v Makefile) +for f in $FILES +do + echo "Updating relative paths of: $f" + DEVICE=$(echo "$f"| cut -d "/" -f 3) + STR="\$ad_hdl_dir\/projects\/$DEVICE" + sed -i "s/\.\.\/common/$STR\/common/g" "$f" +done + +# Rename .prj files since MATLAB ignores then during packaging +FILES=$(grep -lrn hdl/projects/common -e '.prj' | grep -v Makefile | grep -v .git) +for f in $FILES +do + echo "Updating prj reference in: $f" + sed -i "s/\.prj/\.mk/g" "$f" +done +FILES=$(find hdl/projects/common -name "*.prj") +for f in $FILES +do + DEST="${f::-3}mk" + echo "Renaming: $f to $DEST" + mv "$f" "$DEST" +done + +# Remove intel +rm -rf hdl/projects/common/intel +rm -rf hdl/library/intel + +# Remove references to GHDL crap +wget https://raw.githubusercontent.com/analogdevicesinc/hdl/hdl_2018_r2/library/scripts/adi_env.tcl +mv adi_env.tcl hdl/library/scripts/ +cp scripts/adi_env.tcl hdl/projects/scripts/ + +cp scripts/adi_project_xilinx.tcl hdl/projects/scripts/ +cp scripts/adi_ip_xilinx.tcl hdl/library/scripts/ + +# Update cores to move relative paths locally +sed -i 's/add_files/add_files\ -copy_to\ \[pwd\]\ -force/g' hdl/library/jesd204/axi_jesd204_common/axi_jesd204_common_ip.tcl + +# Update new folder names +sed -i 's/util_cdc/analog_lib.com_user_util_cdc_1.0/g' hdl/projects/common/xilinx/adi_fir_filter_bd.tcl +sed -i 's/util_fir_int/analog_lib.com_user_util_fir_int_1.0/g' hdl/projects/adrv9009/common/adrv9009_bd.tcl +sed -i 's/util_fir_int/analog_lib.com_user_util_fir_int_1.0/g' hdl/projects/adrv9371x/common/adrv9371x_bd.tcl + +# Pack IP cores +pwd +echo "Starting IP core packaging" +#vivado -verbose -mode batch -source scripts/pack_all_ips.tcl > /dev/null 2>&1 +vivado -verbose -mode batch -source scripts/pack_all_ips.tcl > log.txt + +# Repack i2s and i2c cores to include xml files +cd hdl/library/axi_i2s_adi/ +pwd +ls +#unzip analog.com_user_axi_i2s_adi_1.0.zip -d tmp +unzip analog_lib.com_user_axi_i2s_adi_1.0.zip -d tmp +#rm analog.com_user_axi_i2s_adi_1.0.zip +rm analog_lib.com_user_axi_i2s_adi_1.0.zip +ls +cp *.xml tmp/ +cd tmp +#zip -r analog.com_user_axi_i2s_adi_1.0.zip * +zip -r analog_lib.com_user_axi_i2s_adi_1.0.zip * +#cp analog.com_user_axi_i2s_adi_1.0.zip ../ +cp analog_lib.com_user_axi_i2s_adi_1.0.zip ../ +cd ../../../.. + +pwd + +cd hdl/library/util_i2c_mixer/ +#unzip analog.com_user_util_i2c_mixer_1.0.zip -d tmp/ +unzip analog_lib.com_user_util_i2c_mixer_1.0.zip -d tmp/ +#rm analog.com_user_util_i2c_mixer_1.0.zip +rm analog_lib.com_user_util_i2c_mixer_1.0.zip +cp *.xml tmp/ +cd tmp +#zip -r analog.com_user_util_i2c_mixer_1.0.zip * +zip -r analog_lib.com_user_util_i2c_mixer_1.0.zip * +#cp analog.com_user_util_i2c_mixer_1.0.zip ../ +cp analog_lib.com_user_util_i2c_mixer_1.0.zip ../ +cd ../../../.. + +pwd + +# Rename zips so they do not overwrite one another +cd hdl/library/jesd204 +FILES=$(find . -name "*.zip") +for f in $FILES +do + M=${f:2} + mv -- "$M" . +done +cd ../../.. + +#cd hdl/library/jesd204 +#FILES=$(find . -name "*.zip") +#for f in $FILES +#do +# echo "Renaming $f" +# M=${f:2} +# echo "Repacking $M" +# FN=${M::-4} +# unzip $M -d $FN +# mv -- "$FN" "jesd204_${FN}" +# cd "jesd204_${FN}" +# zip -r "jesd204_${FN}.zip" * +# cd .. +# mv "jesd204_${FN}/jesd204_${FN}.zip" . +# rm -rf "jesd204_${FN}" +# rm $M +#done +#cd ../../.. + +cd hdl/library/xilinx +FILES=$(find . -name "*.zip") +for f in $FILES +do + M=${f:2} + mv -- "$M" . +done +cd ../../.. + +#cd hdl/library/xilinx +#FILES=$(find . -name "*.zip") +#for f in $FILES +#do +# echo "Renaming $f" +# M=${f:2} +# echo "Repacking $M" +# FN=${M::-4} +# unzip $M -d $FN +# mv -- "$FN" "xilinx_${FN}" +# cd "xilinx_${FN}" +# zip -r "xilinx_${FN}.zip" * +# cd .. +# mv "xilinx_${FN}/xilinx_${FN}.zip" . +# rm -rf "xilinx_${FN}" +# rm $M +#done +#cd ../../.. + + +# Move all cores +echo "Moving all cores" +vivado -mode batch -source scripts/copy_all_packed_ips.tcl || true + +cp -r hdl/library/util_pack/*.zip hdl/library/ +cp -r hdl/library/jesd204/*.zip hdl/library/ +cp -r hdl/library/xilinx/*.zip hdl/library/ +cp -r hdl/projects/common common +cp -r hdl/projects/scripts/adi_board.tcl . + +mv hdl/projects projects_premerge +# Remove pluto since its manually updated +rm -rf projects_premerge/pluto +cp -r projects hdl/ +cp -R projects_premerge/* hdl/projects/ +rm -rf projects_premerge + +cp -R common/* hdl/projects/common/ +rm -rf common +mv adi_board.tcl hdl/projects/scripts/ + +# Update tcl scripts and additional IP cores (MUX) +cp scripts/adi_project.tcl hdl/projects/scripts/ +cp scripts/adi_build.tcl hdl/projects/scripts/ +cp ip/*.zip hdl/library/ + +# Update vivado version in MATLAB API and build script +DEFAULT_V_VERSION='2017.4' +cd .. +echo "SED 1" +grep -rl ${DEFAULT_V_VERSION} hdl/vendor/AnalogDevices/+AnalogDevices | grep -v MODEM | xargs sed -i "s/${DEFAULT_V_VERSION}/$VIVADO/g" +cd CI +echo "SED 2" +grep -rl ${DEFAULT_V_VERSION} hdl/projects/scripts | xargs sed -i "s/${DEFAULT_V_VERSION}/$VIVADOFULL/g" + +# Remove extra projects +FILES=$(find hdl/projects) +for f in $FILES +do + if [[ "$f" == 'adrv9009' ]]; then + continue + elif [[ "$f" == 'adrv9371x' ]]; then + continue + elif [[ "$f" == 'fmcomms2' ]]; then + continue + elif [[ "$f" == 'fmcomms5' ]]; then + continue + elif [[ "$f" == 'pluto' ]]; then + continue + elif [[ "$f" == 'adrv9001' ]]; then + continue + elif [[ "$f" == 'adrv9361z7035' ]]; then + continue + elif [[ "$f" == 'adrv9364z7020' ]]; then + continue + fi + rm -rf "hdl/projects/$f" + +done + +# Remove git directory move to bsp folder +rm -fr hdl/.git* +TARGET="../hdl/vendor/AnalogDevices/vivado" +if [ -d "$TARGET" ]; then + rm -rf "$TARGET" +fi +cp -r hdl $TARGET + + +# Cleanup +rm vivado_* +rm vivado.jou +rm vivado.log +rm -rf hdl diff --git a/CI/scripts/copy_all_packed_ips.tcl b/CI/scripts/copy_all_packed_ips.tcl new file mode 100644 index 0000000..b8132f3 --- /dev/null +++ b/CI/scripts/copy_all_packed_ips.tcl @@ -0,0 +1,74 @@ + + +proc copy_all_packed_ips { DEST_FOLDER } { + + #set WD [pwd] + #set DEST_FOLDER D:/Work/hdlbsp-master/vendor/AnalogDevices/vivado/library + #set DEST_FOLDER $WD + + set folder_list [glob -types d *] + foreach dir $folder_list { + puts "$dir" + cd $dir + + if {[catch {set files_list [glob *]}]} { + cd .. + continue + } + + foreach file $files_list { + set idx [string first .zip $file 1] + if {$idx != -1} { + file copy -force $file $DEST_FOLDER/$file + puts $file + } + } + cd .. + + # Don't remove these folders + if {$dir=="common"} {continue} + if {$dir=="interfaces"} {continue} + if {$dir=="prcfg"} {continue} + if {$dir=="scripts"} {continue} + if {$dir=="xilinx"} {continue} + if {$dir=="jesd204"} {continue} + if {$dir=="spi_engine"} {continue} + if {$dir=="util_pack"} {continue} + file delete -force -- $dir + + + } + +} + +cd hdl + +# Move main library core zips +cd library +set DEST [pwd] +puts $DEST +copy_all_packed_ips $DEST + +# Move Xilinx core zips +cd xilinx +set DEST [pwd] +copy_all_packed_ips $DEST +cd .. + +# Move jesd204 core zips +cd jesd204 +set DEST [pwd] +copy_all_packed_ips $DEST +cd .. + +# Move spi_engine core zips +cd spi_engine +set DEST [pwd] +copy_all_packed_ips $DEST + +# Move util_pack core zips +cd util_pack +set DEST [pwd] +copy_all_packed_ips $DEST + +cd ../../.. diff --git a/CI/scripts/dockermake b/CI/scripts/dockermake new file mode 100644 index 0000000..06c9322 --- /dev/null +++ b/CI/scripts/dockermake @@ -0,0 +1,3 @@ +#!/bin/bash +docker build . -t matlabci -f CI/scripts/Docker +docker run --rm -e "INCLUDE_EXAMPLES=$INCLUDE_EXAMPLES" -e "BOARD=$BOARD" -e "LM_LICENSE_FILE=$LM_LICENSE_FILE" -e "XILINXD_LICENSE_FILE=$XILINXD_LICENSE_FILE" -e "MLRELEASE=$MLRELEASE" -e "HDLBRANCH=$HDLBRANCH" -v "$(pwd):/work" -v /mlhsp:/mlhspro:ro -v /usr/local/MATLAB:/usr/local/MATLAB -v /root/.matlab:/root/.matlabro:ro -v /root/.Xilinx:/root/.Xilinxro:ro -v /opt/Xilinx:/opt/Xilinx --mac-address="$ADDR" matlabci /bin/bash -c "cd /work && chmod +x CI/scripts/setupDocker.sh && ./CI/scripts/setupDocker.sh && make -C CI/scripts '$@'" diff --git a/CI/scripts/genTlbx.m b/CI/scripts/genTlbx.m new file mode 100644 index 0000000..c95c2fb --- /dev/null +++ b/CI/scripts/genTlbx.m @@ -0,0 +1,96 @@ +function genTlbx(examples) + +if nargin==0 + examples = 1; +end + +version = '21.2.1'; +ml = ver('MATLAB'); +ml = ml.Release(2:end-1); +uuid = matlab.lang.internal.uuid; + +%% +cd(fileparts((mfilename('fullpath')))); +cd('../..'); +p = pwd; +cd(fileparts((mfilename('fullpath')))); + +if examples + fid = fopen('bsp.tmpl','r'); +else + fid = fopen('bsp_noexamples.tmpl','r'); +end +f=fread(fid,'*char')'; +fclose(fid); + +f = strrep(f,'__REPO-ROOT__',p); +f = strrep(f,'__VERSION__',version); +f = strrep(f,'__ML-RELEASE__',ml); +f = strrep(f,'__UUID__',uuid); + +fid = fopen('../../bsp.prj','w'); +fprintf(fid,'%s',f); +fclose(fid); + +cd('../..'); +addpath(genpath(matlabshared.supportpkg.getSupportPackageRoot)); +addpath(genpath('.')); +rmpath(genpath('.')); +if examples + ps = {'doc','examples'}; +else + ps = {'doc'}; +end +paths = ''; +for p = ps + pp = genpath(p{:}); + ppF = pp; + pp = pp(1:end-1); + pp = strrep(pp,':',''); + paths = [paths,['',pp,'']]; %#ok + addpath(ppF); +end +rehash +projectFile = 'bsp.prj'; +currentVersion = matlab.addons.toolbox.toolboxVersion(projectFile); +if examples + outputFile = ['AnalogDevicesPrecisionToolbox_v',currentVersion]; +else + outputFile = ['AnalogDevicesPrecisionToolbox_noexamples_v',currentVersion]; +end +matlab.addons.toolbox.packageToolbox(projectFile,outputFile) + +if ~usejava('desktop') + %% Update toolbox paths + mkdir other + movefile([outputFile,'.mltbx'], ['other/',outputFile,'.zip']); + cd other + unzip([outputFile,'.zip'],'out'); + cd('out') + cd('metadata'); + fid = fopen('configuration.xml','r'); + f=fread(fid,'*char')'; + fclose(fid); + + s = ''; + sections = strsplit(f,s); + s1 = sections{1}; + s2 = sections{2}; + newfile = [s1,paths,s,s2]; + + fid = fopen('configuration.xml','w'); + fprintf(fid,'%s',newfile); + fclose(fid); + + %% Repack + cd('..'); + zip([outputFile,'.zip'], '*'); + movefile([outputFile,'.zip'],['../../',outputFile,'.mltbx']); + cd('../..'); + rmdir('other','s'); +end + +delete bsp.prj + + + diff --git a/CI/scripts/genTlbx2.m b/CI/scripts/genTlbx2.m new file mode 100644 index 0000000..4c83292 --- /dev/null +++ b/CI/scripts/genTlbx2.m @@ -0,0 +1,101 @@ +function genTlbx2(examples) + +if nargin==0 + examples = 0; +end + +% Lookup versioning info from adi.Version +cwd = pwd; +parts = strsplit(mfilename('fullpath'),filesep); +tbroot = strjoin(parts(1:end-3),filesep); +cd(tbroot); +v = adi.Version; +uuid = matlab.lang.internal.uuid; +cd(cwd); + +%% +cd(fileparts((mfilename('fullpath')))); +cd('../..'); +p = pwd; +cd(fileparts((mfilename('fullpath')))); + +fid = fopen('bsp.tmpl','r'); +f=fread(fid,'*char')'; +fclose(fid); + +f = strrep(f,'__REPO-ROOT__',p); +f = strrep(f,'__VERSION__',v.Release); +f = strrep(f,'__ML-RELEASE__',v.MATLAB); +f = strrep(f,'__APP-NAME__',v.AppName); +f = strrep(f,'__EXAMPLES-DIR__',v.ExamplesDir); +f = strrep(f,'__UUID__',uuid); + +fid = fopen('../../bsp.prj','w'); +fprintf(fid,'%s',f); +fclose(fid); + +cd('../..'); +addpath(genpath(matlabshared.supportpkg.getSupportPackageRoot)); +addpath(genpath('.')); +rmpath(genpath('.')); +if examples + ps = {'doc',v.ExamplesDir}; +else + ps = {'doc'}; +end +if isprop(v,'HasHDL') && v.HasHDL + ps = [ps(:)',{'hdl'}]; +end + +paths = ''; +for p = ps + pp = genpath(p{:}); + ppF = pp; + pp = pp(1:end-1); + pp = strrep(pp,':',''); + paths = [paths,['',pp,'']]; %#ok + addpath(ppF); +end +rehash +projectFile = 'bsp.prj'; +currentVersion = matlab.addons.toolbox.toolboxVersion(projectFile); +if examples + outputFile = sprintf('AnalogDevices%s_v%s',v.ToolboxName,currentVersion); +else + outputFile = sprintf('AnalogDevices%s_noexamples_v%s',v.ToolboxName,currentVersion); +end +matlab.addons.toolbox.packageToolbox(projectFile,outputFile) + +if ~usejava('desktop') + %% Update toolbox paths + mkdir other + movefile([outputFile,'.mltbx'], ['other/',outputFile,'.zip']); + cd other + unzip([outputFile,'.zip'],'out'); + cd('out') + cd('metadata'); + fid = fopen('configuration.xml','r'); + f=fread(fid,'*char')'; + fclose(fid); + + s = ''; + sections = strsplit(f,s); + s1 = sections{1}; + s2 = sections{2}; + newfile = [s1,paths,s,s2]; + + fid = fopen('configuration.xml','w'); + fprintf(fid,'%s',newfile); + fclose(fid); + + %% Repack + cd('..'); + zip([outputFile,'.zip'], '*'); + movefile([outputFile,'.zip'],['../../',outputFile,'.mltbx']); + cd('../..'); + rmdir('other','s'); +end + +% delete bsp.prj + + diff --git a/CI/scripts/linter.m b/CI/scripts/linter.m new file mode 100644 index 0000000..4a26bff --- /dev/null +++ b/CI/scripts/linter.m @@ -0,0 +1,23 @@ +clc; +ignoreFolders = {'CI','doc','test'}; +cd ../.. +d = pwd; +cd .. +addpath(genpath(d)); +cd(d); + +files = dir('**/*.m'); +for file = 1:length(files) + if contains(files(file).folder,ignoreFolders) + continue; + end + mfile = fullfile(files(file).folder,files(file).name); + rpt = mlint(mfile); + if ~isempty(rpt) + disp(mfile); + for l = 1:length(rpt) + disp([num2str(rpt(l).line) ': ' rpt(l).message]); + end + end +end + diff --git a/CI/scripts/pack_all_ips.tcl b/CI/scripts/pack_all_ips.tcl new file mode 100644 index 0000000..271533c --- /dev/null +++ b/CI/scripts/pack_all_ips.tcl @@ -0,0 +1,58 @@ + +# Create zip of IP cores +proc pack_ip_core {sub} { + + set folder_list [glob -types d *] + + foreach dir $folder_list { + puts "$dir" + cd $dir + + if {[catch {set fp [open ${dir}_ip.tcl r]}]} { + cd .. + continue + } + close $fp + + set fp [open ${dir}_ip.tcl a+] + puts -nonewline $fp "ipx::archive_core -verbose {analog_${sub}.com_user_" + puts -nonewline $fp "$dir" + puts -nonewline $fp "_1.0.zip} \[ipx::current_core\]" + close $fp + + source ./${dir}_ip.tcl + + cd .. + } +} + +source hdl/library/scripts/adi_ip.tcl +source hdl/library/scripts/adi_env.tcl + +cd hdl + +# Pack main library cores +cd library +pack_ip_core "lib" + +# Pack Xilinx cores +cd xilinx +pack_ip_core "xilinx" +cd .. + +# Pack JESD cores +cd jesd204 +pack_ip_core "jesd" +cd .. + +# Pack spi_engine cores +cd spi_engine +pack_ip_core "spi_engine" +cd .. + +# Pack pack cores +cd util_pack +pack_ip_core "util_pack" +cd .. + +cd ../../ diff --git a/CI/scripts/ports.json b/CI/scripts/ports.json new file mode 100644 index 0000000..278ae32 --- /dev/null +++ b/CI/scripts/ports.json @@ -0,0 +1,178 @@ +{ + "ad7380": { + "chip": "AD7380", + "complex": "false", + "fpga": [ + "zcu102" + ], + "supported_rd": [ + "rx" + ], + "ports": [ + { + "rx": [ + { + "input": "false", + "width": 1, + "name": "axi_ad9680_cpack/fifo_wr_en", + "type": "valid" + }, + { + "input": "true", + "width": 1, + "name": "axi_ad9680_tpl/adc_valid_0", + "type": "valid" + }, + { + "input": "false", + "width": 64, + "name": "axi_ad9680_cpack/fifo_wr_data_0", + "type": "data" + }, + { + "input": "false", + "width": 64, + "name": "axi_ad9680_cpack/fifo_wr_data_1", + "type": "data" + }, + { + "input": "true", + "width": 64, + "name": "axi_ad9680_tpl/adc_data_0", + "type": "data" + }, + { + "input": "true", + "width": 64, + "name": "axi_ad9680_tpl/adc_data_1", + "type": "data" + } + ] + } + ] + }, + "ad7768": { + "chip": "AD7768", + "complex": "false", + "fpga": [ + "zcu102" + ], + "supported_rd": [ + "rx" + ], + "ports": [ + { + "rx": [ + { + "input": "false", + "width": 1, + "name": "util_mxfe_cpack/fifo_wr_en", + "type": "valid" + }, + { + "input": "true", + "width": 1, + "name": "rx_mxfe_tpl_core/adc_valid_0", + "type": "valid" + }, + { + "input": "false", + "width": 16, + "name": "util_mxfe_cpack/fifo_wr_data_0", + "type": "data" + }, + { + "input": "false", + "width": 16, + "name": "util_mxfe_cpack/fifo_wr_data_1", + "type": "data" + }, + { + "input": "false", + "width": 16, + "name": "util_mxfe_cpack/fifo_wr_data_2", + "type": "data" + }, + { + "input": "false", + "width": 16, + "name": "util_mxfe_cpack/fifo_wr_data_3", + "type": "data" + }, + { + "input": "false", + "width": 16, + "name": "util_mxfe_cpack/fifo_wr_data_4", + "type": "data" + }, + { + "input": "false", + "width": 16, + "name": "util_mxfe_cpack/fifo_wr_data_5", + "type": "data" + }, + { + "input": "false", + "width": 16, + "name": "util_mxfe_cpack/fifo_wr_data_6", + "type": "data" + }, + { + "input": "false", + "width": 16, + "name": "util_mxfe_cpack/fifo_wr_data_7", + "type": "data" + }, + { + "input": "true", + "width": 16, + "name": "rx_mxfe_tpl_core/adc_data_0", + "type": "data" + }, + { + "input": "true", + "width": 16, + "name": "rx_mxfe_tpl_core/adc_data_1", + "type": "data" + }, + { + "input": "true", + "width": 16, + "name": "rx_mxfe_tpl_core/adc_data_2", + "type": "data" + }, + { + "input": "true", + "width": 16, + "name": "rx_mxfe_tpl_core/adc_data_3", + "type": "data" + }, + { + "input": "true", + "width": 16, + "name": "rx_mxfe_tpl_core/adc_data_4", + "type": "data" + }, + { + "input": "true", + "width": 16, + "name": "rx_mxfe_tpl_core/adc_data_5", + "type": "data" + }, + { + "input": "true", + "width": 16, + "name": "rx_mxfe_tpl_core/adc_data_6", + "type": "data" + }, + { + "input": "true", + "width": 16, + "name": "rx_mxfe_tpl_core/adc_data_7", + "type": "data" + } + ] + } + ] + } +} diff --git a/CI/scripts/read_ports_json.py b/CI/scripts/read_ports_json.py new file mode 100644 index 0000000..7d6a695 --- /dev/null +++ b/CI/scripts/read_ports_json.py @@ -0,0 +1,59 @@ +import json + +# open ports.json file and parse +ports_json_file = 'ports.json' +with open(ports_json_file) as json_file: + ports = json.load(json_file) + + tmp_key = "m_name" + for key0 in ports.keys(): + for key1 in ports[key0]['ports'][0].keys(): + if (key1 == "rx"): + for ii in range(0, len(ports[key0]['ports'][0][key1])): + tmp_dict = ports[key0]['ports'][0][key1][ii] + if (tmp_dict['type'].lower() == "data"): + if (tmp_dict['input'] == "true"): + if tmp_key not in tmp_dict: + tmp_list = tmp_dict['name'].split("_") + last_ele = tmp_list[-1] + if (len(last_ele) == 1): + tmp_dict[tmp_key] = f"{ports[key0]['chip']} ADC Data {last_ele} IN" + elif (len(last_ele) == 2): + tmp_dict[tmp_key] = f"{ports[key0]['chip']} ADC Data {last_ele.upper()}" + elif (tmp_dict['input'] == "false"): + if tmp_key not in tmp_dict: + tmp_list = tmp_dict['name'].split("_") + last_ele = tmp_list[-1] + tmp_dict[tmp_key] = f"IP Data {last_ele.upper()} OUT" + elif (tmp_dict['type'].lower() == "valid"): + if (tmp_dict['input'] == "true"): + tmp_dict[tmp_key] = f"IP Valid Rx Data IN" + elif (tmp_dict['input'] == "false"): + tmp_dict[tmp_key] = f"IP Data Valid OUT" + ports[key0]['ports'][0][key1][ii] = tmp_dict + elif (key1 == "tx"): + for ii in range(0, len(ports[key0]['ports'][0][key1])): + tmp_dict = ports[key0]['ports'][0][key1][ii] + if (tmp_dict['type'].lower() == "data"): + if (tmp_dict['input'] == "false"): + if tmp_key not in tmp_dict: + tmp_list = tmp_dict['name'].split("_") + last_ele = tmp_list[-1] + if (len(last_ele) == 1): + tmp_dict[tmp_key] = f"{ports[key0]['chip']} DAC Data {last_ele} OUT" + elif (len(last_ele) == 2): + tmp_dict[tmp_key] = f"{ports[key0]['chip']} DAC Data {last_ele.upper()}" + elif (tmp_dict['input'] == "true"): + if tmp_key not in tmp_dict: + tmp_list = tmp_dict['name'].split("_") + last_ele = tmp_list[-1] + tmp_dict[tmp_key] = f"IP Data {last_ele.upper()} IN" + elif (tmp_dict['type'].lower() == "valid"): + if (tmp_dict['input'] == "true"): + tmp_dict[tmp_key] = f"IP Valid Tx Data IN" + elif (tmp_dict['input'] == "false"): + tmp_dict[tmp_key] = f"IP Load Tx Data OUT" + ports[key0]['ports'][0][key1][ii] = tmp_dict + +with open(ports_json_file, 'w') as json_file: + json.dump(ports, json_file, indent = 4) \ No newline at end of file diff --git a/CI/scripts/rename_common.py b/CI/scripts/rename_common.py new file mode 100644 index 0000000..46403c6 --- /dev/null +++ b/CI/scripts/rename_common.py @@ -0,0 +1,35 @@ +import os +import glob +import pathlib + +new_dir = "+commonrf" + +path = pathlib.Path(__file__).parent.resolve() + +path = os.path.split(path) +path = os.path.split(path[0])[0] + +files = glob.glob(os.path.join(path, "+adi", "**/*")) +if len(files) == 0: + print("No files found") + print("Did you clone all the submodules?") + exit(1) + +for file in files: + if os.path.isdir(file): + continue + with open(file, "r") as f: + content = f.read() + if "adi.common." in content: + content = content.replace("adi.common.", f"adi.{new_dir[1:]}.") + print("Updating:", file) + with open(file, "w") as f: + f.write(content) + +src = os.path.join(path, "+adi", "+common") +dst = os.path.join(path, "+adi", new_dir) +if os.path.isdir(src): + print("Renaming:", src, "->", dst) + os.rename(src, dst) +else: + print("No +common folder found. Maybe you already renamed it?") diff --git a/CI/scripts/setupDocker.sh b/CI/scripts/setupDocker.sh new file mode 100644 index 0000000..eca338c --- /dev/null +++ b/CI/scripts/setupDocker.sh @@ -0,0 +1,8 @@ +#!/bin/bash +# This file is run inside of the docker container +echo "Copying HSP files" +cp -r /mlhspro /mlhsp +echo "Copying .matlab" +cp -r /root/.matlabro /root/.matlab +echo "Copying .Xilinx" +cp -r /root/.Xilinxro /root/.Xilinx diff --git a/CI/scripts/synth_designs.sh b/CI/scripts/synth_designs.sh new file mode 100644 index 0000000..e99496d --- /dev/null +++ b/CI/scripts/synth_designs.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +BOARD=$1 +MLFLAGS="-nodisplay -nodesktop -nosplash" + +if [ -z "$MLRELEASE" ] +then + MLRELEASE=R2021a +fi + +MLPATH=/usr/local/MATLAB + +cd ../.. +cp hdl/vendor/AnalogDevices/hdlcoder_board_customization.m test/hdlcoder_board_customization_local.m +sed -i "s/hdlcoder_board_customization/hdlcoder_board_customization_local/g" test/hdlcoder_board_customization_local.m +source /opt/Xilinx/Vivado/2019.1/settings64.sh +Xvfb :77 & +export DISPLAY=:77 +export SWT_GTK3=0 +source /opt/Xilinx/Vivado/2019.1/settings64.sh +$MLPATH/$MLRELEASE/bin/matlab $MLFLAGS -r "cd('test');runSynthTests('$BOARD');" +kill -9 `pidof Xvfb` diff --git a/CI/scripts/targeting_designs.sh b/CI/scripts/targeting_designs.sh new file mode 100644 index 0000000..d284fe6 --- /dev/null +++ b/CI/scripts/targeting_designs.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +MLFLAGS="-nodisplay -nodesktop -nosplash" + +if [ -z "$MLRELEASE" ] +then + MLRELEASE=R2021a +fi +if [ -z "$DEMO" ] +then + DEMO="" +fi +echo "Testing demo: $DEMO" + +MLPATH=/usr/local/MATLAB + +cd ../.. +source /opt/Xilinx/Vivado/2019.1/settings64.sh +Xvfb :77 & +export DISPLAY=:77 +export SWT_GTK3=0 +source /opt/Xilinx/Vivado/2019.1/settings64.sh +$MLPATH/$MLRELEASE/bin/matlab $MLFLAGS -r "addpath(genpath('test'));addpath(genpath('deps'));runDemoTests('$DEMO');" +kill -9 `pidof Xvfb` diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000..422d05c --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,51 @@ +//@Library('tfc-lib') _ +library(identifier: 'jenkinssharedlib@MATLAB-bootfiles', retriever: modernSCM( + [$class: 'GitSCMSource', + remote: 'https://github.com/ribhudp23/jenkinssharedlib-private-fork.git', + credentialsId: 'GH-SharedLib-Private-Fork-Access' +])) +https://github.com/ribhudp23/jenkinssharedlib-private-fork.git + +dockerConfig = getDockerConfig(['MATLAB','Vivado'], matlabHSPro=false) +dockerConfig.add("-e MLRELEASE=R2021b") +dockerHost = 'docker' + +//////////////////////////// + + +hdlBranches = ['main'] + +stage("Build Toolbox") { + dockerParallelBuild(hdlBranches, dockerHost, dockerConfig) { + branchName -> + withEnv(['HDLBRANCH='+branchName]) { + checkout scm + sh 'git submodule update --init' + sh 'pip3 install -r requirements_doc.txt' + sh 'make -C ./CI/gen_doc doc' + + sh 'make -C ./CI/scripts gen_tlbx' + } + stash includes: '**', name: 'builtSources', useDefaultExcludes: false + archiveArtifacts artifacts: '*.mltbx', followSymlinks: false, allowEmptyArchive: true + } +} + +///////////////////////////////////////////////////// + + + +////////////////////////////////////////////////////// +node { + stage('Deploy Development') { + unstash "builtSources" + uploadArtifactory('PrecisionToolbox','*.mltbx') + } + if (env.BRANCH_NAME == 'main') { + stage('Deploy Production') { + unstash "builtSources" + uploadFTP('PrecisionToolbox','*.mltbx') + } + } + +} diff --git a/JenkinsfileHW b/JenkinsfileHW new file mode 100644 index 0000000..d6542bc --- /dev/null +++ b/JenkinsfileHW @@ -0,0 +1,68 @@ +// Pipeline +lock(label: 'adgt_test_harness_boards') { + @Library('sdgtt-lib@adgt-test-harness') _ // Not necessary when we turn on global libraries :) + def hdlBranch = "NA" + def linuxBranch = "NA" + def bootPartitionBranch = "release" + def firmwareVersion = 'v0.34' + def bootfile_source = 'artifactory' // options: sftp, artifactory, http, local + def harness = getGauntlet(hdlBranch, linuxBranch, bootPartitionBranch, firmwareVersion, bootfile_source) + + //Udpate repos + harness.set_env('nebula_repo', 'https://github.com/sdgtt/nebula.git') + harness.set_env('nebula_branch','dev') + harness.set_env('nebula_config_branch','release') + harness.set_env('libiio_branch', 'v0.23') + harness.set_env('telemetry_repo', 'https://github.com/sdgtt/telemetry.git') + harness.set_env('telemetry_branch', 'master') + harness.set_env('matlab_repo', 'https://github.com/analogdevicesinc/TransceiverToolbox.git') // Not necessary when using checkout scm + harness.set_env('matlab_release','R2021b') + + //Update nebula config from netbox + harness.set_update_nebula_config(true) + harness.set_env('nebula_config_source','netbox') + harness.set_env('netbox_ip','192.168.10.11') + harness.set_env('netbox_port','8000') + harness.set_env('netbox_base_url','netbox') + harness.set_env('netbox_token','0123456789abcdef0123456789abcdef01234567') + harness.set_env('netbox_devices_tag','active') + + //Update agent with required deps + harness.set_required_agent(["sdg-nuc-01","sdg-nuc-02"]) + harness.update_agents() + + //Set other test parameters + harness.set_nebula_debug(true) + harness.set_enable_docker(true) + harness.set_docker_host_mode(false) + harness.set_send_telemetry(false) + harness.set_log_jira(false) + harness.set_enable_resource_queuing(true) + harness.set_lock_agent(true) // Required for MATLAB toolbox tests + harness.set_elastic_server('192.168.10.1') + //harness.set_required_hardware(["zynq-zed-ad7380", + // "zynq-zed-ad7768", + // "zynq-zed-ad7768-1", + // "zynq-zed-ad4030", + // "zynq-zed-ad4630-16", + // "zynq-zed-ad4630-24"]) + harness.set_required_hardware(["zynq-zed-adv7511-ad7768-1-evb"]) + harness.set_docker_args(['Vivado', 'MATLAB']) + harness.set_nebula_local_fs_source_root("artifactory.analog.com") + + // Set stages (Stages are run sequentially on agents.) + // harness.add_stage(harness.stage_library("UpdateBOOTFiles"), 'stopWhenFail', + // harness.stage_library("RecoverBoard")) + + // Test stage + harness.set_matlab_commands(["addpath(genpath('test'))", + "pyenv('Version','/usr/bin/python3')", + "runHWTests(getenv('board'))"]) + harness.add_stage(harness.stage_library("MATLABTests"),'continueWhenFail') + + // Send results + harness.add_stage(harness.stage_library('SendResults'),'continueWhenFail') + + // Go go + harness.run_stages() +} \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..08d9e52 --- /dev/null +++ b/LICENSE @@ -0,0 +1,33 @@ +Copyright 2019(c) Analog Devices, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + - Neither the name of Analog Devices, Inc. nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + - The use of this software may or may not infringe the patent rights of one + or more patent holders. This license does not release you from the + requirement that you obtain separate licenses from these patent holders to + use this software. + - Use of the software either in source or binary form or filter designs + resulting from the use of this software, must be connected to, run on or + loaded to an Analog Devices Inc. component. + +THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + +IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/README.md b/README.md index 127bf02..fb05de5 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,35 @@ -# PrecisionToolbox -MATLAB toolbox for ADI precision data converter products +# Analog Devices, Inc. Precision Toolbox + +Toolbox created by ADI to be used with MATLAB and Simulink with ADI Precision products. + +License : [![License](https://img.shields.io/badge/license-LGPL2-blue.svg)](https://github.com/analogdevicesinc/PrecisionToolbox/blob/master/LICENSE) +Latest Release : [![GitHub release](https://img.shields.io/github/release/analogdevicesinc/PrecisionToolbox.svg)](https://github.com/analogdevicesinc/PrecisionToolbox/releases/latest) +Downloads : [![Github All Releases](https://img.shields.io/github/downloads/analogdevicesinc/PrecisionToolbox/total.svg)](https://github.com/analogdevicesinc/PrecisionToolbox/releases/latest) + +As with many open-source packages, we use [GitHub](https://github.com/analogdevicesinc/PrecisionToolbox) to do development and maintain the source, and [Jenkins](https://jenkins.com/) for continuous integration. + - If you want to just use PrecisionToolbox, we suggest using the [latest release](https://github.com/analogdevicesinc/PrecisionToolbox/releases/latest). + - If you think you have found a bug in the release, or need a feature which isn't in the release, try the latest **untested** builds from the master branch. + +| MATLAB Release | Installer Package | +|:--------------:|:-------------------:| +| R2021b | | + +If you use it, and like it - please let us know. If you use it, and hate it - please let us know that too. + +## Supported Tools and Releases + +We provide support across two releases of MATLAB. This does not mean older releases will not work but they are not maintained. Currently supported tools are: +- Bug fixes and new features: MATLAB R2021b + +## Support and Documentation + +All support questions should be posted in our [EngineerZone](https://ez.analog.com/data_converters/precision_adcs) forums. Documentation is included within the toolbox but additional documentation is available on the [ADI Wiki](https://wiki.analog.com/resources/tools-software). + +## Building & Installing + +If you don't want to use the toolbox installers you can manually build the toolbox. Should be a quick matter of `make build`: + +``` +rgetz@pinky:~/PrecisionToolbox$ make -C CI/scripts/ build +``` + diff --git a/examples/ad4030_DataCapture.m b/examples/ad4030_DataCapture.m new file mode 100644 index 0000000..66e5c57 --- /dev/null +++ b/examples/ad4030_DataCapture.m @@ -0,0 +1,31 @@ +%% Script for capturing multiple buffers of data from a connected +%% AD4030-24 board + +% Instantiate the AD4030-24 Rx system object, and specify the uri here +rx = adi.AD4030.Rx('uri', 'ip:analog.local'); + +rx.SamplesPerFrame = 4096; % Using values less than 3660 can yield poor +% performance, generally + +% The parameter below specifies the number of frames or buffers to capture. +% Refer to the Streaming section in the documentation if discontinuities +% are observed in the acquired data. +rx.FrameCount = 1; + +% Only a select few channel groupings yield sensible outputs. Refer to the +% Limitations section in the documentation for more details +rx.EnabledChannels = [1]; + +% Capture data +data = rx(); + +enabledChannels = size(data, 2); +figure(1); +for i = 1:enabledChannels + subplot(enabledChannels, 1, i); + plot(data(1:rx.SamplesPerFrame * rx.FrameCount, i)); + title("Channel " + num2str(rx.EnabledChannels(i))); +end + +% Delete the system object +release(rx); diff --git a/examples/ad4630_DataCapture.m b/examples/ad4630_DataCapture.m new file mode 100644 index 0000000..c296161 --- /dev/null +++ b/examples/ad4630_DataCapture.m @@ -0,0 +1,32 @@ +%% Script for capturing multiple buffers of data from a connected AD4630-16 or +%% AD4630-24 Evaluation board + +% Instantiate the AD4630-24 Rx system object, and specify the uri in this +% manner +rx = adi.AD4630_24.Rx('uri', 'ip:analog.local'); + +rx.SamplesPerFrame = 4096; % Using values less than 3660 can yield poor +% performance, generally + +% The parameter below specifies the number of frames or buffers to capture. +% Refer to the Streaming section in the documentation if discontinuities +% are observed in the acquired data. +rx.FrameCount = 1; + +% Only a select few channel groupings yield sensible outputs. Refer to the +% Limitations section in the documentation for more details +rx.EnabledChannels = [1]; + +% Capture data +data = rx(); + +enabledChannels = size(data, 2); +figure(1); +for i = 1:enabledChannels + subplot(enabledChannels, 1, i); + plot(data(1:rx.SamplesPerFrame * rx.FrameCount, i)); + title("Channel " + num2str(rx.EnabledChannels(i))); +end + +% Delete the system object +release(rx); diff --git a/examples/ad7380_DataCapture.m b/examples/ad7380_DataCapture.m new file mode 100644 index 0000000..7773d48 --- /dev/null +++ b/examples/ad7380_DataCapture.m @@ -0,0 +1,32 @@ +%% Script for capturing and displaying a continuous set of samples from a +%% connected AD7380 board + +%% Trigger setup needs to be performed before this example script can be run +%% Refer to the Limitations section in the documentation for details + +% Instantiate the system object +rx = adi.AD7380.Rx; +% Specify uri +rx.uri = 'ip:analog.local'; +rx.SamplesPerFrame = 4096; % Using values less than 3660 can yield poor +% performance, generally +rx.EnabledChannels = [1 2]; + +% The parameter below specifies the number of frames or buffers to capture. +% Refer to the Streaming section in the documentation if discontinuities +% are observed in the acquired data. +rx.FrameCount = 1; + +% Capture data +data = rx(); + +enabledChannels = size(data, 2); +figure(1); +for i = 1:enabledChannels + subplot(enabledChannels, 1, i); + plot(data(1:rx.FrameCount * rx.SamplesPerFrame, i)); + title("Channel " + num2str(rx.EnabledChannels(i))); +end + +% Delete the system object +release(rx); diff --git a/examples/ad7768_1_DataCapture.m b/examples/ad7768_1_DataCapture.m new file mode 100644 index 0000000..ac71450 --- /dev/null +++ b/examples/ad7768_1_DataCapture.m @@ -0,0 +1,29 @@ +%% Script for capturing and displaying a continuous set of samples from a +%% connected AD7768-1 board + +% Instantiate the system object +rx = adi.AD7768_1.Rx; +% Specify uri +rx.uri = 'ip:analog.local'; +rx.SamplesPerFrame = 4096; % Using values less than 3660 can yield poor +% performance, generally +rx.EnabledChannels = [1]; + +% The parameter below specifies the number of frames or buffers to capture. +% Refer to the Streaming section in the documentation if discontinuities +% are observed in the acquired data. +rx.FrameCount = 1; + +% Capture data +data = rx(); + +enabledChannels = size(data, 2); +figure(1); +for i = 1:enabledChannels + subplot(enabledChannels, 1, i); + plot(data(1:rx.FrameCount * rx.SamplesPerFrame, i)); + title("Channel " + num2str(rx.EnabledChannels(i))); +end + +% Delete the system object +release(rx); diff --git a/examples/ad7768_DataCapture.m b/examples/ad7768_DataCapture.m new file mode 100644 index 0000000..fc7327c --- /dev/null +++ b/examples/ad7768_DataCapture.m @@ -0,0 +1,31 @@ +%% Script for capturing and displaying a continuous set of samples from a +%% connected AD7768 board + +% Instantiate the system object +rx = adi.AD7768.Rx; +% Specify uri +rx.uri = 'ip:analog.local'; +rx.SamplesPerFrame = 4096; % Using values less than 3660 can yield poor +% performance, generally +rx.EnabledChannels = [1 2 3 4 5 6 7 8]; + +rx.SampleRate = '128000'; + +% The parameter below specifies the number of frames or buffers to capture. +% Refer to the Streaming section in the documentation if discontinuities +% are observed in the acquired data. +rx.FrameCount = 3; + +% Capture data +data = rx(); + +enabledChannels = size(data, 2); +figure(1); +for i = 1:enabledChannels + subplot(enabledChannels, 1, i); + plot(data(1:rx.FrameCount * rx.SamplesPerFrame, i)); + title("Channel " + num2str(rx.EnabledChannels(i))); +end + +% Delete the system object +release(rx); diff --git a/info.xml b/info.xml new file mode 100644 index 0000000..4e6b3da --- /dev/null +++ b/info.xml @@ -0,0 +1,25 @@ + + + + + + + + + + R2021b + + Analog Devices, Inc. Precision Toolbox + + + toolbox + + + adi_logo.png + + doc + + + adi_logo.png + diff --git a/requirements_doc.txt b/requirements_doc.txt new file mode 100644 index 0000000..55f25fe --- /dev/null +++ b/requirements_doc.txt @@ -0,0 +1,7 @@ +numpy +mkdocs +mkdocs-material +mkdocs-awesome-pages-plugin +mkdocs-mermaid2-plugin +mkdocs-plugin-inline-svg +jinja2 \ No newline at end of file diff --git a/test/AD4030Tests.m b/test/AD4030Tests.m new file mode 100644 index 0000000..0ffe680 --- /dev/null +++ b/test/AD4030Tests.m @@ -0,0 +1,30 @@ +classdef AD4030Tests < HardwareTests + + properties(TestParameter) + end + properties + uri = 'ip:analog-2.local'; + author = 'ADI'; + end + + methods(TestClassSetup) + % Check hardware connected + function CheckForHardware(testCase) + Device = @()adi.AD4030.Rx; + testCase.CheckDevice('ip',Device,testCase.uri(4:end),false); + end + end + + methods (Test) + + function testAD4030Smoke(testCase) + adc = adi.AD4030.Rx('uri',testCase.uri); + data = adc(); + adc.release(); + testCase.assertTrue(sum(abs(double(data)))>0); + end + + end + +end + diff --git a/test/AD4630_16Tests.m b/test/AD4630_16Tests.m new file mode 100644 index 0000000..98ca2d7 --- /dev/null +++ b/test/AD4630_16Tests.m @@ -0,0 +1,30 @@ +classdef AD4630_16Tests < HardwareTests + + properties(TestParameter) + end + properties + uri = 'ip:analog-2.local'; + author = 'ADI'; + end + + methods(TestClassSetup) + % Check hardware connected + function CheckForHardware(testCase) + Device = @()adi.AD4630_16.Rx; + testCase.CheckDevice('ip',Device,testCase.uri(4:end),false); + end + end + + methods (Test) + + function testAD4630_16Smoke(testCase) + adc = adi.AD4630_16.Rx('uri',testCase.uri); + data = adc(); + adc.release(); + testCase.assertTrue(sum(abs(double(data)))>0); + end + + end + +end + diff --git a/test/AD4630_24Tests.m b/test/AD4630_24Tests.m new file mode 100644 index 0000000..b06a676 --- /dev/null +++ b/test/AD4630_24Tests.m @@ -0,0 +1,30 @@ +classdef AD4630_24Tests < HardwareTests + + properties(TestParameter) + end + properties + uri = 'ip:analog-2.local'; + author = 'ADI'; + end + + methods(TestClassSetup) + % Check hardware connected + function CheckForHardware(testCase) + Device = @()adi.AD4630_24.Rx; + testCase.CheckDevice('ip',Device,testCase.uri(4:end),false); + end + end + + methods (Test) + + function testAD4630_24Smoke(testCase) + adc = adi.AD4630_24.Rx('uri',testCase.uri); + data = adc(); + adc.release(); + testCase.assertTrue(sum(abs(double(data)))>0); + end + + end + +end + diff --git a/test/AD7380Tests.m b/test/AD7380Tests.m new file mode 100644 index 0000000..63e7b5a --- /dev/null +++ b/test/AD7380Tests.m @@ -0,0 +1,30 @@ +classdef AD7380Tests < HardwareTests + + properties(TestParameter) + end + properties + uri = 'ip:analog-2.local'; + author = 'ADI'; + end + + methods(TestClassSetup) + % Check hardware connected + function CheckForHardware(testCase) + Device = @()adi.AD7380.Rx; + testCase.CheckDevice('ip',Device,testCase.uri(4:end),false); + end + end + + methods (Test) + + function testAD7380Smoke(testCase) + adc = adi.AD7380.Rx('uri',testCase.uri); + data = adc(); + adc.release(); + testCase.assertTrue(sum(abs(double(data)))>0); + end + + end + +end + diff --git a/test/AD7768Tests.m b/test/AD7768Tests.m new file mode 100644 index 0000000..1e79617 --- /dev/null +++ b/test/AD7768Tests.m @@ -0,0 +1,30 @@ +classdef AD7768Tests < HardwareTests + + properties(TestParameter) + end + properties + uri = 'ip:analog-2.local'; + author = 'ADI'; + end + + methods(TestClassSetup) + % Check hardware connected + function CheckForHardware(testCase) + Device = @()adi.AD7768.Rx; + testCase.CheckDevice('ip',Device,testCase.uri(4:end),false); + end + end + + methods (Test) + + function testAD7768Smoke(testCase) + adc = adi.AD7768.Rx('uri',testCase.uri); + data = adc(); + adc.release(); + testCase.assertTrue(sum(abs(double(data)))>0); + end + + end + +end + diff --git a/test/AD7768_1Tests.m b/test/AD7768_1Tests.m new file mode 100644 index 0000000..f1854eb --- /dev/null +++ b/test/AD7768_1Tests.m @@ -0,0 +1,31 @@ +classdef AD7768_1Tests < HardwareTests + + properties(TestParameter) + end + properties + uri = 'ip:analog'; + author = 'ADI'; + end + + methods(TestClassSetup) + % Check hardware connected + function CheckForHardware(testCase) + Device = @()adi.AD7768_1.Rx; + testCase.CheckDevice('ip',Device,testCase.uri(4:end),false); + end + end + + methods (Test) + + function testAD7768_1Smoke(testCase) + adc = adi.AD7768_1.Rx; + adc.uri = testCase.uri; + data = adc(); + adc.release(); + testCase.assertTrue(sum(abs(double(data)))>0); + end + + end + +end + diff --git a/test/BSPInstallerTests.m b/test/BSPInstallerTests.m new file mode 100644 index 0000000..fb25988 --- /dev/null +++ b/test/BSPInstallerTests.m @@ -0,0 +1,49 @@ +classdef BSPInstallerTests < BSPTestsBase + properties + installed = []; + end + + methods(TestClassSetup) + function removeinstalledbsp(~) + str = 'Analog Devices Board Support Packages'; + ts = matlab.addons.toolbox.installedToolboxes; + for t = ts + if contains(t.Name,str) + disp('Removing installed BSP'); + matlab.addons.toolbox.uninstallToolbox(t); + end + end + end + function installBSP(obj) + %system('wget https://github.com/analogdevicesinc/MathWorks_tools/releases/download/v18.1.0/AnalogDevicesBSP_v18.1.0.mltbx'); + %system('rm *.mltbx'); + %system('curl -s https://api.github.com/repos/analogdevicesinc/MathWorks_tools/releases/latest | grep browser_download_url | cut -d "\"" -f 4 | wget --no-check-certificate -i -'); + %tbname = 'AnalogDevicesBSP_v18.1.mltbx'; + disp('BSP Installer tests setup called'); + files = dir('.'); + for file = 1:length(files) + fn = files(file).name; + try + if strcmpi(fn(end-5:end),'.mltbx') && ~contains(fn,'examples') + tbname = fn; + break + end + catch + continue; + end + end + disp('BSP Installer tests setup called'); + disp(['Found: ',tbname]); + obj.installed = matlab.addons.toolbox.installToolbox(tbname); + obj.installed + disp("Installed"); + end + end + + methods(TestClassTeardown) + function uninstallBSP(obj) + matlab.addons.toolbox.uninstallToolbox(obj.installed); + end + end + +end diff --git a/test/BSPTests.m b/test/BSPTests.m new file mode 100644 index 0000000..052cab6 --- /dev/null +++ b/test/BSPTests.m @@ -0,0 +1,20 @@ +classdef BSPTests < BSPTestsBase + + methods(TestClassSetup) + function removeinstalledbsp(~) + str = 'Analog Devices Board Support Packages'; + ts = matlab.addons.toolbox.installedToolboxes; + for t = ts + if contains(t.Name,str) + disp('Removing installed BSP'); + matlab.addons.toolbox.uninstallToolbox(t); + end + end + end + % Add the necessary files to path + function addbspfiles(~) + addpath(genpath('../hdl')); + end + end + +end diff --git a/test/BSPTestsBase.m b/test/BSPTestsBase.m new file mode 100644 index 0000000..09b5c6c --- /dev/null +++ b/test/BSPTestsBase.m @@ -0,0 +1,186 @@ +classdef BSPTestsBase < matlab.unittest.TestCase + properties(TestParameter) + % Pull in board permutations + configs = board_variants; + ignored_builds = {'AnalogDevices.adrv9361z7035.ccbox_lvds.modem.plugin_board'}; + SynthesizeDesign = {false}; + end + + properties + Count = 0; + TotalTests = 0; + Folder = pwd; + end + + methods(TestClassSetup) + function disableWarnings(~) + warning('off','hdlcommon:hdlcommon:InterfaceNotAssigned'); + end + function testCount(testCase) + testCase.TotalTests = length(testCase.configs); + CountS = 0; + save('tc.mat','CountS'); + end + function setRuntimeFolder(testCase) + testCase.Folder = tempname(pwd); + end + end + + methods(TestClassTeardown) + function enableWarnings(~) + warning('on','hdlcommon:hdlcommon:InterfaceNotAssigned'); + end + function collectLogs(~) + if ~exist([pwd,'/logs'],'dir') + mkdir('logs'); + end + system('cp *.log logs/'); + end + end + + methods(TestMethodSetup) + function loadTestCount(testCase) + l = load('tc.mat'); + CountS = l.CountS + 1; + testCase.Count = CountS; + save('tc.mat','CountS'); + end + end + + + + methods + + function CollectLogs(testCase,cfgb) + disp('Log collector called'); + rdn = strrep(cfgb.ReferenceDesignName,'/','_'); + rdn = strrep(rdn,'(',''); + rdn = strrep(rdn,')',''); + system(join(["find '",testCase.Folder,"' -name 'workflow_task_VivadoIPPackager.log' | xargs -I '{}' cp {} ."],'')); + if exist('workflow_task_VivadoIPPackager.log','file') + disp('Found workflow_task_VivadoIPPackager... copying'); + movefile('workflow_task_VivadoIPPackager.log',[rdn,'_VivadoIPPackager_',cfgb.mode,'.log']); + end + system(join(["find '",testCase.Folder,"' -name 'workflow_task_CreateProject.log' | xargs -I '{}' cp {} ."],'')); + if exist('workflow_task_CreateProject.log','file') + disp('Found workflow_task_CreateProject... copying'); + movefile('workflow_task_CreateProject.log',[rdn,'_CreateProject_',cfgb.mode,'.log']); + end + system(join(["find '",testCase.Folder,"' -name 'workflow_task_BuildFPGABitstream.log' | xargs -I '{}' cp {} ."],'')); + if exist('workflow_task_BuildFPGABitstream.log','file') + disp('Found workflow_task_BuildFPGABitstream... copying'); + movefile('workflow_task_BuildFPGABitstream.log',[rdn,'_BuildFPGABitstream_',cfgb.mode,'.log']); + end + end + + function cfg = ADRV9361_Variants(~,s) + + variants = {... + 'ccbob_cmos','ccbob_lvds',... + 'ccbox_lvds','ccfmc_lvds'}; + cfg = {}; + s = strjoin(s(1:end-2),'.'); + h1 = str2func([s,'.common.plugin_board']);h1 = h1(); + + for k = 1:length(variants) + + mode = 'rx'; + h2 = str2func([s,'.',variants{k},'.plugin_rd_rx']);h2 = h2(); + ReferenceDesignName = h2.ReferenceDesignName; + vivado_version = h2.SupportedToolVersion{:}; + cfg1 = struct('Board',h1,... + 'ReferenceDesignName',ReferenceDesignName,... + 'vivado_version',vivado_version,'mode',mode); + + mode = 'tx'; + h2 = str2func([s,'.',variants{k},'.plugin_rd_tx']);h2 = h2(); + ReferenceDesignName = h2.ReferenceDesignName; + vivado_version = h2.SupportedToolVersion{:}; + cfg2 = struct('Board',h1,... + 'ReferenceDesignName',ReferenceDesignName,... + 'vivado_version',vivado_version,'mode',mode); + + mode = 'rx_tx'; + h2 = str2func([s,'.',variants{k},'.plugin_rd_rxtx']);h2 = h2(); + ReferenceDesignName = h2.ReferenceDesignName; + vivado_version = h2.SupportedToolVersion{:}; + cfg3 = struct('Board',h1,... + 'ReferenceDesignName',ReferenceDesignName,... + 'vivado_version',vivado_version,'mode',mode); + cfg = [cfg(:)',{cfg1},{cfg2},{cfg3}]; + + end + + end + + + function cfg = extractConfigs(~,config) + s = strsplit(config,'.'); + modes = strsplit(s{end},'_'); + mode = modes{end}; + h1 = str2func(config);h1 = h1(); + + if strcmp(s{2},'adrv9361z7035') && ~isempty(strfind(s{2},'modem')) + assert(0); + elseif strcmp(s{2},'adrv9361z7035') || ... + strcmp(s{2},'adrv9364z7020') + h = str2func([strjoin(s(1:2),'.'),'.common.plugin_board']); + else + h = str2func([strjoin(s(1:end-1),'.'),'.plugin_board']); + end + board = h(); + + ReferenceDesignName = h1.ReferenceDesignName; + vivado_version = h1.SupportedToolVersion{:}; + cfg = struct('Board',board,... + 'ReferenceDesignName',ReferenceDesignName,... + 'vivado_version',vivado_version,'mode',mode); + end + + function setVivadoPath(~,vivado) + if ispc + pathname = ['C:\Xilinx\Vivado\',vivado,'\bin\vivado.bat']; + elseif isunix + pathname = ['/opt/Xilinx/Vivado/',vivado,'/bin/vivado']; + end + assert(exist(pathname,'file')>0,'Correct version of Vivado is unavailable or in a non-standard location'); + hdlsetuptoolpath('ToolName', 'Xilinx Vivado', ... + 'ToolPath', pathname); + pause(4); + end + end + + methods(Test) + function testMain(testCase, configs, SynthesizeDesign) + % Filter out ignored configurations + if ismember(configs,testCase.ignored_builds) + assumeFail(testCase); + end + % Extract board configuration + cfgb = testCase.extractConfigs(configs); + % for cfg = cfgs + if exist(testCase.Folder,'dir') + rmdir(testCase.Folder,'s'); + pause(1); + end + % Set up vivado + testCase.setVivadoPath(cfgb.vivado_version); + % Build + disp(repmat('/',1,80)); + disp(['Building: ',cfgb.Board.BoardName,' | ',cfgb.mode,... + ' (',num2str(testCase.Count),' of ',num2str(testCase.TotalTests),')']); + res = build_design(cfgb.Board,cfgb.ReferenceDesignName,... + cfgb.vivado_version,cfgb.mode,cfgb.Board.BoardName,... + SynthesizeDesign,testCase.Folder); + % Check + if isfield(res,'message') || isa(res,'MException') + disp(['Build error: ', cfgb.ReferenceDesignName]); + disp(res); + disp(res.message); + disp(res.stack); + testCase.CollectLogs(cfgb); + verifyEmpty(testCase,res,res.message); + end + end + end +end diff --git a/test/HardwareTests.m b/test/HardwareTests.m new file mode 100644 index 0000000..b640bef --- /dev/null +++ b/test/HardwareTests.m @@ -0,0 +1,50 @@ +classdef HardwareTests < matlab.unittest.TestCase + + properties (Abstract) + author + uri + end + + methods(TestClassSetup) + function UpdateURIFromEnv(testCase) + urienv = getenv('IIO_URI'); + if ~isempty(urienv) + fprintf('Overriding default URI with: %s\n',urienv); + testCase.uri = urienv; + end + end + end + + methods + % Check hardware connected + function CheckDevice(testCase,type,Dev,ip,istx) + try + switch type + case 'usb' + d = Dev(); + case 'ip' + if strcmp(testCase.author,'MathWorks') + d= Dev(); + d.IPAddress = ip; + else + d= Dev(); + d.uri = ['ip:',ip]; + end + otherwise + error('Unknown interface type'); + end + if istx + d(complex(randn(1024,1),randn(1024,1))); + else + d(); + end + + catch ME + disp(ME.message); + assumeFail(testCase,'Filtering test: No device found'); + end + end + + end + +end diff --git a/test/SysObjsTests.m b/test/SysObjsTests.m new file mode 100644 index 0000000..0b7f244 --- /dev/null +++ b/test/SysObjsTests.m @@ -0,0 +1,5 @@ +classdef SysObjsTests < AD9361Tests & AD9363Tests & AD9364Tests + + +end + diff --git a/test/runHWTests.m b/test/runHWTests.m new file mode 100644 index 0000000..e718ada --- /dev/null +++ b/test/runHWTests.m @@ -0,0 +1,71 @@ +function runHWTests(board) + +import matlab.unittest.TestRunner; +import matlab.unittest.TestSuite; +import matlab.unittest.plugins.TestReportPlugin; +import matlab.unittest.plugins.XMLPlugin +import matlab.unittest.plugins.DiagnosticsValidationPlugin +import matlab.unittest.parameters.Parameter +import matlab.unittest.plugins.ToUniqueFile; +import matlab.unittest.plugins.TAPPlugin; +import matlab.unittest.constraints.ContainsSubstring; +import matlab.unittest.selectors.HasName; +import matlab.unittest.selectors.HasProcedureName; + +switch board + case "zynq-zed-ad7380" + at = 'AD7380'; + case "zynq-zed-ad7768" + at = 'AD7768'; + case "zynq-zed-adv7511-ad7768-1-evb" + at = 'AD7768_1'; + case "zynq-zed-ad4030" + at = 'AD4030'; + case "zynq-zed-ad4630-16" + at = 'AD4630_16'; + case "zynq-zed-ad4630-24" + at = 'AD4630_24'; + + otherwise + error('%s unsupported for HW test harness', board); +end +ats = {'AD7380Tests','AD7768Tests','AD7768_1Tests','AD4030Tests',... + 'AD4630_16Tests','AD4630_24Tests'}; + +if nargin == 0 + suite = testsuite(ats); +else + suite = testsuite(ats); + suite = selectIf(suite,HasProcedureName(ContainsSubstring(at,'IgnoringCase',true))); +end + +try + + runner = matlab.unittest.TestRunner.withTextOutput('OutputDetail',1); + runner.addPlugin(DiagnosticsValidationPlugin) + xmlFile = board+"_HWTestResults.xml"; + plugin = XMLPlugin.producingJUnitFormat(xmlFile); + + runner.addPlugin(plugin); + results = runner.run(suite); + + t = table(results); + disp(t); + disp(repmat('#',1,80)); + fid = fopen('failures.txt','a+'); + for test = results + if test.Failed + disp(test.Name); + fprintf(fid,string(test.Name)+'\n'); + end + end + fclose(fid); +catch e + disp(getReport(e,'extended')); + bdclose('all'); + exit(1); +end +save(['BSPTest_',datestr(now,'dd_mm_yyyy-HH_MM_SS'),'.mat'],'t'); +bdclose('all'); +exit(any([results.Failed])); +end