1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-14 10:09:48 +00:00
freebsd/sys/contrib/octeon-sdk/cvmx-dfa.h
Juli Mallett dc4ee6ca91 Merge the Cavium Octeon SDK 2.3.0 Simple Executive code and update FreeBSD to
make use of it where possible.

This primarily brings in support for newer hardware, and FreeBSD is not yet
able to support the abundance of IRQs on new hardware and many features in the
Ethernet driver.

Because of the changes to IRQs in the Simple Executive, we have to maintain our
own list of Octeon IRQs now, which probably can be pared-down and be specific
to the CIU interrupt unit soon, and when other interrupt mechanisms are added
they can maintain their own definitions.

Remove unmasking of interrupts from within the UART device now that the
function used is no longer present in the Simple Executive.  The unmasking
seems to have been gratuitous as this is more properly handled by the buses
above the UART device, and seems to work on that basis.
2012-03-11 06:17:49 +00:00

803 lines
35 KiB
C

/***********************license start***************
* Copyright (c) 2003-2010 Cavium Inc. (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 Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
* This Software, including technical data, may be subject to U.S. export control
* laws, including the U.S. Export Administration Act and its associated
* regulations, and may be subject to export or import regulations in other
* countries.
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. 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.
***********************license end**************************************/
/**
* @file
*
* Interface to the CN31XX, CN38XX, and CN58XX hardware DFA engine.
*
* <hr>$Revision: 70030 $<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
#ifdef __BIG_ENDIAN_BITFIELD
// 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.
#ifdef __BIG_ENDIAN_BITFIELD
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-dfa-defs.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__ */