Code Samples and Examples#

Low-level C API Examples#

cache_flush#

/*******************************************************************************
 * Copyright (C) 2023 Intel Corporation
 *
 * SPDX-License-Identifier: MIT
 ******************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include "dml/dml.h"
#include "examples_utils.h"

#define BUFFER_SIZE  1024u // 1 KB

/*
* This example demonstrates how to create and run a cache flush operation.
*/

int main(int argc, char **argv)
{
    dml_path_t execution_path = DML_PATH_SW;

    // Get path from input argument
    int parse_ret = parse_execution_path(argc, argv, &execution_path);
    if (parse_ret != 0) {
        return 1;
    }

    printf("Starting cache flush job example.\n");
    printf("Flushing 1KB of data from cache to memory.\n");

    dml_job_t *dml_job_ptr = NULL;
    uint32_t size = 0u;

    uint8_t destination[BUFFER_SIZE];

    dml_status_t status = dml_get_job_size(execution_path, &size);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during getting job size.\n", status);
        return 1;
    }

    dml_job_ptr = (dml_job_t *)malloc(size);

    status = dml_init_job(execution_path, dml_job_ptr);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during job initialization.\n", status);
        free(dml_job_ptr);
        return 1;
    }
    
    dml_job_ptr->operation              = DML_OP_CACHE_FLUSH;
    dml_job_ptr->destination_first_ptr  = destination;
    dml_job_ptr->destination_length     = BUFFER_SIZE;

    status = dml_execute_job(dml_job_ptr, DML_WAIT_MODE_BUSY_POLL);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during job execution.\n", status);
        dml_finalize_job(dml_job_ptr);
        free(dml_job_ptr);
        return 1;
    }

    status = dml_finalize_job(dml_job_ptr);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during job finalization.\n", status);
        free(dml_job_ptr);
        return 1;
    }
    free(dml_job_ptr);

    printf("Job Completed Successfully.\n");
    return 0;
}

compare_pattern#

/*******************************************************************************
 * Copyright (C) 2023 Intel Corporation
 *
 * SPDX-License-Identifier: MIT
 ******************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include "dml/dml.h"
#include "examples_utils.h"

#define BUFFER_SIZE  1024u // 1 KB
#define PATTERN_SIZE 8u    // pattern size is always 8

/*
* This example demonstrates how to create and run a compare pattern operation.
*/

int main(int argc, char **argv)
{
    dml_path_t execution_path = DML_PATH_SW;

    // Get path from input argument
    int parse_ret = parse_execution_path(argc, argv, &execution_path);
    if (parse_ret != 0) {
        return 1;
    }

    printf("Starting compare pattern job example.\n");
    printf("Comparing data of size 1KB against pattern 0x0001020304050607.\n");

    dml_job_t *dml_job_ptr = NULL;
    uint32_t size = 0u;

    uint8_t source  [BUFFER_SIZE];
    uint8_t pattern [PATTERN_SIZE] = {0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u};

    for(int i = 0; i < BUFFER_SIZE; i++){
        source[i] = pattern[i%8];
    }

    dml_status_t status = dml_get_job_size(execution_path, &size);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during getting job size.\n", status);
        return 1;
    }

    dml_job_ptr = (dml_job_t *)malloc(size);

    status = dml_init_job(execution_path, dml_job_ptr);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during job initialization.\n", status);
        free(dml_job_ptr);
        return 1;
    }
    
    dml_job_ptr->operation         = DML_OP_COMPARE_PATTERN;
    dml_job_ptr->source_first_ptr  = source;
    dml_job_ptr->source_length     = BUFFER_SIZE;
    
    for (uint8_t i = 0u; i < PATTERN_SIZE; i++)
    {
        dml_job_ptr->pattern[i] = pattern[i];
    }

    status = dml_execute_job(dml_job_ptr, DML_WAIT_MODE_BUSY_POLL);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during job execution.\n", status);
        dml_finalize_job(dml_job_ptr);
        free(dml_job_ptr);
        return 1;
    }

    if(dml_job_ptr->result != 0){
        printf("Error: Operation result is incorrect.\n");
        dml_finalize_job(dml_job_ptr);
        free(dml_job_ptr);
        return 1;
    }

    status = dml_finalize_job(dml_job_ptr);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during job finalization.\n", status);
        free(dml_job_ptr);
        return 1;
    }

    free(dml_job_ptr);
    printf("Job Completed Successfully.\n");
    return 0;
}

compare#

/*******************************************************************************
 * Copyright (C) 2023 Intel Corporation
 *
 * SPDX-License-Identifier: MIT
 ******************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include "dml/dml.h"
#include "examples_utils.h"

#define BUFFER_SIZE 1024u // 1 KB

/*
* This example demonstrates how to create and run a compare operation.
*/

int main(int argc, char **argv)
{
    dml_path_t execution_path = DML_PATH_SW;

    // Get path from input argument
    int parse_ret = parse_execution_path(argc, argv, &execution_path);
    if (parse_ret != 0) {
        return 1;
    }

    printf("Starting compare job example.\n");
    printf("Comparing equal memory regions of size 1KB.\n");

    dml_job_t *dml_job_ptr = NULL;
    uint32_t size = 0u;

    uint8_t source1_ptr[BUFFER_SIZE];
    uint8_t source2_ptr[BUFFER_SIZE];

    for(int i = 0; i < BUFFER_SIZE; i++){
        source1_ptr[i] = i % 256;
        source2_ptr[i] = i % 256;
    }

    dml_status_t status = dml_get_job_size(execution_path, &size);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during getting job size.\n", status);
        return 1;
    }

    dml_job_ptr = (dml_job_t *)malloc(size);

    status = dml_init_job(execution_path, dml_job_ptr);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during job initialization.\n", status);
        free(dml_job_ptr);
        return 1;
    }
    
    dml_job_ptr->operation          = DML_OP_COMPARE;
    dml_job_ptr->source_first_ptr   = source1_ptr;
    dml_job_ptr->source_second_ptr  = source2_ptr;
    dml_job_ptr->source_length      = BUFFER_SIZE;

    status = dml_execute_job(dml_job_ptr, DML_WAIT_MODE_BUSY_POLL);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during job execution.\n", status);
        dml_finalize_job(dml_job_ptr);
        free(dml_job_ptr);
        return 1;
    }

    if(dml_job_ptr->result != 0){
        printf("Error: Operation result is incorrect.\n");
        dml_finalize_job(dml_job_ptr);
        free(dml_job_ptr);
        return 1;
    }

    status = dml_finalize_job(dml_job_ptr);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during job finalization.\n", status);
        free(dml_job_ptr);
        return 1;
    }
    free(dml_job_ptr);

    printf("Job Completed Successfully.\n");
    return 0;
}

copy_crc#

/*******************************************************************************
 * Copyright (C) 2023 Intel Corporation
 *
 * SPDX-License-Identifier: MIT
 ******************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include "dml/dml.h"
#include "examples_utils.h"

#define BUFFER_SIZE 1024 // 1 KB

/*
* This example demonstrates how to create and run a copy_crc operation.
*/

