// ========== Copyright Header Begin ==========================================
// OpenSPARC T2 Processor File: niu_mem.vr
// 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 <vera_defines.vrh>
#include <ListMacros.vrh>
#include "ios_l2_stub.vrh"
#include "top_defines.vrh"
#include "niu_mem_tasks.vri"
#define NEPT_EEPROM_BASE_START 64'hF5000000
#define NEPT_EEPROM_BASE_END 64'hF8FFFFFF
extern hdl_task write_sys_mem (
extern hdl_task read_sys_mem (
extern bit [63:0] FCMemoryAddress_A[4];
extern bit [63:0] FCMemoryAddress_B[4];
extern bit [63:0] FCMemoryAddress_C[4];
extern event FCMemorySync_A[4];
extern event FCMemorySync_B[4];
extern event FCMemorySync_C[4];
#define TIME {get_time(HI), get_time(LO)}
extern ios_l2_stub l2_stub[];
extern StandardDisplay dbg;
extern bit [63:0] IOSMemoryAddress[8];
extern event IOSMemorySync[8];
#include "niu_cb_events.vri"
#include "niu_cbclass.vrh"
#include "niu_memcbmgr.vrh"
extern "C" task SetExtMemBlockSize( integer block_size, integer mode_32b);
extern "C" function bit[39:0] MallocBlock(integer no_of_blocks, integer page_id, integer alignment);
extern "C" function bit[19:0] GetPageHandle();
extern "C" function integer SetPageMask(integer no_of_4Kpages, integer type , integer id);
extern "C" function bit [31:0] GetPageMask(integer id);
extern "C" function bit [31:0] GetPageValue(integer id);
extern "C" function bit [31:0] GetPageReloc(integer id);
extern "C" task SetConfig( integer config, integer seed);
extern "C" task MarkUsedLocations( bit[31:0] address_h, bit[31:0] address_l, integer no_of_blocks );
extern "C" function bit[39:0] XlateAddr( bit[31:0] address_h, bit[31:0] address_l, integer page_id);
extern "C" function integer FreeAddr (bit[31:0] addrh, bit[31:0] addrl, integer no_of_blocks, integer page_id);
extern "C" function integer ForcePageContexts(integer page_id, bit[31:0] mask , bit[31:0] value, bit[31:0] reloc );
extern "C" function integer DeletePageContext (integer id);
extern "C" function integer CheckPageId( bit[31:0] address_h, bit[31:0] address_l);
task new( bit [63:0] t = 0) {
MakeVeraList (AddressTrace);
local VeraList_AddressTrace WriteTrace;
local bit [63:0] last_query_address_time;
last_query_address_time = 0;
task add( AddressTrace Trace) {
WriteTrace.push_back(Trace);
printf(" Adding Time - %d Address - %x \n",Trace.time, Trace.address);
function integer get_currsize() {
get_currsize = WriteTrace.size();
function bit [63:0] query_time () {
query_time = last_query_address_time;
function integer query(bit [63:0] address, (bit flush = 0) ) {
VeraListIterator_AddressTrace item,next_item;
if(WriteTrace.empty()) query = 0;
printf( " Current Size - %d \n",WriteTrace.size());
item = WriteTrace.start();
while( !match & item.neq(WriteTrace.finish())) {
if(Entry.address == address ) {
last_query_address_time = Entry.time;
next_item = WriteTrace.erase(item);
last_query_address_time = 0;
task flushEntry( bit [63:0] address ) {
if(WriteTrace.empty() ) {
printf(" TB ERROR Cannot delete address - %x \n",address);
if(query(address,flush)) {
printf(" DEBUG - Done with flushing address - %x \n",address);
printf(" TB ERROR Cannot delete address - %x \n",address);
// Class to manage pages per DMA channel
// Function to generate unique page handle for all the DMAs ( 32 Tx, 32 Rx )
// Function to generate page-relocation value based upon the no. of bytes required
function bit [19:0] get_page_handle() {
printf(" Inside PM - get_page_handle \n");
get_page_handle = GetPageHandle();
function bit[31:0] get_page_mask(integer no_of_4Kpages, integer type , integer id, var bit[31:0] mask, var bit[31:0] value, var bit [31:0] reloc ) {
get_page_mask = SetPageMask(no_of_4Kpages, type , id);
value = GetPageValue(id);
reloc = GetPageReloc(id);
printf(" ERROR--- incorrect id %d specified for setting pagemasks \n",id);
function integer force_page_contexts(integer page_id, bit[31:0] mask , bit[31:0] value, bit[31:0] reloc ) {
status =ForcePageContexts(page_id, mask , value, reloc );
function integer delete_page_contexts(integer page_id) {
delete_page_contexts = DeletePageContext(page_id);
local MemWriteTrace WriteAddressTrace;
local integer block_size;
local integer force_align;
local integer sem_id_get_addr = -1;
local integer sem_id_free_addr = -1;
local integer sem_id_xlate_addr = -1;
local bit [63:0] trace_address;
local event set_trace_collection;
local event trace_collect_done;
local integer no_of_8bytes_written;
task IOSmarkMemoryLocation(bit [63:0] address, ( integer enable_tracking = 0 ));
task IOSMemory(integer bank);
task FCmarkMemoryLocation_A(bit [63:0] address, ( integer enable_tracking = 0 ));
task FCmarkMemoryLocation_B(bit [63:0] address, ( integer enable_tracking = 0 ));
task FCmarkMemoryLocation_C(bit [63:0] address, ( integer enable_tracking = 0 ));
task FCMemory_A(integer mcu_port_no);
task FCMemory_B(integer mcu_port_no);
task FCMemory_C(integer mcu_port_no);
task WriteVMem( bit [63:0] address, bit [63:0] data, bit [7:0] be, (integer xlate = 0), (integer page_id = 0) , (integer corrupt_xlate = 0), ( integer enable_tracking = 0 ) );
task WriteMem( bit [63:0] address, bit [63:0] data, bit [7:0] be, ( integer enable_tracking = 0 ));
task ReadMem( bit[63:0] address, var bit [63:0] data, bit[7:0] be);
task setused_address( bit[63:0] address, integer no_of_blocks);
function bit [39:0] get_address(integer no_of_blocks, (integer page_id = 0), (integer alignment = 1));
function bit [39:0] xlate_addr(bit[39:0] addr, integer page_id, (integer corrupt_xlation = 0) ) ;
function integer free_addr (bit[39:0] addr, integer no_of_blocks,(integer page_id = 0) );
task set_block_size(integer block_size, (integer mode_32b = 0));
function integer get_block_size() {
get_block_size = block_size;
function integer getNoOf8BytesWritten() {
getNoOf8BytesWritten = no_of_8bytes_written;
function bit[63:0] query_time() {
query_time = WriteAddressTrace.query_time();
function integer query(bit [63:0] address) {
query = WriteAddressTrace.query(address);
task flushEntry( bit [63:0] address ) {
WriteAddressTrace.flushEntry(address);
function bit [19:0] get_page_handle() {
get_page_handle = PM.get_page_handle();
function bit[31:0] get_page_mask(integer no_of_4Kpages, (integer type = 0), ( integer id = 0),var bit[31:0] mask, var bit[31:0] value, var bit [31:0] reloc ) {
get_page_mask = PM.get_page_mask(no_of_4Kpages, type , id, mask, value, reloc ) ;
function integer force_page_contexts(integer page_id, bit[31:0] mask , bit[31:0] value, bit[31:0] reloc ) {
status = PM.force_page_contexts(page_id, mask , value, reloc );
function integer delete_page_contexts ( integer page_id) {
delete_page_contexts = PM.delete_page_contexts(page_id);
function integer check_page_id(bit[63:0] address) {
check_page_id = CheckPageId({24'h0,address[39:32]}, address[31:0]);
local task CollectMemWriteTrace();
task setCallBack ( CcbMem cb) {
task new((integer seed = 0) ) {
integer malloc_block_size;
integer no_of_blocks_for_eeprom;
no_of_8bytes_written = 0;
trigger(OFF, set_trace_collection);
sem_id_get_addr = alloc(SEMAPHORE, 0, 1, 1);
sem_id_free_addr = alloc(SEMAPHORE, 0, 1, 1);
sem_id_xlate_addr = alloc(SEMAPHORE, 0, 1, 1);
WriteAddressTrace = new();
CbMgr = new("NIU_GENERIC_MEMORY");
if (get_plus_arg (CHECK, "malloc_block_size"))
malloc_block_size = get_plus_arg (NUM, "malloc_block_size");
malloc_block_size = 4096;
if (get_plus_arg (CHECK, "NEPT_32bDMA_ADDR")) {
/*ignore the +arg if not neptune*/
set_block_size(malloc_block_size,0);
set_block_size(malloc_block_size);
if (get_plus_arg (CHECK, "malloc_verbose")) {
if (get_plus_arg (CHECK,"FORCE_ADDR_ALIGNMENT")) {
force_align = get_plus_arg (NUM, "FORCE_ADDR_ALIGNMENT");
printf("WARNING: SparseMem::new - get_address byte alignment forced to %d \n",force_align);
task CSparseMem::setused_address(bit [63:0] address, integer no_of_blocks ) {
MarkUsedLocations( {24'h0,address[39:32]}, address[31:0], no_of_blocks );
task CSparseMem::IOSMemory(integer bank) {
sync(ALL,IOSMemorySync[bank]);
trigger(OFF,IOSMemorySync[bank]);
printf ("%0d NIU_MEM: IOS mark memory location %x\n", get_time(LO), IOSMemoryAddress[bank]);
IOSmarkMemoryLocation(IOSMemoryAddress[bank],1);
trigger(IOSMemorySync[bank]);
task CSparseMem::IOSmarkMemoryLocation(bit [63:0] address, ( integer enable_tracking = 0 )) {
// Fu: 4/27 take out the write sync for now, NIU does all back door write before
// sync(ALL, write_sync);
// trigger(OFF, write_sync);
// if enable_tracking is set, the address for which the data has been written is stored into a class
// and sent out as a mailbox
cb_status = CbMgr.checkCallBack(address);
no_of_8bytes_written = no_of_8bytes_written +1;
// trigger(ON,write_sync);
task CSparseMem::FCMemory_A(integer mcu_port_no) {
sync(ALL,FCMemorySync_A[mcu_port_no]);
trigger(OFF,FCMemorySync_A[mcu_port_no]);
printf ("%0d NIU_MEM: FC mark memory location %x\n", get_time(LO), FCMemoryAddress_A[mcu_port_no]);
FCmarkMemoryLocation_A(FCMemoryAddress_A[mcu_port_no],1);
trigger(FCMemorySync_A[mcu_port_no]);
task CSparseMem::FCmarkMemoryLocation_A(bit [63:0] address, ( integer enable_tracking = 0 )) {
cb_status = CbMgr.checkCallBack(address);
no_of_8bytes_written = no_of_8bytes_written +1;
task CSparseMem::FCMemory_B(integer mcu_port_no) {
sync(ALL,FCMemorySync_B[mcu_port_no]);
trigger(OFF,FCMemorySync_B[mcu_port_no]);
printf ("%0d NIU_MEM: FC mark memory location %x\n", get_time(LO), FCMemoryAddress_B[mcu_port_no]);
FCmarkMemoryLocation_B(FCMemoryAddress_B[mcu_port_no],1);
trigger(FCMemorySync_B[mcu_port_no]);
task CSparseMem::FCmarkMemoryLocation_B(bit [63:0] address, ( integer enable_tracking = 0 )) {
cb_status = CbMgr.checkCallBack(address);
no_of_8bytes_written = no_of_8bytes_written +1;
task CSparseMem::FCMemory_C(integer mcu_port_no) {
sync(ALL,FCMemorySync_C[mcu_port_no]);
trigger(OFF,FCMemorySync_C[mcu_port_no]);
printf ("%0d NIU_MEM: FC mark memory location %x\n", get_time(LO), FCMemoryAddress_C[mcu_port_no]);
FCmarkMemoryLocation_C(FCMemoryAddress_C[mcu_port_no],1);
trigger(FCMemorySync_C[mcu_port_no]);
task CSparseMem::FCmarkMemoryLocation_C(bit [63:0] address, ( integer enable_tracking = 0 )) {
cb_status = CbMgr.checkCallBack(address);
no_of_8bytes_written = no_of_8bytes_written +1;
task CSparseMem::set_block_size(integer b, (integer mode_32b = 0 ) ) {
SetExtMemBlockSize(b, mode_32b);
function integer CSparseMem::free_addr (bit[39:0] addr, integer no_of_blocks,(integer page_id = 0)) {
semaphore_get(WAIT, sem_id_free_addr, 1);
free_addr = FreeAddr({24'h0,addr[39:32]},addr[31:0],no_of_blocks,page_id);
semaphore_put(sem_id_free_addr, 1);
function bit [39:0] CSparseMem::get_address(integer no_of_blocks, (integer page_id = 0) , (integer alignment = 1) ) {
// printf(" Page id - %d \n",page_id);
semaphore_get(WAIT, sem_id_get_addr, 1);
if (get_plus_arg (CHECK,"FORCE_ADDR_ALIGNMENT")) {
align = get_plus_arg (NUM, "FORCE_ADDR_ALIGNMENT");
address = MallocBlock(no_of_blocks,page_id,align);
// printf(" Address Allocated - %x \n",address);
semaphore_put(sem_id_get_addr, 1);
function bit [39:0] CSparseMem::xlate_addr(bit[39:0] addr, integer page_id, (integer corrupt_xlation = 0) ) {
semaphore_get(WAIT, sem_id_xlate_addr, 1);
xlate_addr = XlateAddr({24'h0,addr[39:32]},addr[31:0], page_id);
if(xlate_addr === 40'hzzzzzzzzzz) {
error("CSparseMem::xlate_addr Testbench ERROR \n");
semaphore_put(sem_id_xlate_addr, 1);
task CSparseMem::WriteVMem( bit [63:0] address, bit [63:0] data, bit [7:0] be, (integer xlate = 0), (integer page_id = 0) , (integer corrupt_xlate = 0) ,( integer enable_tracking = 0 ) ) {
// printf("CSparseMem::WriteVMem xlate - %d page_id - %d \n",xlate,page_id);
xlateaddr[39:0] = xlate_addr(address[39:0] , page_id,corrupt_xlate);
WriteMem( xlateaddr, data, be , enable_tracking );
task CSparseMem::CollectMemWriteTrace () {
integer address_collected ;
sync(ALL,set_trace_collection);
trigger(OFF, set_trace_collection);
Trace.address = trace_address;
WriteAddressTrace.add(Trace);
trigger (ON, trace_collect_done);
if(address_collected >0) {
printf(" Current Trace Size - %d time - %d\n",WriteAddressTrace.get_currsize(),TIME);
task CSparseMem::WriteMem( bit [63:0] address, bit [63:0] data, bit [7:0] be , (integer enable_tracking = 0 ) ) {
myname = {myname, ".WriteMem"};
// if enable_tracking is set, the address for which the data has been written is stored into a class
// and sent out as a mailbox
trigger (ON,set_trace_collection);
sync(ALL,trace_collect_done);
trigger (OFF, trace_collect_done);
cb_status = CbMgr.checkCallBack(address);
no_of_8bytes_written = no_of_8bytes_written +1;
// $SysWrite_Data(Hostmode,addr_h,addr_l, data[31:0], be[3:0]);
if (address[39] === 1'b1)
dbg.dispmon(myname, MON_WARN, psprintf("L2-Write : Address = %0h PA bit39 is set!", address));
printf ("NIU_MEM write: address=%x, be=%x date=%x\n", address, be, data);
3'd0: rd_data_tmp = l2_stub[0].l2_mem[address[39:9]];
3'd1: rd_data_tmp = l2_stub[1].l2_mem[address[39:9]];
3'd2: rd_data_tmp = l2_stub[2].l2_mem[address[39:9]];
3'd3: rd_data_tmp = l2_stub[3].l2_mem[address[39:9]];
3'd4: rd_data_tmp = l2_stub[4].l2_mem[address[39:9]];
3'd5: rd_data_tmp = l2_stub[5].l2_mem[address[39:9]];
3'd6: rd_data_tmp = l2_stub[6].l2_mem[address[39:9]];
3'd7: rd_data_tmp = l2_stub[7].l2_mem[address[39:9]];
int_data = (data & { {8{be[7]}}, {8{be[6]}}, {8{be[5]}}, {8{be[4]}}, {8{be[3]}}, {8{be[2]}}, {8{be[1]}}, {8{be[0]}} });
// Fu: handle 4 bytes aligned address, only write to upper 32 bits
3'd6: wri_data = {rd_data_tmp[511:64], int_data[31:0], rd_data_tmp[31:0]};
3'd7: wri_data = {rd_data_tmp[511:128], int_data[31:0], rd_data_tmp[95:0]};
3'd4: wri_data = {rd_data_tmp[511:192], int_data[31:0], rd_data_tmp[159:0]};
3'd5: wri_data = {rd_data_tmp[511:256], int_data[31:0], rd_data_tmp[223:0]};
3'd2: wri_data = {rd_data_tmp[511:320], int_data[31:0], rd_data_tmp[287:0]};
3'd3: wri_data = {rd_data_tmp[511:384], int_data[31:0], rd_data_tmp[351:0]};
3'd0: wri_data = {rd_data_tmp[511:448], int_data[31:0], rd_data_tmp[415:0]};
3'd1: wri_data = {int_data[31:0], rd_data_tmp[479:0]};
3'd6: wri_data = {rd_data_tmp[511:64], int_data};
3'd7: wri_data = {rd_data_tmp[511:128], int_data, rd_data_tmp[63:0]};
3'd4: wri_data = {rd_data_tmp[511:192], int_data, rd_data_tmp[127:0]};
3'd5: wri_data = {rd_data_tmp[511:256], int_data, rd_data_tmp[191:0]};
3'd2: wri_data = {rd_data_tmp[511:320], int_data, rd_data_tmp[255:0]};
3'd3: wri_data = {rd_data_tmp[511:384], int_data, rd_data_tmp[319:0]};
3'd0: wri_data = {rd_data_tmp[511:448], int_data, rd_data_tmp[383:0]};
3'd1: wri_data = {int_data, rd_data_tmp[447:0]};
3'd0: l2_stub[0].l2_mem[address[39:9]] = wri_data[511:0];
3'd1: l2_stub[1].l2_mem[address[39:9]] = wri_data[511:0];
3'd2: l2_stub[2].l2_mem[address[39:9]] = wri_data[511:0];
3'd3: l2_stub[3].l2_mem[address[39:9]] = wri_data[511:0];
3'd4: l2_stub[4].l2_mem[address[39:9]] = wri_data[511:0];
3'd5: l2_stub[5].l2_mem[address[39:9]] = wri_data[511:0];
3'd6: l2_stub[6].l2_mem[address[39:9]] = wri_data[511:0];
3'd7: l2_stub[7].l2_mem[address[39:9]] = wri_data[511:0];
dbg.dispmon(myname, MON_NORMAL, psprintf("L2-Write : Address = %0h, Data[511:0] = %0h\n", address, wri_data));
write_sys_mem(address[63:0], data[63:0], ~be ); // write DoubleWord
write_sys_mem(1, address[63:0], data[63:0], ~be ); // write DoubleWord
task CSparseMem::ReadMem( bit [63:0] address, var bit [63:0] data, bit [7:0] be ) {
myname = {myname, ".ReadMem"};
3'd0: rd_data_tmp = l2_stub[0].l2_mem[address[39:9]];
3'd1: rd_data_tmp = l2_stub[1].l2_mem[address[39:9]];
3'd2: rd_data_tmp = l2_stub[2].l2_mem[address[39:9]];
3'd3: rd_data_tmp = l2_stub[3].l2_mem[address[39:9]];
3'd4: rd_data_tmp = l2_stub[4].l2_mem[address[39:9]];
3'd5: rd_data_tmp = l2_stub[5].l2_mem[address[39:9]];
3'd6: rd_data_tmp = l2_stub[6].l2_mem[address[39:9]];
3'd7: rd_data_tmp = l2_stub[7].l2_mem[address[39:9]];
3'd7: tdata[63:0] = rd_data_tmp[63:0];
3'd6: tdata[63:0] = rd_data_tmp[127:64];
3'd5: tdata[63:0] = rd_data_tmp[191:128];
3'd4: tdata[63:0] = rd_data_tmp[255:192];
3'd3: tdata[63:0] = rd_data_tmp[319:256];
3'd2: tdata[63:0] = rd_data_tmp[383:320];
3'd1: tdata[63:0] = rd_data_tmp[447:384];
3'd0: tdata[63:0] = rd_data_tmp[511:448];
// Fu: 5/6/05 swap for endian
rdata = {tdata[7:0], tdata[15:8],tdata[23:16],tdata[31:24],tdata[39:32],tdata[47:40],tdata[55:48],tdata[63:56]};
dbg.dispmon(myname, MON_NORMAL, psprintf("L2-Read : Address = %0h, Data[63:0] = %0h", address, rdata));
read_sys_mem(address[63:0], rdata); // read DoubleWord
read_sys_mem(1, address[63:0], rdata); // read DoubleWord