// ========== Copyright Header Begin ==========================================
// OpenSPARC T2 Processor File: niu_siu_interface.cpp
// Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved
// 4150 Network Circle, Santa Clara, California 95054, U.S.A.
// * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// For the avoidance of doubt, and except that if any non-GPL license
// choice is available it will apply instead, Sun elects to use only
// the General Public License version 2 (GPLv2) at this time for any
// software where a choice of GPL license versions is made
// available with the language indicating that GPLv2 or any later version
// may be used, or where a choice of which version of the GPL is applied is
// otherwise unspecified.
// Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
// CA 95054 USA or visit www.sun.com if you need additional information or
// ========== Copyright Header End ============================================
// ========== Copyright Header Begin ==========================================
// OpenSPARC T2 Processor File: niu_siu_interface.cpp
// Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved
// 4150 Network Circle, Santa Clara, California 95054, U.S.A.
// * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// For the avoidance of doubt, and except that if any non-GPL license
// choice is available it will apply instead, Sun elects to use only
// the General Public License version 2 (GPLv2) at this time for any
// software where a choice of GPL license versions is made
// available with the language indicating that GPLv2 or any later version
// may be used, or where a choice of which version of the GPL is applied is
// otherwise unspecified.
// Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
// CA 95054 USA or visit www.sun.com if you need additional information or
// ========== Copyright Header End ============================================
#include "niu_debug_functions.h"
#include "niu_siu_interface.h"
niu_siu_interface::niu_siu_interface(sc_module_name
) {
SC_METHOD(sii_interface
);
SC_METHOD(sio_interface
);
sii_request_id
= 0; //16-bit request ID
void niu_siu_interface::ecc16(sc_lv
<16> id
, sc_lv
<6> &ecc
) {
ecc
[0] = id
[0] ^ id
[1] ^ id
[3] ^ id
[4] ^ id
[6] ^ id
[8] ^ id
[10] ^ id
[11] ^ id
[13] ^ id
[15];
ecc
[1] = id
[0] ^ id
[2] ^ id
[3] ^ id
[5] ^ id
[6] ^ id
[9] ^ id
[10] ^ id
[12] ^ id
[13];
ecc
[2] = id
[1] ^ id
[2] ^ id
[3] ^ id
[7] ^ id
[8] ^ id
[9] ^ id
[10] ^ id
[14] ^ id
[15];
ecc
[3] = id
[4] ^ id
[5] ^ id
[6] ^ id
[7] ^ id
[8] ^ id
[9] ^ id
[10];
ecc
[4] = id
[11] ^ id
[12] ^ id
[13] ^ id
[14] ^ id
[15];
ecc
[5]= id
[0] ^ id
[1] ^ id
[2] ^ id
[3] ^ ecc
[0] ^ ecc
[1] ^ ecc
[2];
void niu_siu_interface::pa_parity_n(sc_lv
<40> addr
, sc_lv
<2> &aparity
) {
aparity
[0] = ~addr
[ 0] ^ addr
[ 2] ^ addr
[ 4] ^ addr
[ 6] ^ addr
[ 8] ^ addr
[10] ^ addr
[12] ^
addr
[14] ^ addr
[16] ^ addr
[18] ^ addr
[20] ^ addr
[22] ^ addr
[24] ^ addr
[26] ^
addr
[28] ^ addr
[30] ^ addr
[32] ^ addr
[34] ^ addr
[36] ^ addr
[38];
aparity
[1] = ~addr
[ 1] ^ addr
[ 3] ^ addr
[ 5] ^ addr
[ 7] ^ addr
[ 9] ^ addr
[11] ^ addr
[13] ^
addr
[15] ^ addr
[17] ^ addr
[19] ^ addr
[21] ^ addr
[23] ^ addr
[25] ^ addr
[27] ^
addr
[29] ^ addr
[31] ^ addr
[33] ^ addr
[35] ^ addr
[37] ^ addr
[39];
void niu_siu_interface::formHeader(uint64_t paddr
, int write
, sc_lv
<128> &niu_sii_packet
) {
if(write
) command
= "010010"; else command
= "001010";
sc_lv
<1> uncorrectable
= "0";
id
.set_word(0, ++sii_request_id
);
sc_lv
<1> reserved2
= "0";
cparity
[0] = ~command
[0] ^ command
[1] ^ command
[2] ^ command
[3] ^ command
[4] ^ command
[5];
pa
.set_word(0, paddr
& 0xffffffff);
pa
.set_word(1, (paddr
>> 32) & 0xffffffff);
pa_parity_n(pa
, aparity
);
niu_sii_packet
.range(127, 122) = command
;
niu_sii_packet
.range(121, 85) = reserved1
;
niu_sii_packet
.range(84, 83) = aparity
;
niu_sii_packet
.range(82, 82) = timeout
;
niu_sii_packet
.range(81, 81) = unmapped
;
niu_sii_packet
.range(80, 80) = uncorrectable
;
niu_sii_packet
.range(79, 64) = id
;
niu_sii_packet
.range(63, 63) = reserved2
;
niu_sii_packet
.range(62, 62) = cparity
;
niu_sii_packet
.range(61, 56) = ctagecc
;
niu_sii_packet
.range(55, 40) = reserved3
;
niu_sii_packet
.range(39, 0) = pa
;
cout
<< command
<< reserved1
<< aparity
<< timeout
<< unmapped
<< uncorrectable
<< id
<< reserved2
<< cparity
<< ctagecc
<< reserved3
<< pa
<< endl
;
//niu_sii_packet = command, reserved1, timeout,unmapped, uncorrectable, id, reserved2, cparity, ctagecc, reserved3, pa;
cout
<< niu_sii_packet
<< endl
;
void niu_siu_interface::formDataPacket(unsigned char *data
, sc_lv
<128> &niu_sii_packet
, sc_lv
<8> &niu_sii_parity
) {
int bit
= (i
/2) * 32 + (i
% 2) + j
* 2;
parity_bit
^= (data
[15 - (bit
/ 8)] >> (bit
% 8)) & 0x1;
parity
|= parity_bit
<< i
;
niu_sii_parity
.set_cword(0, 0);
niu_sii_parity
.set_word(0, parity
);
for(int j
=0;j
<4; j
++) word
= (word
<< 8) + *data
++;
niu_sii_packet
.set_cword(3-i
, 0);
niu_sii_packet
.set_word(3-i
, word
);
void niu_siu_interface::sii_interface() {
niu_sii_datareq
.write(false);
niu_sii_hdr_vld
.write(false);
niu_sii_reqbypass
.write(false);
if(sii_niu_bqdq
.read()) sii_bypass_credit
++;
if(sii_niu_oqdq
.read()) sii_ordered_credit
++;
if((sii_bypass_credit
> 16) || (sii_bypass_credit
< 0)) {
fprintf(stderr
, "niu_siu_interface::sii_interface - incorrect value for sii_bypass_credit = %d\n", sii_bypass_credit
);
if((sii_ordered_credit
> 16) || (sii_ordered_credit
< 0)) {
fprintf(stderr
, "niu_siu_interface::sii_interface - incorrect value for sii_ordered_credit = %d\n", sii_ordered_credit
);
//There could be simultaneous read & write requests due to sp_sii_wr_available/sp_sii_rd_available
//If read in progress, do not let write to start, or if write is in progress, do not let read to start
//Process READ request here...
if(shmem
->sii_receive_read_req(rd_addr
, rd_size
)) {
//printf("SII READ REQUEST: %llx %llx\n", rd_addr, rd_size);
rd_frag
= rd_addr
% 64; //handle unaligned read requests
rd_size_mod
= rd_size
+ rd_frag
;
if(rd_addr_itr
< (rd_addr
+ rd_size_mod
)) {
//printf("SII READ: RD_ADDR_ITR: %llx %llx %llx %llx\n", rd_addr_itr, rd_addr, rd_size_mod, rd_addr + rd_size_mod);
if(sii_ordered_credit
> 0) {
sc_lv
<128> niu_sii_packet
;
formHeader(rd_addr_itr
, 0, niu_sii_packet
);
rd_request_ids
[rd_request_chunks
++] = sii_request_id
; //keep track of the request IDs
niu_sii_data
.write(niu_sii_packet
);
niu_sii_hdr_vld
.write(true);
rd_addr_itr
= (rd_addr_itr
+ 64) & 0xFFFFFFFFFFFFFFC0ull
; //align to 64-byte boundary
niu_sii_hdr_vld
.write(false);
niu_sii_hdr_vld
.write(false);
//Process Write Requests here
if(shmem
->sii_receive_write_req(wr_addr
, wr_data
, wr_size
)) {
//Need to form the request;
//For each 64-byte, head + 4 x 128 bits data
//Figure out data parity computation
//If size is larger than 64 bytes, need to have multiple requests
//Keep track of the credit as well; no more than 16 requests
//Cannot get a new request while processing one; sp_siu_available...
wr_packet_state
= 1; //5 per 64-byte chunk
//Need to handle credits here...
//printf("NIU WRITE: State:%d ITR=%llx ADDR=%llx SIZE=%llx\n", wr_packet_state, wr_addr_itr, wr_addr, wr_size);
if(wr_packet_state
== 1) { //header cycle
if(sii_ordered_credit
>0) {
sc_lv
<128> niu_sii_packet
;
formHeader(wr_addr_itr
, 1, niu_sii_packet
);
niu_sii_data
.write(niu_sii_packet
);
niu_sii_hdr_vld
.write(true);
niu_sii_datareq
.write(true);
} else if(wr_packet_state
== 6) {
niu_sii_parity
.write("00000000");
sc_lv
<128> niu_sii_packet
;
formDataPacket(&wr_data
[wr_addr_itr
- wr_addr
+ (wr_packet_state
- 2) * 16], niu_sii_packet
, parity
);
niu_sii_data
.write(niu_sii_packet
);
niu_sii_parity
.write(parity
);
niu_sii_hdr_vld
.write(false);
niu_sii_datareq
.write(false);
if(wr_packet_state
== 6) {
if(wr_addr_itr
< (wr_addr
+ wr_size
)) {
wr_packet_state
= 1; //go to the next chunk on the next cycle
void niu_siu_interface::sio_interface() {
sio_data
[4-chunks
] = sio_niu_data
.read();
//received the complete packet; return the data back to sam niu model
niu_sio_dq
.write(true); //dequeue
unsigned int word
= sio_data
[i
].get_word(j
);
data
[i
*16+15 - (j
*4+k
)] = (word
>> (k
*8)) & 0xff;
//printf("RD_PTR: %d\n", rd_ptr);
int rd_vl_data_size
= (rd_ptr
== 0) ? 64 - rd_frag
: 64;
if(rd_ptr
!= 0) rd_ptr
-= rd_frag
;
for(int i
=0;i
<rd_vl_data_size
;i
++) rd_response
[rd_ptr
+ i
] = data
[i
];
//printf("READ REQUEST IDS: ");
for(int i
=0;i
<rd_request_chunks
;i
++) {
//printf("%d ", rd_request_ids[i]);
if(rd_request_ids
[i
] != -1) {
niu_debug_hex_dump("SIO Data Return", rd_response
, rd_size
);
shmem
->sii_read_res(rd_response
, rd_size
);
//A read response is received
if(sio_niu_hdr_vld
.read() & sio_niu_datareq
.read()) {
//printf("SIO Header valid\n");
sio_header
= sio_niu_data
.read();
response_id
= sio_header
.range(79,64).get_word(0);
for(int i
=0;i
<rd_request_chunks
;i
++) {
if(rd_request_ids
[i
] == response_id
) {
printf("niu_siu_interface::sio_interface - incorrect response_id = %d\n", response_id
);