openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

chipsim.c (6982B)


      1 /* 
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * File:        chipsim.c
      8  *
      9  *     The main pcid file; simulates BCM 5670 and 5690.
     10  *
     11  * Requires:
     12  *     util.c routines
     13  *     soc_internal_read/write
     14  *     
     15  * Provides:
     16  *     event_init
     17  *     event_enqueue
     18  *     event_peek
     19  *     event_process_through
     20  *     pcid_counter_activity
     21  *     pcid_check_packet_input
     22  */
     23 
     24 #include <shared/bsl.h>
     25 
     26 #include <unistd.h>
     27 #include <stdlib.h>
     28 #include <ctype.h>
     29 
     30 #include <sys/types.h>
     31 #include <sys/time.h>
     32 #include <soc/mem.h>
     33 #include <soc/hash.h>
     34 #include <soc/higig.h>
     35 
     36 #include <soc/cmic.h>
     37 #include <soc/drv.h>
     38 #include <soc/debug.h>
     39 #include <sal/appl/io.h>
     40 #include <bde/pli/verinet.h>
     41 
     42 #include "pcid.h"
     43 #include "mem.h"
     44 #include "cmicsim.h"
     45 #include "dma.h"
     46 #include "chipsim.h"
     47 
     48 sal_usecs_t     event_past;
     49 event_t        *event_q;
     50 
     51 void
     52 event_init(void)
     53 {
     54     event_t        *ev;
     55 
     56     /* Clear queue in case called more than once */
     57 
     58     while ((ev = event_q) != NULL) {
     59         event_q = ev->next;
     60         sal_free(ev);
     61     }
     62 
     63     event_past = sal_time_usecs();
     64 }
     65 
     66 void
     67 event_enqueue(pcid_info_t *pcid_info, event_handler_t handler,
     68               sal_usecs_t abs_time)
     69 {
     70     event_t        *ev, **pp;
     71 
     72     if ((ev = sal_alloc(sizeof(event_t), "event_t")) == NULL) {
     73         LOG_CLI((BSL_META("pcid: Out of memory\n")));
     74         abort();
     75     }
     76 
     77     /* Disallow enqueuing events in the past */
     78 
     79     ev->pcid_info = pcid_info;
     80     ev->abs_time = (SAL_USECS_SUB(abs_time, event_past) > 0) ?
     81         abs_time : event_past;
     82     ev->handler = handler;
     83 
     84     for (pp = &event_q; *pp != NULL; pp = &(*pp)->next) {
     85         if (SAL_USECS_SUB((*pp)->abs_time, abs_time) > 0) {
     86             break;
     87         }
     88     }
     89 
     90     ev->next = *pp;
     91 
     92     *pp = ev;
     93 }
     94 
     95 event_t        *
     96 event_peek(void)
     97 {
     98     return event_q;
     99 }
    100 
    101 void
    102 event_process_through(sal_usecs_t abs_time)
    103 {
    104     event_t        *ev;
    105 
    106     while ((ev = event_q) != NULL &&
    107            SAL_USECS_SUB(abs_time, ev->abs_time) >= 0) {
    108 
    109         event_q = ev->next;
    110         ev->next = NULL;
    111 
    112         (*ev->handler) (ev);
    113 
    114         sal_free(ev);
    115     }
    116 
    117     event_past = abs_time;
    118 }
    119 
    120 /* 
    121  * pcid_counter_activity
    122  *
    123  *    Simulate random counter activity.
    124  *
    125  *    The lower-numbered ports are most active and the higher-numbered
    126  *    ports are the least active.  There is an exponential drop-off of
    127  *    activity based on the port number.
    128  */
    129 
    130 void
    131 pcid_counter_activity(event_t * ev)
    132 {
    133     soc_port_t      port;
    134     soc_reg_t       ctr_reg;
    135     int             i, incr, offset;
    136     uint32          mask;
    137     uint32          val[SOC_MAX_MEM_WORDS];
    138     pcid_info_t    *pcid_info;
    139     soc_cmap_t     *cmap;
    140     int             ctype;
    141 
    142     pcid_info = ev->pcid_info;
    143 
    144     PBMP_ITER(PBMP_PORT_ALL(pcid_info->unit), port) {
    145         if (IS_FE_PORT(pcid_info->unit, port)) {
    146             ctype = SOC_CTR_TYPE_FE;
    147         } else if (IS_GE_PORT(pcid_info->unit, port)) {
    148             ctype = SOC_CTR_TYPE_GE;
    149         } else if (IS_HG_PORT(pcid_info->unit, port)) {
    150             ctype = SOC_CTR_TYPE_HG;
    151         } else if (IS_XE_PORT(pcid_info->unit, port)) {
    152             ctype = SOC_CTR_TYPE_XE;
    153         } else {
    154             ctype = 0;
    155         }
    156 
    157         cmap = &SOC_CTR_DMA_MAP(pcid_info->unit, ctype);
    158 
    159         for (i = 0; i < cmap->cmap_size; i++) {
    160             incr = 0x100000;       /* Lower-numbered counters are active */
    161 
    162             ctr_reg = cmap->cmap_base[i].reg;
    163 
    164             if (ctr_reg == INVALIDr) {
    165                 continue;
    166 	    }
    167 
    168             offset = soc_reg_addr(pcid_info->unit, ctr_reg, port, 0);
    169 
    170             mask = soc_reg_datamask(pcid_info->unit, ctr_reg, 0);
    171 
    172             soc_internal_read_reg(pcid_info, offset, val);
    173             val[0] = (val[0] + (sal_rand() % incr)) & mask;
    174             soc_internal_write_reg(pcid_info, offset, val);
    175         }
    176     }
    177 
    178     event_enqueue(pcid_info, ev->handler,
    179                   ev->abs_time + COUNTER_ACT_INTERVAL);
    180 }
    181 
    182 void
    183 pcid_check_packet_input(event_t * ev)
    184 {
    185     FILE           *fp;
    186     int             c1, c2, byte;
    187     packet_t       *pkt;
    188     packet_t       *pp;
    189     pcid_info_t    *pcid_info;
    190     int            i;
    191     int            word_count=8; /* FB/ER 3 + 5 words of HG + PBI */
    192 
    193     pcid_info = ev->pcid_info;
    194 
    195     if ((fp = fopen("pkt", "r")) != 0) {
    196         pkt = sal_alloc(sizeof(packet_t), "packet_t");
    197 
    198         pkt->length = 0;
    199         pkt->consum = 0;
    200         pkt->next = 0;
    201 
    202 #ifdef BCM_TRX_SUPPORT
    203         if (SOC_IS_TRX(pcid_info->unit)) {
    204             word_count = 13; /* 4 + 7 words of HG + PBE */
    205         }
    206 #endif /* BCM_TRX_SUPPORT */
    207 
    208         for (i = 0; i < word_count; i++) {
    209             pkt->dcbd[i] = 0x0; /* FB/ER 3 + 5 words of HG + PBI */
    210         }
    211 #ifdef BCM_XGS_SUPPORT
    212         soc_higig_field_set(pcid_info->unit, (soc_higig_hdr_t *)(pkt->dcbd),
    213                             HG_start, SOC_HIGIG_START);
    214         soc_higig_field_set(pcid_info->unit, (soc_higig_hdr_t *)(pkt->dcbd),
    215                             HG_hgi, SOC_HIGIG_HGI);
    216         soc_higig_field_set(pcid_info->unit, (soc_higig_hdr_t *)(pkt->dcbd),
    217                             HG_vlan_id, 1);
    218         soc_higig_field_set(pcid_info->unit, (soc_higig_hdr_t *)(pkt->dcbd),
    219                             HG_opcode, SOC_HIGIG_OP_CPU);
    220         soc_higig_field_set(pcid_info->unit, (soc_higig_hdr_t *)(pkt->dcbd),
    221                             HG_hdr_format, SOC_HIGIG_HDR_DEFAULT);
    222         soc_higig_field_set(pcid_info->unit, (soc_higig_hdr_t *)(pkt->dcbd),
    223                             HG_src_port, CMIC_PORT(pcid_info->unit));
    224 #endif /* BCM_XGS_SUPPORT */
    225 
    226         for (;;) {
    227             do {
    228                 if ((c1 = getc(fp)) == EOF)
    229                     goto eof;
    230             } while (!isxdigit(c1));
    231 
    232             do {
    233                 if ((c2 = getc(fp)) == EOF)
    234                     goto eof;
    235             } while (!isxdigit(c2));
    236 
    237             byte = pcid_x2i(c1) * 16 + pcid_x2i(c2);
    238 
    239             /* Add byte to current packet (up to max length) */
    240 
    241             if (pkt->length < PKT_SIZE_MAX) {
    242                 pkt->data[pkt->length++] = byte;
    243             }
    244         }
    245 
    246       eof:
    247 
    248         fclose(fp);
    249 
    250         unlink("pkt");
    251 
    252 #if 0
    253         LOG_CLI((BSL_META("RX PKT LEN %d:"), pkt->length));
    254         for (c1 = 0; c1 < pkt->length; c1++) {
    255             LOG_CLI((BSL_META(" %02x"), pkt->data[c1]));
    256         }
    257         LOG_CLI((BSL_META("\n")));
    258 #endif
    259 
    260         /* Queue current packet on end of list */
    261         sal_mutex_take(pcid_info->pkt_mutex, sal_mutex_FOREVER);
    262         if (!pcid_info->pkt_list) {
    263             pcid_info->pkt_list = pkt;
    264         } else {
    265             for (pp = pcid_info->pkt_list; pp->next; pp = pp->next)
    266                 ;
    267             pp->next = pkt;
    268         }
    269         sal_mutex_give(pcid_info->pkt_mutex);
    270     }
    271 
    272     event_enqueue(pcid_info, ev->handler,
    273                   ev->abs_time + PACKET_CHECK_INTERVAL);
    274 }