4948f4b8d5
Executive is a library that can be used by standalone applications and kernels to abstract access to Octeon SoC and board-specific hardware and facilities. The FreeBSD port to Octeon will be updated to use this where possible.
801 lines
35 KiB
C
801 lines
35 KiB
C
/***********************license start***************
|
|
* Copyright (c) 2003-2008 Cavium Networks (support@cavium.com). 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 Cavium Networks nor the names of
|
|
* its contributors may be used to endorse or promote products
|
|
* derived from this software without specific prior written
|
|
* permission.
|
|
*
|
|
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
|
|
* AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS
|
|
* OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH
|
|
* RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
|
|
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
|
|
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
|
|
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
|
|
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET
|
|
* POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT
|
|
* OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
|
|
*
|
|
*
|
|
* For any questions regarding licensing please contact marketing@caviumnetworks.com
|
|
*
|
|
***********************license end**************************************/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
* @file
|
|
*
|
|
* Interface to the hardware DFA engine.
|
|
*
|
|
* <hr>$Revision: 41586 $<hr>
|
|
*/
|
|
|
|
#ifndef __CVMX_DFA_H__
|
|
#define __CVMX_DFA_H__
|
|
#include "cvmx-llm.h"
|
|
#include "cvmx-wqe.h"
|
|
#include "cvmx-fpa.h"
|
|
|
|
#include "executive-config.h"
|
|
#ifdef CVMX_ENABLE_DFA_FUNCTIONS
|
|
#include "cvmx-config.h"
|
|
#endif
|
|
|
|
#define ENABLE_DEPRECATED /* Set to enable the old 18/36 bit names */
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
|
|
/* Maximum nodes available in a small encoding */
|
|
#define CVMX_DFA_NODESM_MAX_NODES ((OCTEON_IS_MODEL(OCTEON_CN31XX)) ? 0x8000 : 0x20000)
|
|
#define CVMX_DFA_NODESM_SIZE 512 /* Size of each node for small encoding */
|
|
#define CVMX_DFA_NODELG_SIZE 1024 /* Size of each node for large encoding */
|
|
#define CVMX_DFA_NODESM_LAST_TERMINAL (CVMX_DFA_NODESM_MAX_NODES-1)
|
|
|
|
#ifdef ENABLE_DEPRECATED
|
|
/* These defines are for compatability with old code. They are deprecated */
|
|
#define CVMX_DFA_NODE18_SIZE CVMX_DFA_NODESM_SIZE
|
|
#define CVMX_DFA_NODE36_SIZE CVMX_DFA_NODELG_SIZE
|
|
#define CVMX_DFA_NODE18_MAX_NODES CVMX_DFA_NODESM_MAX_NODES
|
|
#define CVMX_DFA_NODE18_LAST_TERMINAL CVMX_DFA_NODESM_LAST_TERMINAL
|
|
#endif
|
|
|
|
/**
|
|
* Which type of memory encoding is this graph using. Make sure you setup
|
|
* the LLM to match.
|
|
*/
|
|
typedef enum
|
|
{
|
|
CVMX_DFA_GRAPH_TYPE_SM = 0,
|
|
CVMX_DFA_GRAPH_TYPE_LG = 1,
|
|
#ifdef ENABLE_DEPRECATED
|
|
CVMX_DFA_GRAPH_TYPE_18b = 0, /* Deprecated */
|
|
CVMX_DFA_GRAPH_TYPE_36b = 1 /* Deprecated */
|
|
#endif
|
|
} cvmx_dfa_graph_type_t;
|
|
|
|
/**
|
|
* The possible node types.
|
|
*/
|
|
typedef enum
|
|
{
|
|
CVMX_DFA_NODE_TYPE_NORMAL = 0, /**< Node is a branch */
|
|
CVMX_DFA_NODE_TYPE_MARKED = 1, /**< Node is marked special */
|
|
CVMX_DFA_NODE_TYPE_TERMINAL = 2 /**< Node is a terminal leaf */
|
|
} cvmx_dfa_node_type_t;
|
|
|
|
/**
|
|
* The possible reasons the DFA stopped processing.
|
|
*/
|
|
typedef enum
|
|
{
|
|
CVMX_DFA_STOP_REASON_DATA_GONE = 0, /**< DFA ran out of data */
|
|
CVMX_DFA_STOP_REASON_PARITY_ERROR = 1, /**< DFA encountered a memory error */
|
|
CVMX_DFA_STOP_REASON_FULL = 2, /**< DFA is full */
|
|
CVMX_DFA_STOP_REASON_TERMINAL = 3 /**< DFA hit a terminal */
|
|
} cvmx_dfa_stop_reason_t;
|
|
|
|
/**
|
|
* This format describes the DFA pointers in small mode
|
|
*/
|
|
typedef union
|
|
{
|
|
uint64_t u64;
|
|
struct
|
|
{
|
|
uint64_t mbz :32;/**< Must be zero */
|
|
uint64_t p1 : 1;/**< Set if next_node1 is odd parity */
|
|
uint64_t next_node1 :15;/**< Next node if an odd character match */
|
|
uint64_t p0 : 1;/**< Set if next_node0 is odd parity */
|
|
uint64_t next_node0 :15;/**< Next node if an even character match */
|
|
} w32;
|
|
struct
|
|
{
|
|
uint64_t mbz :28;/**< Must be zero */
|
|
uint64_t p1 : 1;/**< Set if next_node1 is odd parity */
|
|
uint64_t next_node1 :17;/**< Next node if an odd character match */
|
|
uint64_t p0 : 1;/**< Set if next_node0 is odd parity */
|
|
uint64_t next_node0 :17;/**< Next node if an even character match */
|
|
} w36;
|
|
struct /**< @ this structure only applies starting in CN58XX and if DFA_CFG[NRPL_ENA] == 1 and IWORD0[NREPLEN] == 1. */
|
|
{
|
|
uint64_t mbz :28;/**< Must be zero */
|
|
uint64_t p1 : 1;/**< Set if next_node1 is odd parity */
|
|
uint64_t per_node_repl1 : 1;/**< enable for extra replicaiton for next node (CN58XX) */
|
|
uint64_t next_node_repl1 : 2;/**< extra replicaiton for next node (CN58XX) (if per_node_repl1 is set) */
|
|
uint64_t next_node1 :14;/**< Next node if an odd character match - IWORD3[Msize], if per_node_repl1==1. */
|
|
uint64_t p0 : 1;/**< Set if next_node0 is odd parity */
|
|
uint64_t per_node_repl0 : 1;/**< enable for extra replicaiton for next node (CN58XX) */
|
|
uint64_t next_node_repl0 : 2;/**< extra replicaiton for next node (CN58XX) (if per_node_repl0 is set) */
|
|
uint64_t next_node0 :14;/**< Next node if an odd character match - IWORD3[Msize], if per_node_repl0==1. */
|
|
} w36nrepl_en; /**< use when next_node_repl[01] is 1. */
|
|
struct /**< this structure only applies starting in CN58XX and if DFA_CFG[NRPL_ENA] == 1 and IWORD0[NREPLEN] == 1. */
|
|
{
|
|
uint64_t mbz :28;/**< Must be zero */
|
|
uint64_t p1 : 1;/**< Set if next_node1 is odd parity */
|
|
uint64_t per_node_repl1 : 1;/**< enable for extra replicaiton for next node (CN58XX) */
|
|
uint64_t next_node1 :16;/**< Next node if an odd character match, if per_node_repl1==0. */
|
|
uint64_t p0 : 1;/**< Set if next_node0 is odd parity */
|
|
uint64_t per_node_repl0 : 1;/**< enable for extra replicaiton for next node (CN58XX) */
|
|
uint64_t next_node0 :16;/**< Next node if an odd character match, if per_node_repl0==0. */
|
|
} w36nrepl_dis; /**< use when next_node_repl[01] is 0. */
|
|
#if defined(ENABLE_DEPRECATED) && !OCTEON_IS_COMMON_BINARY()
|
|
#if CVMX_COMPILED_FOR(OCTEON_CN31XX)
|
|
struct /**< @deprecated unnamed reference to members */
|
|
{
|
|
uint64_t mbz :32;/**< Must be zero */
|
|
uint64_t p1 : 1;/**< Set if next_node1 is odd parity */
|
|
uint64_t next_node1 :15;/**< Next node if an odd character match */
|
|
uint64_t p0 : 1;/**< Set if next_node0 is odd parity */
|
|
uint64_t next_node0 :15;/**< Next node if an even character match */
|
|
};
|
|
#elif CVMX_COMPILED_FOR(OCTEON_CN38XX)
|
|
struct /**< @deprecated unnamed reference to members */
|
|
{
|
|
uint64_t mbz :28;/**< Must be zero */
|
|
uint64_t p1 : 1;/**< Set if next_node1 is odd parity */
|
|
uint64_t next_node1 :17;/**< Next node if an odd character match */
|
|
uint64_t p0 : 1;/**< Set if next_node0 is odd parity */
|
|
uint64_t next_node0 :17;/**< Next node if an even character match */
|
|
};
|
|
#else
|
|
/* Other chips don't support the deprecated unnamed unions */
|
|
#endif
|
|
#endif
|
|
} cvmx_dfa_node_next_sm_t;
|
|
|
|
/**
|
|
* This format describes the DFA pointers in large mode
|
|
*/
|
|
typedef union
|
|
{
|
|
uint64_t u64;
|
|
struct
|
|
{
|
|
uint64_t mbz :32;/**< Must be zero */
|
|
uint64_t ecc : 7;/**< ECC checksum on the rest of the bits */
|
|
cvmx_dfa_node_type_t type : 2;/**< Node type */
|
|
uint64_t mbz2 : 3;/**< Must be zero */
|
|
uint64_t next_node :20;/**< Next node */
|
|
} w32;
|
|
struct
|
|
{
|
|
uint64_t mbz :28;/**< Must be zero */
|
|
uint64_t ecc : 7;/**< ECC checksum on the rest of the bits */
|
|
cvmx_dfa_node_type_t type : 2;/**< Node type */
|
|
uint64_t extra_bits : 5;/**< bits copied to report (PASS3/CN58XX), Must be zero previously */
|
|
uint64_t next_node_repl : 2;/**< extra replicaiton for next node (PASS3/CN58XX), Must be zero previously */
|
|
uint64_t next_node :20;/**< Next node ID, Note, combine with next_node_repl to use as start_node
|
|
for continuation, as in cvmx_dfa_node_next_lgb_t. */
|
|
} w36;
|
|
#if defined(ENABLE_DEPRECATED) && !OCTEON_IS_COMMON_BINARY()
|
|
#if CVMX_COMPILED_FOR(OCTEON_CN31XX)
|
|
struct /**< @deprecated unnamed reference to members */
|
|
{
|
|
uint64_t mbz :32;/**< Must be zero */
|
|
uint64_t ecc : 7;/**< ECC checksum on the rest of the bits */
|
|
cvmx_dfa_node_type_t type : 2;/**< Node type */
|
|
uint64_t mbz2 : 3;/**< Must be zero */
|
|
uint64_t next_node :20;/**< Next node */
|
|
};
|
|
#elif CVMX_COMPILED_FOR(OCTEON_CN38XX)
|
|
struct /**< @deprecated unnamed reference to members */
|
|
{
|
|
uint64_t mbz :28;/**< Must be zero */
|
|
uint64_t ecc : 7;/**< ECC checksum on the rest of the bits */
|
|
cvmx_dfa_node_type_t type : 2;/**< Node type */
|
|
uint64_t extra_bits : 5;/**< bits copied to report (PASS3/CN58XX), Must be zero previously */
|
|
uint64_t next_node_repl : 2;/**< extra replicaiton for next node (PASS3/CN58XX), Must be zero previously */
|
|
uint64_t next_node :20;/**< Next node ID, Note, combine with next_node_repl to use as start_node
|
|
for continuation, as in cvmx_dfa_node_next_lgb_t. */
|
|
};
|
|
#else
|
|
/* Other chips don't support the deprecated unnamed unions */
|
|
#endif
|
|
#endif
|
|
} cvmx_dfa_node_next_lg_t;
|
|
|
|
/**
|
|
* This format describes the DFA pointers in large mode, another way
|
|
*/
|
|
typedef union
|
|
{
|
|
uint64_t u64;
|
|
struct
|
|
{
|
|
uint64_t mbz :32;/**< Must be zero */
|
|
uint64_t ecc : 7;/**< ECC checksum on the rest of the bits */
|
|
uint64_t type_terminal : 1;/**< Node type */
|
|
uint64_t type_marked : 1;/**< Node type */
|
|
uint64_t mbz2 : 3;/**< Must be zero */
|
|
uint64_t next_node :20;/**< Next node */
|
|
} w32;
|
|
struct
|
|
{
|
|
uint64_t mbz :28;/**< Must be zero */
|
|
uint64_t ecc : 7;/**< ECC checksum on the rest of the bits */
|
|
uint64_t type_terminal : 1;/**< Node type */
|
|
uint64_t type_marked : 1;/**< Node type */
|
|
uint64_t extra_bits : 5;/**< bits copied to report (PASS3/CN58XX), Must be zero previously */
|
|
uint64_t next_node_id_and_repl :22;/**< Next node ID (and repl for PASS3/CN58XX or repl=0 if not),
|
|
use this as start node for continuation. */
|
|
} w36;
|
|
#if defined(ENABLE_DEPRECATED) && !OCTEON_IS_COMMON_BINARY()
|
|
#if CVMX_COMPILED_FOR(OCTEON_CN31XX)
|
|
struct /**< @deprecated unnamed reference to members */
|
|
{
|
|
uint64_t mbz :32;/**< Must be zero */
|
|
uint64_t ecc : 7;/**< ECC checksum on the rest of the bits */
|
|
uint64_t type_terminal : 1;/**< Node type */
|
|
uint64_t type_marked : 1;/**< Node type */
|
|
uint64_t mbz2 : 3;/**< Must be zero */
|
|
uint64_t next_node :20;/**< Next node */
|
|
};
|
|
#elif CVMX_COMPILED_FOR(OCTEON_CN38XX)
|
|
struct /**< @deprecated unnamed reference to members */
|
|
{
|
|
uint64_t mbz :28;/**< Must be zero */
|
|
uint64_t ecc : 7;/**< ECC checksum on the rest of the bits */
|
|
uint64_t type_terminal : 1;/**< Node type */
|
|
uint64_t type_marked : 1;/**< Node type */
|
|
uint64_t extra_bits : 5;/**< bits copied to report (PASS3/CN58XX), Must be zero previously */
|
|
uint64_t next_node_id_and_repl :22;/**< Next node ID (and repl for PASS3/CN58XX or repl=0 if not),
|
|
use this as start node for continuation. */
|
|
};
|
|
#else
|
|
/* Other chips don't support the deprecated unnamed unions */
|
|
#endif
|
|
#endif
|
|
} cvmx_dfa_node_next_lgb_t;
|
|
|
|
/**
|
|
* This format describes the DFA pointers in large mode
|
|
*/
|
|
typedef union
|
|
{
|
|
uint64_t u64;
|
|
struct
|
|
{
|
|
uint64_t mbz :27;/**< Must be zero */
|
|
uint64_t x0 : 1;/**< XOR of the rest of the bits */
|
|
uint64_t reserved : 4;/**< Must be zero */
|
|
uint64_t data :32;/**< LLM Data */
|
|
} w32;
|
|
struct
|
|
{
|
|
uint64_t mbz :27;/**< Must be zero */
|
|
uint64_t x0 : 1;/**< XOR of the rest of the bits */
|
|
uint64_t data :36;/**< LLM Data */
|
|
} w36;
|
|
#if defined(ENABLE_DEPRECATED) && !OCTEON_IS_COMMON_BINARY()
|
|
#if CVMX_COMPILED_FOR(OCTEON_CN31XX)
|
|
struct /**< @deprecated unnamed reference to members */
|
|
{
|
|
uint64_t mbz :27;/**< Must be zero */
|
|
uint64_t x0 : 1;/**< XOR of the rest of the bits */
|
|
uint64_t reserved : 4;/**< Must be zero */
|
|
uint64_t data :32;/**< LLM Data */
|
|
};
|
|
#elif CVMX_COMPILED_FOR(OCTEON_CN38XX)
|
|
struct /**< @deprecated unnamed reference to members */
|
|
{
|
|
uint64_t mbz :27;/**< Must be zero */
|
|
uint64_t x0 : 1;/**< XOR of the rest of the bits */
|
|
uint64_t data :36;/**< LLM Data */
|
|
};
|
|
#else
|
|
/* Other chips don't support the deprecated unnamed unions */
|
|
#endif
|
|
#endif
|
|
} cvmx_dfa_node_next_read_t;
|
|
|
|
/**
|
|
* This structure defines the data format in the low-latency memory
|
|
*/
|
|
typedef union
|
|
{
|
|
uint64_t u64;
|
|
cvmx_dfa_node_next_sm_t sm; /**< This format describes the DFA pointers in small mode */
|
|
cvmx_dfa_node_next_lg_t lg; /**< This format describes the DFA pointers in large mode */
|
|
cvmx_dfa_node_next_lgb_t lgb; /**< This format describes the DFA pointers in large mode, another way */
|
|
cvmx_dfa_node_next_read_t read; /**< This format describes the DFA pointers in large mode */
|
|
#ifdef ENABLE_DEPRECATED
|
|
cvmx_dfa_node_next_sm_t s18; /**< Deprecated */
|
|
cvmx_dfa_node_next_lg_t s36; /**< Deprecated */
|
|
cvmx_dfa_node_next_lgb_t s36b; /**< Deprecated */
|
|
#endif
|
|
} cvmx_dfa_node_next_t;
|
|
|
|
/**
|
|
* These structures define a DFA instruction
|
|
*/
|
|
typedef union
|
|
{
|
|
uint64_t u64[4];
|
|
uint32_t u32;
|
|
struct
|
|
{
|
|
// WORD 0
|
|
uint64_t gxor : 8; /**< Graph XOR value (PASS3/CN58XX), Must be zero for other chips
|
|
or if DFA_CFG[GXOR_ENA] == 0. */
|
|
uint64_t nxoren : 1; /**< Node XOR enable (PASS3/CN58XX), Must be zero for other chips
|
|
or if DFA_CFG[NXOR_ENA] == 0. */
|
|
uint64_t nreplen : 1; /**< Node Replication mode enable (PASS3/CN58XX), Must be zero for other chips
|
|
or if DFA_CFG[NRPL_ENA] == 0 or IWORD0[Ty] == 0. */
|
|
#if 0
|
|
uint64_t snrepl : 2; /**< Start_Node Replication (PASS3/CN58XX), Must be zero for other chips
|
|
or if DFA_CFG[NRPL_ENA] == 0 or IWORD0[Ty] == 0 or IWORD0[NREPLEN] == 0. */
|
|
uint64_t start_node_id : 20; /**< Node to start the walk from */
|
|
#else
|
|
uint64_t start_node : 22; /**< Node to start the walk from, includes ID and snrepl, see notes above. */
|
|
#endif
|
|
|
|
uint64_t unused02 : 2; /**< Must be zero */
|
|
cvmx_llm_replication_t replication : 2; /**< Type of memory replication to use */
|
|
uint64_t unused03 : 3; /**< Must be zero */
|
|
cvmx_dfa_graph_type_t type : 1; /**< Type of graph */
|
|
uint64_t unused04 : 4; /**< Must be zero */
|
|
uint64_t base : 20; /**< All tables start on 1KB boundary */
|
|
|
|
// WORD 1
|
|
uint64_t input_length : 16; /**< In bytes, # pointers in gather case */
|
|
uint64_t use_gather : 1; /**< Set to use gather */
|
|
uint64_t no_L2_alloc : 1; /**< Set to disable loading of the L2 cache by the DFA */
|
|
uint64_t full_block_write : 1; /**< If set, HW can write entire cache blocks @ result_ptr */
|
|
uint64_t little_endian : 1; /**< Affects only packet data, not instruction, gather list, or result */
|
|
uint64_t unused1 : 8; /**< Must be zero */
|
|
uint64_t data_ptr : 36; /**< Either directly points to data or the gather list. If gather list,
|
|
data_ptr<2:0> must be zero (i.e. 8B aligned) */
|
|
// WORD 2
|
|
uint64_t max_results : 16; /**< in 64-bit quantities, mbz for store */
|
|
uint64_t unused2 : 12; /**< Must be zero */
|
|
uint64_t result_ptr : 36; /**< must be 128 byte aligned */
|
|
|
|
// WORD 3
|
|
uint64_t tsize : 8; /**< tsize*256 is the number of terminal nodes for GRAPH_TYPE_SM */
|
|
uint64_t msize : 16; /**< msize is the number of marked nodes for GRAPH_TYPE_SM */
|
|
uint64_t unused3 : 4; /**< Must be zero */
|
|
uint64_t wq_ptr : 36; /**< 0 for no work queue entry creation */
|
|
} s;
|
|
} cvmx_dfa_command_t;
|
|
|
|
/**
|
|
* Format of the first result word written by the hardware.
|
|
*/
|
|
typedef union
|
|
{
|
|
uint64_t u64;
|
|
struct
|
|
{
|
|
cvmx_dfa_stop_reason_t reas : 2;/**< Reason the DFA stopped */
|
|
uint64_t mbz :44;/**< Zero */
|
|
uint64_t last_marked : 1;/**< Set if the last entry written is marked */
|
|
uint64_t done : 1;/**< Set to 1 when the DFA completes */
|
|
uint64_t num_entries :16;/**< Number of result words written */
|
|
} s;
|
|
} cvmx_dfa_result0_t;
|
|
|
|
/**
|
|
* Format of the second result word and subsequent result words written by the hardware.
|
|
*/
|
|
typedef union
|
|
{
|
|
uint64_t u64;
|
|
struct
|
|
{
|
|
uint64_t byte_offset : 16; /**< Number of bytes consumed */
|
|
uint64_t extra_bits_high: 4; /**< If PASS3 or CN58XX and DFA_CFG[NRPL_ENA] == 1 and IWORD0[Ty] == 1,
|
|
then set to <27:24> of the last next-node pointer. Else set to 0x0. */
|
|
uint64_t prev_node : 20; /**< Index of the previous node */
|
|
uint64_t extra_bits_low : 2; /**< If PASS3 or CN58XX and DFA_CFG[NRPL_ENA] == 1 and IWORD0[Ty] == 1,
|
|
then set to <23:22> of the last next-node pointer. Else set to 0x0. */
|
|
uint64_t next_node_repl : 2; /**< If PASS3 or CN58XX and DFA_CFG[NRPL_ENA] == 1 and IWORD0[Ty] == 1, then set
|
|
to next_node_repl (<21:20>) of the last next-node pointer. Else set to 0x0. */
|
|
uint64_t current_node : 20; /**< Index of the current node */
|
|
} s;
|
|
struct
|
|
{
|
|
uint64_t byte_offset : 16; /**< Number of bytes consumed */
|
|
uint64_t extra_bits_high: 4; /**< If PASS3 or CN58XX and DFA_CFG[NRPL_ENA] == 1 and IWORD0[Ty] == 1,
|
|
then set to <27:24> of the last next-node pointer. Else set to 0x0. */
|
|
uint64_t prev_node : 20; /**< Index of the previous node */
|
|
uint64_t extra_bits_low : 2; /**< If PASS3 or CN58XX and DFA_CFG[NRPL_ENA] == 1 and IWORD0[Ty] == 1,
|
|
then set to <23:22> of the last next-node pointer. Else set to 0x0. */
|
|
uint64_t curr_id_and_repl:22; /**< Use ths as start_node for continuation. */
|
|
} s2;
|
|
} cvmx_dfa_result1_t;
|
|
|
|
/**
|
|
* Abstract DFA graph
|
|
*/
|
|
typedef struct
|
|
{
|
|
cvmx_llm_replication_t replication; /**< Level of memory replication to use. Must match the LLM setup */
|
|
cvmx_dfa_graph_type_t type; /**< Type of graph */
|
|
uint64_t base_address; /**< LLM start address of the graph */
|
|
union {
|
|
struct {
|
|
uint64_t gxor : 8; /**< Graph XOR value (PASS3/CN58XX), Must be zero for other chips
|
|
or if DFA_CFG[GXOR_ENA] == 0. */
|
|
uint64_t nxoren : 1; /**< Node XOR enable (PASS3/CN58XX), Must be zero for other chips
|
|
or if DFA_CFG[NXOR_ENA] == 0. */
|
|
uint64_t nreplen : 1; /**< Node Replication mode enable (PASS3/CN58XX), Must be zero for other chips
|
|
or if DFA_CFG[NRPL_ENA] == 0 or IWORD0[Ty] == 0. */
|
|
uint64_t snrepl : 2; /**< Start_Node Replication (PASS3/CN58XX), Must be zero for other chips
|
|
or if DFA_CFG[NRPL_ENA] == 0 or IWORD0[Ty] == 0 or IWORD0[NREPLEN] == 0.*/
|
|
uint64_t start_node_id : 20; /**< Start node index for the root of the graph */
|
|
};
|
|
uint32_t start_node; /**< Start node index for the root of the graph, incl. snrepl (PASS3/CN58XX)
|
|
NOTE: for backwards compatibility this name includes the the
|
|
gxor, nxoren, nreplen, and snrepl fields which will all be
|
|
zero in applicaitons existing before the introduction of these
|
|
fields, so that existing applicaiton do not need to change. */
|
|
};
|
|
int num_terminal_nodes; /**< Number of terminal nodes in the graph. Only needed for small graphs. */
|
|
int num_marked_nodes; /**< Number of marked nodes in the graph. Only needed for small graphs. */
|
|
} cvmx_dfa_graph_t;
|
|
|
|
/**
|
|
* DFA internal global state -- stored in 8 bytes of FAU
|
|
*/
|
|
typedef union
|
|
{
|
|
uint64_t u64;
|
|
struct {
|
|
#define CVMX_DFA_STATE_TICKET_BIT_POS 16
|
|
#if __BYTE_ORDER == __BIG_ENDIAN
|
|
// NOTE: must clear LSB of base_address_div16 due to ticket overflow
|
|
uint32_t base_address_div16; /**< Current DFA instruction queue chunck base address/16 (clear LSB). */
|
|
uint8_t ticket_loops; /**< bits [15:8] of total number of tickets requested. */
|
|
uint8_t ticket; /**< bits [7:0] of total number of tickets requested (current ticket held). */
|
|
// NOTE: index and now_serving are written together
|
|
uint8_t now_serving; /**< current ticket being served (or ready to be served). */
|
|
uint8_t index; /**< index into current chunk: (base_address_div16*16)[index] = next entry. */
|
|
#else // NOTE: little endian mode probably won't work
|
|
uint8_t index;
|
|
uint8_t now_serving;
|
|
uint8_t ticket;
|
|
uint8_t ticket_loops;
|
|
uint32_t base_address_div16;
|
|
#endif
|
|
} s;
|
|
struct { // a bitfield version of the same thing to extract base address while clearing carry.
|
|
#if __BYTE_ORDER == __BIG_ENDIAN
|
|
uint64_t base_address_div32 : 31; /**< Current DFA instruction queue chunck base address/32. */
|
|
uint64_t carry : 1; /**< Carry out from total_tickets. */
|
|
uint64_t total_tickets : 16; /**< Total tickets. */
|
|
uint64_t now_serving : 8 ; /**< current ticket being served (or ready to be served). */
|
|
uint64_t index : 8 ; /**< index into current chunk. */
|
|
#else // NOTE: little endian mode probably won't work
|
|
uint64_t index : 8 ;
|
|
uint64_t now_serving : 8 ;
|
|
uint64_t total_tickets : 16;
|
|
uint64_t carry : 1;
|
|
uint64_t base_address_div32 : 31;
|
|
#endif
|
|
} s2;
|
|
} cvmx_dfa_state_t;
|
|
|
|
/* CSR typedefs have been moved to cvmx-csr-*.h */
|
|
|
|
/**
|
|
* Write a small node edge to LLM.
|
|
*
|
|
* @param graph Graph to modify
|
|
* @param source_node
|
|
* Source node for this edge
|
|
* @param match_index
|
|
* Index into the node edge table. This is the match character/2.
|
|
* @param destination_node0
|
|
* Destination if the character matches (match_index*2).
|
|
* @param destination_node1
|
|
* Destination if the character matches (match_index*2+1).
|
|
*/
|
|
static inline void cvmx_dfa_write_edge_sm(const cvmx_dfa_graph_t *graph,
|
|
uint64_t source_node, uint64_t match_index,
|
|
uint64_t destination_node0, uint64_t destination_node1)
|
|
{
|
|
cvmx_llm_address_t address;
|
|
cvmx_dfa_node_next_t next_ptr;
|
|
|
|
address.u64 = graph->base_address + source_node * CVMX_DFA_NODESM_SIZE + match_index * 4;
|
|
|
|
next_ptr.u64 = 0;
|
|
if (OCTEON_IS_MODEL(OCTEON_CN31XX))
|
|
{
|
|
next_ptr.sm.w32.next_node0 = destination_node0;
|
|
next_ptr.sm.w32.p0 = cvmx_llm_parity(destination_node0);
|
|
|
|
next_ptr.sm.w32.next_node1 = destination_node1;
|
|
next_ptr.sm.w32.p1 = cvmx_llm_parity(destination_node1);
|
|
}
|
|
else
|
|
{
|
|
next_ptr.sm.w36.next_node0 = destination_node0;
|
|
next_ptr.sm.w36.p0 = cvmx_llm_parity(destination_node0);
|
|
|
|
next_ptr.sm.w36.next_node1 = destination_node1;
|
|
next_ptr.sm.w36.p1 = cvmx_llm_parity(destination_node1);
|
|
}
|
|
|
|
cvmx_llm_write36(address, next_ptr.u64, 0);
|
|
}
|
|
#ifdef ENABLE_DEPRECATED
|
|
#define cvmx_dfa_write_edge18 cvmx_dfa_write_edge_sm
|
|
#endif
|
|
|
|
|
|
/**
|
|
* Write a large node edge to LLM.
|
|
*
|
|
* @param graph Graph to modify
|
|
* @param source_node
|
|
* Source node for this edge
|
|
* @param match Character to match before taking this edge.
|
|
* @param destination_node
|
|
* Destination node of the edge.
|
|
* @param destination_type
|
|
* Node type at the end of this edge.
|
|
*/
|
|
static inline void cvmx_dfa_write_node_lg(const cvmx_dfa_graph_t *graph,
|
|
uint64_t source_node, unsigned char match,
|
|
uint64_t destination_node, cvmx_dfa_node_type_t destination_type)
|
|
{
|
|
cvmx_llm_address_t address;
|
|
cvmx_dfa_node_next_t next_ptr;
|
|
|
|
address.u64 = graph->base_address + source_node * CVMX_DFA_NODELG_SIZE + (uint64_t)match * 4;
|
|
|
|
next_ptr.u64 = 0;
|
|
if (OCTEON_IS_MODEL(OCTEON_CN31XX))
|
|
{
|
|
next_ptr.lg.w32.type = destination_type;
|
|
next_ptr.lg.w32.next_node = destination_node;
|
|
next_ptr.lg.w32.ecc = cvmx_llm_ecc(next_ptr.u64);
|
|
}
|
|
else
|
|
{
|
|
next_ptr.lg.w36.type = destination_type;
|
|
next_ptr.lg.w36.next_node = destination_node;
|
|
next_ptr.lg.w36.ecc = cvmx_llm_ecc(next_ptr.u64);
|
|
}
|
|
|
|
cvmx_llm_write36(address, next_ptr.u64, 0);
|
|
}
|
|
#ifdef ENABLE_DEPRECATED
|
|
#define cvmx_dfa_write_node36 cvmx_dfa_write_node_lg
|
|
#endif
|
|
|
|
/**
|
|
* Ring the DFA doorbell telling it that new commands are
|
|
* available.
|
|
*
|
|
* @param num_commands
|
|
* Number of new commands
|
|
*/
|
|
static inline void cvmx_dfa_write_doorbell(uint64_t num_commands)
|
|
{
|
|
CVMX_SYNCWS;
|
|
cvmx_write_csr(CVMX_DFA_DBELL, num_commands);
|
|
}
|
|
|
|
/**
|
|
* @INTERNAL
|
|
* Write a new command to the DFA. Calls to this function
|
|
* are internally synchronized across all processors, and
|
|
* the doorbell is rung during this function.
|
|
*
|
|
* @param command Command to write
|
|
*/
|
|
|
|
#ifdef CVMX_ENABLE_DFA_FUNCTIONS
|
|
static inline void __cvmx_dfa_write_command(cvmx_dfa_command_t *command)
|
|
{
|
|
cvmx_dfa_state_t cvmx_dfa_state;
|
|
uint64_t my_ticket; // needs to wrap to 8 bits
|
|
uint64_t index;
|
|
cvmx_dfa_command_t *head;
|
|
|
|
CVMX_PREFETCH0(command);
|
|
// take a ticket.
|
|
cvmx_dfa_state.u64 = cvmx_fau_fetch_and_add64(CVMX_FAU_DFA_STATE, 1ull<<CVMX_DFA_STATE_TICKET_BIT_POS);
|
|
my_ticket = cvmx_dfa_state.s.ticket;
|
|
|
|
// see if it is our turn
|
|
while (my_ticket != cvmx_dfa_state.s.now_serving) {
|
|
int delta = my_ticket - cvmx_dfa_state.s.now_serving;
|
|
if (delta < 0) delta += 256;
|
|
cvmx_wait(10*delta); // reduce polling load on system
|
|
cvmx_dfa_state.u64 = cvmx_fau_fetch_and_add64(CVMX_FAU_DFA_STATE, 0); // poll for my_ticket==now_serving
|
|
}
|
|
|
|
// compute index and instruction queue head pointer
|
|
index = cvmx_dfa_state.s.index;
|
|
|
|
// NOTE: the DFA only supports 36-bit addressing
|
|
head = &((CASTPTR(cvmx_dfa_command_t, (cvmx_dfa_state.s2.base_address_div32 * 32ull))[index]));
|
|
head = (cvmx_dfa_command_t*)cvmx_phys_to_ptr(CAST64(head)); // NOTE: since we are not storing bit 63 of address, we must set it now
|
|
|
|
// copy the command to the instruction queue
|
|
*head++ = *command;
|
|
|
|
// check if a new chunk is needed
|
|
if (cvmx_unlikely((++index >= ((CVMX_FPA_DFA_POOL_SIZE-8)/sizeof(cvmx_dfa_command_t))))) {
|
|
uint64_t *new_base = (uint64_t*)cvmx_fpa_alloc(CVMX_FPA_DFA_POOL); // could make this async
|
|
if (new_base) {
|
|
// put the link into the instruction queue's "Next Chunk Buffer Ptr"
|
|
*(uint64_t *)head = cvmx_ptr_to_phys(new_base);
|
|
// update our state (note 32-bit write to not disturb other fields)
|
|
cvmx_fau_atomic_write32((cvmx_fau_reg_32_t)(CVMX_FAU_DFA_STATE + (CAST64(&cvmx_dfa_state.s.base_address_div16)-CAST64(&cvmx_dfa_state))),
|
|
(CAST64(new_base))/16);
|
|
}
|
|
else {
|
|
cvmx_dprintf("__cvmx_dfa_write_command: Out of memory. Expect crashes.\n");
|
|
}
|
|
index=0;
|
|
}
|
|
|
|
cvmx_dfa_write_doorbell(1);
|
|
|
|
// update index and now_serving in the DFA state FAU location (NOTE: this write16 updates to 8-bit values.)
|
|
// NOTE: my_ticket+1 carry out is lost due to write16 and index has already been wrapped to fit in uint8.
|
|
cvmx_fau_atomic_write16((cvmx_fau_reg_16_t)(CVMX_FAU_DFA_STATE+(CAST64(&cvmx_dfa_state.s.now_serving) - CAST64(&cvmx_dfa_state))),
|
|
((my_ticket+1)<<8) | index);
|
|
}
|
|
|
|
|
|
/**
|
|
* Submit work to the DFA units for processing
|
|
*
|
|
* @param graph Graph to process
|
|
* @param start_node
|
|
* The node to start (or continue) walking from
|
|
* includes. start_node_id and snrepl (PASS3/CN58XX), but gxor,
|
|
* nxoren, and nreplen are taken from the graph structure
|
|
* @param input The input to match against
|
|
* @param input_length
|
|
* The length of the input in bytes
|
|
* @param use_gather
|
|
* The input and input_length are of a gather list
|
|
* @param is_little_endian
|
|
* Set to 1 if the input is in little endian format and must
|
|
* be swapped before compare.
|
|
* @param result Location the DFA should put the results in. This must be
|
|
* an area sized in multiples of a cache line.
|
|
* @param max_results
|
|
* The maximum number of 64-bit result1 words after result0.
|
|
* That is, "size of the result area in 64-bit words" - 1.
|
|
* max_results must be at least 1.
|
|
* @param work Work queue entry to submit when DFA completes. Can be NULL.
|
|
*/
|
|
static inline void cvmx_dfa_submit(const cvmx_dfa_graph_t *graph, int start_node,
|
|
void *input, int input_length, int use_gather, int is_little_endian,
|
|
cvmx_dfa_result0_t *result, int max_results, cvmx_wqe_t *work)
|
|
{
|
|
cvmx_dfa_command_t command;
|
|
|
|
/* Make sure the result's first 64bit word is zero so we can tell when the
|
|
DFA is done. */
|
|
result->u64 = 0;
|
|
|
|
// WORD 0
|
|
command.u64[0] = 0;
|
|
command.s.gxor = graph->gxor; // (PASS3/CN58XX)
|
|
command.s.nxoren = graph->nxoren; // (PASS3/CN58XX)
|
|
command.s.nreplen = graph->nreplen; // (PASS3/CN58XX)
|
|
command.s.start_node = start_node; // includes snrepl (PASS3/CN58XX)
|
|
command.s.replication = graph->replication;
|
|
command.s.type = graph->type;
|
|
command.s.base = graph->base_address>>10;
|
|
|
|
// WORD 1
|
|
command.u64[1] = 0;
|
|
command.s.input_length = input_length;
|
|
command.s.use_gather = use_gather;
|
|
command.s.no_L2_alloc = 0;
|
|
command.s.full_block_write = 1;
|
|
command.s.little_endian = is_little_endian;
|
|
command.s.data_ptr = cvmx_ptr_to_phys(input);
|
|
|
|
// WORD 2
|
|
command.u64[2] = 0;
|
|
command.s.max_results = max_results;
|
|
command.s.result_ptr = cvmx_ptr_to_phys(result);
|
|
|
|
// WORD 3
|
|
command.u64[3] = 0;
|
|
if (graph->type == CVMX_DFA_GRAPH_TYPE_SM)
|
|
{
|
|
command.s.tsize = (graph->num_terminal_nodes + 255) / 256;
|
|
command.s.msize = graph->num_marked_nodes;
|
|
}
|
|
command.s.wq_ptr = cvmx_ptr_to_phys(work);
|
|
|
|
__cvmx_dfa_write_command(&command); // NOTE: this does synchronization and rings doorbell
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
* DFA gather list element
|
|
*/
|
|
typedef struct {
|
|
uint64_t length : 16; /**< length of piece of data at addr */
|
|
uint64_t reserved : 12; /**< reserved, set to 0 */
|
|
uint64_t addr : 36; /**< pointer to piece of data */
|
|
} cvmx_dfa_gather_entry_t;
|
|
|
|
|
|
/**
|
|
* Check if a DFA has completed processing
|
|
*
|
|
* @param result_ptr Result area the DFA is using
|
|
* @return Non zero if the DFA is done
|
|
*/
|
|
static inline uint64_t cvmx_dfa_is_done(cvmx_dfa_result0_t *result_ptr)
|
|
{
|
|
/* DFA sets the first result 64bit word to non zero when it's done */
|
|
return ((volatile cvmx_dfa_result0_t *)result_ptr)->s.done;
|
|
}
|
|
|
|
|
|
#ifdef CVMX_ENABLE_DFA_FUNCTIONS
|
|
/**
|
|
* Initialize the DFA hardware before use
|
|
* Returns 0 on success, -1 on failure
|
|
*/
|
|
int cvmx_dfa_initialize(void);
|
|
|
|
|
|
/**
|
|
* Shutdown and cleanup resources used by the DFA
|
|
*/
|
|
void cvmx_dfa_shutdown(void);
|
|
#endif
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* __CVMX_DFA_H__ */
|