int main(int argc, char **argv)
{
    dml_path_t execution_path = DML_PATH_SW;

    // Get path from input argument
    int parse_ret = parse_execution_path(argc, argv, &execution_path);
    if (parse_ret != 0) {
        return 1;
    }

    printf("Starting copy crc job example.\n");
    printf("Copying and calculating CRC for region of size 1KB.\n");

    dml_job_t *dml_job_ptr = NULL;
    uint32_t size = 0u;

    uint8_t source      [BUFFER_SIZE];
    uint8_t destination [BUFFER_SIZE];

    for(int i = 0; i < BUFFER_SIZE; i++){
        source[i] = i % 256;
    }

    dml_status_t status = dml_get_job_size(execution_path, &size);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during getting job size.\n", status);
        return 1;
    }

    dml_job_ptr = (dml_job_t *)malloc(size);

    status = dml_init_job(execution_path, dml_job_ptr);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during job initialization.\n", status);
        free(dml_job_ptr);
        return 1;
    }

    uint32_t crc = 1;

    dml_job_ptr->operation              = DML_OP_COPY_CRC;
    dml_job_ptr->source_first_ptr       = source;
    dml_job_ptr->destination_first_ptr  = destination;
    dml_job_ptr->source_length          = BUFFER_SIZE;
    dml_job_ptr->crc_checksum_ptr       = &crc;
    dml_job_ptr->flags                  = DML_FLAG_CRC_READ_SEED; // read value from crc_checksum_ptr as crc seed

    status = dml_execute_job(dml_job_ptr, DML_WAIT_MODE_BUSY_POLL);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during job execution.\n", status);
        dml_finalize_job(dml_job_ptr);
        free(dml_job_ptr);
        return 1;
    }

    for(int i = 0; i < BUFFER_SIZE; i++){
        if(destination[i] != source[i]){
            printf("Error: Operation result is incorrect.\n");
            dml_finalize_job(dml_job_ptr);
            free(dml_job_ptr);
            return 1;
        }
    }

    printf("Calculated CRC is: 0x%08x\n", crc);

    status = dml_finalize_job(dml_job_ptr);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during job finalization.\n", status);
        free(dml_job_ptr);
        return 1;
    }
    free(dml_job_ptr);

    printf("Finished successfully.\n");
    return 0;
}

crc#

/*******************************************************************************
 * Copyright (C) 2023 Intel Corporation
 *
 * SPDX-License-Identifier: MIT
 ******************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include "dml/dml.h"
#include "examples_utils.h"

#define BUFFER_SIZE 1024 // 1 KB

/*
* This example demonstrates how to create and run a crc operation.
*/

int main(int argc, char **argv)
{
    dml_path_t execution_path = DML_PATH_SW;

    // Get path from input argument
    int parse_ret = parse_execution_path(argc, argv, &execution_path);
    if (parse_ret != 0) {
        return 1;
    }

    printf("Starting CRC job example.\n");
    printf("Calculating CRC for region of size 1KB.\n");

    dml_job_t *dml_job_ptr = NULL;
    uint32_t size = 0u;

    uint8_t source      [BUFFER_SIZE];

    for(int i = 0; i < BUFFER_SIZE; i++){
        source[i] = i % 256;
    }

    dml_status_t status = dml_get_job_size(execution_path, &size);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during getting job size.\n", status);
        return 1;
    }

    dml_job_ptr = (dml_job_t *)malloc(size);

    status = dml_init_job(execution_path, dml_job_ptr);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during job initialization.\n", status);
        free(dml_job_ptr);
        return 1;
    }

    uint32_t crc = 1;

    dml_job_ptr->operation              = DML_OP_CRC;
    dml_job_ptr->source_first_ptr       = source;
    dml_job_ptr->source_length          = BUFFER_SIZE;
    dml_job_ptr->crc_checksum_ptr       = &crc;
    dml_job_ptr->flags                  = DML_FLAG_CRC_READ_SEED; // read value from crc_checksum_ptr as crc seed

    status = dml_execute_job(dml_job_ptr, DML_WAIT_MODE_BUSY_POLL);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during job execution.\n", status);
        dml_finalize_job(dml_job_ptr);
        free(dml_job_ptr);
        return 1;
    }

    printf("Calculated CRC is: 0x%08x\n", crc);

    status = dml_finalize_job(dml_job_ptr);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during job finalization.\n", status);
        free(dml_job_ptr);
        return 1;
    }
    free(dml_job_ptr);

    printf("Finished successfully.\n");
    return 0;
}

delta#

/*******************************************************************************
 * Copyright (C) 2023 Intel Corporation
 *
 * SPDX-License-Identifier: MIT
 ******************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include "dml/dml.h"
#include "examples_utils.h"

#define BUFFER_SIZE       1024 // 1 KB
#define DELTAS_PER_RECORD 8u   // 8 Deltas Per record
#define DELTA_RECORD_SIZE 10u  // Delta Record size 2 bytes (offset) + 8 bytes (Deltas)
#define DELTA_SIZE        BUFFER_SIZE / DELTAS_PER_RECORD * DELTA_RECORD_SIZE // Deltas for 1 KB of data where 10 bytes is needed to store deltas for 8 bytes

/*
* This example demonstrates how to use the delta operations.
* It shows how to create and apply a delta.
*/


int main(int argc, char **argv)
{
    dml_path_t execution_path = DML_PATH_SW;

    // Get path from input argument
    int parse_ret = parse_execution_path(argc, argv, &execution_path);
    if (parse_ret != 0) {
        return 1;
    }

    if (execution_path == DML_PATH_HW) {
        printf("Delta operations are not supported on the hardware path.\n");
        return 0;
    }

    printf("Starting delta job example.\n");
    printf("Creating delta comparing data regions of size 1KB.\n");

    dml_job_t *dml_job_ptr = NULL;
    uint32_t size = 0u;

    uint8_t source1     [BUFFER_SIZE];
    uint8_t source2     [BUFFER_SIZE];
    uint8_t delta       [DELTA_SIZE];

    for(int i = 0; i < BUFFER_SIZE; i++){
        source1[i]  = i % 256;
        source2[i]  = 0;
    }

    dml_status_t status = dml_get_job_size(execution_path, &size);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during getting job size.\n", status);
        return 1;
    }

    dml_job_ptr = (dml_job_t *)malloc(size);

    status = dml_init_job(execution_path, dml_job_ptr);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during job initialization.\n", status);
        free(dml_job_ptr);
        return 1;
    }

    dml_job_ptr->operation              = DML_OP_DELTA_CREATE;
    dml_job_ptr->source_first_ptr       = source1;
    dml_job_ptr->source_second_ptr      = source2;
    dml_job_ptr->destination_first_ptr  = delta;
    dml_job_ptr->source_length          = BUFFER_SIZE;
    dml_job_ptr->destination_length     = DELTA_SIZE;

    status = dml_execute_job(dml_job_ptr, DML_WAIT_MODE_BUSY_POLL);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during job execution.\n", status);
        dml_finalize_job(dml_job_ptr);
        free(dml_job_ptr);
        return 1;
    }

    if(dml_job_ptr->result != 1){
        printf("Error: Operation result is incorrect.\n");
        dml_finalize_job(dml_job_ptr);
        free(dml_job_ptr);
        return 1;
    }

    printf("Completed creating delta.\n");
    printf("Applying created delta to data region of size 1KB\n");

    dml_job_ptr->operation              = DML_OP_DELTA_APPLY;
    dml_job_ptr->source_first_ptr       = delta;
    dml_job_ptr->source_length          = dml_job_ptr->destination_length;
    dml_job_ptr->destination_first_ptr  = source1;
    dml_job_ptr->destination_length     = BUFFER_SIZE;

    status = dml_execute_job(dml_job_ptr, DML_WAIT_MODE_BUSY_POLL);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during job execution.\n", status);
        dml_finalize_job(dml_job_ptr);
        free(dml_job_ptr);
        return 1;
    }

    for(int i = 0; i < BUFFER_SIZE; i++){
        if(source1[i] != source2[i]){
            printf("Error: Operation result is incorrect.\n");
            dml_finalize_job(dml_job_ptr);
            free(dml_job_ptr);
            return 1;
        }
    }

    status = dml_finalize_job(dml_job_ptr);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during job finalization.\n", status);
        free(dml_job_ptr);
        return 1;
    }
    free(dml_job_ptr);

    printf("Job Completed Successfully.\n");
    return 0;
}

dualcast#

/*******************************************************************************
 * Copyright (C) 2023 Intel Corporation
 *
 * SPDX-License-Identifier: MIT
 ******************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include "dml/dml.h"
#include "examples_utils.h"

#define BUFFER_SIZE  1024  // 1 KB
#define PADDING_SIZE 4096  // DML_OP_DUALCAST requirement "dst1 and dst2 address must bits 11:0 must be the same"

/*
* This example demonstrates how to create and run a dualcast operation.
*/

