Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / cpus / vonk / ss / lib / ras / src / SS_AsiArray.h
/*
* ========== Copyright Header Begin ==========================================
*
* OpenSPARC T2 Processor File: SS_AsiArray.h
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
*
* The above named program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License version 2 as published by the Free Software Foundation.
*
* The above named 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 work; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*
* ========== Copyright Header End ============================================
*/
#ifndef __SS_AsiArray_h__
#define __SS_AsiArray_h__
#include "BL_BoundedArray.h"
#include "BL_Mutex.h"
#include "SS_AsiSpace.h"
// SS_AsiArray template creates an array of Asi control
// registers with the machinery to easily add them to an SS_AsiSpace.
// The elements of the array are intended to be SS_AsiCtrReg's
// extended with a valid bit to detect whether an element has been
// initialized.
//
// Additionally, there is an get() method which takes either an
// SS_Vaddr or a specialized type for constructing addresses (usually
// another SS_AsiCtrReg). These get() routines index the array of Asi
// elements with the virtual and return a reference to the
// corresponding element.
// The template takes a class name, AsiType, which must have
// the following class members:
//
// typedef <addressing type> ADDR_TYPE;
// const static ASI = <array's asi number>;
// const static SIZE = <number of elements in the array>;
// const static SHIFT = <log2(vaddr stride between elements)>;
//
// The base address of the array must be the value of produced by the
// default constructor of ADDR_TYPE.
//
// SS_AsiArray provides methods to add all its elements to the
// asi space AsiType::ASI by calling add_asi_map().
class SS_Node;
// The SS_AsiArray template class creates an array of asi registers.
template<class AsiType> class SS_AsiArray {
public:
int lock() { return _mutex.lock(); }
int unlock() { return _mutex.unlock(); }
int trylock() { return _mutex.trylock(); }
// Get an asi element by virtual address
AsiType& get(SS_Vaddr va) {
return array[(va >> AsiType::SHIFT) % AsiType::SIZE];
}
// Get an asi element by specialized virtual address class
AsiType& get(typename AsiType::ADDR_TYPE va) {
return get(va.get());
}
// Add this Asi array to a SS_Node.
void add_asi_map(SS_Node* node, SS_Vaddr base_offset = 0)
{
AsiType::ADDR_TYPE base_addr;
for (SS_Vaddr ndx = 0 ; ndx < AsiType::SIZE; ++ndx)
node->asi_map[AsiType::ASI].add(base_addr.get() +
(ndx << AsiType::SHIFT) + base_offset,
node,
(void*)&array[ndx],
SS_AsiCtrReg::ld64,
SS_AsiCtrReg::st64,
SS_AsiCtrReg::rd64,
SS_AsiCtrReg::wr64);
}
// Add this Asi array to a SS_Node.
void add_asi_map(SS_Node* node, SS_AsiSpace::Read ld64,
SS_AsiSpace::Write st64,
SS_AsiSpace::Read rd64,
SS_AsiSpace::Write wr64,
SS_Vaddr base_offset = 0)
{
AsiType::ADDR_TYPE base_addr;
for (SS_Vaddr ndx = 0 ; ndx < AsiType::SIZE; ++ndx)
node->asi_map[AsiType::ASI].add(base_addr.get() +
(ndx << AsiType::SHIFT) + base_offset,
node,
(void*)&array[ndx],
ld64, st64, rd64, wr64);
}
// Add this Asi array to a SS_Strand.
void add_asi_map(SS_Strand* strand)
{
AsiType::ADDR_TYPE base_addr;
for (SS_Vaddr ndx = 0 ; ndx < AsiType::SIZE; ++ndx)
strand->asi_map[AsiType::ASI].add(base_addr.get() +
(ndx << AsiType::SHIFT),
(SS_Node*)strand,
SS_AsiCtrReg::ld64,
SS_AsiCtrReg::st64,
SS_AsiCtrReg::rd64,
SS_AsiCtrReg::wr64)
}
private:
BL_BoundedArray<AsiType, AsiType::SIZE> array;
BL_Mutex _mutex;
};
#endif /* __SS_AsiArray_h__ */