How to use the hardware hash unit in the MicroEngines:

dispatch_loop/dlsystems.h:
....
....

#ifndef MAC_TABLE_SRAM_BASE
#define MAC_TABLE_SRAM_BASE       0x80065000
#define MAC_TABLE_SRAM_BASE_UE    0x65000

#define MAC_ENTRIES          20
#define MAC_MASK             (MAC_ENTRIES -1)
#define MAC_SIZE             6
#define MAC_TABLE_SRAM_SIZE     (MAC_ENTRIES * 4 * MAC_SIZE) // Each entry is 3 unsigned ints
#endif
....
....

mac_table.h:

typedef struct mac_table_t{
  unsigned int      ip;          //ip address 
  unsigned int      mac0;        //first 32 bit of mac addresss
  unsigned int      mac1;        //last 16 bit of mac addresss
  unsigned int      port;        //port number or interface
  unsigned int      sent;        //how many times you have sent an arp req.
  unsigned int      valid;       //is this a valid entry

}  mac_table_t;

packet_echo.h:

#include "mac_table.h"

mac_table_t mac_entry;
__declspec(sram) mac_table_t *mac_base;

void init_hash();
int add_arp_entry(mac_table_t *ae);
int find_arp_entry(unsigned int ip);

mac_base = (struct  mac_table_t *)  MAC_TABLE_SRAM_BASE_UE;
init_hash();

mac_entry.mac0 = highmac;           // higest 32 bit of mac adress
mac_entry.mac1 = lowmac;            // lowest 16 bit of mac adress
mac_entry.ip = i;                   // ip adress
mac_entry.port = pMeta->inputPort;  // port number host is on
mac_entry.valid = 1;                // 1 so we know that it is a valid entry
	  
add_arp_entry(&mac_entry);          // enters ip in hash table

i = find_arp_entry(ip);             // finds the index in the mac_base
                                    // table


//How to initialize the hash unit from the microde:

void init_hash() {
 __declspec(sram_write_reg) int hash_multiplier[4];

 SIGNAL hash_init0, hash_init1;  //signals to wait for writing to be done
      
 hash_multiplier[0] = 0x12345678;    //these numbers you choose as you like
 hash_multiplier[1] = 0x87654321;    //Just remember to fill a whole 32 bit number
 hash_multiplier[2] = 0x7531abcd;
 hash_multiplier[3] = 0x44444444;
 
 // see ixp.h for cap scr hash adresses.
 // we need to write to the registers in the hash unit. these registers tells
 // the hash unit how to hash teh values.
 // first we do the 48 bit multiplers:
 cap_csr_write(&hash_multiplier[0], csr_hash_multiplier_48_0, sig_done,&hash_init0);
 cap_csr_write(&hash_multiplier[1], csr_hash_multiplier_48_1, sig_done,&hash_init1);
 
 wait_for_all(&hash_init0, &hash_init1);
 
 // then we do the 128 bit multiplers:
 cap_csr_write(&hash_multiplier[2], csr_hash_multiplier_128_0, sig_done,&hash_init0); 
 cap_csr_write(&hash_multiplier[3], csr_hash_multiplier_128_1, sig_done,&hash_init1);
 wait_for_all(&hash_init0, &hash_init1);
 
}

/* Function to insert an entry into the ARP table.                     */
/* Note: because our code uses a simplified ARP table in which entries */
/* do not expire, there is no need to check for duplicate entries.     */
int add_arp_entry(mac_table_t *ae) {
  __declspec(sram_read_reg) unsigned int  d_out[8];   /* hased data */
  __declspec(sram_write_reg) unsigned int  d_in[8];   /* data to hash */
  int i,j;
  SIGNAL_PAIR  sig_h;   // used as signal when hash is done
 
  d_in[0] = ae->ip;     // we hash with respect to ip adress.
  d_in[1] = 0;

  hash_48(&d_out[0], &d_in[0],2, sig_done, &sig_h);  // the hash operation
  wait_for_all(&sig_h);                              // wait until done

  j = d_out[0] & MAC_MASK;     // the mask makes sure we hash to a valid index
                               // in the has table.

  for (i=0;i < MAC_ENTRIES;i++) {   //if two ip's hash to the same index, we take
                                  // the next one, and so on    
    if(ae->ip == mac_base[j].ip && mac_base[j].valid)  // ip is already hashed
      return(1);                                        // exit
    
    if(mac_base[j].valid == 0) {    //something there that is not valid or empty 
                                    //enter our data there
      mac_base[j].ip   = ae->ip;
      mac_base[j].mac0 = ae->mac0;
      mac_base[j].mac1 = ae->mac1;
      mac_base[j].port = ae->port;
      mac_base[j].sent = ae->sent;
      mac_base[j].valid= ae->valid;
      return(1);
    }
    
    j=(j+1)&MAC_MASK;               // look at next enrty, in case we had 
                                    // two ip adresses map to the same entry.
  }
  // there was no room in table, return 0
  return(0);
}



// takes mac adress, returns index in mac_base table
int find_arp_entry(unsigned int ip) {
  int i,j;
  __declspec(sram_read_reg) unsigned int  d_out[8];   /* hased data */
  __declspec(sram_write_reg) unsigned int  d_in[8];   /* data to hash */
  SIGNAL_PAIR  sig_h;         // used as signal when hash is done
  
  d_in[0] = ip;               // we hash with respect to ip adress.
  d_in[1] = 0;
  hash_48(&d_out[0], &d_in[0],2, sig_done, &sig_h);  // the hash operation
  wait_for_all(&sig_h);                              // wait until done
  
  j = d_out[0] & MAC_MASK;     // the mask makes sure we hash to a valid index
                               // in the hash table.
  
  for (i=0;i< MAC_ENTRIES;i++) {   //if two ip's hash to the same index, we look
                                  //at the next one, and so on
    if(ip == mac_base[j].ip && mac_base[j].valid )  // we found it and 
        return(j);                                  // exit
 
    j=(j+1)&MAC_MASK;               // look at next entry, in case we had 
                                    // two ip adresses map to the same entry.
  }
  return -1;                        // not found, return a not-found-value
}