| 1 | // ========== Copyright Header Begin ========================================== |
| 2 | // |
| 3 | // OpenSPARC T2 Processor File: fc_ncu_csr_probe.v |
| 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 "fc.vh" |
| 36 | `include "defines.vh" |
| 37 | `include "ccx.vri" |
| 38 | `include "cmp.vri" |
| 39 | |
| 40 | |
| 41 | |
| 42 | `define NIU_UCB `CPU.rdp.niu_pio_ucb |
| 43 | `define NIU_PIO `CPU.rdp.niu_pio |
| 44 | |
| 45 | `timescale 1 ps/ 1 ps |
| 46 | |
| 47 | module fc_ncu_csr_probe; |
| 48 | //array to store snooped address |
| 49 | reg [48:0] snoop_address [0:63]; |
| 50 | |
| 51 | //------------------------------ |
| 52 | // PCX packet |
| 53 | |
| 54 | wire ncu_pcx_valid; |
| 55 | wire [39:0] ncu_pcx_pa; |
| 56 | wire [2:0] ncu_pcx_cid; |
| 57 | wire [2:0] ncu_pcx_tid; |
| 58 | wire [5:0] ncu_pcx_tnum; |
| 59 | wire [4:0] ncu_pcx_typ; |
| 60 | wire [7:0] ncu_pcx_size; |
| 61 | wire ncu_clk; |
| 62 | |
| 63 | integer ncu_csr; |
| 64 | |
| 65 | assign ncu_pcx_typ = `CPU.ncu.ncu_fcd_ctl.ncu_c2ifcd_ctl.ncu_c2ifd_ctl.pcx_ncu_data[`PCX_RQTYP]; |
| 66 | assign ncu_pcx_pa = `CPU.ncu.ncu_fcd_ctl.ncu_c2ifcd_ctl.ncu_c2ifd_ctl.pcx_ncu_data[`PCX_ADDR]; |
| 67 | assign ncu_pcx_size = `CPU.ncu.ncu_fcd_ctl.ncu_c2ifcd_ctl.ncu_c2ifd_ctl.pcx_ncu_data[`PCX_SIZE]; |
| 68 | assign ncu_pcx_cid = `CPU.ncu.ncu_fcd_ctl.ncu_c2ifcd_ctl.ncu_c2ifd_ctl.pcx_ncu_data[`PCX_CID]; |
| 69 | assign ncu_pcx_tid = `CPU.ncu.ncu_fcd_ctl.ncu_c2ifcd_ctl.ncu_c2ifd_ctl.pcx_ncu_data[`PCX_TID]; |
| 70 | assign ncu_pcx_tnum = {ncu_pcx_cid,ncu_pcx_tid}; |
| 71 | assign ncu_pcx_valid = `CPU.ncu.ncu_fcd_ctl.ncu_c2ifcd_ctl.ncu_c2ifd_ctl.pcx_ncu_vld && |
| 72 | `CPU.ncu.ncu_fcd_ctl.ncu_c2ifcd_ctl.ncu_c2ifc_ctl.pcx_ncu_data_rdy; |
| 73 | assign #1 ncu_clk = `CPU.ncu.gclk; |
| 74 | |
| 75 | //When a valid packet to NCU space is snooped it gets recorded into the array |
| 76 | |
| 77 | always @(negedge ncu_clk) begin // { |
| 78 | if( ncu_pcx_valid && (ncu_pcx_typ == 5'b00000)) begin // { |
| 79 | // a PIO read to NCU status registers gets recorded in the array |
| 80 | if ((ncu_pcx_pa[39:32] == 8'h80) || (ncu_pcx_pa[39:32] == 8'h90)) begin // { |
| 81 | snoop_address[ncu_pcx_tnum[5:0]] <= {1'b1,ncu_pcx_pa[39:0]}; |
| 82 | end // } |
| 83 | // a PIO read to RST status registers gets recorded in the array |
| 84 | else if ((ncu_pcx_pa[39:0] == 40'h89_00000808)||(ncu_pcx_pa[39:0] == 40'h89_00000810)|| |
| 85 | (ncu_pcx_pa[39:0] == 40'h89_00000818)||(ncu_pcx_pa[39:0] == 40'h89_00000838)) |
| 86 | begin // { |
| 87 | snoop_address[ncu_pcx_tnum[5:0]] <= {1'b1,ncu_pcx_pa[39:0]}; |
| 88 | end // } |
| 89 | `ifdef FC_NO_PEUSAT_CODE |
| 90 | // a PIO read to PEP registers gets recorded in the array |
| 91 | else if (ncu_pcx_pa[39:36] == 4'hC) begin // { <= checks for PCIE PIO address |
| 92 | snoop_address[ncu_pcx_tnum[5:0]] <= {ncu_pcx_size,1'b1,ncu_pcx_pa[39:0]}; |
| 93 | end // } |
| 94 | `endif |
| 95 | end // } |
| 96 | end // } |
| 97 | |
| 98 | //When their is a read from the iobuf then read the contents of snooped address and |
| 99 | //print it out |
| 100 | wire iobuf_cpx_valid; |
| 101 | wire [40:0] iobuf_cpx_pa; |
| 102 | wire [2:0] iobuf_cpx_cid; |
| 103 | wire [2:0] iobuf_cpx_tid; |
| 104 | wire [5:0] iobuf_cpx_tnum; |
| 105 | wire [63:0] iobuf_cpx_data; |
| 106 | wire [63:0] iobuf_cpx_data_le; |
| 107 | wire [3:0] iobuf_cpx_typ; |
| 108 | wire [7:0] iobuf_cpx_size; |
| 109 | wire iobuf_rd_en; |
| 110 | wire [7:0] iobuf_asi; |
| 111 | reg [7:0] iobuf_pio_size; |
| 112 | |
| 113 | assign iobuf_asi_rd = (iobuf_cpx_pa[39:32] == 8'h90); // JTAG block |
| 114 | |
| 115 | assign iobuf_asi_41 = (iobuf_cpx_pa[25:18] == 8'h41); |
| 116 | assign iobuf_asi_45 = (iobuf_cpx_pa[25:18] == 8'h45); |
| 117 | //assign iobuf_asi_73 = (iobuf_cpx_pa[25:18] == 8'h73); |
| 118 | |
| 119 | assign iobuf_core_available = (iobuf_asi_rd & iobuf_asi_41 & (iobuf_cpx_pa[17:0] == 18'h0000)); |
| 120 | assign iobuf_core_enable_status = (iobuf_asi_rd & iobuf_asi_41 & (iobuf_cpx_pa[17:0] == 18'h0010)); |
| 121 | assign iobuf_core_enable = (iobuf_asi_rd & iobuf_asi_41 & (iobuf_cpx_pa[17:0] == 18'h0020)); |
| 122 | assign iobuf_core_xir_steering = (iobuf_asi_rd & iobuf_asi_41 & (iobuf_cpx_pa[17:0] == 18'h0030)); |
| 123 | assign iobuf_core_tick_enable = (iobuf_asi_rd & iobuf_asi_41 & (iobuf_cpx_pa[17:0] == 18'h0038)); |
| 124 | assign iobuf_core_run_rw = (iobuf_asi_rd & iobuf_asi_41 & (iobuf_cpx_pa[17:0] == 18'h0050)); |
| 125 | assign iobuf_core_run_status = (iobuf_asi_rd & iobuf_asi_41 & (iobuf_cpx_pa[17:0] == 18'h0058)); |
| 126 | |
| 127 | assign iobuf_rst_vec_mask = (iobuf_asi_rd & iobuf_asi_45 & (iobuf_cpx_pa[17:0] == 18'h0018)); |
| 128 | |
| 129 | assign iobuf_do_asi_read = iobuf_core_run_status | |
| 130 | iobuf_core_run_rw | |
| 131 | iobuf_rst_vec_mask ; |
| 132 | |
| 133 | assign iobuf_do_not_follow = iobuf_core_available | // rw registers riesling can handle |
| 134 | iobuf_core_enable_status | |
| 135 | iobuf_core_enable | |
| 136 | iobuf_core_xir_steering | |
| 137 | iobuf_core_tick_enable ; |
| 138 | |
| 139 | assign iobuf_asi = iobuf_cpx_pa[25:18]; |
| 140 | |
| 141 | assign iobuf_cpx_cid = convert_onehot(`CPU.ncu.ncu_fcd_ctl.ncu_i2cfcd_ctl.ncu_i2cfd_ctl.iobuf_dout_muxed[153:146]); |
| 142 | assign iobuf_cpx_tid = `CPU.ncu.ncu_fcd_ctl.ncu_i2cfcd_ctl.ncu_i2cfd_ctl.iobuf_dout_muxed[`CPX_TID]; |
| 143 | assign iobuf_cpx_valid = `CPU.ncu.ncu_fcd_ctl.ncu_i2cfcd_ctl.ncu_i2cfd_ctl.iobuf_dout_muxed[`CPX_VALID]; |
| 144 | assign iobuf_cpx_tnum = {iobuf_cpx_cid, iobuf_cpx_tid}; |
| 145 | assign iobuf_cpx_typ = `CPU.ncu.ncu_fcd_ctl.ncu_i2cfcd_ctl.ncu_i2cfd_ctl.iobuf_dout_muxed[`CPX_RTNTYP]; |
| 146 | assign iobuf_cpx_data = `CPU.ncu.ncu_fcd_ctl.ncu_i2cfcd_ctl.ncu_i2cfd_ctl.iobuf_dout_muxed[63:0]; |
| 147 | assign iobuf_cpx_pa = snoop_address[iobuf_cpx_tnum]; |
| 148 | assign iobuf_cpx_size = snoop_address[iobuf_cpx_tnum] >> 41; |
| 149 | assign iobuf_rd_en = `CPU.ncu.ncu_fcd_ctl.ncu_i2cfcd_ctl.ncu_i2cfd_ctl.iobuf_rd; |
| 150 | |
| 151 | // accesses to PEP PIO regs are little endian, and 4 byte len, so reverse the data |
| 152 | assign iobuf_cpx_data_le = {iobuf_cpx_data[7:0],iobuf_cpx_data[15:8],iobuf_cpx_data[23:16],iobuf_cpx_data[31:24], |
| 153 | iobuf_cpx_data[39:32],iobuf_cpx_data[47:40],iobuf_cpx_data[55:48],iobuf_cpx_data[63:56] |
| 154 | }; |
| 155 | |
| 156 | always @(negedge ncu_clk) begin // { |
| 157 | if( iobuf_rd_en && iobuf_cpx_valid && (iobuf_cpx_typ == 4'b1000) && (iobuf_cpx_pa[40] == 1'b1)) begin // { |
| 158 | `ifdef FC_NO_PEUSAT_CODE |
| 159 | if (iobuf_cpx_pa[39:36] == 4'hC) begin // { <= check for PCIE PIO address |
| 160 | if (`PARGS.nas_check_on ) begin // { |
| 161 | iobuf_pio_size = (iobuf_cpx_size == 8'h00) ? 8'h01 : |
| 162 | (iobuf_cpx_size == 8'h01) ? 8'h02 : |
| 163 | (iobuf_cpx_size == 8'h02) ? 8'h04 : |
| 164 | (iobuf_cpx_size == 8'h03) ? 8'h08 : 8'h10; |
| 165 | |
| 166 | // send big endian data to Riesling, but account for some little |
| 167 | // endian ordering in the data coming back. |
| 168 | // review: this currently only handles 4 byte loads, so you need to |
| 169 | // add handling of 1 and 2 byte loads. |
| 170 | if ((iobuf_pio_size==4) && (iobuf_cpx_pa[2])) begin // { |
| 171 | `PR_NORMAL ("ncu_csr_probe", `NORMAL, |
| 172 | " PLI_PIO_READ pa=%h data=%0h sz=%0h ts=%0d (PEP PIO RD RTN)", |
| 173 | iobuf_cpx_pa[39:0], iobuf_cpx_data, iobuf_pio_size, `TOP.core_cycle_cnt-1); |
| 174 | ncu_csr = $sim_send(`PLI_PIO_READ, {24'b0,iobuf_cpx_pa[39:0]}, iobuf_cpx_data, 8'h0, iobuf_pio_size); |
| 175 | end // } |
| 176 | else begin // { |
| 177 | `PR_NORMAL ("ncu_csr_probe", `NORMAL, |
| 178 | " PLI_PIO_READ pa=%h data=%0h sz=%0h ts=%0d (PEP PIO RD RTN)", |
| 179 | iobuf_cpx_pa[39:0], iobuf_cpx_data, iobuf_pio_size, `TOP.core_cycle_cnt-1); |
| 180 | ncu_csr = $sim_send(`PLI_PIO_READ, {24'b0,iobuf_cpx_pa[39:0]}, {32'b0,iobuf_cpx_data[63:32]}, 8'h0, iobuf_pio_size); |
| 181 | end // } |
| 182 | |
| 183 | end // } |
| 184 | end // } |
| 185 | else |
| 186 | `endif |
| 187 | begin // { |
| 188 | if (`PARGS.nas_check_on ) begin // { |
| 189 | if(iobuf_do_not_follow) begin // { |
| 190 | end // } |
| 191 | else if(iobuf_do_asi_read) begin // { |
| 192 | `PR_NORMAL ("ncu_csr_probe", `NORMAL, |
| 193 | " PLI_ASI_READ asi=%h va=%h tid=%02h data=%0h", |
| 194 | iobuf_asi, iobuf_cpx_pa[17:0], iobuf_cpx_data, iobuf_cpx_tnum); |
| 195 | ncu_csr = $sim_send(`PLI_ASI_READ, iobuf_cpx_tnum, iobuf_asi, {46'b0,iobuf_cpx_pa[17:0]}, iobuf_cpx_data); |
| 196 | end // } |
| 197 | else begin // { |
| 198 | `PR_NORMAL ("ncu_csr_probe", `NORMAL, |
| 199 | " PLI_CSR_READ pa=%h data=%0h tid=%02h ts=%0d", |
| 200 | iobuf_cpx_pa[39:0], iobuf_cpx_data, iobuf_cpx_tnum, `TOP.core_cycle_cnt-1); |
| 201 | ncu_csr = $sim_send(`PLI_CSR_READ, {24'b0,iobuf_cpx_pa[39:0]}, iobuf_cpx_data, 8'h0); |
| 202 | end // } |
| 203 | end // } |
| 204 | end // } |
| 205 | @(posedge ncu_clk) |
| 206 | snoop_address[iobuf_cpx_tnum[5:0]] <= 64'b0; |
| 207 | end // } |
| 208 | end // } |
| 209 | |
| 210 | //When their is a read from the iobuf then read the contents of snooped address and |
| 211 | //print it out |
| 212 | wire intbuf_cpx_valid; |
| 213 | wire [40:0] intbuf_cpx_pa; |
| 214 | wire [2:0] intbuf_cpx_cid; |
| 215 | wire [2:0] intbuf_cpx_tid; |
| 216 | wire [5:0] intbuf_cpx_tnum; |
| 217 | wire [63:0] intbuf_cpx_data; |
| 218 | wire [3:0] intbuf_cpx_typ; |
| 219 | wire intbuf_rd_en; |
| 220 | |
| 221 | assign intbuf_cpx_cid = convert_onehot(`CPU.ncu.ncu_fcd_ctl.ncu_i2cfcd_ctl.ncu_i2cfd_ctl.intbuf_dout_muxed[153:146]); |
| 222 | assign intbuf_cpx_tid = `CPU.ncu.ncu_fcd_ctl.ncu_i2cfcd_ctl.ncu_i2cfd_ctl.intbuf_dout_muxed[`CPX_TID]; |
| 223 | assign intbuf_cpx_valid = `CPU.ncu.ncu_fcd_ctl.ncu_i2cfcd_ctl.ncu_i2cfd_ctl.intbuf_dout_muxed[`CPX_VALID]; |
| 224 | assign intbuf_cpx_tnum = {intbuf_cpx_cid, intbuf_cpx_tid}; |
| 225 | assign intbuf_cpx_typ = `CPU.ncu.ncu_fcd_ctl.ncu_i2cfcd_ctl.ncu_i2cfd_ctl.intbuf_dout_muxed[`CPX_RTNTYP]; |
| 226 | assign intbuf_cpx_data = `CPU.ncu.ncu_fcd_ctl.ncu_i2cfcd_ctl.ncu_i2cfd_ctl.intbuf_dout_muxed[63:0]; |
| 227 | assign intbuf_cpx_pa = snoop_address[intbuf_cpx_tnum]; |
| 228 | assign intbuf_rd_en = `CPU.ncu.ncu_fcd_ctl.ncu_i2cfcd_ctl.ncu_i2cfd_ctl.intbuf_rd; |
| 229 | |
| 230 | always @(negedge ncu_clk) begin |
| 231 | if( intbuf_rd_en && intbuf_cpx_valid && (intbuf_cpx_typ == 4'b1000) && (intbuf_cpx_pa[40] == 1'b1)) begin |
| 232 | `PR_INFO ("ncu_csr_probe", `INFO, "ts=%0d NIU CSR READ RETURN: address %x data %x ", |
| 233 | `TOP.core_cycle_cnt-1, intbuf_cpx_pa, intbuf_cpx_data[63:0] ); |
| 234 | if (`PARGS.nas_check_on ) begin |
| 235 | ncu_csr = $sim_send(`PLI_CSR_READ, {24'b0,intbuf_cpx_pa[39:0]}, intbuf_cpx_data, 8'h0); |
| 236 | end |
| 237 | @(posedge ncu_clk) |
| 238 | snoop_address[intbuf_cpx_tnum[5:0]] <= 64'b0; |
| 239 | end |
| 240 | end |
| 241 | |
| 242 | //---------------------------------------------------------- |
| 243 | function [2:0] convert_onehot; |
| 244 | input [7:0] one_hot; |
| 245 | |
| 246 | begin |
| 247 | case (one_hot) |
| 248 | 8'h1: convert_onehot = 3'b000; |
| 249 | 8'h2: convert_onehot = 3'b001; |
| 250 | 8'h4: convert_onehot = 3'b010; |
| 251 | 8'h8: convert_onehot = 3'b011; |
| 252 | 8'h10: convert_onehot = 3'b100; |
| 253 | 8'h20: convert_onehot = 3'b101; |
| 254 | 8'h40: convert_onehot = 3'b110; |
| 255 | 8'h80: convert_onehot = 3'b111; |
| 256 | endcase |
| 257 | end |
| 258 | endfunction |
| 259 | //---------------------------------------------------------- |
| 260 | |
| 261 | endmodule // fc_niu_csr_probe |