int main(int argc, char **argv)
{
    dml_path_t execution_path = DML_PATH_SW;

    // Get path from input argument
    int parse_ret = parse_execution_path(argc, argv, &execution_path);
    if (parse_ret != 0) {
        return 1;
    }

    printf("Starting dualcast job example.\n");
    printf("Dualcasting region of size 1KB.\n");

    dml_job_t *dml_job_ptr = NULL;
    uint32_t size = 0u;

    uint8_t source      [BUFFER_SIZE];
    uint8_t destination [BUFFER_SIZE * 2 + PADDING_SIZE];

    for(int i = 0; i < BUFFER_SIZE; i++){
        source[i] = i % 256;
    }
    

    dml_status_t status = dml_get_job_size(execution_path, &size);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during getting job size.\n", status);
        return 1;
    }

    dml_job_ptr = (dml_job_t *)malloc(size);

    status = dml_init_job(execution_path, dml_job_ptr);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during job initialization.\n", status);
        free(dml_job_ptr);
        return 1;
    }
    
    dml_job_ptr->operation              = DML_OP_DUALCAST;
    dml_job_ptr->source_first_ptr       = source;
    dml_job_ptr->destination_first_ptr  = destination;
    dml_job_ptr->destination_second_ptr = destination+PADDING_SIZE;
    dml_job_ptr->source_length          = BUFFER_SIZE;
    dml_job_ptr->destination_length     = BUFFER_SIZE;

    status = dml_execute_job(dml_job_ptr, DML_WAIT_MODE_BUSY_POLL);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during job execution.\n", status);
        dml_finalize_job(dml_job_ptr);
        free(dml_job_ptr);
        return 1;
    }

    for(int i = 0; i < BUFFER_SIZE; i++){
        if(destination[i] != source[i] || destination[i+PADDING_SIZE] != source[i]){
            printf("Error: Operation result is incorrect.\n");
            dml_finalize_job(dml_job_ptr);
            free(dml_job_ptr);
            return 1;
        }
    }

    status = dml_finalize_job(dml_job_ptr);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during job finalization.\n", status);
        free(dml_job_ptr);
        return 1;
    }
    free(dml_job_ptr);

    printf("Job Completed Successfully.\n");
    return 0;
}

fill#

/*******************************************************************************
 * Copyright (C) 2023 Intel Corporation
 *
 * SPDX-License-Identifier: MIT
 ******************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include "dml/dml.h"
#include "examples_utils.h"

#define BUFFER_SIZE  1024u // 1 KB
#define PATTERN_SIZE 8u    // pattern size is always 8

/*
* This example demonstrates how to create and run a fill operation.
*/

int main(int argc, char **argv)
{
    dml_path_t execution_path = DML_PATH_SW;

    // Get path from input argument
    int parse_ret = parse_execution_path(argc, argv, &execution_path);
    if (parse_ret != 0) {
        return 1;
    }

    printf("Starting fill job example.\n");
    printf("Filling memory regions of size 1KB with pattern 0x0001020304050607.\n");

    dml_job_t *dml_job_ptr = NULL;
    uint32_t size = 0u;

    uint8_t destination [BUFFER_SIZE];
    uint8_t pattern     [PATTERN_SIZE] = {0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u};

    dml_status_t status = dml_get_job_size(execution_path, &size);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during getting job size.\n", status);
        return 1;
    }

    dml_job_ptr = (dml_job_t *)malloc(size);

    status = dml_init_job(execution_path, dml_job_ptr);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during job initialization.\n", status);
        free(dml_job_ptr);
        return 1;
    }
    
    dml_job_ptr->operation              = DML_OP_FILL;
    dml_job_ptr->destination_first_ptr  = destination;
    dml_job_ptr->destination_length     = BUFFER_SIZE;
    
    for (uint8_t i = 0u; i < PATTERN_SIZE; i++)
    {
        dml_job_ptr->pattern[i] = pattern[i];
    }

    status = dml_execute_job(dml_job_ptr, DML_WAIT_MODE_BUSY_POLL);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during job execution.\n", status);
        free(dml_job_ptr);
        return 1;
    }

    for(int i = 0; i < BUFFER_SIZE; i++){
        if(destination[i] != pattern[i % 8]){
            printf("Error: Operation result is incorrect.\n");
            free(dml_job_ptr);
            return 1;
        }
    }

    status = dml_finalize_job(dml_job_ptr);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during job finalization.\n", status);
        free(dml_job_ptr);
        return 1;
    }
    free(dml_job_ptr);

    printf("Job Completed Successfully.\n");
    return 0;
}

mem_move#

/*******************************************************************************
 * Copyright (C) 2023 Intel Corporation
 *
 * SPDX-License-Identifier: MIT
 ******************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include "dml/dml.h"
#include "examples_utils.h"

#define BUFFER_SIZE 1024 // 1 KB

/*
* This example demonstrates how to create and run a mem_move operation
*/

int main(int argc, char **argv)
{
    dml_path_t execution_path = DML_PATH_SW;

    // Get path from input argument
    int parse_ret = parse_execution_path(argc, argv, &execution_path);
    if (parse_ret != 0) {
        return 1;
    }

    printf("Starting memory move job example.\n");
    printf("Moving region of size 1KB.\n");

    dml_job_t *dml_job_ptr = NULL;
    uint32_t size = 0u;

    uint8_t source      [BUFFER_SIZE];
    uint8_t destination [BUFFER_SIZE];

    for(int i = 0; i < BUFFER_SIZE; i++){
        source[i] = i % 256;
    }

    dml_status_t status = dml_get_job_size(execution_path, &size);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during getting job size.\n", status);
        return 1;
    }

    dml_job_ptr = (dml_job_t *)malloc(size);

    status = dml_init_job(execution_path, dml_job_ptr);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during job initialization.\n", status);
        free(dml_job_ptr);
        return 1;
    }
    
    dml_job_ptr->operation              = DML_OP_MEM_MOVE;
    dml_job_ptr->source_first_ptr       = source;
    dml_job_ptr->destination_first_ptr  = destination;
    dml_job_ptr->source_length          = BUFFER_SIZE;

    status = dml_execute_job(dml_job_ptr, DML_WAIT_MODE_BUSY_POLL);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during job execution.\n", status);
        dml_finalize_job(dml_job_ptr);
        free(dml_job_ptr);
        return 1;
    }

    for(int i = 0; i < BUFFER_SIZE; i++){
        if(destination[i] != source[i]){
            printf("Error: Operation result is incorrect.\n");
            dml_finalize_job(dml_job_ptr);
            free(dml_job_ptr);
            return 1;
        }
    }

    status = dml_finalize_job(dml_job_ptr);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during job finalization.\n", status);
        free(dml_job_ptr);
        return 1;
    }
    free(dml_job_ptr);

    printf("Job Completed Successfully.\n");
    return 0;
}

batch#

/*******************************************************************************
 * Copyright (C) 2023 Intel Corporation
 *
 * SPDX-License-Identifier: MIT
 ******************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include "dml/dml.h"
#include "examples_utils.h"

#define BUFFER_SIZE  1024 // 1 KB
#define PADDING_SIZE 4096 // DML_OP_DUALCAST requirement "dst1 and dst2 address bits 11:0 must be the same"
#define BATCH_COUNT  8u   // 8 ops for this batch operation
#define PATTERN_SIZE 8u   // pattern size is always 8

/*
* This example demonstrates how to create and run a batch operation with
* multiple operations including the nop operation used as a fence.
*/

