/*
  Copyright (c) 2013 Cisco and/or its affiliates.

  * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/

#ifndef included_clib_pfhash_h
#define included_clib_pfhash_h


#include <vppinfra/clib.h>
#include <vppinfra/hash.h>
#include <vppinfra/pool.h>

#if defined(CLIB_HAVE_VEC128) && ! defined (__ALTIVEC__)

typedef struct
{
  /* 3 x 16 = 48 key bytes */
  union
  {
    u32x4 k_u32x4[3];
    u64 k_u64[6];
  } kb;
  /* 3 x 4 = 12 value bytes */
  u32 values[3];
  u32 pad;
} pfhash_kv_16_t;

typedef struct
{
  /* 5 x 8 = 40 key bytes */
  union
  {
    u64 k_u64[5];
  } kb;

  /* 5 x 4 = 20 value bytes */
  u32 values[5];
  u32 pad;
} pfhash_kv_8_t;

typedef struct
{
  /* 4 x 8 = 32 key bytes */
  union
  {
    u64 k_u64[4];
  } kb;

  /* 4 x 8 = 32 value bytes */
  u64 values[4];
} pfhash_kv_8v8_t;

typedef struct
{
  /* 8 x 4 = 32 key bytes */
  union
  {
    u32x4 k_u32x4[2];
    u32 kb[8];
  } kb;

  /* 8 x 4 = 32 value bytes */
  u32 values[8];
} pfhash_kv_4_t;

typedef union
{
  pfhash_kv_16_t kv16;
  pfhash_kv_8_t kv8;
  pfhash_kv_8v8_t kv8v8;
  pfhash_kv_4_t kv4;
} pfhash_kv_t;

typedef struct
{
  /* Bucket vector */
  u32 *buckets;
#define PFHASH_BUCKET_OVERFLOW (u32)~0

  /* Pool of key/value pairs */
  pfhash_kv_t *kvp;

  /* overflow plain-o-hash */
  uword *overflow_hash;

  /* Pretty-print name */
  u8 *name;

  u32 key_size;
  u32 value_size;

  u32 overflow_count;
  u32 nitems;
  u32 nitems_in_overflow;
} pfhash_t;

void pfhash_init (pfhash_t * p, char *name, u32 key_size, u32 value_size,
		  u32 nbuckets);
void pfhash_free (pfhash_t * p);
u64 pfhash_get (pfhash_t * p, u32 bucket, void *key);
void pfhash_set (pfhash_t * p, u32 bucket, void *key, void *value);
void pfhash_unset (pfhash_t * p, u32 bucket, void *key);

format_function_t format_pfhash;

static inline void
pfhash_prefetch_bucket (pfhash_t * p, u32 bucket)
{
  CLIB_PREFETCH (&p->buckets[bucket], CLIB_CACHE_LINE_BYTES, LOAD);
}

static inline u32
pfhash_read_bucket_prefetch_kv (pfhash_t * p, u32 bucket)
{
  u32 bucket_contents = p->buckets[bucket];
  if (PREDICT_TRUE ((bucket_contents & PFHASH_BUCKET_OVERFLOW) == 0))
    CLIB_PREFETCH (&p->kvp[bucket_contents], CLIB_CACHE_LINE_BYTES, LOAD);
  return bucket_contents;
}

/*
 * pfhash_search_kv_16
 * See if the supplied 16-byte key matches one of three 16-byte (key,value) pairs.
 * Return the indicated value, or ~0 if no match
 *
 * Note: including the overflow test, the fast path is 35 instrs
 * on x86_64. Elves will steal your keyboard in the middle of the night if
 * you "improve" it without checking the generated code!
 */
