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