int main(int argc, char **argv)
{
    dml_path_t execution_path = DML_PATH_SW;

    // Get path from input argument
    int parse_ret = parse_execution_path(argc, argv, &execution_path);
    if (parse_ret != 0) {
        return 1;
    }

    printf("Starting batch job example.\n");

    dml_job_t *dml_job_ptr = NULL;
    uint32_t size = 0u;

    uint8_t buffer_one    [BUFFER_SIZE];
    uint8_t buffer_two    [BUFFER_SIZE];
    uint8_t buffer_three  [BUFFER_SIZE * 2 + PADDING_SIZE];

    dml_status_t status = dml_get_job_size(execution_path, &size);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during getting job size.\n", status);
        return 1;
    }

    dml_job_ptr = (dml_job_t *)malloc(size);

    status = dml_init_job(execution_path, dml_job_ptr);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during job initialization.\n", status);
        free(dml_job_ptr);
        return 1;
    }

    uint32_t batch_buffer_length = 0u;

    status = dml_get_batch_size(dml_job_ptr, BATCH_COUNT, &batch_buffer_length);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during getting batch size.\n", status);
        goto cleanup;
    }

    uint8_t * batch_buffer_ptr = (uint8_t *) malloc(batch_buffer_length);

    dml_job_ptr->operation              = DML_OP_BATCH;
    dml_job_ptr->destination_first_ptr  = batch_buffer_ptr;
    dml_job_ptr->destination_length     = batch_buffer_length;

    printf("Filling 1KB of data with 0x00ABCDEFABCDEF00 pattern\n");
    uint8_t pattern     [PATTERN_SIZE] = {0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u};

    status = dml_batch_set_fill_by_index(dml_job_ptr, 0, pattern, buffer_one, BUFFER_SIZE, DML_FLAG_PREFETCH_CACHE);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during setting of batch operation.\n", status);
        goto cleanup;
    }

    printf("Fencing in batch to ensure fill completes before copying.\n");
    status = dml_batch_set_nop_by_index(dml_job_ptr, 1, DML_FLAG_FENCE);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during setting of batch operation.\n", status);
        goto cleanup;
    }

    printf("Moving 1KB of data\n");
    status = dml_batch_set_mem_move_by_index(dml_job_ptr, 2, buffer_one, buffer_two, BUFFER_SIZE, DML_FLAG_PREFETCH_CACHE);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during setting of batch operation.\n", status);
        goto cleanup;
    }

    printf("Dualcasting 1KB of data\n");
    status = dml_batch_set_dualcast_by_index(dml_job_ptr, 3, buffer_one, buffer_three, buffer_three + PADDING_SIZE, BUFFER_SIZE, DML_FLAG_PREFETCH_CACHE);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during setting of batch operation.\n", status);
        goto cleanup;
    }

    printf("Fencing in batch to ensure all moving completes.\n");
    status = dml_batch_set_nop_by_index(dml_job_ptr, 4, DML_FLAG_FENCE);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during setting of batch operation.\n", status);
        goto cleanup;
    }

    printf("Comparing 1KB of data to 0x00ABCDEFABCDEF00 pattern\n");
    status = dml_batch_set_compare_pattern_by_index(dml_job_ptr, 5, buffer_three + PADDING_SIZE, pattern, BUFFER_SIZE, 0, 0x00);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during setting of batch operation.\n", status);
        goto cleanup;
    }

    printf("Comparing two buffers of 1KB of data\n");
    status = dml_batch_set_compare_by_index(dml_job_ptr, 6, buffer_three, buffer_two, BUFFER_SIZE, 0, 0x00);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during setting of batch operation.\n", status);
        goto cleanup;
    }

    uint32_t crc_seed = 1;
    printf("Calculating CRC buffers of 1KB of data\n");
    status = dml_batch_set_crc_by_index(dml_job_ptr, 7, buffer_one, BUFFER_SIZE, &crc_seed, 0x00);


    status = dml_execute_job(dml_job_ptr, DML_WAIT_MODE_BUSY_POLL);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during job execution.\n", status);
        goto cleanup;
    }

    if(dml_job_ptr->result != 0){
        printf("Error: Operation result is incorrect.\n");
        goto cleanup;
    }

    uint32_t crc;

    status = dml_batch_get_crc(dml_job_ptr, 7, &crc);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occured during getting crc result.\n", status);
        goto cleanup;
    }

    printf("CRC result: 0x%08X\n", crc);

    status = dml_finalize_job(dml_job_ptr);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during job finalization.\n", status);
        free(dml_job_ptr);
        return 1;
    }
    free(dml_job_ptr);

    printf("Job Completed Successfully.\n");
    return 0;

    cleanup:
        dml_finalize_job(dml_job_ptr);
        free(dml_job_ptr);
        return 1;
}

batch#

/*******************************************************************************
 * Copyright (C) 2023 Intel Corporation
 *
 * SPDX-License-Identifier: MIT
 ******************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include "dml/dml.h"
#include "examples_utils.h"

#define BUFFER_SIZE     4096 // 4 KB
#define PROTECTED_SIZE  4104 // 4 KB data with DIF

/*
* This example demonstrates how to use the DIF operations.
* It shows how to insert, update, check, and strip a DIF.
*/

int main(int argc, char **argv)
{
    dml_path_t execution_path = DML_PATH_SW;

    // Get path from input argument
    int parse_ret = parse_execution_path(argc, argv, &execution_path);
    if (parse_ret != 0) {
        return 1;
    }

    printf("Starting DIF job example.\n");
    printf("Inserting DIF into data region of size 4KB.\n");

    dml_job_t *dml_job_ptr = NULL;
    uint32_t size = 0u;

    uint8_t data                    [PROTECTED_SIZE]; // Same size is used because of DML_STATUS_DIF_STRIP_ADJACENT_ERROR
    uint8_t protected_data          [PROTECTED_SIZE];
    uint8_t updated_protected_data  [PROTECTED_SIZE];

    for(int i = 0; i < BUFFER_SIZE; i++){
        data[i]  = i % 256;
    }

    dml_status_t status = dml_get_job_size(execution_path, &size);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during getting job size.\n", status);
        return 1;
    }

    dml_job_ptr = (dml_job_t *)malloc(size);

    status = dml_init_job(execution_path, dml_job_ptr);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during job initialization.\n", status);
        free(dml_job_ptr);
        return 1;
    }
    
    dml_job_ptr->operation              = DML_OP_DIF_INSERT;
    dml_job_ptr->source_first_ptr       = data;
    dml_job_ptr->source_length          = BUFFER_SIZE;
    dml_job_ptr->destination_first_ptr  = protected_data;
    dml_job_ptr->destination_length     = PROTECTED_SIZE;

    dml_job_ptr->dif_config.block_size  = DML_DIF_BLOCK_SIZE_4096;

    dml_job_ptr->dif_config.destination_application_tag_mask = 0x0u;
    dml_job_ptr->dif_config.destination_application_tag_seed = 0x0100;
    dml_job_ptr->dif_config.destination_reference_tag_seed   = 0u;

    dml_job_ptr->dif_config.flags = DML_DIF_FLAG_INVERT_CRC_SEED
                                    | DML_DIF_FLAG_INVERT_CRC_RESULT
                                    | DML_DIF_FLAG_DST_INC_APP_TAG
                                    | DML_DIF_FLAG_DST_FIX_REF_TAG;

    status = dml_execute_job(dml_job_ptr, DML_WAIT_MODE_BUSY_POLL);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during job execution.\n", status);
        dml_finalize_job(dml_job_ptr);
        free(dml_job_ptr);
        return 1;
    }

    if(dml_job_ptr->result != 0){
        printf("Error: Operation result is incorrect.\n");
        dml_finalize_job(dml_job_ptr);
        free(dml_job_ptr);
        return 1;
    }

    printf("Completed inserting DIF.\n");
    printf("Checking DIF on protected region of size 4104 bytes\n");
    
    dml_job_ptr->operation              = DML_OP_DIF_CHECK;
    dml_job_ptr->source_first_ptr       = protected_data;
    dml_job_ptr->source_length          = PROTECTED_SIZE;


    dml_job_ptr->dif_config.block_size  = DML_DIF_BLOCK_SIZE_4096;

    dml_job_ptr->dif_config.source_application_tag_mask = 0x0u;
    dml_job_ptr->dif_config.source_application_tag_seed = 0x0100;
    dml_job_ptr->dif_config.source_reference_tag_seed   = 0u;

    dml_job_ptr->dif_config.flags = DML_DIF_FLAG_INVERT_CRC_SEED
                                    | DML_DIF_FLAG_INVERT_CRC_RESULT
                                    | DML_DIF_FLAG_DST_INC_APP_TAG
                                    | DML_DIF_FLAG_DST_FIX_REF_TAG;

    status = dml_execute_job(dml_job_ptr, DML_WAIT_MODE_BUSY_POLL);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during job execution.\n", status);
        dml_finalize_job(dml_job_ptr);
        free(dml_job_ptr);
        return 1;
    }

    if(dml_job_ptr->result != 0){
        printf("Error: Operation result is incorrect.\n");
        dml_finalize_job(dml_job_ptr);
        free(dml_job_ptr);
        return 1;
    }

    printf("Completed checking DIF.\n");
    printf("Updating DIF on protected region of size 4104 bytes\n");
    
    dml_job_ptr->operation              = DML_OP_DIF_UPDATE;
    dml_job_ptr->source_first_ptr       = protected_data;
    dml_job_ptr->source_length          = PROTECTED_SIZE;
    dml_job_ptr->destination_first_ptr  = updated_protected_data;
    dml_job_ptr->destination_length     = PROTECTED_SIZE;
    


    dml_job_ptr->dif_config.block_size  = DML_DIF_BLOCK_SIZE_4096;

    dml_job_ptr->dif_config.source_application_tag_mask = 0x0u;
    dml_job_ptr->dif_config.source_application_tag_seed = 0x0100;
    dml_job_ptr->dif_config.source_reference_tag_seed   = 0u;

    dml_job_ptr->dif_config.destination_application_tag_mask = 0xFF00u;
    dml_job_ptr->dif_config.destination_application_tag_seed = 0x0200u;
    dml_job_ptr->dif_config.destination_reference_tag_seed   = 0u;

    dml_job_ptr->dif_config.flags = DML_DIF_FLAG_INVERT_CRC_SEED
                                    | DML_DIF_FLAG_INVERT_CRC_RESULT
                                    | DML_DIF_FLAG_SRC_GUARD_CHECK_DISABLE
                                    | DML_DIF_FLAG_SRC_REF_TAG_CHECK_DISABLE
                                    | DML_DIF_FLAG_DST_INC_APP_TAG
                                    | DML_DIF_FLAG_DST_FIX_REF_TAG;

    status = dml_execute_job(dml_job_ptr, DML_WAIT_MODE_BUSY_POLL);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during job execution.\n", status);
        dml_finalize_job(dml_job_ptr);
        free(dml_job_ptr);
        return 1;
    }

    if(dml_job_ptr->result != 0){
        printf("Error: Operation result is incorrect.\n");
        dml_finalize_job(dml_job_ptr);
        free(dml_job_ptr);
        return 1;
    }

    printf("Completed updating DIF.\n");
    printf("Stripping DIF from protected region of size 4104 bytes\n");
    
    dml_job_ptr->operation              = DML_OP_DIF_STRIP;
    dml_job_ptr->source_first_ptr       = updated_protected_data;
    dml_job_ptr->source_length          = PROTECTED_SIZE;
    dml_job_ptr->destination_first_ptr  = data;
    dml_job_ptr->destination_length     = BUFFER_SIZE;

    dml_job_ptr->dif_config.block_size  = DML_DIF_BLOCK_SIZE_4096;

    dml_job_ptr->dif_config.source_application_tag_mask = 0xFF00u;
    dml_job_ptr->dif_config.source_application_tag_seed = 0x0200u;
    dml_job_ptr->dif_config.source_reference_tag_seed   = 0u;

    dml_job_ptr->dif_config.flags = DML_DIF_FLAG_INVERT_CRC_SEED
                                    | DML_DIF_FLAG_INVERT_CRC_RESULT
                                    | DML_DIF_FLAG_DST_INC_APP_TAG
                                    | DML_DIF_FLAG_DST_FIX_REF_TAG;

    status = dml_execute_job(dml_job_ptr, DML_WAIT_MODE_BUSY_POLL);
    if (DML_STATUS_OK != status) {
        printf("An error %i occurred during job execution.\n", status);
        dml_finalize_job(dml_job_ptr);
        free(dml_job_ptr);
        return 1;
    }

    for(int i = 0; i < BUFFER_SIZE; i++){
        if(data[i] != i % 256){
            printf("Error: Operation result is incorrect.\n");
            dml_finalize_job(dml_job_ptr);
            free(dml_job_ptr);
            return 1;
        }
    }

    status = dml_finalize_job(dml_job_ptr);
    if (DML_STATUS_OK != status) {
        printf("An error (%u) occurred during job finalization.\n", status);
        free(dml_job_ptr);
        return 1;
    }
    free(dml_job_ptr);

    printf("Job Completed Successfully.\n");
    return 0;
}

