Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / cpus / vonk / ss / lib / ras / src / SS_ValidAsiArray.h
/*
* ========== Copyright Header Begin ==========================================
*
* OpenSPARC T2 Processor File: SS_ValidAsiArray.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_ValidAsiArray_h__
#define __SS_ValidAsiArray_h__
#include "BL_BoundedArray.h"
#include "BL_Mutex.h"
#include "SS_AsiSpace.h"
// SS_ValidAsiArray 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 returned reference is actually of type
// SS_ValidAsiType<class AsiType> which extends the basic AsiType
// (e.g. SS_AsiCtrReg) with a valid bit.
//
// 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_ValidAsiArray provides methods to add all its elements to the
// asi space AsiType::ASI by calling add_asi_map().
class SS_Node;
// This template class extends a type (typically a SS_AsiCsrReg) with
// a valid bit and 64_bits of unsigned user data.
template<class AsiType> class SS_ValidAsiType : public AsiType {
public:
SS_ValidAsiType() : valid_plus_data(0) {}
SS_ValidAsiType(const AsiType& rhs) :
valid_plus_data(rhs.valid_plus_data), AsiType(rhs) {}
bool valid() const {return valid_plus_data & v_bit; }
SS_ValidAsiType<AsiType>& valid(bool v)
{
if (v)
valid_plus_data |= v_bit;
else
valid_plus_data &= ~v_bit;
return *this;
}
SS_ValidAsiType& set(uint64_t val)
{
AsiType::set(val);
valid_plus_data |= v_bit;
return *this;
}
SS_ValidAsiType& set_unmasked(uint64_t val)
{
AsiType::set_unmasked(val);
valid_plus_data |= v_bit;
return *this;
}
SS_ValidAsiType& set(AsiType asi_reg)
{
return AsiType::set_unmasked(asi_reg.get());
}
uint64_t data63() const { return valid_plus_data & ~v_bit; }
SS_ValidAsiType& data63(uint64_t d)
{
valid_plus_data &= v_bit;
valid_plus_data |= (d & ~v_bit);
return *this;
}
static const uint64_t v_bit = (1ULL <<63);
private:
uint64_t valid_plus_data;
};
// The SS_ValidAsiArray template class creates an array of asi
// elements with valid bits.
template<class AsiType> class SS_ValidAsiArray {
public:
typedef SS_ValidAsiType<AsiType> ValidAsiType;
int lock() { return _mutex.lock(); }
int unlock() { return _mutex.unlock(); }
int trylock() { return _mutex.trylock(); }
// Get an asi element by virtual address
ValidAsiType& get(SS_Vaddr va) {
return array[(va >> AsiType::SHIFT) & (AsiType::SIZE - 1)];
}
// Get an asi element by specialized virtual address class
ValidAsiType& get(typename AsiType::ADDR_TYPE va) {
return get(va.get());
}
// The four i/o routines for asi's
static SS_AsiSpace::Error ld64( SS_Node*, void* _reg, SS_Strand*, SS_Vaddr,
uint64_t* data )
{
ValidAsiType* reg = (ValidAsiType*)_reg;
*data = reg->get();
if (!reg->valid())
return SS_AsiSpace::NOT_INIT;
return SS_AsiSpace::OK;
}
static SS_AsiSpace::Error st64( SS_Node*, void* _reg, SS_Strand*, SS_Vaddr,
uint64_t data )
{
ValidAsiType* reg = (ValidAsiType*)_reg;
reg->set(data);
return SS_AsiSpace::OK;
}
static SS_AsiSpace::Error rd64( SS_Node*, void* _reg, SS_Strand*, SS_Vaddr,
uint64_t* data )
{
ValidAsiType* reg = (ValidAsiType*)_reg;
*data = reg->get();
if (!reg->valid())
return SS_AsiSpace::NOT_INIT;
return SS_AsiSpace::OK;
}
static SS_AsiSpace::Error wr64( SS_Node*, void* _reg, SS_Strand*, SS_Vaddr,
uint64_t data )
{
ValidAsiType* reg = (ValidAsiType*)_reg;
reg->set_unmasked(data);
return SS_AsiSpace::OK;
}
// 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],
ld64, st64, rd64, 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,
ld64, st64, rd64, wr64);
}
private:
BL_BoundedArray<ValidAsiType, AsiType::SIZE> array;
BL_Mutex _mutex;
};
#endif /* __SS_ValidAsiArray_h__ */