static inline u32
pfhash_search_kv_16 (pfhash_t * p, u32 bucket_contents, u32x4 * key)
{
  u32x4 diff0, diff1, diff2;
  u32 is_equal0, is_equal1, is_equal2;
  u32 no_match;
  pfhash_kv_16_t *kv;
  u32 rv;

  if (PREDICT_FALSE (bucket_contents == PFHASH_BUCKET_OVERFLOW))
    {
      uword *hp;
      hp = hash_get_mem (p->overflow_hash, key);
      if (hp)
	return hp[0];
      return (u32) ~ 0;
    }

  kv = &p->kvp[bucket_contents].kv16;

  diff0 = u32x4_sub (kv->kb.k_u32x4[0], key[0]);
  diff1 = u32x4_sub (kv->kb.k_u32x4[1], key[0]);
  diff2 = u32x4_sub (kv->kb.k_u32x4[2], key[0]);

  no_match = is_equal0 = (i16) u32x4_zero_byte_mask (diff0);
  is_equal1 = (i16) u32x4_zero_byte_mask (diff1);
  no_match |= is_equal1;
  is_equal2 = (i16) u32x4_zero_byte_mask (diff2);
  no_match |= is_equal2;
  /* If any of the three items matched, no_match will be zero after this line */
  no_match = ~no_match;

  rv = (is_equal0 & kv->values[0])
    | (is_equal1 & kv->values[1]) | (is_equal2 & kv->values[2]) | no_match;

  return rv;
}

static inline u32
pfhash_search_kv_8 (pfhash_t * p, u32 bucket_contents, u64 * key)
{
  pfhash_kv_8_t *kv;
  u32 rv = (u32) ~ 0;

  if (PREDICT_FALSE (bucket_contents == PFHASH_BUCKET_OVERFLOW))
    {
      uword *hp;
      hp = hash_get_mem (p->overflow_hash, key);
      if (hp)
	return hp[0];
      return (u32) ~ 0;
    }

  kv = &p->kvp[bucket_contents].kv8;

  rv = (kv->kb.k_u64[0] == key[0]) ? kv->values[0] : rv;
  rv = (kv->kb.k_u64[1] == key[0]) ? kv->values[1] : rv;
  rv = (kv->kb.k_u64[2] == key[0]) ? kv->values[2] : rv;
  rv = (kv->kb.k_u64[3] == key[0]) ? kv->values[3] : rv;
  rv = (kv->kb.k_u64[4] == key[0]) ? kv->values[4] : rv;

  return rv;
}

static inline u64
pfhash_search_kv_8v8 (pfhash_t * p, u32 bucket_contents, u64 * key)
{
  pfhash_kv_8v8_t *kv;
  u64 rv = (u64) ~ 0;

  if (PREDICT_FALSE (bucket_contents == PFHASH_BUCKET_OVERFLOW))
    {
      uword *hp;
      hp = hash_get_mem (p->overflow_hash, key);
      if (hp)
	return hp[0];
      return (u64) ~ 0;
    }

  kv = &p->kvp[bucket_contents].kv8v8;

  rv = (kv->kb.k_u64[0] == key[0]) ? kv->values[0] : rv;
  rv = (kv->kb.k_u64[1] == key[0]) ? kv->values[1] : rv;
  rv = (kv->kb.k_u64[2] == key[0]) ? kv->values[2] : rv;
  rv = (kv->kb.k_u64[3] == key[0]) ? kv->values[3] : rv;

  return rv;
}

static inline u32
pfhash_search_kv_4 (pfhash_t * p, u32 bucket_contents, u32 * key)
{
  u32x4 vector_key;
  u32x4 is_equal[2];
  u32 zbm[2], winner_index;
  pfhash_kv_4_t *kv;

  if (PREDICT_FALSE (bucket_contents == PFHASH_BUCKET_OVERFLOW))
    {
      uword *hp;
      hp = hash_get_mem (p->overflow_hash, key);
      if (hp)
	return hp[0];
      return (u32) ~ 0;
    }

  kv = &p->kvp[bucket_contents].kv4;

  vector_key = u32x4_splat (key[0]);

  is_equal[0] = (kv->kb.k_u32x4[0] == vector_key);
  is_equal[1] = (kv->kb.k_u32x4[1] == vector_key);
  zbm[0] = ~u32x4_zero_byte_mask (is_equal[0]) & 0xFFFF;
  zbm[1] = ~u32x4_zero_byte_mask (is_equal[1]) & 0xFFFF;

  if (PREDICT_FALSE ((zbm[0] == 0) && (zbm[1] == 0)))
    return (u32) ~ 0;

  winner_index = min_log2 (zbm[0]) >> 2;
  winner_index = zbm[1] ? (4 + (min_log2 (zbm[1]) >> 2)) : winner_index;

  return kv->values[winner_index];
}

#endif /* CLIB_HAVE_VEC128 */

#endif /* included_clib_pfhash_h */

/*
 * fd.io coding-style-patch-verification: ON
 *
 * Local Variables:
 * eval: (c-set-style "gnu")
 * End:
 */
