Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / verif / model / systemc / niu / niu_siu_interface.cpp
CommitLineData
86530b38
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: niu_siu_interface.cpp
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// ========== Copyright Header Begin ==========================================
36//
37// OpenSPARC T2 Processor File: niu_siu_interface.cpp
38// Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved
39// 4150 Network Circle, Santa Clara, California 95054, U.S.A.
40//
41// * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
42//
43// This program is free software; you can redistribute it and/or modify
44// it under the terms of the GNU General Public License as published by
45// the Free Software Foundation; version 2 of the License.
46//
47// This program is distributed in the hope that it will be useful,
48// but WITHOUT ANY WARRANTY; without even the implied warranty of
49// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
50// GNU General Public License for more details.
51//
52// You should have received a copy of the GNU General Public License
53// along with this program; if not, write to the Free Software
54// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
55//
56// For the avoidance of doubt, and except that if any non-GPL license
57// choice is available it will apply instead, Sun elects to use only
58// the General Public License version 2 (GPLv2) at this time for any
59// software where a choice of GPL license versions is made
60// available with the language indicating that GPLv2 or any later version
61// may be used, or where a choice of which version of the GPL is applied is
62// otherwise unspecified.
63//
64// Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
65// CA 95054 USA or visit www.sun.com if you need additional information or
66// have any questions.
67//
68// ========== Copyright Header End ============================================
69#include <systemc.h>
70#include "niu_debug_functions.h"
71
72#include "niu_siu_interface.h"
73#include "sharedmem.h"
74
75
76extern sharedmem *shmem;
77
78
79niu_siu_interface::niu_siu_interface(sc_module_name) {
80 SC_METHOD(sii_interface);
81 sensitive << clk.pos();
82 SC_METHOD(sio_interface);
83 sensitive << clk.pos();
84
85 sii_bypass_credit = 16;
86 sii_ordered_credit = 16;
87 sii_request_id = 0; //16-bit request ID
88
89 wr_packet_state = 0;
90 wr_busy = false;
91 rd_busy = false;
92 chunks = 0;
93 reset = 1;
94}
95
96
97void niu_siu_interface::ecc16(sc_lv<16> id, sc_lv<6> &ecc) {
98 ecc[0] = id[0] ^ id[1] ^ id[3] ^ id[4] ^ id[6] ^ id[8] ^ id[10] ^ id[11] ^ id[13] ^ id[15];
99 ecc[1] = id[0] ^ id[2] ^ id[3] ^ id[5] ^ id[6] ^ id[9] ^ id[10] ^ id[12] ^ id[13];
100 ecc[2] = id[1] ^ id[2] ^ id[3] ^ id[7] ^ id[8] ^ id[9] ^ id[10] ^ id[14] ^ id[15];
101 ecc[3] = id[4] ^ id[5] ^ id[6] ^ id[7] ^ id[8] ^ id[9] ^ id[10];
102 ecc[4] = id[11] ^ id[12] ^ id[13] ^ id[14] ^ id[15];
103 ecc[5]= id[0] ^ id[1] ^ id[2] ^ id[3] ^ ecc[0] ^ ecc[1] ^ ecc[2];
104}
105
106void niu_siu_interface::pa_parity_n(sc_lv<40> addr, sc_lv<2> &aparity) {
107 aparity[0] = ~addr[ 0] ^ addr[ 2] ^ addr[ 4] ^ addr[ 6] ^ addr[ 8] ^ addr[10] ^ addr[12] ^
108 addr[14] ^ addr[16] ^ addr[18] ^ addr[20] ^ addr[22] ^ addr[24] ^ addr[26] ^
109 addr[28] ^ addr[30] ^ addr[32] ^ addr[34] ^ addr[36] ^ addr[38];
110 aparity[1] = ~addr[ 1] ^ addr[ 3] ^ addr[ 5] ^ addr[ 7] ^ addr[ 9] ^ addr[11] ^ addr[13] ^
111 addr[15] ^ addr[17] ^ addr[19] ^ addr[21] ^ addr[23] ^ addr[25] ^ addr[27] ^
112 addr[29] ^ addr[31] ^ addr[33] ^ addr[35] ^ addr[37] ^ addr[39];
113}
114
115
116
117void niu_siu_interface::formHeader(uint64_t paddr, int write, sc_lv<128> &niu_sii_packet) {
118 sc_lv<6> command;
119 if(write) command = "010010"; else command = "001010";
120 sc_lv<37> reserved1 = 0;
121 sc_lv<2> aparity;
122 sc_lv<1> timeout = "0";
123 sc_lv<1> unmapped = "0";
124 sc_lv<1> uncorrectable = "0";
125 sc_lv<16> id;
126 id.set_cword(0, 0);
127 id.set_word(0, ++sii_request_id);
128 sc_lv<1> reserved2 = "0";
129 sc_lv<1> cparity;
130 cparity[0] = ~command[0] ^ command[1] ^ command[2] ^ command[3] ^ command[4] ^ command[5];
131 sc_lv<6> ctagecc;
132 sc_lv<16> reserved3 = 0;
133 sc_lv<40> pa;
134 pa.set_cword(0, 0);
135 pa.set_cword(1, 0);
136 pa.set_word(0, paddr & 0xffffffff);
137 pa.set_word(1, (paddr >> 32) & 0xffffffff);
138 ecc16(id, ctagecc);
139 pa_parity_n(pa, aparity);
140
141 niu_sii_packet.range(127, 122) = command;
142 niu_sii_packet.range(121, 85) = reserved1;
143 niu_sii_packet.range(84, 83) = aparity;
144 niu_sii_packet.range(82, 82) = timeout;
145 niu_sii_packet.range(81, 81) = unmapped;
146 niu_sii_packet.range(80, 80) = uncorrectable;
147 niu_sii_packet.range(79, 64) = id;
148 niu_sii_packet.range(63, 63) = reserved2;
149 niu_sii_packet.range(62, 62) = cparity;
150 niu_sii_packet.range(61, 56) = ctagecc;
151 niu_sii_packet.range(55, 40) = reserved3;
152 niu_sii_packet.range(39, 0) = pa;
153
154 cout << command << reserved1 << aparity << timeout << unmapped << uncorrectable << id << reserved2 << cparity << ctagecc << reserved3 << pa << endl;
155 //niu_sii_packet = command, reserved1, timeout,unmapped, uncorrectable, id, reserved2, cparity, ctagecc, reserved3, pa;
156 cout << niu_sii_packet << endl;
157}
158
159void niu_siu_interface::formDataPacket(unsigned char *data, sc_lv<128> &niu_sii_packet, sc_lv<8> &niu_sii_parity) {
160 int parity = 0;
161 for(int i=0;i<8;i++) {
162 int parity_bit = 1;
163 for(int j=0;j<16;j++) {
164 int bit = (i/2) * 32 + (i % 2) + j * 2;
165 parity_bit ^= (data[15 - (bit / 8)] >> (bit % 8)) & 0x1;
166 }
167 parity |= parity_bit << i;
168 }
169 niu_sii_parity.set_cword(0, 0);
170 niu_sii_parity.set_word(0, parity);
171
172 for(int i=0;i<4; i++) {
173 unsigned int word = 0;
174 for(int j=0;j<4; j++) word = (word << 8) + *data++;
175 niu_sii_packet.set_cword(3-i, 0);
176 niu_sii_packet.set_word(3-i, word);
177 }
178}
179
180
181void niu_siu_interface::sii_interface() {
182 if(reset) {
183 niu_sii_data.write(0);
184 niu_sii_parity.write(0);
185 niu_sii_datareq.write(false);
186 niu_sii_hdr_vld.write(false);
187 niu_sii_reqbypass.write(false);
188 niu_sio_dq.write(false);
189 reset = 0;
190 }
191
192 //Check queue credits
193 if(sii_niu_bqdq.read()) sii_bypass_credit++;
194 if(sii_niu_oqdq.read()) sii_ordered_credit++;
195 if((sii_bypass_credit > 16) || (sii_bypass_credit < 0)) {
196 fprintf(stderr, "niu_siu_interface::sii_interface - incorrect value for sii_bypass_credit = %d\n", sii_bypass_credit);
197 exit(1);
198 }
199 if((sii_ordered_credit > 16) || (sii_ordered_credit < 0)) {
200 fprintf(stderr, "niu_siu_interface::sii_interface - incorrect value for sii_ordered_credit = %d\n", sii_ordered_credit);
201 exit(1);
202 }
203
204//There could be simultaneous read & write requests due to sp_sii_wr_available/sp_sii_rd_available
205//If read in progress, do not let write to start, or if write is in progress, do not let read to start
206
207
208 //Process READ request here...
209 if(shmem)
210 if(wr_busy == false)
211 if(shmem->sii_receive_read_req(rd_addr, rd_size)) {
212 //printf("SII READ REQUEST: %llx %llx\n", rd_addr, rd_size);
213 rd_frag = rd_addr % 64; //handle unaligned read requests
214 rd_size_mod = rd_size + rd_frag;
215 rd_addr_itr = rd_addr;
216 rd_busy = true;
217 rd_request_chunks = 0;
218 }
219 if(rd_busy) {
220 if(rd_addr_itr < (rd_addr + rd_size_mod)) {
221 //printf("SII READ: RD_ADDR_ITR: %llx %llx %llx %llx\n", rd_addr_itr, rd_addr, rd_size_mod, rd_addr + rd_size_mod);
222 if(sii_ordered_credit > 0) {
223 sc_lv<128> niu_sii_packet;
224 formHeader(rd_addr_itr, 0, niu_sii_packet);
225 rd_request_ids[rd_request_chunks++] = sii_request_id; //keep track of the request IDs
226 niu_sii_data.write(niu_sii_packet);
227 niu_sii_hdr_vld.write(true);
228 sii_ordered_credit--;
229 rd_addr_itr = (rd_addr_itr + 64) & 0xFFFFFFFFFFFFFFC0ull ; //align to 64-byte boundary
230 } else {
231 niu_sii_hdr_vld.write(false);
232 }
233 } else {
234 rd_busy = false;
235 niu_sii_hdr_vld.write(false);
236 return;
237 }
238 }
239
240
241 //Process Write Requests here
242 if(shmem)
243 if(rd_busy == false)
244 if(shmem->sii_receive_write_req(wr_addr, wr_data, wr_size)) {
245 //Need to form the request;
246 //For each 64-byte, head + 4 x 128 bits data
247 //Figure out data parity computation
248 //If size is larger than 64 bytes, need to have multiple requests
249 //Keep track of the credit as well; no more than 16 requests
250 //Cannot get a new request while processing one; sp_siu_available...
251 wr_busy = true;
252 wr_addr_itr = wr_addr;
253 wr_packet_state = 1; //5 per 64-byte chunk
254 }
255 //Need to handle credits here...
256 if(wr_busy) {
257 //printf("NIU WRITE: State:%d ITR=%llx ADDR=%llx SIZE=%llx\n", wr_packet_state, wr_addr_itr, wr_addr, wr_size);
258 if(wr_packet_state == 1) { //header cycle
259 if(sii_ordered_credit >0) {
260 sc_lv<128> niu_sii_packet;
261 formHeader(wr_addr_itr, 1, niu_sii_packet);
262 niu_sii_data.write(niu_sii_packet);
263 niu_sii_hdr_vld.write(true);
264 niu_sii_datareq.write(true);
265 sii_ordered_credit--;
266 wr_packet_state++;
267 }
268 } else if(wr_packet_state == 6) {
269 //done with the write
270 wr_busy = false;
271 wr_packet_state = 0;
272 niu_sii_parity.write("00000000");
273 niu_sii_data.write(0);
274 shmem->sii_write_res();
275 } else { //data cycle
276 sc_lv<128> niu_sii_packet;
277 sc_lv<8> parity;
278 formDataPacket(&wr_data[wr_addr_itr - wr_addr + (wr_packet_state - 2) * 16], niu_sii_packet, parity);
279 niu_sii_data.write(niu_sii_packet);
280 niu_sii_parity.write(parity);
281 niu_sii_hdr_vld.write(false);
282 niu_sii_datareq.write(false);
283 wr_packet_state++;
284 if(wr_packet_state == 6) {
285 wr_addr_itr += 64;
286 if(wr_addr_itr < (wr_addr + wr_size)) {
287 wr_packet_state = 1; //go to the next chunk on the next cycle
288 }
289 }
290 }
291 }
292}
293
294
295void niu_siu_interface::sio_interface() {
296
297 if(chunks != 0) {
298 sio_data[4-chunks] = sio_niu_data.read();
299 if(chunks == 1) {
300 //received the complete packet; return the data back to sam niu model
301 niu_sio_dq.write(true); //dequeue
302 uint8_t data[64];
303 for(int i=0;i<4;i++) {
304 for(int j=0;j<4;j++) {
305 for(int k=0;k<4;k++) {
306 unsigned int word = sio_data[i].get_word(j);
307 data[i*16+15 - (j*4+k)] = (word >> (k*8)) & 0xff;
308 }
309 }
310 }
311 //printf("RD_PTR: %d\n", rd_ptr);
312 int rd_vl_data_size = (rd_ptr == 0) ? 64 - rd_frag : 64;
313 if(rd_ptr != 0) rd_ptr -= rd_frag;
314 for(int i=0;i<rd_vl_data_size;i++) rd_response[rd_ptr + i] = data[i];
315
316 int flag = 1;
317 //printf("READ REQUEST IDS: ");
318 for(int i=0;i<rd_request_chunks;i++) {
319 //printf("%d ", rd_request_ids[i]);
320 if(rd_request_ids[i] != -1) {
321 flag = 0;
322 break;
323 }
324 }
325 //printf("\n");
326 if(flag) {
327 niu_debug_hex_dump("SIO Data Return", rd_response, rd_size);
328 shmem->sii_read_res(rd_response, rd_size);
329 }
330 }
331 chunks--;
332 } else
333 niu_sio_dq.write(false);
334
335 //A read response is received
336 if(sio_niu_hdr_vld.read() & sio_niu_datareq.read()) {
337 //printf("SIO Header valid\n");
338 sio_header = sio_niu_data.read();
339 response_id = sio_header.range(79,64).get_word(0);
340 rd_ptr = -1;
341 for(int i=0;i<rd_request_chunks;i++) {
342 if(rd_request_ids[i] == response_id) {
343 rd_ptr = i * 64;
344 rd_request_ids[i] = -1;
345 break;
346 }
347 }
348 if(rd_ptr == -1) {
349 printf("niu_siu_interface::sio_interface - incorrect response_id = %d\n", response_id);
350 exit(1);
351 }
352 chunks = 4;
353 }
354}
355
356