get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/124962/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 124962,
    "url": "https://patches.dpdk.org/api/patches/124962/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/20230310082015.20200-17-syalavarthi@marvell.com/",
    "project": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20230310082015.20200-17-syalavarthi@marvell.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20230310082015.20200-17-syalavarthi@marvell.com",
    "date": "2023-03-10T08:19:52",
    "name": "[v6,16/39] ml/cnxk: find OCM mask and page slots for a model",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "5809fdb40d54a8747e2cbc4264aeff09248ef657",
    "submitter": {
        "id": 2480,
        "url": "https://patches.dpdk.org/api/people/2480/?format=api",
        "name": "Srikanth Yalavarthi",
        "email": "syalavarthi@marvell.com"
    },
    "delegate": {
        "id": 310,
        "url": "https://patches.dpdk.org/api/users/310/?format=api",
        "username": "jerin",
        "first_name": "Jerin",
        "last_name": "Jacob",
        "email": "jerinj@marvell.com"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/20230310082015.20200-17-syalavarthi@marvell.com/mbox/",
    "series": [
        {
            "id": 27325,
            "url": "https://patches.dpdk.org/api/series/27325/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=27325",
            "date": "2023-03-10T08:19:36",
            "name": "Implementation of ML CNXK driver",
            "version": 6,
            "mbox": "https://patches.dpdk.org/series/27325/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/124962/comments/",
    "check": "success",
    "checks": "https://patches.dpdk.org/api/patches/124962/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from mails.dpdk.org (mails.dpdk.org [217.70.189.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 5D0B941D3D;\n\tFri, 10 Mar 2023 09:22:10 +0100 (CET)",
            "from mails.dpdk.org (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id E692D42D79;\n\tFri, 10 Mar 2023 09:20:46 +0100 (CET)",
            "from mx0b-0016f401.pphosted.com (mx0b-0016f401.pphosted.com\n [67.231.156.173])\n by mails.dpdk.org (Postfix) with ESMTP id 6A36C42B8E\n for <dev@dpdk.org>; Fri, 10 Mar 2023 09:20:29 +0100 (CET)",
            "from pps.filterd (m0045851.ppops.net [127.0.0.1])\n by mx0b-0016f401.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id\n 32A7uId9021875 for <dev@dpdk.org>; Fri, 10 Mar 2023 00:20:28 -0800",
            "from dc5-exch01.marvell.com ([199.233.59.181])\n by mx0b-0016f401.pphosted.com (PPS) with ESMTPS id 3p80k782tf-8\n (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT)\n for <dev@dpdk.org>; Fri, 10 Mar 2023 00:20:28 -0800",
            "from DC5-EXCH02.marvell.com (10.69.176.39) by DC5-EXCH01.marvell.com\n (10.69.176.38) with Microsoft SMTP Server (TLS) id 15.0.1497.42;\n Fri, 10 Mar 2023 00:20:22 -0800",
            "from maili.marvell.com (10.69.176.80) by DC5-EXCH02.marvell.com\n (10.69.176.39) with Microsoft SMTP Server id 15.0.1497.42 via Frontend\n Transport; Fri, 10 Mar 2023 00:20:23 -0800",
            "from ml-host-33.caveonetworks.com (unknown [10.110.143.233])\n by maili.marvell.com (Postfix) with ESMTP id E4DE03F709F;\n Fri, 10 Mar 2023 00:20:20 -0800 (PST)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com;\n h=from : to : cc :\n subject : date : message-id : in-reply-to : references : mime-version :\n content-type; s=pfpt0220; bh=F94bsZ2WeTem3ulcLpWQPjqCN/0b0TFwrKEhwhKc7+o=;\n b=D+gf1ZwFiHiz/ZgiTwTJxjl8/iTShB0YOdYdRCwlX/wMRIVNdf7HN4dc3H2UDu6miajY\n ZqjfhkrgnmFgRmnFuOYBWAeUmx3+5By6qINK/IfCJQbbWD3m/l4S26R2zqRPu2XBAs34\n p3WG4Pv0BYH0565CMl4iVB7mydYSk6i1FysgSz56hiIr8ZlIg33G2ijU/1IkjHwGlqaC\n Ie82b++2GlM4/JloKyX/CkEut/C8Jg8Yv/ohNIpagH6LzP/Rk3bmQCqMttxRnuxKGfHQ\n J8SpfaLT/IfbLSNasJY2DPwvKjTJi0YaL/1lF3HIbTRc52BZCkipG/y+Ef/U1GHz05kq Zg==",
        "From": "Srikanth Yalavarthi <syalavarthi@marvell.com>",
        "To": "Srikanth Yalavarthi <syalavarthi@marvell.com>",
        "CC": "<dev@dpdk.org>, <sshankarnara@marvell.com>, <jerinj@marvell.com>,\n <aprabhu@marvell.com>, <ptakkar@marvell.com>, <pshukla@marvell.com>",
        "Subject": "[PATCH v6 16/39] ml/cnxk: find OCM mask and page slots for a model",
        "Date": "Fri, 10 Mar 2023 00:19:52 -0800",
        "Message-ID": "<20230310082015.20200-17-syalavarthi@marvell.com>",
        "X-Mailer": "git-send-email 2.17.1",
        "In-Reply-To": "<20230310082015.20200-1-syalavarthi@marvell.com>",
        "References": "<20221208200220.20267-1-syalavarthi@marvell.com>\n <20230310082015.20200-1-syalavarthi@marvell.com>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain",
        "X-Proofpoint-GUID": "wFS3ZNHw8500LJNwS1RUaSqmd5-BsqF1",
        "X-Proofpoint-ORIG-GUID": "wFS3ZNHw8500LJNwS1RUaSqmd5-BsqF1",
        "X-Proofpoint-Virus-Version": "vendor=baseguard\n engine=ICAP:2.0.254,Aquarius:18.0.942,Hydra:6.0.573,FMLib:17.11.170.22\n definitions=2023-03-10_02,2023-03-09_01,2023-02-09_01",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org"
    },
    "content": "Added support to compute OCM tilemask and page start for a\nmodel. The computed tilemask and page start are used during\nmodel start to copy model weights and bias to OCM. OCM slot\nfor a model is allocated from the tiles with maximum amount\nof free memory.\n\nSigned-off-by: Srikanth Yalavarthi <syalavarthi@marvell.com>\n---\n drivers/ml/cnxk/cn10k_ml_ocm.c | 330 +++++++++++++++++++++++++++++++++\n drivers/ml/cnxk/cn10k_ml_ocm.h |   5 +\n 2 files changed, 335 insertions(+)",
    "diff": "diff --git a/drivers/ml/cnxk/cn10k_ml_ocm.c b/drivers/ml/cnxk/cn10k_ml_ocm.c\nindex b1c62f2963..df2fa4c514 100644\n--- a/drivers/ml/cnxk/cn10k_ml_ocm.c\n+++ b/drivers/ml/cnxk/cn10k_ml_ocm.c\n@@ -2,4 +2,334 @@\n  * Copyright (c) 2022 Marvell.\n  */\n \n+#include <rte_mldev_pmd.h>\n+\n+#include \"cn10k_ml_dev.h\"\n #include \"cn10k_ml_ocm.h\"\n+\n+#include \"roc_api.h\"\n+\n+/* OCM macros */\n+#define BYTE_LEN\t  8\n+#define OCM_MAP_WORD_SIZE (sizeof(uint8_t) * BYTE_LEN)\n+#define SET_BIT(num, n)\t  ((num) | (1 << (n)))\n+\n+/* Left shift multi-word mask by 1 bit.\n+ *\n+ * For example, given a mask of two uint8_t words\n+ * Input:  [00110101] [00110111]\n+ * Output: [01101010] [01101110]\n+ */\n+static void\n+lshift_mask(uint8_t *mask, int nwords)\n+{\n+\tint i;\n+\tint word_sz;\n+\n+\tword_sz = sizeof(uint8_t) * BYTE_LEN;\n+\tfor (i = nwords - 1; i >= 0; i--) {\n+\t\tmask[i] = mask[i] << 1;\n+\t\tif (i != 0)\n+\t\t\tmask[i] = mask[i] | (mask[i - 1] >> (word_sz - 1));\n+\t}\n+}\n+\n+/* Get the index of the first unused slot in a multi-word mask (base_mask). Unused slots only after\n+ * the start_pos are considered. An unused slot is a sequence of slot_sz continuous unset bits in\n+ * the multi-word mask. For example given a multi-word mask,\n+ *\n+ * The program creates a search_mask with slot_sz bits set. Uses a sliding windows approach to scan\n+ * the mask to identify the available first slot. search_mask slides left from start_pos to end.\n+ *\n+ * [10111000] [01001001]\n+ * - WORD 1 --- WORD 0 -\n+ *\n+ * When start = 0,\n+ * Index of the first unused slot of size 4 is 7.\n+ * Index of the first unused slot of size 3 is 7.\n+ * Index of the first unused slot of size 2 is 1.\n+ * Index of the first unused slot of size 1 is 1.\n+ *\n+ * When start = 2,\n+ * Index of the first unused slot of size 4 is 7.\n+ * Index of the first unused slot of size 2 is 4.\n+ * Index of the first unused slot of size 1 is 2.\n+ *\n+ * When unable to find a valid slot, return 0\n+ * When slot_sz is zero, return max_idx + 1\n+ */\n+static int\n+slot_index_lowest(uint8_t *base_mask, int nwords, int slot_sz, int start_pos)\n+{\n+\tuint8_t *search_mask;\n+\tint word_sz;\n+\tint end_pos;\n+\tint min_idx;\n+\tint max_idx;\n+\tbool match;\n+\tint i, j;\n+\tint idx;\n+\n+\tword_sz = sizeof(uint8_t) * BYTE_LEN;\n+\tmin_idx = 0;\n+\tmax_idx = word_sz * nwords;\n+\tidx = min_idx - 1;\n+\n+\tif (slot_sz == 0)\n+\t\treturn max_idx;\n+\n+\t/* Create a mask with slot_sz bits set */\n+\tsearch_mask = plt_zmalloc(nwords * sizeof(uint8_t), 0);\n+\tif (search_mask == NULL)\n+\t\tgoto error;\n+\n+\tfor (i = 0; i < nwords; i++) {\n+\t\tif (i < slot_sz / word_sz)\n+\t\t\tsearch_mask[i] = 0xFF;\n+\t\telse if (i > slot_sz / word_sz)\n+\t\t\tsearch_mask[i] = 0x00;\n+\t\telse\n+\t\t\tsearch_mask[i] = (1 << (slot_sz % word_sz)) - 1;\n+\t}\n+\n+\t/* Shift search mask by start_pos bits */\n+\tfor (i = 0; i < start_pos; i++)\n+\t\tlshift_mask(search_mask, nwords);\n+\n+\t/* Scan for a slot, left shift search mask after every iteration */\n+\tend_pos = nwords * word_sz - slot_sz + 1;\n+\tfor (j = start_pos; j < end_pos; j++) {\n+\t\tmatch = true;\n+\t\tfor (i = 0; i < nwords; i++)\n+\t\t\tmatch = match && (((~base_mask[i]) & search_mask[i]) == search_mask[i]);\n+\n+\t\tif (match) {\n+\t\t\tidx = j;\n+\t\t\tgoto found;\n+\t\t}\n+\n+\t\tlshift_mask(search_mask, nwords);\n+\t}\n+\n+found:\n+\tplt_free(search_mask);\n+\n+error:\n+\treturn idx;\n+}\n+\n+/* Find the largest possible unused slot, with a minimum size of search_sz in a multi-work mask. The\n+ * function returns the start index of the slot and the size of the identified slot (slot_sz).\n+ *\n+ * For example, in multi-word mask\n+ *\n+ * [10111000] [01001001]\n+ * - WORD 1 --- WORD 0 -\n+ *\n+ * When search_sz > 4, return value = -1, slot_sz = 0\n+ * When search_sz <=4, return value = 7, slot_sz = 4\n+ */\n+static int\n+slot_index_largest(uint8_t *base_mask, int nwords, int search_sz, int *slot_sz)\n+{\n+\tuint8_t *search_mask;\n+\tint mask_sz;\n+\tint word_sz;\n+\tint end_pos;\n+\tbool match;\n+\tint i, j;\n+\tint idx;\n+\n+\tword_sz = sizeof(uint8_t) * BYTE_LEN;\n+\tmask_sz = nwords * word_sz;\n+\tidx = -1;\n+\n+\t/* Create a mask with mask_sz bits set */\n+\tsearch_mask = plt_zmalloc(mask_sz, 0);\n+\tif (search_mask == NULL)\n+\t\tgoto error;\n+\n+start:\n+\tfor (i = 0; i < nwords; i++) {\n+\t\tif (i < mask_sz / word_sz)\n+\t\t\tsearch_mask[i] = 0xFF;\n+\t\telse if (i > mask_sz / word_sz)\n+\t\t\tsearch_mask[i] = 0x00;\n+\t\telse\n+\t\t\tsearch_mask[i] = (1 << (mask_sz % word_sz)) - 1;\n+\t}\n+\n+\t/* Scan for a slot, left shift search mask after every iteration */\n+\tend_pos = nwords * word_sz - mask_sz + 1;\n+\tfor (j = 0; j < end_pos; j++) {\n+\t\tmatch = true;\n+\t\tfor (i = 0; i < nwords; i++)\n+\t\t\tmatch = match && (((~base_mask[i]) & search_mask[i]) == search_mask[i]);\n+\n+\t\tif (match) {\n+\t\t\tidx = j;\n+\t\t\tgoto found;\n+\t\t}\n+\t\tlshift_mask(search_mask, nwords);\n+\t}\n+\n+\tmask_sz--;\n+\tif (mask_sz >= search_sz)\n+\t\tgoto start;\n+\telse\n+\t\tmask_sz = 0;\n+\n+found:\n+\tplt_free(search_mask);\n+\tif (search_sz == 0)\n+\t\tidx = word_sz * nwords;\n+\n+error:\n+\tif (slot_sz)\n+\t\t*slot_sz = mask_sz;\n+\n+\treturn idx;\n+}\n+\n+/* Count number of bits in a tilemask. Assumes that all set bits are contiguous. */\n+int\n+cn10k_ml_ocm_tilecount(uint64_t tilemask, int *start, int *end)\n+{\n+\tuint8_t count;\n+\n+\tPLT_ASSERT(tilemask != 0);\n+\n+\t*start = __builtin_ctzl(tilemask);\n+\t*end = 64 - __builtin_clzl(tilemask) - 1;\n+\tcount = *end - *start + 1;\n+\n+\tPLT_ASSERT(count == __builtin_popcountl(tilemask));\n+\treturn count;\n+}\n+\n+/* Find the tiles and wb_page_start to load the model on given 'num_tiles' tiles with the specified\n+ * scratch & WB pages and OCM allocation mode.\n+ */\n+int\n+cn10k_ml_ocm_tilemask_find(struct rte_ml_dev *dev, uint8_t num_tiles, uint16_t wb_pages,\n+\t\t\t   uint16_t scratch_pages, uint64_t *tilemask)\n+{\n+\tstruct cn10k_ml_dev *mldev;\n+\tstruct cn10k_ml_ocm *ocm;\n+\n+\tuint8_t local_ocm_mask[ML_CN10K_OCM_MASKWORDS] = {0};\n+\tuint16_t used_scratch_pages_max;\n+\tuint16_t scratch_page_start;\n+\tint used_last_wb_page_max;\n+\tuint16_t scratch_page_end;\n+\tuint8_t search_start_tile;\n+\tuint8_t search_end_tile;\n+\tint wb_page_start_curr;\n+\tint max_slot_sz_curr;\n+\tuint8_t tile_start;\n+\tint ocm_alloc_mode;\n+\tint wb_page_start;\n+\tuint16_t tile_id;\n+\tuint16_t word_id;\n+\tuint8_t tile_idx;\n+\tint max_slot_sz;\n+\tint start_tile;\n+\tint page_id;\n+\n+\tmldev = dev->data->dev_private;\n+\tocm = &mldev->ocm;\n+\n+\tif (num_tiles > ML_CN10K_OCM_NUMTILES) {\n+\t\tplt_err(\"Invalid num_tiles = %u (> ML_CN10K_OCM_NUMTILES)\", num_tiles);\n+\t\treturn -1;\n+\t}\n+\n+\tmemset(tilemask, 0, sizeof(uint64_t));\n+\twb_page_start = -1;\n+\tused_scratch_pages_max = 0;\n+\tused_last_wb_page_max = -1;\n+\tstart_tile = -1;\n+\tmax_slot_sz_curr = 0;\n+\tmax_slot_sz = 0;\n+\ttile_idx = 0;\n+\tocm_alloc_mode = 2;\n+\n+\tif ((start_tile != -1) && (start_tile % num_tiles != 0)) {\n+\t\tplt_err(\"Invalid start_tile, %d\", start_tile);\n+\t\treturn -1;\n+\t}\n+\n+\tif (start_tile < 0) {\n+\t\tsearch_start_tile = 0;\n+\t\tsearch_end_tile = ocm->num_tiles - num_tiles;\n+\t} else {\n+\t\tsearch_start_tile = start_tile;\n+\t\tsearch_end_tile = start_tile;\n+\t}\n+\n+\ttile_start = search_start_tile;\n+start_search:\n+\tused_scratch_pages_max = 0;\n+\tused_last_wb_page_max = -1;\n+\tfor (tile_id = tile_start; tile_id < tile_start + num_tiles; tile_id++) {\n+\t\tused_scratch_pages_max =\n+\t\t\tPLT_MAX(ocm->tile_ocm_info[tile_id].scratch_pages, used_scratch_pages_max);\n+\t\tused_last_wb_page_max =\n+\t\t\tPLT_MAX(ocm->tile_ocm_info[tile_id].last_wb_page, used_last_wb_page_max);\n+\t}\n+\n+\tmemset(local_ocm_mask, 0, sizeof(local_ocm_mask));\n+\tfor (tile_id = tile_start; tile_id < tile_start + num_tiles; tile_id++) {\n+\t\tfor (word_id = 0; word_id < ocm->mask_words; word_id++)\n+\t\t\tlocal_ocm_mask[word_id] |= ocm->tile_ocm_info[tile_id].ocm_mask[word_id];\n+\t}\n+\n+\tif (used_scratch_pages_max < scratch_pages) { /* Check for extra scratch pages */\n+\t\tif (ocm->num_pages - used_last_wb_page_max - 1 >=\n+\t\t    scratch_pages) { /* Pages available */\n+\t\t\tscratch_page_start = ocm->num_pages - scratch_pages;\n+\t\t\tscratch_page_end = ocm->num_pages - 1;\n+\t\t\tfor (page_id = scratch_page_start; page_id <= scratch_page_end;\n+\t\t\t     page_id++) { /* Mark the extra scratch pages as used */\n+\t\t\t\tlocal_ocm_mask[page_id / OCM_MAP_WORD_SIZE] =\n+\t\t\t\t\tSET_BIT(local_ocm_mask[page_id / OCM_MAP_WORD_SIZE],\n+\t\t\t\t\t\tpage_id % OCM_MAP_WORD_SIZE);\n+\t\t\t}\n+\t\t} else { /* Pages not available, check for next set of tiles */\n+\t\t\tgoto next_search;\n+\t\t}\n+\t}\n+\n+\tif (ocm_alloc_mode == 1) {\n+\t\twb_page_start = slot_index_lowest(local_ocm_mask, ocm->mask_words, wb_pages, 0);\n+\t\tif (wb_page_start != -1) { /* Have a valid slot for WB, else next set of tiles */\n+\t\t\ttile_idx = tile_start;\n+\t\t\tgoto found;\n+\t\t}\n+\t} else if (ocm_alloc_mode == 2) {\n+\t\twb_page_start_curr = slot_index_largest(local_ocm_mask, ocm->mask_words, wb_pages,\n+\t\t\t\t\t\t\t&max_slot_sz_curr);\n+\t\tif (max_slot_sz_curr > max_slot_sz) {\n+\t\t\twb_page_start = wb_page_start_curr;\n+\t\t\tmax_slot_sz = max_slot_sz_curr;\n+\t\t\ttile_idx = tile_start;\n+\t\t} else if (max_slot_sz_curr == max_slot_sz) {\n+\t\t\twb_page_start = wb_page_start_curr;\n+\t\t\tif (wb_page_start == ocm->num_pages) {\n+\t\t\t\ttile_idx = tile_start;\n+\t\t\t\tgoto found;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+next_search:\n+\ttile_start = tile_start + num_tiles;\n+\tif (tile_start <= search_end_tile)\n+\t\tgoto start_search;\n+\n+found:\n+\tif (wb_page_start != -1)\n+\t\t*tilemask = GENMASK_ULL(tile_idx + num_tiles - 1, tile_idx);\n+\n+\treturn wb_page_start;\n+}\ndiff --git a/drivers/ml/cnxk/cn10k_ml_ocm.h b/drivers/ml/cnxk/cn10k_ml_ocm.h\nindex 44390396f9..2e26271a7a 100644\n--- a/drivers/ml/cnxk/cn10k_ml_ocm.h\n+++ b/drivers/ml/cnxk/cn10k_ml_ocm.h\n@@ -6,6 +6,7 @@\n #define _CN10K_ML_OCM_H_\n \n #include <rte_mldev.h>\n+#include <rte_mldev_pmd.h>\n \n /* Page size in bytes. */\n #define ML_CN10K_OCM_PAGESIZE 0x4000\n@@ -76,4 +77,8 @@ struct cn10k_ml_ocm {\n \tstruct cn10k_ml_ocm_tile_info tile_ocm_info[ML_CN10K_OCM_NUMTILES];\n };\n \n+int cn10k_ml_ocm_tilecount(uint64_t tilemask, int *start, int *end);\n+int cn10k_ml_ocm_tilemask_find(struct rte_ml_dev *dev, uint8_t num_tiles, uint16_t wb_pages,\n+\t\t\t       uint16_t scratch_pages, uint64_t *tilemask);\n+\n #endif /* _CN10K_ML_OCM_H_ */\n",
    "prefixes": [
        "v6",
        "16/39"
    ]
}