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 }