Multi-Socket Library Usage#

This sample shows how to utilize several sockets on the system using manual numa_id setting in the dml_job_t structure. Thus, the memory_move operation can be applied to one data array using several sockets at the same time.

/*******************************************************************************
 * Copyright (C) 2022 Intel Corporation
 *
 * SPDX-License-Identifier: MIT
 ******************************************************************************/

#include <dml/dml.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define SOCKET_COUNT 4u

// 1 MB per socket
static const uint32_t transfer_size = 1024u * 1024 * SOCKET_COUNT;

int main()
{
    int exit_status = EXIT_SUCCESS;

    dml_job_t *jobs = NULL;
    uint8_t   *src  = NULL;
    uint8_t   *dst  = NULL;

    printf("Starting example for multi-socket memory move:\n");

    uint32_t job_size = 0;

    dml_status_t status = dml_get_job_size(DML_PATH_AUTO, &job_size);
    if (status != DML_STATUS_OK)
    {
        printf("Failed to get job size\n");
        exit_status = EXIT_FAILURE;
        goto finish;
    }

    jobs = (dml_job_t*)malloc(job_size * SOCKET_COUNT);
    if (jobs == NULL)
    {
        printf("Failed to allocate memory for jobs\n");
        exit_status = EXIT_FAILURE;
        goto finish;
    }

    for (uint32_t i = 0; i < SOCKET_COUNT; ++i)
    {
        status = dml_init_job(DML_PATH_AUTO, (dml_job_t*)((uint8_t*)jobs + (job_size * i)));
        if (status != DML_STATUS_OK)
        {
            printf("Failed to initialize job %d\n", i);
            exit_status = EXIT_FAILURE;
            goto finish;
        }
    }

    src = (uint8_t*)malloc(transfer_size);
    if (src == NULL)
    {
        exit_status = EXIT_FAILURE;
        printf("Failed to allocate source memory\n");
        goto cleanup;
    }

    dst = (uint8_t*)malloc(transfer_size);
    if (dst == NULL)
    {
        exit_status = EXIT_FAILURE;
        printf("Failed to allocate destination memory\n");
        goto cleanup;
    }

    memset(src, 1, transfer_size);
    memset(dst, 0, transfer_size);

    for (uint32_t i = 0; i < SOCKET_COUNT; ++i)
    {
        const uint32_t chunk_size = transfer_size / SOCKET_COUNT;

        dml_job_t* current_job = (dml_job_t*)((uint8_t*)jobs + (job_size * i));

        current_job->operation             = DML_OP_MEM_MOVE;
        current_job->source_first_ptr      = src + (chunk_size * i);
        current_job->destination_first_ptr = dst + (chunk_size * i);
        current_job->source_length         = chunk_size;
        current_job->flags                 = DML_FLAG_PREFETCH_CACHE;
        current_job->numa_id               = i;
    }

    for (uint32_t i = 0; i < SOCKET_COUNT; ++i)
    {
        status = dml_submit_job((dml_job_t*)((uint8_t*)jobs + (job_size * i)));
        if (status != DML_STATUS_OK)
        {
            printf("Failed to submit to node %d", i);
            exit_status = EXIT_FAILURE;
            goto cleanup;
        }
    }

    for (uint32_t i = 0; i < SOCKET_COUNT; ++i)
    {
        status = dml_wait_job((dml_job_t*)((uint8_t*)jobs + (job_size * i)), DML_WAIT_MODE_BUSY_POLL);
        if (status != DML_STATUS_OK)
        {
            printf("Operation status is %d", status);
            exit_status = EXIT_FAILURE;
            goto cleanup;
        }
    }

    if (memcmp(src, dst, transfer_size) != 0)
    {
        printf("Fail!");
        exit_status = EXIT_FAILURE;
    }
    else
    {
        printf("Success!");
        exit_status = EXIT_SUCCESS;
    }

cleanup:
    for (uint32_t i = 0; i < SOCKET_COUNT; ++i)
    {
        status = dml_finalize_job((dml_job_t*)((uint8_t*)jobs + (job_size * i)));
        if (status != DML_STATUS_OK)
        {
            printf("Failed to finalize job, status is %d", status);
            exit_status = EXIT_FAILURE;
        }
    }

finish:
    if (jobs)
    {
        free(jobs);
    }
    if (src)
    {
        free(src);
    }
    if (dst)
    {
        free(dst);
    }

    return exit_status;
}

