Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / cpus / vonk / ss / lib / ras / src / SS_ValidAsiArray.h
CommitLineData
920dae64
AT
1/*
2* ========== Copyright Header Begin ==========================================
3*
4* OpenSPARC T2 Processor File: SS_ValidAsiArray.h
5* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
6* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
7*
8* The above named program is free software; you can redistribute it and/or
9* modify it under the terms of the GNU General Public
10* License version 2 as published by the Free Software Foundation.
11*
12* The above named program is distributed in the hope that it will be
13* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15* General Public License for more details.
16*
17* You should have received a copy of the GNU General Public
18* License along with this work; if not, write to the Free Software
19* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
20*
21* ========== Copyright Header End ============================================
22*/
23#ifndef __SS_ValidAsiArray_h__
24#define __SS_ValidAsiArray_h__
25
26#include "BL_BoundedArray.h"
27#include "BL_Mutex.h"
28#include "SS_AsiSpace.h"
29
30// SS_ValidAsiArray template creates an array of Asi control
31// registers with the machinery to easily add them to an SS_AsiSpace.
32// The elements of the array are intended to be SS_AsiCtrReg's
33// extended with a valid bit to detect whether an element has been
34// initialized.
35//
36// Additionally, there is an get() method which takes either an
37// SS_Vaddr or a specialized type for constructing addresses (usually
38// another SS_AsiCtrReg). These get() routines index the array of Asi
39// elements with the virtual and return a reference to the
40// corresponding element. The returned reference is actually of type
41// SS_ValidAsiType<class AsiType> which extends the basic AsiType
42// (e.g. SS_AsiCtrReg) with a valid bit.
43//
44// The template takes a class name, AsiType, which must have
45// the following class members:
46//
47// typedef <addressing type> ADDR_TYPE;
48// const static ASI = <array's asi number>;
49// const static SIZE = <number of elements in the array>;
50// const static SHIFT = <log2(vaddr stride between elements)>;
51//
52// The base address of the array must be the value of produced by the
53// default constructor of ADDR_TYPE.
54//
55// SS_ValidAsiArray provides methods to add all its elements to the
56// asi space AsiType::ASI by calling add_asi_map().
57
58class SS_Node;
59
60// This template class extends a type (typically a SS_AsiCsrReg) with
61// a valid bit and 64_bits of unsigned user data.
62
63template<class AsiType> class SS_ValidAsiType : public AsiType {
64 public:
65 SS_ValidAsiType() : valid_plus_data(0) {}
66
67 SS_ValidAsiType(const AsiType& rhs) :
68 valid_plus_data(rhs.valid_plus_data), AsiType(rhs) {}
69
70 bool valid() const {return valid_plus_data & v_bit; }
71
72 SS_ValidAsiType<AsiType>& valid(bool v)
73 {
74 if (v)
75 valid_plus_data |= v_bit;
76 else
77 valid_plus_data &= ~v_bit;
78 return *this;
79 }
80
81 SS_ValidAsiType& set(uint64_t val)
82 {
83 AsiType::set(val);
84 valid_plus_data |= v_bit;
85 return *this;
86 }
87
88 SS_ValidAsiType& set_unmasked(uint64_t val)
89 {
90 AsiType::set_unmasked(val);
91 valid_plus_data |= v_bit;
92 return *this;
93 }
94
95 SS_ValidAsiType& set(AsiType asi_reg)
96 {
97 return AsiType::set_unmasked(asi_reg.get());
98 }
99
100 uint64_t data63() const { return valid_plus_data & ~v_bit; }
101
102 SS_ValidAsiType& data63(uint64_t d)
103 {
104 valid_plus_data &= v_bit;
105 valid_plus_data |= (d & ~v_bit);
106 return *this;
107 }
108
109 static const uint64_t v_bit = (1ULL <<63);
110
111
112 private:
113 uint64_t valid_plus_data;
114};
115
116
117// The SS_ValidAsiArray template class creates an array of asi
118// elements with valid bits.
119
120template<class AsiType> class SS_ValidAsiArray {
121 public:
122 typedef SS_ValidAsiType<AsiType> ValidAsiType;
123
124 int lock() { return _mutex.lock(); }
125 int unlock() { return _mutex.unlock(); }
126 int trylock() { return _mutex.trylock(); }
127
128 // Get an asi element by virtual address
129 ValidAsiType& get(SS_Vaddr va) {
130 return array[(va >> AsiType::SHIFT) & (AsiType::SIZE - 1)];
131 }
132
133 // Get an asi element by specialized virtual address class
134 ValidAsiType& get(typename AsiType::ADDR_TYPE va) {
135 return get(va.get());
136 }
137
138 // The four i/o routines for asi's
139 static SS_AsiSpace::Error ld64( SS_Node*, void* _reg, SS_Strand*, SS_Vaddr,
140 uint64_t* data )
141 {
142 ValidAsiType* reg = (ValidAsiType*)_reg;
143 *data = reg->get();
144 if (!reg->valid())
145 return SS_AsiSpace::NOT_INIT;
146 return SS_AsiSpace::OK;
147 }
148
149 static SS_AsiSpace::Error st64( SS_Node*, void* _reg, SS_Strand*, SS_Vaddr,
150 uint64_t data )
151 {
152 ValidAsiType* reg = (ValidAsiType*)_reg;
153 reg->set(data);
154 return SS_AsiSpace::OK;
155 }
156
157 static SS_AsiSpace::Error rd64( SS_Node*, void* _reg, SS_Strand*, SS_Vaddr,
158 uint64_t* data )
159 {
160 ValidAsiType* reg = (ValidAsiType*)_reg;
161 *data = reg->get();
162 if (!reg->valid())
163 return SS_AsiSpace::NOT_INIT;
164 return SS_AsiSpace::OK;
165 }
166
167 static SS_AsiSpace::Error wr64( SS_Node*, void* _reg, SS_Strand*, SS_Vaddr,
168 uint64_t data )
169 {
170 ValidAsiType* reg = (ValidAsiType*)_reg;
171 reg->set_unmasked(data);
172 return SS_AsiSpace::OK;
173 }
174
175 // Add this Asi array to a SS_Node.
176 void add_asi_map(SS_Node* node, SS_Vaddr base_offset = 0)
177 {
178 AsiType::ADDR_TYPE base_addr;
179 for (SS_Vaddr ndx = 0 ; ndx < AsiType::SIZE; ++ndx)
180 node->asi_map[AsiType::ASI].add(base_addr.get() +
181 (ndx << AsiType::SHIFT) + base_offset,
182 node,
183 (void*)&array[ndx],
184 ld64, st64, rd64, wr64);
185 }
186
187 // Add this Asi array to a SS_Node.
188 void add_asi_map(SS_Node* node, SS_AsiSpace::Read ld64,
189 SS_AsiSpace::Write st64,
190 SS_AsiSpace::Read rd64,
191 SS_AsiSpace::Write wr64,
192 SS_Vaddr base_offset = 0)
193 {
194 AsiType::ADDR_TYPE base_addr;
195 for (SS_Vaddr ndx = 0 ; ndx < AsiType::SIZE; ++ndx)
196 node->asi_map[AsiType::ASI].add(base_addr.get() +
197 (ndx << AsiType::SHIFT) + base_offset,
198 node,
199 (void*)&array[ndx],
200 ld64, st64, rd64, wr64);
201 }
202
203 // Add this Asi array to a SS_Strand.
204 void add_asi_map(SS_Strand* strand)
205 {
206 AsiType::ADDR_TYPE base_addr;
207 for (SS_Vaddr ndx = 0 ; ndx < AsiType::SIZE; ++ndx)
208 strand->asi_map[AsiType::ASI].add(base_addr.get() +
209 (ndx << AsiType::SHIFT),
210 (SS_Node*)strand,
211 ld64, st64, rd64, wr64);
212 }
213
214 private:
215 BL_BoundedArray<ValidAsiType, AsiType::SIZE> array;
216
217 BL_Mutex _mutex;
218};
219
220
221
222#endif /* __SS_ValidAsiArray_h__ */