cvmx-dfa.h revision 210286
1/***********************license start***************
2 *  Copyright (c) 2003-2008 Cavium Networks (support@cavium.com). All rights
3 *  reserved.
4 *
5 *
6 *  Redistribution and use in source and binary forms, with or without
7 *  modification, are permitted provided that the following conditions are
8 *  met:
9 *
10 *      * Redistributions of source code must retain the above copyright
11 *        notice, this list of conditions and the following disclaimer.
12 *
13 *      * Redistributions in binary form must reproduce the above
14 *        copyright notice, this list of conditions and the following
15 *        disclaimer in the documentation and/or other materials provided
16 *        with the distribution.
17 *
18 *      * Neither the name of Cavium Networks nor the names of
19 *        its contributors may be used to endorse or promote products
20 *        derived from this software without specific prior written
21 *        permission.
22 *
23 *  TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
24 *  AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS
25 *  OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH
26 *  RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
27 *  REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
28 *  DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
29 *  OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
30 *  PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET
31 *  POSSESSION OR CORRESPONDENCE TO DESCRIPTION.  THE ENTIRE RISK ARISING OUT
32 *  OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
33 *
34 *
35 *  For any questions regarding licensing please contact marketing@caviumnetworks.com
36 *
37 ***********************license end**************************************/
38
39
40
41
42
43
44/**
45 * @file
46 *
47 * Interface to the hardware DFA engine.
48 *
49 * <hr>$Revision: 41586 $<hr>
50 */
51
52#ifndef __CVMX_DFA_H__
53#define __CVMX_DFA_H__
54#include "cvmx-llm.h"
55#include "cvmx-wqe.h"
56#include "cvmx-fpa.h"
57
58#include "executive-config.h"
59#ifdef CVMX_ENABLE_DFA_FUNCTIONS
60#include "cvmx-config.h"
61#endif
62
63#define ENABLE_DEPRECATED   /* Set to enable the old 18/36 bit names */
64
65#ifdef	__cplusplus
66extern "C" {
67#endif
68
69
70/* Maximum nodes available in a small encoding */
71#define CVMX_DFA_NODESM_MAX_NODES       ((OCTEON_IS_MODEL(OCTEON_CN31XX)) ? 0x8000 : 0x20000)
72#define CVMX_DFA_NODESM_SIZE            512     /* Size of each node for small encoding */
73#define CVMX_DFA_NODELG_SIZE            1024    /* Size of each node for large encoding */
74#define CVMX_DFA_NODESM_LAST_TERMINAL  (CVMX_DFA_NODESM_MAX_NODES-1)
75
76#ifdef ENABLE_DEPRECATED
77/* These defines are for compatability with old code. They are deprecated */
78#define CVMX_DFA_NODE18_SIZE            CVMX_DFA_NODESM_SIZE
79#define CVMX_DFA_NODE36_SIZE            CVMX_DFA_NODELG_SIZE
80#define CVMX_DFA_NODE18_MAX_NODES       CVMX_DFA_NODESM_MAX_NODES
81#define CVMX_DFA_NODE18_LAST_TERMINAL   CVMX_DFA_NODESM_LAST_TERMINAL
82#endif
83
84/**
85 * Which type of memory encoding is this graph using. Make sure you setup
86 * the LLM to match.
87 */
88typedef enum
89{
90    CVMX_DFA_GRAPH_TYPE_SM              = 0,
91    CVMX_DFA_GRAPH_TYPE_LG              = 1,
92#ifdef ENABLE_DEPRECATED
93    CVMX_DFA_GRAPH_TYPE_18b             = 0,    /* Deprecated */
94    CVMX_DFA_GRAPH_TYPE_36b             = 1     /* Deprecated */
95#endif
96} cvmx_dfa_graph_type_t;
97
98/**
99 * The possible node types.
100 */
101typedef enum
102{
103    CVMX_DFA_NODE_TYPE_NORMAL           = 0,    /**< Node is a branch */
104    CVMX_DFA_NODE_TYPE_MARKED           = 1,    /**< Node is marked special */
105    CVMX_DFA_NODE_TYPE_TERMINAL         = 2     /**< Node is a terminal leaf */
106} cvmx_dfa_node_type_t;
107
108/**
109 * The possible reasons the DFA stopped processing.
110 */
111typedef enum
112{
113    CVMX_DFA_STOP_REASON_DATA_GONE      = 0,    /**< DFA ran out of data */
114    CVMX_DFA_STOP_REASON_PARITY_ERROR   = 1,    /**< DFA encountered a memory error */
115    CVMX_DFA_STOP_REASON_FULL           = 2,    /**< DFA is full */
116    CVMX_DFA_STOP_REASON_TERMINAL       = 3     /**< DFA hit a terminal */
117} cvmx_dfa_stop_reason_t;
118
119/**
120 * This format describes the DFA pointers in small mode
121 */
122typedef union
123{
124    uint64_t u64;
125    struct
126    {
127        uint64_t                mbz         :32;/**< Must be zero */
128        uint64_t                p1          : 1;/**< Set if next_node1 is odd parity */
129        uint64_t                next_node1  :15;/**< Next node if an odd character match */
130        uint64_t                p0          : 1;/**< Set if next_node0 is odd parity */
131        uint64_t                next_node0  :15;/**< Next node if an even character match */
132    } w32;
133    struct
134    {
135        uint64_t                mbz         :28;/**< Must be zero */
136        uint64_t                p1          : 1;/**< Set if next_node1 is odd parity */
137        uint64_t                next_node1  :17;/**< Next node if an odd character match */
138        uint64_t                p0          : 1;/**< Set if next_node0 is odd parity */
139        uint64_t                next_node0  :17;/**< Next node if an even character match */
140    } w36;
141    struct /**< @ this structure only applies starting in CN58XX and if DFA_CFG[NRPL_ENA] == 1 and IWORD0[NREPLEN] == 1.  */
142    {
143        uint64_t                mbz         :28;/**< Must be zero */
144        uint64_t                p1          : 1;/**< Set if next_node1 is odd parity */
145        uint64_t                per_node_repl1  : 1;/**< enable for extra replicaiton for next node (CN58XX) */
146        uint64_t                next_node_repl1 : 2;/**< extra replicaiton for next node (CN58XX) (if per_node_repl1 is set) */
147        uint64_t                next_node1  :14;/**< Next node if an odd character match - IWORD3[Msize], if per_node_repl1==1. */
148        uint64_t                p0          : 1;/**< Set if next_node0 is odd parity */
149        uint64_t                per_node_repl0  : 1;/**< enable for extra replicaiton for next node (CN58XX) */
150        uint64_t                next_node_repl0 : 2;/**< extra replicaiton for next node (CN58XX) (if per_node_repl0 is set) */
151        uint64_t                next_node0  :14;/**< Next node if an odd character match - IWORD3[Msize], if per_node_repl0==1. */
152    } w36nrepl_en; /**< use when next_node_repl[01] is 1. */
153    struct /**< this structure only applies starting in CN58XX and if DFA_CFG[NRPL_ENA] == 1 and IWORD0[NREPLEN] == 1.  */
154    {
155        uint64_t                mbz         :28;/**< Must be zero */
156        uint64_t                p1          : 1;/**< Set if next_node1 is odd parity */
157        uint64_t                per_node_repl1  : 1;/**< enable for extra replicaiton for next node (CN58XX) */
158        uint64_t                next_node1  :16;/**< Next node if an odd character match, if per_node_repl1==0. */
159        uint64_t                p0          : 1;/**< Set if next_node0 is odd parity */
160        uint64_t                per_node_repl0  : 1;/**< enable for extra replicaiton for next node (CN58XX) */
161        uint64_t                next_node0  :16;/**< Next node if an odd character match, if per_node_repl0==0. */
162    } w36nrepl_dis; /**< use when next_node_repl[01] is 0. */
163#if defined(ENABLE_DEPRECATED) && !OCTEON_IS_COMMON_BINARY()
164#if CVMX_COMPILED_FOR(OCTEON_CN31XX)
165    struct /**< @deprecated unnamed reference to members */
166    {
167        uint64_t                mbz         :32;/**< Must be zero */
168        uint64_t                p1          : 1;/**< Set if next_node1 is odd parity */
169        uint64_t                next_node1  :15;/**< Next node if an odd character match */
170        uint64_t                p0          : 1;/**< Set if next_node0 is odd parity */
171        uint64_t                next_node0  :15;/**< Next node if an even character match */
172    };
173#elif CVMX_COMPILED_FOR(OCTEON_CN38XX)
174    struct /**< @deprecated unnamed reference to members */
175    {
176        uint64_t                mbz         :28;/**< Must be zero */
177        uint64_t                p1          : 1;/**< Set if next_node1 is odd parity */
178        uint64_t                next_node1  :17;/**< Next node if an odd character match */
179        uint64_t                p0          : 1;/**< Set if next_node0 is odd parity */
180        uint64_t                next_node0  :17;/**< Next node if an even character match */
181    };
182#else
183    /* Other chips don't support the deprecated unnamed unions */
184#endif
185#endif
186} cvmx_dfa_node_next_sm_t;
187
188/**
189 * This format describes the DFA pointers in large mode
190 */
191typedef union
192{
193    uint64_t u64;
194    struct
195    {
196        uint64_t                mbz         :32;/**< Must be zero */
197        uint64_t                ecc         : 7;/**< ECC checksum on the rest of the bits */
198        cvmx_dfa_node_type_t    type        : 2;/**< Node type */
199        uint64_t                mbz2        : 3;/**< Must be zero */
200        uint64_t                next_node   :20;/**< Next node */
201    } w32;
202    struct
203    {
204        uint64_t                mbz         :28;/**< Must be zero */
205        uint64_t                ecc         : 7;/**< ECC checksum on the rest of the bits */
206        cvmx_dfa_node_type_t    type        : 2;/**< Node type */
207        uint64_t                extra_bits     : 5;/**< bits copied to report (PASS3/CN58XX), Must be zero previously */
208        uint64_t                next_node_repl : 2;/**< extra replicaiton for next node (PASS3/CN58XX), Must be zero previously */
209        uint64_t                next_node   :20;/**< Next node ID,  Note, combine with next_node_repl to use as start_node
210                                                     for continuation, as in cvmx_dfa_node_next_lgb_t. */
211    } w36;
212#if defined(ENABLE_DEPRECATED) && !OCTEON_IS_COMMON_BINARY()
213#if CVMX_COMPILED_FOR(OCTEON_CN31XX)
214    struct /**< @deprecated unnamed reference to members */
215    {
216        uint64_t                mbz         :32;/**< Must be zero */
217        uint64_t                ecc         : 7;/**< ECC checksum on the rest of the bits */
218        cvmx_dfa_node_type_t    type        : 2;/**< Node type */
219        uint64_t                mbz2        : 3;/**< Must be zero */
220        uint64_t                next_node   :20;/**< Next node */
221    };
222#elif CVMX_COMPILED_FOR(OCTEON_CN38XX)
223    struct /**< @deprecated unnamed reference to members */
224    {
225        uint64_t                mbz         :28;/**< Must be zero */
226        uint64_t                ecc         : 7;/**< ECC checksum on the rest of the bits */
227        cvmx_dfa_node_type_t    type        : 2;/**< Node type */
228        uint64_t                extra_bits     : 5;/**< bits copied to report (PASS3/CN58XX), Must be zero previously */
229        uint64_t                next_node_repl : 2;/**< extra replicaiton for next node (PASS3/CN58XX), Must be zero previously */
230        uint64_t                next_node   :20;/**< Next node ID,  Note, combine with next_node_repl to use as start_node
231                                                     for continuation, as in cvmx_dfa_node_next_lgb_t. */
232    };
233#else
234    /* Other chips don't support the deprecated unnamed unions */
235#endif
236#endif
237} cvmx_dfa_node_next_lg_t;
238
239/**
240 * This format describes the DFA pointers in large mode, another way
241 */
242typedef union
243{
244    uint64_t u64;
245    struct
246    {
247        uint64_t                mbz         :32;/**< Must be zero */
248        uint64_t                ecc         : 7;/**< ECC checksum on the rest of the bits */
249        uint64_t  		type_terminal : 1;/**< Node type */
250        uint64_t	        type_marked   : 1;/**< Node type */
251        uint64_t                mbz2        : 3;/**< Must be zero */
252        uint64_t                next_node   :20;/**< Next node */
253    } w32;
254    struct
255    {
256        uint64_t                mbz         :28;/**< Must be zero */
257        uint64_t                ecc         : 7;/**< ECC checksum on the rest of the bits */
258        uint64_t                type_terminal : 1;/**< Node type */
259        uint64_t                type_marked   : 1;/**< Node type */
260        uint64_t                extra_bits     : 5;/**< bits copied to report (PASS3/CN58XX), Must be zero previously */
261        uint64_t                next_node_id_and_repl   :22;/**< Next node ID (and repl for PASS3/CN58XX or repl=0 if not),
262                                                                 use this as start node for continuation. */
263    } w36;
264#if defined(ENABLE_DEPRECATED) && !OCTEON_IS_COMMON_BINARY()
265#if CVMX_COMPILED_FOR(OCTEON_CN31XX)
266    struct /**< @deprecated unnamed reference to members */
267    {
268        uint64_t                mbz         :32;/**< Must be zero */
269        uint64_t                ecc         : 7;/**< ECC checksum on the rest of the bits */
270        uint64_t  		type_terminal : 1;/**< Node type */
271        uint64_t	        type_marked   : 1;/**< Node type */
272        uint64_t                mbz2        : 3;/**< Must be zero */
273        uint64_t                next_node   :20;/**< Next node */
274    };
275#elif CVMX_COMPILED_FOR(OCTEON_CN38XX)
276    struct /**< @deprecated unnamed reference to members */
277    {
278        uint64_t                mbz         :28;/**< Must be zero */
279        uint64_t                ecc         : 7;/**< ECC checksum on the rest of the bits */
280        uint64_t                type_terminal : 1;/**< Node type */
281        uint64_t                type_marked   : 1;/**< Node type */
282        uint64_t                extra_bits     : 5;/**< bits copied to report (PASS3/CN58XX), Must be zero previously */
283        uint64_t                next_node_id_and_repl   :22;/**< Next node ID (and repl for PASS3/CN58XX or repl=0 if not),
284                                                                 use this as start node for continuation. */
285    };
286#else
287    /* Other chips don't support the deprecated unnamed unions */
288#endif
289#endif
290} cvmx_dfa_node_next_lgb_t;
291
292/**
293 * This format describes the DFA pointers in large mode
294 */
295typedef union
296{
297    uint64_t u64;
298    struct
299    {
300        uint64_t                mbz         :27;/**< Must be zero */
301        uint64_t                x0          : 1;/**< XOR of the rest of the bits */
302        uint64_t                reserved    : 4;/**< Must be zero */
303        uint64_t                data        :32;/**< LLM Data */
304    } w32;
305    struct
306    {
307        uint64_t                mbz         :27;/**< Must be zero */
308        uint64_t                x0          : 1;/**< XOR of the rest of the bits */
309        uint64_t                data        :36;/**< LLM Data */
310    } w36;
311#if defined(ENABLE_DEPRECATED) && !OCTEON_IS_COMMON_BINARY()
312#if CVMX_COMPILED_FOR(OCTEON_CN31XX)
313    struct /**< @deprecated unnamed reference to members */
314    {
315        uint64_t                mbz         :27;/**< Must be zero */
316        uint64_t                x0          : 1;/**< XOR of the rest of the bits */
317        uint64_t                reserved    : 4;/**< Must be zero */
318        uint64_t                data        :32;/**< LLM Data */
319    };
320#elif CVMX_COMPILED_FOR(OCTEON_CN38XX)
321    struct /**< @deprecated unnamed reference to members */
322    {
323        uint64_t                mbz         :27;/**< Must be zero */
324        uint64_t                x0          : 1;/**< XOR of the rest of the bits */
325        uint64_t                data        :36;/**< LLM Data */
326    };
327#else
328    /* Other chips don't support the deprecated unnamed unions */
329#endif
330#endif
331} cvmx_dfa_node_next_read_t;
332
333/**
334 * This structure defines the data format in the low-latency memory
335 */
336typedef union
337{
338    uint64_t u64;
339    cvmx_dfa_node_next_sm_t     sm;     /**< This format describes the DFA pointers in small mode */
340    cvmx_dfa_node_next_lg_t     lg;     /**< This format describes the DFA pointers in large mode */
341    cvmx_dfa_node_next_lgb_t    lgb;    /**< This format describes the DFA pointers in large mode, another way */
342    cvmx_dfa_node_next_read_t   read;   /**< This format describes the DFA pointers in large mode */
343#ifdef ENABLE_DEPRECATED
344    cvmx_dfa_node_next_sm_t     s18;    /**< Deprecated */
345    cvmx_dfa_node_next_lg_t     s36;    /**< Deprecated */
346    cvmx_dfa_node_next_lgb_t    s36b;   /**< Deprecated */
347#endif
348} cvmx_dfa_node_next_t;
349
350/**
351 * These structures define a DFA instruction
352 */
353typedef union
354{
355    uint64_t u64[4];
356    uint32_t u32;
357    struct
358    {
359        // WORD 0
360        uint64_t gxor                   : 8;   /**< Graph XOR value (PASS3/CN58XX), Must be zero for other chips
361                                                     or if DFA_CFG[GXOR_ENA] == 0.  */
362        uint64_t nxoren                 : 1;   /**< Node XOR enable (PASS3/CN58XX), Must be zero for other chips
363                                                     or if DFA_CFG[NXOR_ENA] == 0.  */
364        uint64_t nreplen                : 1;   /**< Node Replication mode enable (PASS3/CN58XX), Must be zero for other chips
365                                                     or if DFA_CFG[NRPL_ENA] == 0 or IWORD0[Ty] == 0.  */
366#if 0
367        uint64_t snrepl                 : 2;   /**< Start_Node Replication (PASS3/CN58XX), Must be zero for other chips
368                                                     or if DFA_CFG[NRPL_ENA] == 0 or IWORD0[Ty] == 0 or IWORD0[NREPLEN] == 0.  */
369        uint64_t start_node_id          : 20;   /**< Node to start the walk from */
370#else
371        uint64_t start_node             : 22;   /**< Node to start the walk from, includes ID and snrepl, see notes above. */
372#endif
373
374        uint64_t unused02               :  2;   /**< Must be zero */
375        cvmx_llm_replication_t replication : 2; /**< Type of memory replication to use */
376        uint64_t unused03               :  3;   /**< Must be zero */
377        cvmx_dfa_graph_type_t type      :  1;   /**< Type of graph */
378        uint64_t unused04               :  4;   /**< Must be zero */
379        uint64_t base                   : 20;   /**< All tables start on 1KB boundary */
380
381        // WORD 1
382        uint64_t input_length           : 16;   /**< In bytes, # pointers in gather case */
383        uint64_t use_gather             :  1;   /**< Set to use gather */
384        uint64_t no_L2_alloc            :  1;   /**< Set to disable loading of the L2 cache by the DFA */
385        uint64_t full_block_write       :  1;   /**< If set, HW can write entire cache blocks @ result_ptr */
386        uint64_t little_endian          :  1;   /**< Affects only packet data, not instruction, gather list, or result */
387        uint64_t unused1                :  8;   /**< Must be zero */
388        uint64_t data_ptr               : 36;   /**< Either directly points to data or the gather list. If gather list,
389                                                    data_ptr<2:0> must be zero (i.e. 8B aligned) */
390        // WORD 2
391        uint64_t max_results            : 16;   /**< in 64-bit quantities, mbz for store */
392        uint64_t unused2                : 12;   /**< Must be zero */
393        uint64_t result_ptr             : 36;   /**< must be 128 byte aligned */
394
395        // WORD 3
396        uint64_t tsize                  :  8;   /**< tsize*256 is the number of terminal nodes for GRAPH_TYPE_SM */
397        uint64_t msize                  : 16;   /**< msize is the number of marked nodes for GRAPH_TYPE_SM */
398        uint64_t unused3                :  4;   /**< Must be zero */
399        uint64_t wq_ptr                 : 36;   /**< 0 for no work queue entry creation */
400    } s;
401} cvmx_dfa_command_t;
402
403/**
404 * Format of the first result word written by the hardware.
405 */
406typedef union
407{
408    uint64_t u64;
409    struct
410    {
411        cvmx_dfa_stop_reason_t  reas        : 2;/**< Reason the DFA stopped */
412        uint64_t                mbz         :44;/**< Zero */
413        uint64_t                last_marked : 1;/**< Set if the last entry written is marked */
414        uint64_t                done        : 1;/**< Set to 1 when the DFA completes */
415        uint64_t                num_entries :16;/**< Number of result words written */
416    } s;
417} cvmx_dfa_result0_t;
418
419/**
420 * Format of the second result word and subsequent result words written by the hardware.
421 */
422typedef union
423{
424    uint64_t u64;
425    struct
426    {
427        uint64_t byte_offset    : 16;   /**< Number of bytes consumed */
428        uint64_t extra_bits_high:  4;   /**< If PASS3 or CN58XX and DFA_CFG[NRPL_ENA] == 1 and IWORD0[Ty] == 1,
429                                             then set to <27:24> of the last next-node pointer. Else set to 0x0.  */
430        uint64_t prev_node      : 20;   /**< Index of the previous node */
431        uint64_t extra_bits_low :  2;   /**< If PASS3 or CN58XX and DFA_CFG[NRPL_ENA] == 1 and IWORD0[Ty] == 1,
432                                             then set to <23:22> of the last next-node pointer. Else set to 0x0.  */
433        uint64_t next_node_repl :  2;   /**< If PASS3 or CN58XX and DFA_CFG[NRPL_ENA] == 1 and IWORD0[Ty] == 1, then set
434                                             to next_node_repl (<21:20>) of the last next-node pointer. Else set to 0x0.  */
435        uint64_t current_node   : 20;   /**< Index of the current node */
436    } s;
437    struct
438    {
439        uint64_t byte_offset    : 16;   /**< Number of bytes consumed */
440        uint64_t extra_bits_high:  4;   /**< If PASS3 or CN58XX and DFA_CFG[NRPL_ENA] == 1 and IWORD0[Ty] == 1,
441                                             then set to <27:24> of the last next-node pointer. Else set to 0x0.  */
442        uint64_t prev_node      : 20;   /**< Index of the previous node */
443        uint64_t extra_bits_low :  2;   /**< If PASS3 or CN58XX and DFA_CFG[NRPL_ENA] == 1 and IWORD0[Ty] == 1,
444                                             then set to <23:22> of the last next-node pointer. Else set to 0x0.  */
445        uint64_t curr_id_and_repl:22;   /**< Use ths as start_node for continuation. */
446    } s2;
447} cvmx_dfa_result1_t;
448
449/**
450 * Abstract DFA graph
451 */
452typedef struct
453{
454    cvmx_llm_replication_t      replication;        /**< Level of memory replication to use. Must match the LLM setup */
455    cvmx_dfa_graph_type_t       type;               /**< Type of graph */
456    uint64_t                    base_address;       /**< LLM start address of the graph */
457    union {
458        struct {
459            uint64_t            gxor         : 8;   /**< Graph XOR value (PASS3/CN58XX), Must be zero for other chips
460                                                          or if DFA_CFG[GXOR_ENA] == 0.  */
461            uint64_t            nxoren       : 1;   /**< Node XOR enable (PASS3/CN58XX), Must be zero for other chips
462                                                          or if DFA_CFG[NXOR_ENA] == 0.  */
463            uint64_t            nreplen      : 1;   /**< Node Replication mode enable (PASS3/CN58XX), Must be zero for other chips
464                                                          or if DFA_CFG[NRPL_ENA] == 0 or IWORD0[Ty] == 0.  */
465            uint64_t            snrepl       : 2;   /**< Start_Node Replication (PASS3/CN58XX), Must be zero for other chips
466                                                          or if DFA_CFG[NRPL_ENA] == 0 or IWORD0[Ty] == 0 or IWORD0[NREPLEN] == 0.*/
467            uint64_t            start_node_id : 20; /**< Start node index for the root of the graph */
468        };
469        uint32_t                start_node;         /**< Start node index for the root of the graph, incl. snrepl (PASS3/CN58XX)
470                                                           NOTE: for backwards compatibility this name includes the the
471                                                                 gxor, nxoren, nreplen, and snrepl fields which will all be
472                                                                 zero in applicaitons existing before the introduction of these
473                                                                 fields, so that existing applicaiton do not need to change. */
474    };
475    int                         num_terminal_nodes; /**< Number of terminal nodes in the graph. Only needed for small graphs. */
476    int                         num_marked_nodes;   /**< Number of marked nodes in the graph. Only needed for small graphs. */
477} cvmx_dfa_graph_t;
478
479/**
480 * DFA internal global state -- stored in 8 bytes of FAU
481 */
482typedef union
483{
484    uint64_t u64;
485    struct {
486#define CVMX_DFA_STATE_TICKET_BIT_POS 16
487#if __BYTE_ORDER == __BIG_ENDIAN
488	// NOTE:  must clear LSB of base_address_div16 due to ticket overflow
489	uint32_t		base_address_div16;  /**< Current DFA instruction queue chunck base address/16 (clear LSB). */
490	uint8_t			ticket_loops;	     /**< bits [15:8] of total number of tickets requested. */
491	uint8_t			ticket;		     /**< bits [7:0] of total number of tickets requested (current ticket held). */
492	// NOTE: index and now_serving are written together
493	uint8_t			now_serving;	     /**< current ticket being served (or ready to be served). */
494	uint8_t			index;		     /**< index into current chunk: (base_address_div16*16)[index] = next entry. */
495#else	// NOTE: little endian mode probably won't work
496	uint8_t			index;
497	uint8_t			now_serving;
498	uint8_t			ticket;
499	uint8_t			ticket_loops;
500	uint32_t		base_address_div16;
501#endif
502    } s;
503    struct {	// a bitfield version of the same thing to extract base address while clearing carry.
504#if __BYTE_ORDER == __BIG_ENDIAN
505	uint64_t		base_address_div32	: 31;	/**< Current DFA instruction queue chunck base address/32. */
506	uint64_t		carry			: 1;	/**< Carry out from total_tickets. */
507	uint64_t		total_tickets		: 16;	/**< Total tickets. */
508	uint64_t		now_serving		: 8 ;	/**< current ticket being served (or ready to be served). */
509	uint64_t		index			: 8 ;   /**< index into current chunk. */
510#else	// NOTE: little endian mode probably won't work
511	uint64_t		index			: 8 ;
512	uint64_t		now_serving		: 8 ;
513	uint64_t		total_tickets		: 16;
514	uint64_t		carry			: 1;
515	uint64_t		base_address_div32	: 31;
516#endif
517    } s2;
518} cvmx_dfa_state_t;
519
520/* CSR typedefs have been moved to cvmx-csr-*.h */
521
522/**
523 * Write a small node edge to LLM.
524 *
525 * @param graph  Graph to modify
526 * @param source_node
527 *               Source node for this edge
528 * @param match_index
529 *               Index into the node edge table. This is the match character/2.
530 * @param destination_node0
531 *               Destination if the character matches (match_index*2).
532 * @param destination_node1
533 *               Destination if the character matches (match_index*2+1).
534 */
535static inline void cvmx_dfa_write_edge_sm(const cvmx_dfa_graph_t *graph,
536                                         uint64_t source_node, uint64_t match_index,
537                                         uint64_t destination_node0, uint64_t destination_node1)
538{
539    cvmx_llm_address_t address;
540    cvmx_dfa_node_next_t    next_ptr;
541
542    address.u64 = graph->base_address + source_node * CVMX_DFA_NODESM_SIZE + match_index * 4;
543
544    next_ptr.u64 = 0;
545    if (OCTEON_IS_MODEL(OCTEON_CN31XX))
546    {
547        next_ptr.sm.w32.next_node0 = destination_node0;
548        next_ptr.sm.w32.p0 = cvmx_llm_parity(destination_node0);
549
550        next_ptr.sm.w32.next_node1 = destination_node1;
551        next_ptr.sm.w32.p1 = cvmx_llm_parity(destination_node1);
552    }
553    else
554    {
555        next_ptr.sm.w36.next_node0 = destination_node0;
556        next_ptr.sm.w36.p0 = cvmx_llm_parity(destination_node0);
557
558        next_ptr.sm.w36.next_node1 = destination_node1;
559        next_ptr.sm.w36.p1 = cvmx_llm_parity(destination_node1);
560    }
561
562    cvmx_llm_write36(address, next_ptr.u64, 0);
563}
564#ifdef ENABLE_DEPRECATED
565#define cvmx_dfa_write_edge18 cvmx_dfa_write_edge_sm
566#endif
567
568
569/**
570 * Write a large node edge to LLM.
571 *
572 * @param graph  Graph to modify
573 * @param source_node
574 *               Source node for this edge
575 * @param match  Character to match before taking this edge.
576 * @param destination_node
577 *               Destination node of the edge.
578 * @param destination_type
579 *               Node type at the end of this edge.
580 */
581static inline void cvmx_dfa_write_node_lg(const cvmx_dfa_graph_t *graph,
582                                         uint64_t source_node, unsigned char match,
583                                         uint64_t destination_node, cvmx_dfa_node_type_t destination_type)
584{
585    cvmx_llm_address_t      address;
586    cvmx_dfa_node_next_t    next_ptr;
587
588    address.u64 = graph->base_address + source_node * CVMX_DFA_NODELG_SIZE + (uint64_t)match * 4;
589
590    next_ptr.u64 = 0;
591    if (OCTEON_IS_MODEL(OCTEON_CN31XX))
592    {
593        next_ptr.lg.w32.type = destination_type;
594        next_ptr.lg.w32.next_node = destination_node;
595        next_ptr.lg.w32.ecc = cvmx_llm_ecc(next_ptr.u64);
596    }
597    else
598    {
599        next_ptr.lg.w36.type = destination_type;
600        next_ptr.lg.w36.next_node = destination_node;
601        next_ptr.lg.w36.ecc = cvmx_llm_ecc(next_ptr.u64);
602    }
603
604    cvmx_llm_write36(address, next_ptr.u64, 0);
605}
606#ifdef ENABLE_DEPRECATED
607#define cvmx_dfa_write_node36 cvmx_dfa_write_node_lg
608#endif
609
610/**
611 * Ring the DFA doorbell telling it that new commands are
612 * available.
613 *
614 * @param num_commands
615 *               Number of new commands
616 */
617static inline void cvmx_dfa_write_doorbell(uint64_t num_commands)
618{
619    CVMX_SYNCWS;
620    cvmx_write_csr(CVMX_DFA_DBELL, num_commands);
621}
622
623/**
624 * @INTERNAL
625 * Write a new command to the DFA. Calls to this function
626 * are internally synchronized across all processors, and
627 * the doorbell is rung during this function.
628 *
629 * @param command Command to write
630 */
631
632#ifdef CVMX_ENABLE_DFA_FUNCTIONS
633static inline void __cvmx_dfa_write_command(cvmx_dfa_command_t *command)
634{
635    cvmx_dfa_state_t cvmx_dfa_state;
636    uint64_t my_ticket;	// needs to wrap to 8 bits
637    uint64_t index;
638    cvmx_dfa_command_t *head;
639
640    CVMX_PREFETCH0(command);
641    // take a ticket.
642    cvmx_dfa_state.u64 = cvmx_fau_fetch_and_add64(CVMX_FAU_DFA_STATE, 1ull<<CVMX_DFA_STATE_TICKET_BIT_POS);
643    my_ticket = cvmx_dfa_state.s.ticket;
644
645    // see if it is our turn
646    while (my_ticket != cvmx_dfa_state.s.now_serving) {
647	int delta = my_ticket - cvmx_dfa_state.s.now_serving;
648	if (delta < 0) delta += 256;
649	cvmx_wait(10*delta);	// reduce polling load on system
650	cvmx_dfa_state.u64 = cvmx_fau_fetch_and_add64(CVMX_FAU_DFA_STATE, 0);		// poll for my_ticket==now_serving
651    }
652
653    // compute index and instruction queue head pointer
654    index = cvmx_dfa_state.s.index;
655
656    // NOTE: the DFA only supports 36-bit addressing
657    head = &((CASTPTR(cvmx_dfa_command_t, (cvmx_dfa_state.s2.base_address_div32 * 32ull))[index]));
658    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
659
660    // copy the command to the instruction queue
661    *head++ = *command;
662
663    // check if a new chunk is needed
664    if (cvmx_unlikely((++index >= ((CVMX_FPA_DFA_POOL_SIZE-8)/sizeof(cvmx_dfa_command_t))))) {
665        uint64_t *new_base = (uint64_t*)cvmx_fpa_alloc(CVMX_FPA_DFA_POOL);	// could make this async
666        if (new_base) {
667	    // put the link into the instruction queue's "Next Chunk Buffer Ptr"
668            *(uint64_t *)head = cvmx_ptr_to_phys(new_base);
669	    // update our state (note 32-bit write to not disturb other fields)
670            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))),
671		    (CAST64(new_base))/16);
672        }
673        else {
674            cvmx_dprintf("__cvmx_dfa_write_command: Out of memory. Expect crashes.\n");
675        }
676	index=0;
677    }
678
679    cvmx_dfa_write_doorbell(1);
680
681    // update index and now_serving in the DFA state FAU location (NOTE: this write16 updates to 8-bit values.)
682    // NOTE: my_ticket+1 carry out is lost due to write16 and index has already been wrapped to fit in uint8.
683    cvmx_fau_atomic_write16((cvmx_fau_reg_16_t)(CVMX_FAU_DFA_STATE+(CAST64(&cvmx_dfa_state.s.now_serving) - CAST64(&cvmx_dfa_state))),
684	    ((my_ticket+1)<<8) | index);
685}
686
687
688/**
689 * Submit work to the DFA units for processing
690 *
691 * @param graph   Graph to process
692 * @param start_node
693 *                The node to start (or continue) walking from
694 *                includes. start_node_id and snrepl (PASS3/CN58XX), but gxor,
695 *                nxoren, and nreplen are taken from the graph structure
696 * @param input   The input to match against
697 * @param input_length
698 *                The length of the input in bytes
699 * @param use_gather
700 *		  The input and input_length are of a gather list
701 * @param is_little_endian
702 *                Set to 1 if the input is in little endian format and must
703 *                be swapped before compare.
704 * @param result  Location the DFA should put the results in. This must be
705 *                an area sized in multiples of a cache line.
706 * @param max_results
707 *                The maximum number of 64-bit result1 words after result0.
708 *                That is, "size of the result area in 64-bit words" - 1.
709 *                max_results must be at least 1.
710 * @param work    Work queue entry to submit when DFA completes. Can be NULL.
711 */
712static inline void cvmx_dfa_submit(const cvmx_dfa_graph_t *graph, int start_node,
713                                  void *input, int input_length, int use_gather, int is_little_endian,
714                                  cvmx_dfa_result0_t *result, int max_results, cvmx_wqe_t *work)
715{
716    cvmx_dfa_command_t command;
717
718    /* Make sure the result's first 64bit word is zero so we can tell when the
719        DFA is done. */
720    result->u64 = 0;
721
722    // WORD 0
723    command.u64[0] = 0;
724    command.s.gxor          = graph->gxor;      // (PASS3/CN58XX)
725    command.s.nxoren        = graph->nxoren;    // (PASS3/CN58XX)
726    command.s.nreplen       = graph->nreplen;   // (PASS3/CN58XX)
727    command.s.start_node    = start_node;       // includes snrepl (PASS3/CN58XX)
728    command.s.replication   = graph->replication;
729    command.s.type          = graph->type;
730    command.s.base          = graph->base_address>>10;
731
732    // WORD 1
733    command.u64[1] = 0;
734    command.s.input_length  = input_length;
735    command.s.use_gather   = use_gather;
736    command.s.no_L2_alloc   = 0;
737    command.s.full_block_write = 1;
738    command.s.little_endian = is_little_endian;
739    command.s.data_ptr      = cvmx_ptr_to_phys(input);
740
741    // WORD 2
742    command.u64[2] = 0;
743    command.s.max_results   = max_results;
744    command.s.result_ptr    = cvmx_ptr_to_phys(result);
745
746    // WORD 3
747    command.u64[3] = 0;
748    if (graph->type == CVMX_DFA_GRAPH_TYPE_SM)
749    {
750        command.s.tsize     = (graph->num_terminal_nodes + 255) / 256;
751        command.s.msize     = graph->num_marked_nodes;
752    }
753    command.s.wq_ptr        = cvmx_ptr_to_phys(work);
754
755    __cvmx_dfa_write_command(&command);	// NOTE: this does synchronization and rings doorbell
756}
757#endif
758
759/**
760 * DFA gather list element
761 */
762typedef struct {
763    uint64_t length         : 16;   /**< length of piece of data at addr */
764    uint64_t reserved       : 12;   /**< reserved, set to 0 */
765    uint64_t addr           : 36;   /**< pointer to piece of data */
766} cvmx_dfa_gather_entry_t;
767
768
769/**
770 * Check if a DFA has completed processing
771 *
772 * @param result_ptr Result area the DFA is using
773 * @return Non zero if the DFA is done
774 */
775static inline uint64_t cvmx_dfa_is_done(cvmx_dfa_result0_t *result_ptr)
776{
777    /* DFA sets the first result 64bit word to non zero when it's done */
778    return ((volatile cvmx_dfa_result0_t *)result_ptr)->s.done;
779}
780
781
782#ifdef CVMX_ENABLE_DFA_FUNCTIONS
783/**
784 * Initialize the DFA hardware before use
785 * Returns 0 on success, -1 on failure
786 */
787int cvmx_dfa_initialize(void);
788
789
790/**
791 * Shutdown and cleanup resources used by the DFA
792 */
793void cvmx_dfa_shutdown(void);
794#endif
795
796#ifdef	__cplusplus
797}
798#endif
799
800#endif /* __CVMX_DFA_H__ */
801