High-level C++ API Examples#

cache_flush#

/*******************************************************************************
 * Copyright (C) 2021 Intel Corporation
 *
 * SPDX-License-Identifier: MIT
 ******************************************************************************/

#include <dml/dml.hpp>
#include <numeric>
#include <vector>
#include <iostream>

constexpr auto size = 1024u;  // 1 KB

template <typename path>
int execute_cache_flush(){
    std::cout << "Starting dml::cache_flush example..." << std::endl;
    std::cout << "Flush 1KB of data from the cache to the memory..." << std::endl;

    // Prepare data
    auto dst = std::vector<std::uint8_t>(size, 0u);

    // Run operation
    auto result = dml::execute<path>(dml::cache_flush, dml::make_view(dst));

    // Check result
    if (result.status == dml::status_code::ok) {
        std::cout << "Finished successfully" << std::endl;
        return 0;
    }
    else {
        std::cout << "Failure occurred" << std::endl;
        return -1;
    }

    return 0;
}

int main(int argc, char **argv)
{
    if (argc < 2) {
        std::cout << "Missing the execution path as the first parameter."
                  <<  "Use hardware_path, software_path or automatic_path." << std::endl;
        return 1;
    }

    std::string path = argv[1];
    if (path == "hardware_path") {
        std::cout << "Executing using dml::hardware path" << std::endl;
        return execute_cache_flush<dml::hardware>();
    }
    else if (path == "software_path") {
        std::cout << "Executing using dml::software path" << std::endl;
        return execute_cache_flush<dml::software>();
    }
    else if (path == "auto_path") {
        std::cout << "Executing using dml::automatic path" << std::endl;
        return execute_cache_flush<dml::automatic>();
    }
    else {
        std::cout << "Unrecognized value for parameter."
                  << "Use hardware_path, software_path or automatic_path." << std::endl;
        return 1;
    }
}

compare_pattern#

/*******************************************************************************
 * Copyright (C) 2021 Intel Corporation
 *
 * SPDX-License-Identifier: MIT
 ******************************************************************************/

#include <dml/dml.hpp>
#include <iostream>
#include <numeric>
#include <vector>

constexpr auto size = 1024u;  // 1 KB

template <typename path>
int execute_compare_pattern() {
    std::cout << "Starting dml::compare_pattern example..." << std::endl;
    std::cout << "Compare 1KB memory region with a 0x00ABCDEFABCDEF00 pattern..." << std::endl;

    // Prepare data
    auto pattern  = 0x00ABCDEFABCDEF00;
    auto src      = std::vector<std::uint8_t>(size);
    auto src_data = reinterpret_cast<std::uint64_t *>(src.data());
    std::fill_n(src_data, size / sizeof(std::uint64_t), pattern);

    // Run operation
    auto result = dml::execute<path>(dml::compare_pattern, pattern, dml::make_view(src));

    // Check result
    if (result.status == dml::status_code::ok) {
        std::cout << "Finished successfully." << std::endl;
    }
    else {
        std::cout << "Failure occurred." << std::endl;
        return -1;
    }

    if (result.result != dml::comparison_result::equal) {
        std::cout << "Operation result is incorrect" << std::endl;
        return -1;
    }

    return 0;
}

int main(int argc, char **argv)
{
    if (argc < 2) {
        std::cout << "Missing the execution path as the first parameter."
                  <<  "Use hardware_path, software_path or automatic_path." << std::endl;
        return 1;
    }

    std::string path = argv[1];
    if (path == "hardware_path") {
        std::cout << "Executing using dml::hardware path" << std::endl;
        return execute_compare_pattern<dml::hardware>();
    }
    else if (path == "software_path") {
        std::cout << "Executing using dml::software path" << std::endl;
        return execute_compare_pattern<dml::software>();
    }
    else if (path == "auto_path") {
        std::cout << "Executing using dml::automatic path" << std::endl;
        return execute_compare_pattern<dml::automatic>();
    }
    else {
        std::cout << "Unrecognized value for parameter."
                  << "Use hardware_path, software_path or automatic_path." << std::endl;
        return 1;
    }
}

compare#

/*******************************************************************************
 * Copyright (C) 2021 Intel Corporation
 *
 * SPDX-License-Identifier: MIT
 ******************************************************************************/

#include <dml/dml.hpp>
#include <numeric>
#include <vector>
#include <iostream>

constexpr auto size = 1024u;  // 1 KB

template <typename path>
int execute_compare(){
    std::cout << "Starting dml::compare example..." << std::endl;
    std::cout << "Compare equal memory regions with size of 1KB..." << std::endl;

    // Prepare data
    auto src1 = std::vector<std::uint8_t>(size);
    std::iota(src1.begin(), src1.end(), 0u);
    auto src2 = src1;

    // Run operation
    auto result = dml::execute<path>(dml::compare, dml::make_view(src1), dml::make_view(src2));

    // Check result
    if (result.status == dml::status_code::ok) {
        std::cout << "Finished successfully" << std::endl;
    }
    else {
        std::cout << "Failure occurred" << std::endl;
        return -1;
    }

    if (result.result != dml::comparison_result::equal) {
        std::cout << "Operation result is incorrect" << std::endl;
        return -1;
    }

    return 0;
}

int main(int argc, char **argv)
{
    if (argc < 2) {
        std::cout << "Missing the execution path as the first parameter."
                  <<  "Use hardware_path, software_path or automatic_path." << std::endl;
        return 1;
    }

    std::string path = argv[1];
    if (path == "hardware_path") {
        std::cout << "Executing using dml::hardware path" << std::endl;
        return execute_compare<dml::hardware>();
    }
    else if (path == "software_path") {
        std::cout << "Executing using dml::software path" << std::endl;
        return execute_compare<dml::software>();
    }
    else if (path == "auto_path") {
        std::cout << "Executing using dml::automatic path" << std::endl;
        return execute_compare<dml::automatic>();
    }
    else {
        std::cout << "Unrecognized value for parameter."
                  << "Use hardware_path, software_path or automatic_path." << std::endl;
        return 1;
    }
}

copy_crc#

/*******************************************************************************
 * Copyright (C) 2021 Intel Corporation
 *
 * SPDX-License-Identifier: MIT
 ******************************************************************************/

#include <dml/dml.hpp>
#include <iostream>
#include <string>
#include <vector>

constexpr auto string = "Calculate CRC value for this string...\n";

template <typename path>
int execute_copy_crc(){
    std::cout << "Starting dml::copy_crc example...\n";
    std::cout << string;

    // Prepare data
    auto crc_seed = std::uint32_t(0u);
    auto src      = std::basic_string<std::uint8_t>(reinterpret_cast<const std::uint8_t *>(string));
    auto dst      = std::basic_string<std::uint8_t>(src.size(), '0');

    // Run operation
    auto result = dml::execute<path>(dml::copy_crc, dml::make_view(src), dml::make_view(dst), crc_seed);

    // Check result
    if (result.status == dml::status_code::ok) {
        std::cout << "Finished successfully. Calculated CRC is: 0x" << std::hex << result.crc_value << std::dec << std::endl;
    }
    else {
        std::cout << "Failure occurred." << std::endl;
        return -1;
    }

    if (src != dst) {
        std::cout << "Operation result is incorrect" << std::endl;
        return -1;
    }

    return 0;
}

int main(int argc, char **argv)
{
    if (argc < 2) {
        std::cout << "Missing the execution path as the first parameter."
                  <<  "Use hardware_path, software_path or automatic_path." << std::endl;
        return 1;
    }

    std::string path = argv[1];
    if (path == "hardware_path") {
        std::cout << "Executing using dml::hardware path" << std::endl;
        return execute_copy_crc<dml::hardware>();
    }
    else if (path == "software_path") {
        std::cout << "Executing using dml::software path" << std::endl;
        return execute_copy_crc<dml::software>();
    }
    else if (path == "auto_path") {
        std::cout << "Executing using dml::automatic path" << std::endl;
        return execute_copy_crc<dml::automatic>();
    }
    else {
        std::cout << "Unrecognized value for parameter."
                  << "Use hardware_path, software_path or automatic_path." << std::endl;
        return 1;
    }
}

