| 1 | // ========== Copyright Header Begin ========================================== |
| 2 | // |
| 3 | // OpenSPARC T2 Processor File: N2fcilupeuIngressDmaWrStr.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 "l2_packet.vrh" |
| 36 | #include "ios_l2_stub.vrh" |
| 37 | #include "fc_top.if.vrh" |
| 38 | |
| 39 | extern VeraList_l2_packet l2_list0; |
| 40 | extern VeraList_l2_packet l2_list1; |
| 41 | extern VeraList_l2_packet l2_list2; |
| 42 | extern VeraList_l2_packet l2_list3; |
| 43 | extern VeraList_l2_packet l2_list4; |
| 44 | extern VeraList_l2_packet l2_list5; |
| 45 | extern VeraList_l2_packet l2_list6; |
| 46 | extern VeraList_l2_packet l2_list7; |
| 47 | extern ios_l2_stub l2_stub[]; |
| 48 | |
| 49 | extern StandardDisplay dbg; |
| 50 | |
| 51 | |
| 52 | class N2fcDmaWrPEUStr extends PEUStrBase { |
| 53 | |
| 54 | local bit [63:0] N2fcSAddr; |
| 55 | local bit [63:0] N2fcEAddr; |
| 56 | local bit N2fcAddrSpecified; |
| 57 | local bit [31:0] length; |
| 58 | local bit [31:0] dat; |
| 59 | bit [511:0] write_data = 0; |
| 60 | bit [63:0] start_data = 0; |
| 61 | bit msi_dma = 0; |
| 62 | N2fcIommuMgr MMU; |
| 63 | bit [7:0] bus_id; |
| 64 | |
| 65 | integer f_len; // The packet's payload length |
| 66 | bit[3:0] f_firstDWBE; // It's "first DWBE" field |
| 67 | bit[3:0] f_lastDWBE; // It's "last DWBE" field |
| 68 | integer f_bndy; // The address' boundary |
| 69 | bit f_lenSpecified; // Was a length specified? |
| 70 | bit f_firstSpecified; // Was a "firstDWBE" specified? |
| 71 | bit f_lastSpecified; // Was a "lastDWBE" specified? |
| 72 | bit f_bndySpecified; // Was an addr bndy specified? |
| 73 | integer f_tc; // The packet's traffic class |
| 74 | |
| 75 | function bit [63:0] hashpa (bit [63:0] pa) { |
| 76 | if (probe_if.hashing && ~pa[39]) |
| 77 | hashpa = {pa[63:18], pa[32:28] ^ pa[17:13], pa[19:18] ^ pa[12:11], pa[10:0]}; |
| 78 | else |
| 79 | hashpa = pa; |
| 80 | } |
| 81 | |
| 82 | task new( PEUTestEnv a_env) { |
| 83 | bit [3:0] index; |
| 84 | |
| 85 | super.new( a_env ); |
| 86 | |
| 87 | if (!msi_dma){ |
| 88 | if (!get_plus_arg(CHECK, "DISABLE_L2_CHECKER")) { |
| 89 | for ( index=0; index <8; index++){ |
| 90 | l2_stub[index].enable_l2_checker = 1; |
| 91 | l2_stub[index].enable_l2_wr_checker = 1; |
| 92 | } |
| 93 | } |
| 94 | } |
| 95 | f_lenSpecified = 0; |
| 96 | f_firstSpecified = 0; |
| 97 | f_lastSpecified = 0; |
| 98 | f_bndySpecified = 0; |
| 99 | N2fcAddrSpecified = 0; |
| 100 | f_tc = -1; |
| 101 | MMU = new(); |
| 102 | |
| 103 | printf ("%0d- N2fcDmaWrPEUStr:new first random # = %0h\n", get_time(LO), random() ); |
| 104 | } |
| 105 | |
| 106 | task SetLen( integer a_len ) |
| 107 | { |
| 108 | f_len = a_len; |
| 109 | f_lenSpecified = 1; |
| 110 | } |
| 111 | task SetFirstDWBE( bit[3:0] a_dwbe ) |
| 112 | { |
| 113 | f_firstDWBE = a_dwbe; |
| 114 | f_firstSpecified = 1; |
| 115 | } |
| 116 | task SetLastDWBE( bit[3:0] a_dwbe ) |
| 117 | { |
| 118 | f_lastDWBE = a_dwbe; |
| 119 | f_lastSpecified = 1; |
| 120 | } |
| 121 | task SetAddrBndy( integer a_bndy ) |
| 122 | { |
| 123 | f_bndy = a_bndy; |
| 124 | f_bndySpecified = 1; |
| 125 | } |
| 126 | |
| 127 | task N2fcSetAddr( bit [63:0] i_saddr, bit [63:0] i_eaddr ) |
| 128 | { |
| 129 | N2fcAddrSpecified = 1; |
| 130 | N2fcSAddr = i_saddr; |
| 131 | N2fcEAddr = i_eaddr; |
| 132 | } |
| 133 | |
| 134 | //------------------------------------------------------------------- |
| 135 | // Method Name: |
| 136 | // Description: |
| 137 | //------------------------------------------------------------------- |
| 138 | function bit[31:0] gen_4bytes_exp_data (bit [31:0] data, bit [3:0] bytemask){ |
| 139 | integer index; |
| 140 | |
| 141 | for (index =0; index < 4; index++){ |
| 142 | if (bytemask[3-index]) { |
| 143 | gen_4bytes_exp_data[31-8*index:32-8*(index+1)] = data[31-8*index:32-8*(index+1)]; |
| 144 | } else { |
| 145 | gen_4bytes_exp_data[31-8*index:32-8*(index+1)] = 8'hx; |
| 146 | } |
| 147 | } |
| 148 | } |
| 149 | |
| 150 | //------------------------------------------------------------------- |
| 151 | // Method Name: |
| 152 | // Description: |
| 153 | //------------------------------------------------------------------- |
| 154 | task gen_exp_l2_pkt8bytes( |
| 155 | bit [31:0] dma_dword_len, |
| 156 | var bit [63:0] address, |
| 157 | bit bypass_first_word, |
| 158 | bit bypass_last_word, |
| 159 | var integer ingressData, |
| 160 | bit [7:0] ingressTag |
| 161 | ){ |
| 162 | integer i, j; |
| 163 | bit [7:0] bytemask; |
| 164 | l2_packet l2_pkt = new("L2Expect", dbg); |
| 165 | bit last_packet = 0; |
| 166 | bit [2:0] bank_number; |
| 167 | reg [3:0] pbank = {probe_if.ba67, probe_if.ba45, probe_if.ba23, probe_if.ba01}; |
| 168 | integer index; |
| 169 | write_data = 0; |
| 170 | for (j = 0; j < dma_dword_len; j++) { |
| 171 | bit [31:0] tmp_data; |
| 172 | |
| 173 | |
| 174 | if (j==0 && address[2]){ |
| 175 | index = 1; |
| 176 | } else if (j == 0 ){ |
| 177 | index = 0; |
| 178 | } |
| 179 | if (index%2 == 0){ |
| 180 | bytemask = 8'hff; |
| 181 | } |
| 182 | tmp_data = f_env.nextPayloadDW( ingressData ); |
| 183 | |
| 184 | if (j == 0 && !bypass_first_word){ // modify for first words |
| 185 | if (address[2]){ |
| 186 | bytemask [3:0] = {f_firstDWBE[0],f_firstDWBE[1],f_firstDWBE[2],f_firstDWBE[3]}; |
| 187 | bytemask [7:4] = 0; |
| 188 | } else { |
| 189 | bytemask [7:4] = {f_firstDWBE[0],f_firstDWBE[1],f_firstDWBE[2],f_firstDWBE[3]}; |
| 190 | if (dma_dword_len == 1){ |
| 191 | bytemask [3:0] = 0; |
| 192 | } |
| 193 | } |
| 194 | } else if (j == dma_dword_len-1 && !bypass_last_word){ // modify for last words |
| 195 | if (address[2]){ |
| 196 | // bytemask[7:4] = 0; |
| 197 | bytemask[3:0] = {f_lastDWBE[0], f_lastDWBE[1], f_lastDWBE[2], f_lastDWBE[3]}; |
| 198 | } else { |
| 199 | bytemask[7:4] = {f_lastDWBE[0], f_lastDWBE[1], f_lastDWBE[2], f_lastDWBE[3]}; |
| 200 | bytemask [3:0] = 0; |
| 201 | } |
| 202 | } |
| 203 | |
| 204 | |
| 205 | if (index%2 == 0){ |
| 206 | write_data[63:32] = gen_4bytes_exp_data(tmp_data, bytemask[7:4]); |
| 207 | if (j == dma_dword_len-1){ |
| 208 | write_data[31:0] = gen_4bytes_exp_data(tmp_data, bytemask[3:0]); |
| 209 | } |
| 210 | } else { |
| 211 | write_data[31:0] = gen_4bytes_exp_data(tmp_data, bytemask[3:0]); |
| 212 | if (j == 0 ){ |
| 213 | write_data[63:32] = gen_4bytes_exp_data(tmp_data, bytemask[7:4]); |
| 214 | |
| 215 | } |
| 216 | } |
| 217 | |
| 218 | last_packet = ((j == dma_dword_len - 1) || (address[5:2] == 4'b1111)); |
| 219 | |
| 220 | if(index%2 == 1 || j == dma_dword_len -1 ){ |
| 221 | |
| 222 | l2_pkt.set("tag", ingressTag); |
| 223 | l2_pkt.set("address", hashpa({address[63:3], 3'h0}) ); |
| 224 | l2_pkt.set("data", write_data); |
| 225 | l2_pkt.set("bytemask", bytemask); |
| 226 | l2_pkt.set("opes", 4'b1101); |
| 227 | // printf("last_packet is %0b", last_packet); |
| 228 | l2_pkt.set("last_packet", last_packet); |
| 229 | //bank_number = address[8:6]; |
| 230 | bank_number = address[8:6]; |
| 231 | if (probe_if.pm === 1'b1) |
| 232 | bank_number = pbank_sel(pbank, bank_number); |
| 233 | |
| 234 | l2_pkt.set("bank_number", bank_number); |
| 235 | l2_pkt.display("Putting a packet on the L2 Expect Queue"); |
| 236 | case (bank_number) { |
| 237 | 0: l2_list0.push_back(l2_pkt.copy()); |
| 238 | 1: l2_list1.push_back(l2_pkt.copy()); |
| 239 | 2: l2_list2.push_back(l2_pkt.copy()); |
| 240 | 3: l2_list3.push_back(l2_pkt.copy()); |
| 241 | 4: l2_list4.push_back(l2_pkt.copy()); |
| 242 | 5: l2_list5.push_back(l2_pkt.copy()); |
| 243 | 6: l2_list6.push_back(l2_pkt.copy()); |
| 244 | 7: l2_list7.push_back(l2_pkt.copy()); |
| 245 | } |
| 246 | } |
| 247 | address = address + 4; |
| 248 | index++; |
| 249 | } |
| 250 | } |
| 251 | |
| 252 | //------------------------------------------------------------------- |
| 253 | // Method Name: |
| 254 | // Description: |
| 255 | //------------------------------------------------------------------- |
| 256 | task Execute() |
| 257 | { |
| 258 | bit [63:0] address = 64'b0; // Virtual address |
| 259 | bit [39:0] pa = 40'b0; // Physical address |
| 260 | bit [63:0] response = 64'b0; |
| 261 | bit [5:0] start_add; |
| 262 | |
| 263 | l2_packet l2_pkt; |
| 264 | |
| 265 | bit [7:0] bytemask; |
| 266 | bit [2:0] bank_number; |
| 267 | |
| 268 | bit last_packet; |
| 269 | |
| 270 | bit[PEC_PCI__HDR] ingressHdr; // The ingress TLP's header |
| 271 | integer ingressData; // A payload descriptor |
| 272 | bit[7:0] ingressTag; // The tag for the TLP |
| 273 | reg [3:0] pbank = {probe_if.ba67, probe_if.ba45, probe_if.ba23, probe_if.ba01}; |
| 274 | |
| 275 | if (N2fcAddrSpecified == 1) { |
| 276 | address = N2fcSAddr; |
| 277 | } |
| 278 | else { |
| 279 | error ("N2fcDmaWrPEUStr::Execute() : the start and end address must be specifed\n"); |
| 280 | } |
| 281 | |
| 282 | // First, get in line for a DMA tag... |
| 283 | f_env.allocDmaTag( ingressTag ); |
| 284 | |
| 285 | // Then build a TLP |
| 286 | if ( f_lenSpecified ) |
| 287 | f_env.genIngressWrReq( ingressTag, ingressHdr, ingressData, f_len ); |
| 288 | else |
| 289 | error ("N2fcDmaWrPEUStr::Execute() : the length must be specifed\n"); |
| 290 | |
| 291 | if( address[63:32] != 32'h00000000 ) { |
| 292 | ingressHdr[PEC_PCI__FMT_4DW] = 1; // 4DW hdr fmt, 64-bit address |
| 293 | ingressHdr[PEC_PCI__ADDR] = address; |
| 294 | } |
| 295 | else { |
| 296 | ingressHdr[PEC_PCI__FMT_4DW] = 0; // 3DW hdr fmt, 32-bit address |
| 297 | ingressHdr[PEC_PCI__ADDR32] = address[31:0]; |
| 298 | } |
| 299 | |
| 300 | // set the Traffic Class |
| 301 | if( f_tc != -1 ) { |
| 302 | ingressHdr[PEC_PCI__TC] = f_tc; |
| 303 | } |
| 304 | |
| 305 | printf ("%0d- UDEBUG N2fcDmaWrPEUStr:Execute Address = %0h Byp = %0h, Len = 'd%0d\n", |
| 306 | get_time(LO), address, address[63:39], f_len); |
| 307 | |
| 308 | // ...and set fields as requested |
| 309 | // by the caller. |
| 310 | |
| 311 | if ( f_bndySpecified ) |
| 312 | f_env.setAddrBndy( ingressHdr, f_bndy, 4 ); |
| 313 | |
| 314 | if ( f_firstSpecified ) |
| 315 | ingressHdr[PEC_PCI__FIRST_DWBE] = f_firstDWBE; |
| 316 | if ( f_lastSpecified ) |
| 317 | ingressHdr[PEC_PCI__LAST_DWBE] = f_lastDWBE; |
| 318 | |
| 319 | // add for MSI data |
| 320 | if (msi_dma) { |
| 321 | ingressData = start_data; |
| 322 | } |
| 323 | // add for MSI data |
| 324 | |
| 325 | |
| 326 | f_env.drivePCIE( ingressHdr, ingressData, *,*,*,*,*,1 ); |
| 327 | |
| 328 | bus_id = ingressHdr[ILUPEU_TLP_HDR_REQ_BUS_NUM_BITS]; |
| 329 | if (msi_dma) { |
| 330 | gen_msi_exp_data(address, ingressData, ingressTag, ingressHdr[PEC_PCI__REQ_ID]); |
| 331 | } |
| 332 | else if ((f_len > 1) || |
| 333 | ((f_len == 1) && ingressHdr[PEC_PCI__FIRST_DWBE])) { |
| 334 | integer index; |
| 335 | bit bypass_first_word = 0; |
| 336 | bit do_cache_line; |
| 337 | |
| 338 | l2_pkt = new("L2Expect", dbg); |
| 339 | |
| 340 | if (MMU.get_physical_address(address, pa, bus_id, 1)) { |
| 341 | address = pa; // use the physical address from here on |
| 342 | } |
| 343 | else { |
| 344 | printf("N2fcDmaWrPEUStr:Execute problem found during translation, so no L2 expects will be setup.\n"); |
| 345 | return; |
| 346 | } |
| 347 | |
| 348 | start_add = address[5:0] ; |
| 349 | |
| 350 | if ((f_len >(64-start_add+3)/4 ) && (start_add !==0)){ |
| 351 | gen_exp_l2_pkt8bytes((64-start_add+3)/4, address, 0,1, ingressData,ingressTag); |
| 352 | |
| 353 | bypass_first_word = 1; |
| 354 | f_len = f_len - (64-start_add+3)/4 ; |
| 355 | address[5:0] = 0; |
| 356 | } // align to catch line start address |
| 357 | |
| 358 | |
| 359 | if (f_len > 16 && (address[5:0] == 0)){ |
| 360 | do_cache_line =1; |
| 361 | } else if (f_len === 16 && (address[5:0] == 0)){ |
| 362 | if (&f_lastDWBE){ |
| 363 | do_cache_line = 1; |
| 364 | } else { |
| 365 | do_cache_line = 0; |
| 366 | } |
| 367 | } else { |
| 368 | do_cache_line = 0; |
| 369 | } |
| 370 | |
| 371 | while (do_cache_line){ // f_len is dword length |
| 372 | bytemask = 8'h0; |
| 373 | write_data = 0; |
| 374 | for (index=0; index <64/4; index++){ |
| 375 | write_data[511-32*index:512-32*(index+1)] = f_env.nextPayloadDW( ingressData ); |
| 376 | |
| 377 | } |
| 378 | //last_packet = (f_len == 64/4); |
| 379 | last_packet = 1; |
| 380 | |
| 381 | l2_pkt.set("tag", ingressTag); |
| 382 | l2_pkt.set("address", hashpa(address) ); |
| 383 | l2_pkt.set("data", write_data); |
| 384 | l2_pkt.set("bytemask", bytemask); |
| 385 | l2_pkt.set("opes", 4'b1101); |
| 386 | //printf("last_packet is %0b", last_packet); |
| 387 | l2_pkt.set("last_packet", last_packet); |
| 388 | bank_number = address[8:6]; |
| 389 | if (probe_if.pm === 1'b1) |
| 390 | bank_number = pbank_sel(pbank, bank_number); |
| 391 | l2_pkt.set("bank_number", bank_number); |
| 392 | l2_pkt.display("Putting catch line packet on the L2 Expect Queue"); |
| 393 | case (bank_number) { |
| 394 | 0: l2_list0.push_back(l2_pkt.copy()); |
| 395 | 1: l2_list1.push_back(l2_pkt.copy()); |
| 396 | 2: l2_list2.push_back(l2_pkt.copy()); |
| 397 | 3: l2_list3.push_back(l2_pkt.copy()); |
| 398 | 4: l2_list4.push_back(l2_pkt.copy()); |
| 399 | 5: l2_list5.push_back(l2_pkt.copy()); |
| 400 | 6: l2_list6.push_back(l2_pkt.copy()); |
| 401 | 7: l2_list7.push_back(l2_pkt.copy()); |
| 402 | } |
| 403 | address = address + 64; |
| 404 | response = response + 64; |
| 405 | f_len = f_len - 64/4; |
| 406 | if (f_len > 16 && (address[5:0] == 0)){ |
| 407 | do_cache_line =1; |
| 408 | } else if (f_len === 16 && (address[5:0] == 0)){ |
| 409 | if (&f_lastDWBE){ |
| 410 | do_cache_line = 1; |
| 411 | } else { |
| 412 | do_cache_line = 0; |
| 413 | } |
| 414 | } else { |
| 415 | do_cache_line = 0; |
| 416 | } |
| 417 | |
| 418 | |
| 419 | bypass_first_word = 1; |
| 420 | } |
| 421 | if (f_len >0) { |
| 422 | gen_exp_l2_pkt8bytes(f_len, address, bypass_first_word,0,ingressData,ingressTag); |
| 423 | } |
| 424 | } |
| 425 | |
| 426 | f_env.freeDmaTag( ingressTag ); |
| 427 | |
| 428 | } /* end Execute */ |
| 429 | |
| 430 | //------------------------------------------------------------------- |
| 431 | // Method Name: pbank_sel |
| 432 | // Description: Calculate the bank number based on the partial bank |
| 433 | // controls. |
| 434 | //------------------------------------------------------------------- |
| 435 | function reg[2:0] pbank_sel(reg[3:0] pbank, reg[2:0] bank_sel) |
| 436 | { |
| 437 | reg [2:0] result = bank_sel; |
| 438 | |
| 439 | case (pbank) { |
| 440 | 4'b0001: result[2:1] = 2'b00; |
| 441 | 4'b0010: result[2:1] = 2'b01; |
| 442 | 4'b0011: result[2] = 1'b0; |
| 443 | 4'b0100: result[2:1] = 2'b10; |
| 444 | 4'b0101: result[2:1] = {bank_sel[1], 1'b0}; |
| 445 | 4'b0110: result[2:1] = {bank_sel[1], ~bank_sel[1]}; |
| 446 | 4'b1000: result[2:1] = 2'b11; |
| 447 | 4'b1001: result[2:1] = {bank_sel[1], bank_sel[1]}; |
| 448 | 4'b1010: result[2:1] = {bank_sel[1], 1'b1}; |
| 449 | 4'b1100: result[2:1] = {1'b1, bank_sel[1]}; |
| 450 | 4'b1111: result = bank_sel; |
| 451 | default: |
| 452 | error ("ERROR! illegal partial bank selection: %0b\n", pbank); |
| 453 | } |
| 454 | |
| 455 | pbank_sel = result; |
| 456 | } |
| 457 | |
| 458 | //------------------------------------------------------------------- |
| 459 | // Method Name: gen_msi_exp_data |
| 460 | // Description: Generate the expected L2 write packet for an MSI msg. |
| 461 | //------------------------------------------------------------------- |
| 462 | task gen_msi_exp_data (bit [63:0] msiaddress, |
| 463 | bit [31:0] msidata, |
| 464 | bit [ 7:0] ingressTag, |
| 465 | bit [15:0] rid) |
| 466 | { |
| 467 | integer MSI_num = msidata[7:0]; |
| 468 | integer EQ_num; |
| 469 | bit [63:0] address; |
| 470 | bit [39:0] pa = 40'b0; // Physical address |
| 471 | bit [63:0] word0, word1; |
| 472 | bit [7:0] bytemask = 0; |
| 473 | bit [2:0] bank_number; |
| 474 | reg [3:0] pbank = {probe_if.ba67, probe_if.ba45, probe_if.ba23, probe_if.ba01}; |
| 475 | bit [6:0] tmpEQTail; |
| 476 | |
| 477 | l2_packet l2_pkt; |
| 478 | |
| 479 | // Figure out if the MSI is mapped |
| 480 | if( !PiuCsrs.MsiIsValid(MSI_num) ) return; |
| 481 | |
| 482 | // If an MSI has been sent to the EQ, but not cleared, |
| 483 | // we can't do it again |
| 484 | if( PiuCsrs.MsiIsEqWr(MSI_num) ) return; |
| 485 | EQ_num = PiuCsrs.GetMsiEqNum(MSI_num); |
| 486 | |
| 487 | //if( PiuCsrs.EQBaseAddr[63:39] != 25'b1111_1111_1111_1100_0000_0000_0) { |
| 488 | // error("ERROR: N2fcDmaWrPEUStr::gen_msi_exp_data - a non-bypass EQ BASE address is not supported!"); |
| 489 | //} |
| 490 | |
| 491 | // check if the EQ table is full |
| 492 | tmpEQTail = PiuCsrs.EQTail[EQ_num] + 1; |
| 493 | if (tmpEQTail == PiuCsrs.EQHead[EQ_num]) { |
| 494 | printf("Not writting to EQ[%d] for MSI %d because it is full\n", EQ_num, MSI_num); |
| 495 | return; |
| 496 | } |
| 497 | |
| 498 | // all seems well ... |
| 499 | address = PiuCsrs.EQBaseAddr[63:0] + (EQ_num * 8*1024) + (PiuCsrs.EQTail[EQ_num] * 64); |
| 500 | |
| 501 | MMU.set_msi(1); |
| 502 | if (MMU.get_physical_address(address, pa, bus_id, 1)) { |
| 503 | address = pa; // use the physical address from here on |
| 504 | } |
| 505 | else { |
| 506 | printf("N2fcDmaWrPEUStr:gen_msi_exp_data problem found during translation, so no L2 expects will be setup.\n"); |
| 507 | MMU.set_msi(0); |
| 508 | return; |
| 509 | } |
| 510 | MMU.set_msi(0); |
| 511 | |
| 512 | PiuCsrs.SetMsiEqWr(MSI_num); |
| 513 | PiuCsrs.EQTail[EQ_num]++; |
| 514 | |
| 515 | // set up the msi data that will be sent |
| 516 | msidata[15: 8] = msidata[7:0] + 1; |
| 517 | msidata[23:16] = msidata[7:0] + 2; |
| 518 | msidata[31:24] = msidata[7:0] + 3; |
| 519 | |
| 520 | // set up expected data (from table 16-19 of the PRM) |
| 521 | word0[63] = 0; |
| 522 | word0[62:56] = (msiaddress[63:32]==0) ? 7'b1011000 : 7'b1111000; // FMT/TYPE |
| 523 | word0[55:46] = 1; // LENGTH in DW |
| 524 | word0[45:32] = msiaddress[15:2]; // ADDR[15:2] |
| 525 | word0[31:16] = rid; word0[15: 0] = msidata[15:0]; // DATA |
| 526 | |
| 527 | word1[63:16] = msiaddress[63:16]; // ADDR[63:16] |
| 528 | word1[15: 0] = msidata[31:16]; // DATA |
| 529 | |
| 530 | write_data[511-64*0:512-64*1] = word0; |
| 531 | write_data[511-64*1:512-64*2] = word1; |
| 532 | write_data[511-64*2:512-64*3] = 0; |
| 533 | write_data[511-64*3:512-64*4] = 0; |
| 534 | write_data[511-64*4:512-64*5] = 0; |
| 535 | write_data[511-64*5:512-64*6] = 0; |
| 536 | write_data[511-64*6:512-64*7] = 0; |
| 537 | write_data[511-64*7:512-64*8] = 0; |
| 538 | |
| 539 | l2_pkt = new("L2Expect", dbg); |
| 540 | |
| 541 | l2_pkt.set("tag", ingressTag); |
| 542 | l2_pkt.set("address", hashpa(address) ); |
| 543 | l2_pkt.set("data", write_data); |
| 544 | l2_pkt.set("bytemask", bytemask); |
| 545 | l2_pkt.set("opes", 4'b1101); |
| 546 | l2_pkt.set("last_packet", 1); |
| 547 | bank_number = address[8:6]; |
| 548 | if (probe_if.pm === 1'b1) |
| 549 | bank_number = pbank_sel(pbank, bank_number); |
| 550 | l2_pkt.set("bank_number", bank_number); |
| 551 | l2_pkt.display("Putting cache line packet on the L2 Expect Queue"); |
| 552 | case (bank_number) { |
| 553 | 0: l2_list0.push_back(l2_pkt.copy()); |
| 554 | 1: l2_list1.push_back(l2_pkt.copy()); |
| 555 | 2: l2_list2.push_back(l2_pkt.copy()); |
| 556 | 3: l2_list3.push_back(l2_pkt.copy()); |
| 557 | 4: l2_list4.push_back(l2_pkt.copy()); |
| 558 | 5: l2_list5.push_back(l2_pkt.copy()); |
| 559 | 6: l2_list6.push_back(l2_pkt.copy()); |
| 560 | 7: l2_list7.push_back(l2_pkt.copy()); |
| 561 | } |
| 562 | |
| 563 | } |
| 564 | |
| 565 | } |