classdef TargetInterface < handle
%

% Copyright 2013-2017 The MathWorks, Inc.
    properties (Access = private)
        SourceFileTargetInterface;
        HeaderFileTargetInterface;
    end
    
    properties (Access = protected)
        TargetWordSize;
        IdentifierCDataType;
        IdentifierTypeSize;
        SingleThreadTiming;
        ProfilingTimer;
        GlobalRegistry;
    end
    
    properties (SetAccess = public, GetAccess = private)
        TargetCollectDataFcnName;
    end
    
    methods
        function set.ProfilingTimer(this, lTimer)
            if isa(lTimer, 'coder.profile.Timer')
                % Backwards compatibility
                this.ProfilingTimer = coder.profile.private.TimerWrap(lTimer);
            else
                this.ProfilingTimer = lTimer;
            end
        end
    end
    
    methods (Access = public)
        function init (this, lTargetWordSize, lSingleThreadTiming, lProfilingTimer, lGlobalRegistry)
            this.TargetWordSize = lTargetWordSize;
            
            this.IdentifierCDataType = ...
                coder.profile.ExecTimeConfig.getIdentifierCDataType...
                (lTargetWordSize);
            
            this.IdentifierTypeSize = ...
                coder.profile.ExecTimeConfig.getIdTypeSize...
                (lTargetWordSize);
            
            this.SingleThreadTiming = lSingleThreadTiming;
            
            this.ProfilingTimer = lProfilingTimer;
            
            this.GlobalRegistry = lGlobalRegistry;
        end
        
        function targetWriteSectionBanner(~, writer, filename, isHeader, lProfilingTimer)
            banner = 'Code generated for instrumentation.';
            
            writer.writeLine('/*');
            writer.writeLine(' * File: %s', filename);
            writer.writeLine(' *');
            writer.writeLine(' * %s', banner);
            writer.writeLine(' *');
            
            if isempty(lProfilingTimer) && ~isHeader
                writer.writeLine(...
                    ' * This file contains stub implementations of the instrumentation utility');
                writer.writeLine(...
                    ' * functions. These stubs allow instrumented code to be compiled');
                writer.writeLine(...
                    ' * into an executable that does not support collection of execution');
                writer.writeLine(...
                    ' * instrumentation data.');
                writer.writeLine(' *');
            end
            
            writer.writeLine(' */');
            writer.newLine;
        end
        
        function targetWriteSectionLocalInclude(~, writer, filename)
            writer.writeLine('#include "%s"', filename);
            writer.newLine;
        end
        
        function targetWriteSectionExportedIncludes(this, writer)
            if ~isempty(this.ProfilingTimer)
                timerHeaderFile = this.ProfilingTimer.getTimerHeader;
                if ~isempty(timerHeaderFile)
                    writer.writeCellLines...
                        ({'/* Functions with a C call interface */';
                        '#ifdef __cplusplus';
                        'extern "C" {';
                        '#endif'});
                    writer.writeLine(['#include "' timerHeaderFile '"']);
                    writer.writeCellLines...
                        ({'#ifdef __cplusplus';
                        '}';
                        '#endif'});
                end
            end

            writer.writeLine('#include "rtwtypes.h"');
            writer.newLine;
        end
        
        function targetWriteSectionExportedFcnPrototypes(this, writer, collect)
            if ~isequal(length(collect), 0)
                writer.wComment('Upload code instrumentation data point');
                writer.writeLine('void %s(', collect);
                writer.incIndent;
                lCodeInstrSizeCDataType = ...
                    coder.profile.ExecTimeConfig.getCodeInstrNumElsCDataType...
                    (this.TargetWordSize);
                writer.writeLine('void* pData, %s numMemUnits, %s sectionId);',...
                                 lCodeInstrSizeCDataType, this.IdentifierCDataType);
                writer.decIndent;
                writer.newLine;
            end
        end
        
        function targetWriteSectionExportedAtomicFcn(this, writer, collect)
            if ~isempty(collect)
                writer.wComment('Atomic function to read timer and upload data point');
                writer.writeLine('void %s(%s sectionId);', collect, this.IdentifierCDataType);
                writer.newLine;
            end
        end
        
       function ret = targetWritePauseCall(~)
          % default implementation: no function called
          ret = '';
       end

       function ret = targetWriteTerminateCall(~)
          % default implementation: no function called
          ret = '';
       end

       function ret = targetWriteStepCall(~)
          % default implementation: no function called
          ret = '';
       end

    end
    
    methods (Abstract, Access = public)
        targetWriteSectionFcns(this, writer, targetCollectDataFcnName, executed);
        targetWriteProbeExportedFcnPrototypes(this, writer, executed);
        targetWriteInit(this, executed);
        
        % Functions to manage the generation of the buffer management code with
        % extmode via XCP
        targetWriteXCPInitAndValidate(this, eventID);
        targetWriteXCPManagementSource(this, writer, bufferName, coreIDFcn, threadIDFcn, addHeaders);
        targetWriteXCPManagementHeader(this, writer);
    end
        
end

% LocalWords:  cplusplus extmode XCP