crc#

/*******************************************************************************
 * Copyright (C) 2021 Intel Corporation
 *
 * SPDX-License-Identifier: MIT
 ******************************************************************************/

#include <dml/dml.hpp>
#include <iostream>
#include <string>
#include <vector>

constexpr auto string  = "Calculate CRC value for this string...\n";

template <typename path>
int execute_crc() {
    std::cout << "Starting dml::crc example...\n";
    std::cout << string;

    // Prepare data
    auto crc_seed = std::uint32_t(0u);
    auto src      = std::basic_string<std::uint8_t>(reinterpret_cast<const std::uint8_t *>(string));

    // Run operation
    auto result = dml::execute<path>(dml::crc, dml::make_view(src), crc_seed);

    // Check result
    if (result.status == dml::status_code::ok) {
        std::cout << "Finished successfully. Calculated CRC is: 0x" << std::hex << result.crc_value << std::dec << std::endl;
    }
    else {
        std::cout << "Failure occurred." << std::endl;
        return -1;
    }

    return 0;
}

int main(int argc, char **argv)
{
    if (argc < 2) {
        std::cout << "Missing the execution path as the first parameter."
                  <<  "Use hardware_path, software_path or automatic_path." << std::endl;
        return 1;
    }

    std::string path = argv[1];
    if (path == "hardware_path") {
        std::cout << "Executing using dml::hardware path" << std::endl;
        return execute_crc<dml::hardware>();
    }
    else if (path == "software_path") {
        std::cout << "Executing using dml::software path" << std::endl;
        return execute_crc<dml::software>();
    }
    else if (path == "auto_path") {
        std::cout << "Executing using dml::automatic path" << std::endl;
        return execute_crc<dml::automatic>();
    }
    else {
        std::cout << "Unrecognized value for parameter."
                  << "Use hardware_path, software_path or automatic_path." << std::endl;
        return 1;
    }
}

delta#

/*******************************************************************************
 * Copyright (C) 2021 Intel Corporation
 *
 * SPDX-License-Identifier: MIT
 ******************************************************************************/

#include <dml/dml.hpp>
#include <iostream>
#include <numeric>
#include <vector>

constexpr auto size = 1024u;  // 1 KB
constexpr auto delta_record_size = size * 10u / 8u;

template <typename path>
int execute_delta() {
    std::cout << "Starting dml::create_delta and dml::apply_delta example..." << std::endl;
    std::cout << "Create delta record of two 1KB memory_regions..." << std::endl;

    // Prepare data
    auto src1 = std::vector<std::uint8_t>(size);
    std::iota(src1.begin(), src1.end(), 0u);
    auto src2 = std::vector<std::uint8_t>(size);
    std::iota(src2.begin(), src2.end(), 1u);
    auto delta = std::vector<std::uint8_t>(delta_record_size, 0u);

    // Run operation
    auto create_result = dml::execute<path>(
        dml::create_delta, dml::make_view(src1), dml::make_view(src2), dml::make_view(delta));

    // Check result
    if (create_result.status == dml::status_code::ok) {
        std::cout << "Done. Next step..." << std::endl;
    }
    else {
        std::cout << "Failure occurred!" << std::endl;
        return -1;
    }

    std::cout << "Apply delta record to the first 1KB memory_region..." << std::endl;

    auto apply_result = dml::execute<path>(
        dml::apply_delta, dml::make_view(delta), dml::make_view(src1), create_result);

    // Check result
    if (apply_result.status == dml::status_code::ok) {
        std::cout << "Finished successfully!" << std::endl;
    }
    else {
        std::cout << "Failure occurred!" << std::endl;
        return -1;
    }

    if (src1 != src2) {
        std::cout << "But operation was done wrongly." << std::endl;
        return -1;
    }

    return 0;
}

int main(int argc, char **argv)
{
    if (argc < 2) {
        std::cout << "Missing the execution path as the first parameter."
                  << "Use hardware_path, software_path or automatic_path." << std::endl;
        return 1;
    }

    std::string path = argv[1];
    if (path == "hardware_path") {
        std::cout << "Executing using dml::hardware path is currently not supported for Delta Record operations" << std::endl;
        return 0;
    }
    else if (path == "software_path") {
        std::cout << "Executing using dml::software path" << std::endl;
        return execute_delta<dml::software>();
    }
    else if (path == "auto_path") {
        std::cout << "Executing using dml::automatic path" << std::endl;
        return execute_delta<dml::automatic>();
    }
    else {
        std::cout << "Unrecognized value for parameter."
                  << "Use hardware_path, software_path or automatic_path." << std::endl;
        return 1;
    }
}

dualcast#

/*******************************************************************************
 * Copyright (C) 2021 Intel Corporation
 *
 * SPDX-License-Identifier: MIT
 ******************************************************************************/

#include <dml/dml.hpp>
#include <iostream>
#include <numeric>
#include <vector>

constexpr auto size    = 1024u;  // 1 KB
constexpr auto padding = 0x1000; // dml::dualcast requirement, see documentation

template <typename path>
int execute_dualcast() {
    std::cout << "Starting dml::dualcast example..." << std::endl;
    std::cout << "Copy 1KB of data from source into two destinations..." << std::endl;

    // Prepare data
    auto src = std::vector<std::uint8_t>(size);
    std::iota(src.begin(), src.end(), 0u);
    auto dst_data = std::vector<std::uint8_t>(size + padding, 0u);
    auto dst1_ptr = dst_data.data();
    auto dst2_ptr = dst1_ptr + padding;

    // Run operation
    auto result = dml::execute<path>(
        dml::dualcast, dml::make_view(src), dml::make_view(dst1_ptr, size), dml::make_view(dst2_ptr, size));

    // Check result
    if (result.status == dml::status_code::ok) {
        std::cout << "Finished successfully." << std::endl;
    }
    else {
        std::cout << "Failure occurred." << std::endl;
        return -1;
    }

    if (src != std::vector<uint8_t>(dst1_ptr, dst1_ptr + size) || src != std::vector<uint8_t>(dst2_ptr, dst2_ptr + size)) {
        std::cout << "Operation result is incorrect." << std::endl;
        return -1;
    }

    return 0;
}

int main(int argc, char **argv)
{
    if (argc < 2) {
        std::cout << "Missing the execution path as the first parameter."
                  <<  "Use hardware_path, software_path or automatic_path." << std::endl;
        return 1;
    }

    std::string path = argv[1];
    if (path == "hardware_path") {
        std::cout << "Executing using dml::hardware path" << std::endl;
        return execute_dualcast<dml::hardware>();
    }
    else if (path == "software_path") {
        std::cout << "Executing using dml::software path" << std::endl;
        return execute_dualcast<dml::software>();
    }
    else if (path == "auto_path") {
        std::cout << "Executing using dml::automatic path" << std::endl;
        return execute_dualcast<dml::automatic>();
    }
    else {
        std::cout << "Unrecognized value for parameter."
                  << "Use hardware_path, software_path or automatic_path." << std::endl;
        return 1;
    }
}

fill#

/*******************************************************************************
 * Copyright (C) 2021 Intel Corporation
 *
 * SPDX-License-Identifier: MIT
 ******************************************************************************/

#include <dml/dml.hpp>
#include <vector>
#include <algorithm>
#include <iostream>

constexpr auto size = 1024u;  // 1 KB

template <typename path>
int execute_fill() {
    std::cout << "Starting dml::fill example..." << std::endl;;
    std::cout << "Fill 1KB of data with a 0x00ABCDEFABCDEF00 pattern" << std::endl;;

    // Prepare data
    auto pattern = 0x00ABCDEFABCDEF00;
    auto dst = std::vector<std::uint8_t>(size, 0u);

    // Run operation
    auto result = dml::execute<path>(dml::fill, pattern, dml::make_view(dst));

    // Check result
    if (result.status == dml::status_code::ok) {
        std::cout << "Finished successfully." << std::endl;;
    }
    else {
        std::cout << "Failure occurred." << std::endl;;
        return -1;
    }

    auto ref = std::vector<std::uint8_t>(size);
    auto ref_data = reinterpret_cast<std::uint64_t*>(ref.data());
    std::fill_n(ref_data, size / sizeof(std::uint64_t), pattern);
    if (ref != dst)
    {
        std::cout << "Operation result is incorrect" << std::endl;
        return -1;
    }

    return 0;
}

