* ========== 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"
// 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
// 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().
// 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
{
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
)
valid_plus_data
|= v_bit
;
valid_plus_data
&= ~v_bit
;
SS_ValidAsiType
& set(uint64_t val
)
valid_plus_data
|= v_bit
;
SS_ValidAsiType
& set_unmasked(uint64_t val
)
AsiType::set_unmasked(val
);
valid_plus_data
|= v_bit
;
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
);
static const uint64_t v_bit
= (1ULL <<63);
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
{
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
) {
// The four i/o routines for asi's
static SS_AsiSpace::Error
ld64( SS_Node
*, void* _reg
, SS_Strand
*, SS_Vaddr
,
ValidAsiType
* reg
= (ValidAsiType
*)_reg
;
return SS_AsiSpace::NOT_INIT
;
static SS_AsiSpace::Error
st64( SS_Node
*, void* _reg
, SS_Strand
*, SS_Vaddr
,
ValidAsiType
* reg
= (ValidAsiType
*)_reg
;
static SS_AsiSpace::Error
rd64( SS_Node
*, void* _reg
, SS_Strand
*, SS_Vaddr
,
ValidAsiType
* reg
= (ValidAsiType
*)_reg
;
return SS_AsiSpace::NOT_INIT
;
static SS_AsiSpace::Error
wr64( SS_Node
*, void* _reg
, SS_Strand
*, SS_Vaddr
,
ValidAsiType
* reg
= (ValidAsiType
*)_reg
;
// 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
,
// Add this Asi array to a SS_Node.
void add_asi_map(SS_Node
* node
, SS_AsiSpace::Read ld64
,
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
,
// 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() +
BL_BoundedArray
<ValidAsiType
, AsiType::SIZE
> array
;
#endif /* __SS_ValidAsiArray_h__ */