| 1 | // ========== Copyright Header Begin ========================================== |
| 2 | // |
| 3 | // OpenSPARC T2 Processor File: pcg_lib.vr |
| 4 | // Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved |
| 5 | // 4150 Network Circle, Santa Clara, California 95054, U.S.A. |
| 6 | // |
| 7 | // * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| 8 | // |
| 9 | // This program is free software; you can redistribute it and/or modify |
| 10 | // it under the terms of the GNU General Public License as published by |
| 11 | // the Free Software Foundation; version 2 of the License. |
| 12 | // |
| 13 | // This program is distributed in the hope that it will be useful, |
| 14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 16 | // GNU General Public License for more details. |
| 17 | // |
| 18 | // You should have received a copy of the GNU General Public License |
| 19 | // along with this program; if not, write to the Free Software |
| 20 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 21 | // |
| 22 | // For the avoidance of doubt, and except that if any non-GPL license |
| 23 | // choice is available it will apply instead, Sun elects to use only |
| 24 | // the General Public License version 2 (GPLv2) at this time for any |
| 25 | // software where a choice of GPL license versions is made |
| 26 | // available with the language indicating that GPLv2 or any later version |
| 27 | // may be used, or where a choice of which version of the GPL is applied is |
| 28 | // otherwise unspecified. |
| 29 | // |
| 30 | // Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
| 31 | // CA 95054 USA or visit www.sun.com if you need additional information or |
| 32 | // have any questions. |
| 33 | // |
| 34 | // ========== Copyright Header End ============================================ |
| 35 | #include <vera_defines.vrh> |
| 36 | #include "pcg_defines.vri" |
| 37 | #include "pcg_types.vri" |
| 38 | #include "pcg_classes.vrh" |
| 39 | #include "pack_db.vrh" |
| 40 | #include "pack_db_tasks.vrh" |
| 41 | #include "flow_db.vrh" |
| 42 | #include "flow_db_tasks.vrh" |
| 43 | #include "mbox_class.vrh" |
| 44 | #include "get_mbox_id.vrh" |
| 45 | #include "pg_top_pp.vrh" |
| 46 | |
| 47 | extern pack_db_entry pack_db[]; |
| 48 | // extern flow_db_entry flow_db[]; |
| 49 | // extern integer pack_db_index; |
| 50 | // extern integer flow_num; |
| 51 | // extern integer pack_db_lock; |
| 52 | // extern integer flow_db_lock; |
| 53 | extern mbox_class mbox_id; |
| 54 | // extern integer quiet_on; |
| 55 | extern flow_desc flow[]; |
| 56 | extern class pc; |
| 57 | |
| 58 | extern pg ptr_to_first_pg; |
| 59 | extern pg pack_gen[16]; |
| 60 | |
| 61 | extern pc pack_check[4]; |
| 62 | |
| 63 | |
| 64 | |
| 65 | |
| 66 | /* |
| 67 | extern class pg; |
| 68 | extern pg ptr_to_first_pg; |
| 69 | extern pg pack_gen[4]; |
| 70 | |
| 71 | */ |
| 72 | |
| 73 | |
| 74 | task build_frame(integer itoken, byte_array buf, var integer len,(integer header_id=-1),(integer new_crc=0)) { |
| 75 | integer n; |
| 76 | integer ptr=0; |
| 77 | integer tagged = 0; |
| 78 | integer my_port, org_port; |
| 79 | bit [31:0] tmp32; |
| 80 | integer data_len, header_len; |
| 81 | integer debug = 0; |
| 82 | integer token; |
| 83 | integer adj_len=0; |
| 84 | integer min,max; |
| 85 | bit [15:0] tx_status; |
| 86 | |
| 87 | tmp32 = itoken; |
| 88 | token = tmp32[25:0]; |
| 89 | //debug = tmp32[31]; |
| 90 | |
| 91 | if(debug) |
| 92 | printf("DEBUG: build_frame: Started Build-Frame. (Input: Token: %0d, Len: %0d Hdr: %0d, NewCRC: %0d Port: %0d)\n", |
| 93 | token,len,header_id,new_crc,my_port); |
| 94 | |
| 95 | if( assoc_index(CHECK, pack_db, token) == 0 ) { |
| 96 | printf("ERROR: PG LIB: build_frame: Token (%0d) is invalid/entry could not be found in packet database.\n", |
| 97 | token); |
| 98 | len = 0; |
| 99 | buf = null; |
| 100 | return; |
| 101 | } |
| 102 | |
| 103 | my_port = pack_db[token].org_port; |
| 104 | org_port = pack_db[token].org_port; |
| 105 | if(header_id != -1) my_port = header_id; |
| 106 | |
| 107 | |
| 108 | if(INTER_FEDX) { |
| 109 | buf.val[ptr++] = pack_db[token].ifedx_control[07:0]; |
| 110 | buf.val[ptr++] = pack_db[token].ifedx_control[15:8]; |
| 111 | if(debug) printf("DEBUG: build_frame: Building INTERFEDX packet\n"); |
| 112 | } |
| 113 | |
| 114 | if(debug) printf("DEBUG: build_frame: (1)ptr: %0d\n",ptr); |
| 115 | |
| 116 | |
| 117 | if(header_id==-1) { |
| 118 | header_len = pack_db[token].header_len[ pack_db[token].use_hdr ]; |
| 119 | |
| 120 | for(n=0;n< header_len ;n++) |
| 121 | buf.val[ptr++] = pack_db[token].header[ pack_db[token].use_hdr ].val[n]; |
| 122 | } else { |
| 123 | |
| 124 | #define out_use_header pack_db[token].out_header[header_id].use_header |
| 125 | |
| 126 | if( assoc_index(CHECK,pack_db[token].out_header,header_id) & |
| 127 | assoc_index(CHECK,pack_db[token].out_header[header_id].header, out_use_header) ) { |
| 128 | |
| 129 | header_len = pack_db[token].out_header[header_id].header_len[ out_use_header ]; |
| 130 | |
| 131 | for(n=0; n < header_len ; n++) |
| 132 | buf.val[ptr++] =pack_db[token].out_header[header_id].header[out_use_header].val[n]; |
| 133 | } else { |
| 134 | printf("ERROR: PG LIB: build_frame: out header invalid. (Token:%0d, Out header id: %0d).\n", |
| 135 | token,header_id); |
| 136 | len = 0; |
| 137 | buf = null; |
| 138 | return; |
| 139 | } |
| 140 | } |
| 141 | |
| 142 | if(debug) printf("DEBUG: build_frame: header_len: %0d\n",header_len); |
| 143 | if(debug) printf("DEBUG: build_frame: (2)ptr: %0d\n",ptr); |
| 144 | |
| 145 | |
| 146 | if(pack_db[token].frame.data_type != DAT_FC_PAUSE) |
| 147 | '{buf.val[ptr++], buf.val[ptr++]} = token; // Store token in payload |
| 148 | |
| 149 | |
| 150 | if(pack_db[token].org_port<17 & my_port>16) adj_len += 6; |
| 151 | if(pack_db[token].org_port>16 & my_port<17) adj_len -= 6; |
| 152 | |
| 153 | if(debug) printf("DEBUG: build_frame: adj_len: %0d\n",adj_len); |
| 154 | |
| 155 | |
| 156 | if( pack_db[token].frame.frame_type[2] ) tagged = 1; |
| 157 | |
| 158 | if(debug) printf("DEBUG: build_frame: (3)ptr: DAT_LEN_EXACT: %0d\n", |
| 159 | ptr_to_first_pg.check_option(pack_db[token].frame.data_type, DAT_LEN_EXACT) ); |
| 160 | |
| 161 | |
| 162 | if(pack_db[token].data_length<0) { |
| 163 | |
| 164 | case(pack_db[token].data_length) { |
| 165 | -1: pack_db[token].data_length = 64; |
| 166 | -2: pack_db[token].data_length = 128; |
| 167 | -3: pack_db[token].data_length = 256; |
| 168 | -4: pack_db[token].data_length = 512; |
| 169 | -5: pack_db[token].data_length = 1024; |
| 170 | -6: pack_db[token].data_length = (tagged) ? 1522 : 1518; |
| 171 | -7: { |
| 172 | // pack_db[token].data_length = random(pack_db[token].frame.data_seed); // Vera supports only one random |
| 173 | |
| 174 | pack_db[token].data_length = random(); |
| 175 | min = 64; |
| 176 | max = (tagged) ? 1522 : 1518; |
| 177 | while(pack_db[token].data_length<min | pack_db[token].data_length>max) |
| 178 | pack_db[token].data_length = random(); |
| 179 | } |
| 180 | -8: pack_db[token].data_length = 63; |
| 181 | -9: pack_db[token].data_length = 65; |
| 182 | -10: pack_db[token].data_length = (tagged) ? 1521 : 1517; |
| 183 | -11: pack_db[token].data_length = (tagged) ? 1523 : 1519; |
| 184 | } |
| 185 | |
| 186 | pack_db[token].frame.data_type = pack_db[token].frame.data_type | DAT_LEN_EXACT; |
| 187 | } |
| 188 | |
| 189 | |
| 190 | if( ptr_to_first_pg.check_option(pack_db[token].frame.data_type, DAT_LEN_EXACT) ) { |
| 191 | |
| 192 | // Convert exact length to actual data length, clear exact flag and use that data length from now on. |
| 193 | // data_len = pack_db[token].data_length + header_len - pack_db[token].header_len[0] + adj_len; |
| 194 | |
| 195 | data_len = pack_db[token].data_length - header_len - 4; // data_len - header_len - crc_len |
| 196 | |
| 197 | |
| 198 | if(INTER_FEDX) data_len = data_len - 6; |
| 199 | |
| 200 | pack_db[token].data_length = data_len; |
| 201 | pack_db[token].frame.data_type = pack_db[token].frame.data_type & DAT_TYPE_MASK; |
| 202 | } |
| 203 | else |
| 204 | data_len = pack_db[token].data_length; |
| 205 | |
| 206 | |
| 207 | if(debug) printf("DEBUG: build_frame: (3)ptr: %0d\n",ptr); |
| 208 | if(debug) printf("DEBUG: build_frame: data_len: %0d\n",data_len); |
| 209 | |
| 210 | if( pack_db[token].frame.frame_type[2] ) tagged = 1; |
| 211 | pack_gen[my_port].data_gen( pack_db[token].frame.data_type, |
| 212 | pack_db[token].frame.data_seed, |
| 213 | data_len, |
| 214 | buf, ptr, pack_db[token].options, pack_gen[my_port], tagged, INTER_FEDX); |
| 215 | |
| 216 | if(debug) printf("DEBUG: build_frame: (4)ptr: %0d\n",ptr); |
| 217 | |
| 218 | |
| 219 | |
| 220 | if(INTER_FEDX) |
| 221 | tmp32 = pack_gen[my_port].crc_gen(buf, 2, ptr); // Skip Interfedx Control Word |
| 222 | else |
| 223 | tmp32 = pack_gen[my_port].crc_gen(buf, 0, ptr); |
| 224 | |
| 225 | |
| 226 | if( pack_gen[my_port].check_option( pack_db[token].options, O_CRC_ERR) ) |
| 227 | tmp32 = tmp32 ^ pack_gen[my_port].cfg_reg[CFG_CRC_MASK]; |
| 228 | |
| 229 | |
| 230 | if(!new_crc) |
| 231 | '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = pack_db[token].pack_crc; |
| 232 | else { |
| 233 | if ( (org_port==17) | (org_port==18) ) { |
| 234 | if(INTER_FEDX) { |
| 235 | //packets that orginated on ifedx ports cannot be looped to another ifedx, except |
| 236 | // in iom tests. |
| 237 | '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = pack_db[token].pack_crc; |
| 238 | } |
| 239 | else { |
| 240 | //this pkt orginated on a ifedx port and is being sent out on a ext-port. |
| 241 | // look at the tx_mac status word to decide whether new pkt-crc is required. |
| 242 | |
| 243 | tx_status = pack_db[token].mac.tx_status; |
| 244 | |
| 245 | if(tx_status[14]) |
| 246 | '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = pack_db[token].pack_crc; |
| 247 | else '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = tmp32; |
| 248 | } |
| 249 | } //end of if ( (org_port==17) | (org_port==18) ) |
| 250 | else { |
| 251 | if(INTER_FEDX) |
| 252 | '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = pack_db[token].pack_crc; |
| 253 | else '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = tmp32; |
| 254 | } |
| 255 | } |
| 256 | |
| 257 | if(INTER_FEDX) { |
| 258 | tmp32 = pack_gen[my_port].crc_gen(buf, 0, ptr); |
| 259 | if( pack_gen[my_port].check_option( pack_db[token].options, O_IF_CRC_ERR) ) |
| 260 | tmp32 = tmp32 ^ pack_gen[my_port].cfg_reg[CFG_CRC_MASK]; |
| 261 | |
| 262 | if(new_crc) { |
| 263 | '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = tmp32; |
| 264 | pack_db[token].ifedx_crc = tmp32; |
| 265 | } else |
| 266 | '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = pack_db[token].ifedx_crc; |
| 267 | } |
| 268 | |
| 269 | if(debug) printf("DEBUG: build_frame: (5)ptr: %0d\n",ptr); |
| 270 | if(debug) printf("DEBUG: build_frame: Done.\n"); |
| 271 | len = ptr; |
| 272 | |
| 273 | /* |
| 274 | if(header_len>66) { |
| 275 | printf("ERROR: build_frame: Possibly corrupted header. Header is %0d bytes long !\n",header_len); |
| 276 | printf(" Input: Token: %0d, Len: %0d Hdr: %0d, NewCRC: %0d Port: %0d\n", |
| 277 | token, len, header_id, new_crc,my_port); |
| 278 | |
| 279 | printf("----------------------------------------- \n"); |
| 280 | printf("build_frame: displaying buffer: \n"); |
| 281 | printf("----------------------------------------- \n"); |
| 282 | ptr_to_first_pg.display_buf(buf, len, INTER_FEDX); |
| 283 | } |
| 284 | */ |
| 285 | } |
| 286 | |
| 287 | task build_header(integer itoken, byte_array buf, var integer len,(integer header_id=-1),(integer new_crc=0)) { |
| 288 | |
| 289 | |
| 290 | integer n; |
| 291 | integer ptr=0; |
| 292 | integer tagged = 0; |
| 293 | integer my_port, org_port; |
| 294 | bit [31:0] tmp32; |
| 295 | integer data_len, header_len; |
| 296 | integer debug = 1; |
| 297 | integer token; |
| 298 | integer adj_len=0; |
| 299 | integer min,max; |
| 300 | bit [15:0] tx_status; |
| 301 | |
| 302 | tmp32 = itoken; |
| 303 | token = tmp32[25:0]; |
| 304 | // debug = tmp32[31]; |
| 305 | |
| 306 | |
| 307 | if(debug) |
| 308 | printf("DEBUG: build_header: Started Build-Header (Input: Token: %0d, Len: %0d Hdr: %0d, NewCRC: %0d Port: %0d)\n", |
| 309 | token,len,header_id,new_crc,my_port); |
| 310 | |
| 311 | if( assoc_index(CHECK, pack_db, token) == 0 ) { |
| 312 | printf("ERROR: PG LIB: build_frame: Token (%0d) is invalid/entry could not be found in packet database.\n", |
| 313 | token); |
| 314 | len = 0; |
| 315 | buf = null; |
| 316 | return; |
| 317 | } |
| 318 | |
| 319 | my_port = pack_db[token].org_port; |
| 320 | org_port = pack_db[token].org_port; |
| 321 | if(header_id != -1) my_port = header_id; |
| 322 | |
| 323 | |
| 324 | if(INTER_FEDX) { |
| 325 | buf.val[ptr++] = pack_db[token].ifedx_control[07:0]; |
| 326 | buf.val[ptr++] = pack_db[token].ifedx_control[15:8]; |
| 327 | if(debug) printf("DEBUG: build_frame: Building INTERFEDX packet\n"); |
| 328 | } |
| 329 | |
| 330 | if(debug) printf("DEBUG: build_header: (1)ptr: %0d\n",ptr); |
| 331 | |
| 332 | |
| 333 | if(header_id==-1) { |
| 334 | header_len = pack_db[token].header_len[ pack_db[token].use_hdr ]; |
| 335 | |
| 336 | for(n=0;n< header_len ;n++) |
| 337 | buf.val[ptr++] = pack_db[token].header[ pack_db[token].use_hdr ].val[n]; |
| 338 | } else { |
| 339 | |
| 340 | #define out_use_header pack_db[token].out_header[header_id].use_header |
| 341 | |
| 342 | if( assoc_index(CHECK,pack_db[token].out_header,header_id) & |
| 343 | assoc_index(CHECK,pack_db[token].out_header[header_id].header, out_use_header) ) { |
| 344 | |
| 345 | header_len = pack_db[token].out_header[header_id].header_len[ out_use_header ]; |
| 346 | |
| 347 | for(n=0; n < header_len ; n++) |
| 348 | buf.val[ptr++] =pack_db[token].out_header[header_id].header[out_use_header].val[n]; |
| 349 | } else { |
| 350 | printf("ERROR: PG LIB: build_header: out header invalid. (Token:%0d, Out header id: %0d).\n", |
| 351 | token,header_id); |
| 352 | len = 0; |
| 353 | buf = null; |
| 354 | return; |
| 355 | } |
| 356 | } |
| 357 | |
| 358 | if(debug) printf("DEBUG: build_header: header_len: %0d\n",header_len); |
| 359 | if(debug) printf("DEBUG: build_header: (2)ptr: %0d\n",ptr); |
| 360 | |
| 361 | |
| 362 | if(pack_db[token].frame.data_type != DAT_FC_PAUSE) |
| 363 | '{buf.val[ptr++], buf.val[ptr++]} = token; // Store token in payload |
| 364 | |
| 365 | /**** |
| 366 | |
| 367 | if(header_len>66) { |
| 368 | printf("ERROR: build_header: Possibly corrupted header. Header is %0d bytes long !\n",header_len); |
| 369 | printf(" Input: Token: %0d, Len: %0d Hdr: %0d, NewCRC: %0d Port: %0d\n", |
| 370 | token, len, header_id, new_crc,my_port); |
| 371 | |
| 372 | printf("----------------------------------------- \n"); |
| 373 | printf("build_header: displaying buffer: \n"); |
| 374 | printf("----------------------------------------- \n"); |
| 375 | ptr_to_first_pg.display_buf(buf, header_len, INTER_FEDX); |
| 376 | } |
| 377 | ***/ |
| 378 | } |
| 379 | |
| 380 | |
| 381 | task build_ip_segment ( integer token , var bit[7:0]pkt_data[], integer offset, integer size){ |
| 382 | |
| 383 | |
| 384 | byte_array pkt_buf; |
| 385 | integer pkt_length; |
| 386 | integer j, k,arr_size ; |
| 387 | |
| 388 | //arr_size = (size -offset) + 1; |
| 389 | arr_size = (size +offset) ; |
| 390 | |
| 391 | pkt_buf = new; |
| 392 | |
| 393 | build_frame(token, pkt_buf, pkt_length); |
| 394 | // pack_gen[0].display_buf(pkt_buf, pkt_length); |
| 395 | |
| 396 | j = 0; |
| 397 | |
| 398 | for (k=offset;k<arr_size;k++){ |
| 399 | pkt_data[j] = pkt_buf.val[k]; |
| 400 | j++; |
| 401 | } |
| 402 | |
| 403 | |
| 404 | } |
| 405 | |
| 406 | |
| 407 | task get_ippkt_size(integer token, var integer ippkt_length){ |
| 408 | |
| 409 | ippkt_length = pack_db[token].data_length; |
| 410 | |
| 411 | } |
| 412 | |
| 413 | task get_ippkthdr_size(integer token, var integer iphdr_length){ |
| 414 | |
| 415 | iphdr_length = pack_db[token].header_len[ pack_db[token].use_hdr ]; |
| 416 | |
| 417 | } |
| 418 | |
| 419 | task get_ippaylod_size(integer token, var integer ippayload_length){ |
| 420 | |
| 421 | ippayload_length = { (pack_db[token].data_length) - |
| 422 | (pack_db[token].header_len[ pack_db[token].use_hdr ])}; |
| 423 | } |
| 424 | |
| 425 | |
| 426 | |
| 427 | |
| 428 | function integer getIpHdrSz (integer token){ |
| 429 | |
| 430 | |
| 431 | getIpHdrSz = pack_db[token].header_len[ pack_db[token].use_hdr ]; |
| 432 | |
| 433 | } |
| 434 | |
| 435 | function integer getIpPayloadSz (integer token){ |
| 436 | |
| 437 | |
| 438 | // getIpPayloadSz = (pack_db[token].data_length) + 4 ; |
| 439 | getIpPayloadSz = { (pack_db[token].data_length) - |
| 440 | (pack_db[token].header_len[ pack_db[token].use_hdr ]) - 4 }; |
| 441 | |
| 442 | } |
| 443 | |
| 444 | function integer getIpPktSz (integer token){ |
| 445 | |
| 446 | // getIpPktSz = pack_db[token].data_length + (pack_db[token].header_len[ pack_db[token].use_hdr ]) + 4; |
| 447 | getIpPktSz = pack_db[token].data_length; |
| 448 | |
| 449 | } |