int main(int argc, char **argv)
{
    if (argc < 2) {
        std::cout << "Missing the execution path as the first parameter."
                  <<  "Use hardware_path, software_path or automatic_path." << std::endl;
        return 1;
    }

    std::string path = argv[1];
    if (path == "hardware_path") {
        std::cout << "Executing using dml::hardware path" << std::endl;
        return execute_fill<dml::hardware>();
    }
    else if (path == "software_path") {
        std::cout << "Executing using dml::software path" << std::endl;
        return execute_fill<dml::software>();
    }
    else if (path == "auto_path") {
        std::cout << "Executing using dml::automatic path" << std::endl;
        return execute_fill<dml::automatic>();
    }
    else {
        std::cout << "Unrecognized value for parameter."
                  << "Use hardware_path, software_path or automatic_path." << std::endl;
        return 1;
    }
}

mem_move#

/*******************************************************************************
 * Copyright (C) 2021 Intel Corporation
 *
 * SPDX-License-Identifier: MIT
 ******************************************************************************/

#include <dml/dml.hpp>
#include <numeric>
#include <vector>
#include <iostream>

constexpr auto size = 1024u;  // 1 KB

template <typename path>
int execute_mem_move() {
    std::cout << "Starting dml::mem_move example..." << std::endl;
    std::cout << "Copy 1KB of data from source into destination..." << std::endl;

    // Prepare data
    auto src = std::vector<std::uint8_t>(size);
    std::iota(src.begin(), src.end(), 0u);
    auto dst = std::vector<std::uint8_t>(size, 0u);

    // Run operation
    auto result = dml::execute<path>(dml::mem_move, dml::make_view(src), dml::make_view(dst));

    // Check result
    if (result.status == dml::status_code::ok) {
        std::cout << "Finished successfully." << std::endl;
    }
    else {
        std::cout << "Failure occurred." << std::endl;
        return -1;
    }

    if (src != dst) {
        std::cout << "Operation result is incorrect" << std::endl;
        return -1;
    }

    return 0;
}

int main(int argc, char **argv)
{
    if (argc < 2) {
        std::cout << "Missing the execution path as the first parameter."
                  <<  "Use hardware_path, software_path or automatic_path." << std::endl;
        return 1;
    }

    std::string path = argv[1];
    if (path == "hardware_path") {
        std::cout << "Executing using dml::hardware path" << std::endl;
        return execute_mem_move<dml::hardware>();
    }
    else if (path == "software_path") {
        std::cout << "Executing using dml::software path" << std::endl;
        return execute_mem_move<dml::software>();
    }
    else if (path == "auto_path") {
        std::cout << "Executing using dml::automatic path" << std::endl;
        return execute_mem_move<dml::automatic>();
    }
    else {
        std::cout << "Unrecognized value for parameter."
                  << "Use hardware_path, software_path or automatic_path." << std::endl;
        return 1;
    }
}

batch#

/*******************************************************************************
 * Copyright (C) 2023 Intel Corporation
 *
 * SPDX-License-Identifier: MIT
 ******************************************************************************/

#include <dml/dml.hpp>
#include <numeric>
#include <string>
#include <vector>
#include <algorithm>
#include <iostream>

constexpr auto size = 1024u;  // 1 KB
constexpr auto delta_record_size = size * 10u / 8u;

template <typename path>
int execute_batch() {
    
    std::cout << "Starting dml::batch example..." << std::endl;

    // Prepare data
    auto pattern = 0x00ABCDEFABCDEF00;
    auto src = std::vector<std::uint8_t>(size);

    auto dst1 = std::vector<std::uint8_t>(size, 0u);
    auto dst2 = std::vector<std::uint8_t>(size, 0u);
    auto dst3 = std::vector<std::uint8_t>(size);

    auto delta = std::vector<std::uint8_t>(delta_record_size, 0u);
    constexpr auto count  = 7u;

    auto sequence = dml::sequence(count, std::allocator<dml::byte_t>());

    std::cout << "Fill 1KB of data with a 0x00ABCDEFABCDEF00 pattern" << std::endl;
    sequence.add(dml::fill, pattern, dml::make_view(src));

    std::cout << "Add No-op to batch to ensure fill completes before copying..." << std::endl;
    sequence.add(dml::nop);
    
    std::cout << "Copy 1KB of data from source into destination..." << std::endl;
    sequence.add(dml::mem_move, dml::make_view(src), dml::make_view(dst1));
    
    std::cout << "Copy 1KB of data from source1 into two destinations..." << std::endl;
    sequence.add(dml::dualcast, dml::make_view(src), dml::make_view(dst2), dml::make_view(dst3));

    std::cout << "Add No-op to batch to ensure all copies complete..." << std::endl;
    sequence.add(dml::nop);

    std::cout << "Compare 1KB memory region with a 0x00ABCDEFABCDEF00 pattern..." << std::endl;
    sequence.add(dml::compare_pattern, pattern, dml::make_view(dst1));

    std::cout << "Compare equal memory regions with size of 1KB..." << std::endl;
    sequence.add(dml::compare, dml::make_view(dst2), dml::make_view(dst3));

    // Run operation
    auto result = dml::execute<path>(dml::batch, sequence);

    // Check result
    if (result.status == dml::status_code::ok) {
        std::cout << "Finished successfully." << std::endl;;
    }
    else {
        std::cout << "Failure occurred." << std::endl;;
        return -1;
    }

    return 0;
}

int main(int argc, char **argv)
{
    if (argc < 2) {
        std::cout << "Missing the execution path as the first parameter."
                  <<  "Use hardware_path, software_path or automatic_path." << std::endl;
        return 1;
    }

    std::string path = argv[1];
    if (path == "hardware_path") {
        std::cout << "Executing using dml::hardware path" << std::endl;
        return execute_batch<dml::hardware>();
    }
    else if (path == "software_path") {
        std::cout << "Executing using dml::software path" << std::endl;
        return execute_batch<dml::software>();
    }
    else if (path == "auto_path") {
        std::cout << "Executing using dml::automatic path" << std::endl;
        return execute_batch<dml::automatic>();
    }
    else {
        std::cout << "Unrecognized value for parameter."
                  << "Use hardware_path, software_path or automatic_path." << std::endl;
        return 1;
    }
}

Multi-Socket Library Usage#

This sample shows how to utilize several sockets on the system. Thus, the memory_move operation can be applied to one data array using several sockets at the same time.

/*******************************************************************************
 * Copyright (C) 2022 Intel Corporation
 *
 * SPDX-License-Identifier: MIT
 ******************************************************************************/

#include <dml/dml.hpp>
#include <iostream>
#include <vector>

constexpr auto socket_count = 4u;

// 1 MB per socket
constexpr auto transfer_size = 1024u * 1024 * socket_count;

int main()
{
    std::cout << "Starting example for multi-socket memory move:\n";

    auto src = std::vector<std::uint8_t>(transfer_size, 1);
    auto dst = std::vector<std::uint8_t>(transfer_size, 0);

    auto handlers =
        std::vector<dml::handler<dml::mem_move_operation, std::allocator<std::uint8_t>>>();
    handlers.reserve(socket_count);

    auto results = std::vector<dml::mem_move_result>();

    for (auto i = 0u; i < socket_count; ++i)
    {
        auto execution_interface = dml::default_execution_interface<dml::automatic>();
        handlers.emplace_back(dml::submit<dml::automatic>(dml::mem_move,
                                                          dml::make_view(src),
                                                          dml::make_view(dst),
                                                          execution_interface,
                                                          i));
    }

    for (auto& handler : handlers)
    {
        results.emplace_back(handler.get());
    }

    if (src != dst)
    {
        std::cout << "Fail!\n";
        return EXIT_FAILURE;
    }
    else
    {
        std::cout << "Success!\n";
        return EXIT_SUCCESS;
    }
}