Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / cpus / vonk / ss / lib / ras / src / SS_CKMemory.cc
CommitLineData
920dae64
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: SS_CKMemory.cc
4// Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
5// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
6//
7// The above named program is free software; you can redistribute it and/or
8// modify it under the terms of the GNU General Public
9// License version 2 as published by the Free Software Foundation.
10//
11// The above named program is distributed in the hope that it will be
12// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14// General Public License for more details.
15//
16// You should have received a copy of the GNU General Public
17// License along with this work; if not, write to the Free Software
18// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
19//
20// ========== Copyright Header End ============================================
21#include "SS_CKMemory.h"
22
23SS_CKMemory::SS_CKMemory(SS_Memory *mem)/*{{{*/
24 :ss_mem(mem),
25 debug_CK(getenv("CK_CHIPKILL_DEBUG") != NULL)
26{
27}
28/*}}}*/
29SS_CKMemory::~SS_CKMemory()/*{{{*/
30{
31}
32/*}}}*/
33
34uint64_t SS_CKMemory::ras_ld_buf( uint64_t addr, uint_t size )/*{{{*/
35{
36 mem_xact.paddr(addr);
37 mem_xact.size(size);
38 mem_xact.access(MemoryTransaction::READ);
39 mem_xact.referenceType(MemoryTransaction::DATA);
40
41 read_dram_error_corrected(mem_xact);
42 return mem_xact.getData();
43}
44/*}}}*/
45void SS_CKMemory::ras_ld( uint64_t addr, uint_t size, uint64_t* data )/*{{{*/
46{
47 mem_xact.paddr(addr);
48 mem_xact.size(size);
49 mem_xact.access(MemoryTransaction::READ);
50 mem_xact.referenceType(MemoryTransaction::DATA);
51
52 read_dram_error_corrected(mem_xact);
53 for (uint_t i=0; size; i++, size -= 8)
54 data[i]= mem_xact.getData(i);
55}
56/*}}}*/
57
58
59
60uint32_t SS_CKMemory::fetch32( uint64_t addr )/*{{{*/
61{
62 mem_xact.paddr(addr);
63 mem_xact.size(4);
64 mem_xact.access(MemoryTransaction::READ);
65 mem_xact.referenceType(MemoryTransaction::INSTR);
66
67 read_dram_error_corrected(mem_xact);
68 return mem_xact.getData();
69}
70/*}}}*/
71void SS_CKMemory::fetch256( uint64_t addr, uint64_t data[4] )/*{{{*/
72{
73 mem_xact.paddr(addr);
74 mem_xact.size(32);
75 mem_xact.access(MemoryTransaction::READ);
76 mem_xact.referenceType(MemoryTransaction::INSTR);
77
78 read_dram_error_corrected(mem_xact);
79 uint_t size = 32;
80 for (uint_t i=0; size; i++, size -= 8)
81 data[i]= mem_xact.getData(i);
82}
83/*}}}*/
84void SS_CKMemory::fetch512( uint64_t addr, uint64_t data[8] )/*{{{*/
85{
86 mem_xact.paddr(addr);
87 mem_xact.size(64);
88 mem_xact.access(MemoryTransaction::READ);
89 mem_xact.referenceType(MemoryTransaction::INSTR);
90
91 read_dram_error_corrected(mem_xact);
92
93 uint_t size = 64;
94 for (uint_t i=0; size; i++, size -= 8)
95 data[i]= mem_xact.getData(i);
96}
97/*}}}*/
98
99void SS_CKMemory::st8( uint64_t addr, uint8_t data )/*{{{*/
100{
101 ss_mem->st8(addr,data);
102}
103/*}}}*/
104void SS_CKMemory::st16( uint64_t addr, uint16_t data )/*{{{*/
105{
106 ss_mem->st16(addr,data);
107}
108/*}}}*/
109void SS_CKMemory::st32( uint64_t addr, uint32_t data )/*{{{*/
110{
111 ss_mem->st32(addr,data);
112}
113/*}}}*/
114void SS_CKMemory::st64( uint64_t addr, uint64_t data )/*{{{*/
115{
116 ss_mem->st64(addr,data);
117}
118/*}}}*/
119void SS_CKMemory::st128( uint64_t addr, uint64_t data[2] )/*{{{*/
120{
121 ss_mem->st128(addr,data);
122}
123/*}}}*/
124void SS_CKMemory::st512( uint64_t addr, uint64_t data[8] )/*{{{*/
125{
126 ss_mem->st512(addr,data);
127}
128/*}}}*/
129
130uint8_t SS_CKMemory::ld8u ( uint64_t addr )/*{{{*/
131{
132 return ras_ld_buf(addr,1);
133}
134/*}}}*/
135int8_t SS_CKMemory::ld8s( uint64_t addr )/*{{{*/
136{
137 return ras_ld_buf(addr,1);
138}
139/*}}}*/
140uint16_t SS_CKMemory::ld16u( uint64_t addr )/*{{{*/
141{
142 return ras_ld_buf(addr,2);
143}
144/*}}}*/
145int16_t SS_CKMemory::ld16s( uint64_t addr )/*{{{*/
146{
147 return ras_ld_buf(addr,2);
148}
149/*}}}*/
150uint32_t SS_CKMemory::ld32u( uint64_t addr )/*{{{*/
151{
152 return ras_ld_buf(addr,4);
153}
154/*}}}*/
155int32_t SS_CKMemory::ld32s( uint64_t addr )/*{{{*/
156{
157 return ras_ld_buf(addr,4);
158}
159/*}}}*/
160uint64_t SS_CKMemory::ld64( uint64_t addr )/*{{{*/
161{
162 return ras_ld_buf(addr,8);
163}
164/*}}}*/
165void SS_CKMemory::ld128( uint64_t addr, uint64_t data[2] ) /*{{{*/
166{
167 ras_ld(addr,16,data);
168}
169/*}}}*/
170void SS_CKMemory::ld256( uint64_t addr, uint64_t data[4] )/*{{{*/
171{
172 ras_ld(addr,32,data);
173}
174/*}}}*/
175void SS_CKMemory::ld512( uint64_t addr, uint64_t data[8] )/*{{{*/
176{
177 ras_ld(addr,64,data);
178}
179/*}}}*/
180
181void SS_CKMemory::st64partial( uint64_t addr, uint64_t data, uint64_t mask ) /*{{{*/
182{
183 ss_mem->st64partial(addr,data,mask);
184}
185/*}}}*/
186
187void SS_CKMemory::ld128atomic( uint64_t addr, uint64_t data[2] )/*{{{*/
188{
189 ras_ld(addr,16,data);
190}
191/*}}}*/
192
193uint8_t SS_CKMemory::ldstub( uint64_t addr )/*{{{*/
194{
195 mem_xact.referenceType(MemoryTransaction::DATA);
196 mem_xact.paddr(addr);
197 mem_xact.size(1);
198 mem_xact.access(MemoryTransaction::READ|MemoryTransaction::ATOMIC);
199
200 read_dram_error_corrected(mem_xact);
201 uint64_t data = mem_xact.getData();
202 ss_mem->poke8(addr,0xff);
203 return data;
204}
205/*}}}*/
206uint32_t SS_CKMemory::swap( uint64_t addr, uint32_t rd )/*{{{*/
207{
208 mem_xact.referenceType(MemoryTransaction::DATA);
209 mem_xact.paddr(addr);
210 mem_xact.size(4);
211 mem_xact.access(MemoryTransaction::READ|MemoryTransaction::ATOMIC);
212
213 read_dram_error_corrected(mem_xact);
214 uint64_t data = mem_xact.getData();
215 ss_mem->poke32(addr,rd);
216 return data;
217}
218/*}}}*/
219uint64_t SS_CKMemory::casx( uint64_t addr, uint64_t rd, uint64_t rs2 )/*{{{*/
220{
221 mem_xact.referenceType(MemoryTransaction::DATA);
222 mem_xact.paddr(addr);
223 mem_xact.size(8);
224 mem_xact.access(MemoryTransaction::READ|MemoryTransaction::ATOMIC);
225
226 read_dram_error_corrected(mem_xact);
227
228 uint64_t data = mem_xact.getData();
229 if (data == rs2)
230 {
231 ss_mem->poke64(addr,rd);
232 }
233 return data;
234}
235/*}}}*/
236uint32_t SS_CKMemory::cas( uint64_t addr, uint32_t rd, uint32_t rs2 )/*{{{*/
237{
238 mem_xact.referenceType(MemoryTransaction::DATA);
239 mem_xact.paddr(addr);
240 mem_xact.size(4);
241 mem_xact.access(MemoryTransaction::READ|MemoryTransaction::ATOMIC);
242
243 read_dram_error_corrected(mem_xact);
244
245 uint32_t data = mem_xact.getData();
246 if (data == rs2)
247 {
248 ss_mem->poke32(addr,rd);
249 }
250 return data;
251}
252/*}}}*/
253
254// read_dram_error_corrected() reads the memory specified in a
255// MemoryTransaction, memXact, and applies Chip-Kill error correction
256// to the data as needed.
257//
258// Returns false if memXact specifies no Chip-Kill correction or if the
259// access is to the I/O space (where CK doesn't apply).
260
261bool SS_CKMemory::read_dram_error_corrected(MemoryTransaction &memXact)/*{{{*/
262{
263 if (memXact.writeXact()) {
264 fprintf(stderr, "SS_CKMemory::corrrectDramError() "
265 "WRITE or READ_WRITE memXact.");
266 exit(-1);
267 }
268
269 if( memXact.size() < 8 ){
270 memXact.setData(read_short_corrected_dram_data(memXact.paddr(),
271 memXact.size()));
272 } else {
273 if( memXact.size() % 8 ){
274 fprintf(stderr, "Read of size %d, is not a multiple of 8 bytes",
275 memXact.size() );
276 exit(-1);
277 }
278 uint_t size = memXact.size() / 8;
279 for( uint_t i = 0; i < size; ++i ){
280 uint64_t data = read_corrected_dram_data(memXact.paddr() + i * 8, 8);
281 memXact.setData(i, data);
282 }
283 }
284
285 return true;
286}
287
288// read_corrected_dram_data() reads Chip-Kill corrected data from
289// paddress. Allowed sizes are 1, 2, 4, and multiples of 8.
290
291uint64_t SS_CKMemory::read_corrected_dram_data(uint64_t paddress,
292 uint8_t size)/*{{{*/
293{
294 if (size < 8) {
295 return read_short_corrected_dram_data(paddress, size);
296 }
297
298 if (size % 8) {
299 fprintf(stderr, "SS_CKMemory::readCorrectedDramData: read of "
300 "size %d, is not a multiple of 8 bytes", size);
301 }
302
303 uint64_t ckPaddr = paddress & ~(DRAM_LINE_LENGTH - 1);
304 BL_CKEccFile::ChipKillLine line = read_raw_CK_line(ckPaddr);
305 if (ecc_exists(ckPaddr)) {
306 uint64_t storedECC = fetch_ecc(ckPaddr);
307
308 uint64_t old_msdw = line.msdw;
309 uint64_t old_lsdw = line.lsdw;
310
311 // if debugging Chip-Kill, inject data errors
312 if (debug_CK) {
313 if (random() % 2)
314 line.msdw ^= ((random() % 16) << (4*(random() % 16)));
315 else
316 line.lsdw ^= ((random() % 16) << (4*(random() % 16)));
317 }
318 BL_CKSyndrome ckSyndrome(line, storedECC);
319
320 // if there is no error for this CK line, remove its ECC value
321 if (ckSyndrome.noError()) {
322 dram_ecc_map.erase(ckPaddr);
323 } else { // try to fix the line
324 ckSyndrome.correctChipKillLine(line);
325 }
326 // if the error weren't fixed, die
327 if (debug_CK && old_msdw != line.msdw && old_lsdw != line.lsdw) {
328 fprintf(stderr,"SS_CKMemory::"
329 "readCorrectedDramData(): "
330 "Chip-Kill failed");
331
332 exit(-1);
333 }
334 }
335
336 return (paddress & (DRAM_LINE_LENGTH/2)) ? line.lsdw : line.msdw;
337}
338/*}}}*/
339
340// read_short_corrected_dram_data() reads Chip-Kill corrected data from
341// paddress. Allowed sizes are 1, 2, 4.
342
343uint64_t SS_CKMemory::read_short_corrected_dram_data(uint64_t paddress,
344 uint8_t size)/*{{{*/
345{
346 uint64_t data = read_corrected_dram_data(paddress & ~0x07ULL , 8);
347 switch( size )
348 {
349 case 4:
350 data = ( data >> ( 32 - (paddress & 0x04ULL) * 8)) & 0x0ffffffff;
351 break;
352 case 2:
353 data = ( data >> ( 48 - (paddress & 0x06ULL) * 8)) & 0x0ffff;
354 break;
355 case 1:
356 data = ( data >> ( 56 - (paddress & 0x07ULL) * 8)) & 0x0ff;
357 break;
358 default:
359 fprintf(stderr, "Read of size %d is not supported. Reads must be "
360 "1, 2, 4, or 8 bytes.", size );
361 exit;
362 }
363
364 /*fprintf(stderr, "Read of %d bytes of data from 0x%0.16llx data=%0.16llx\n",
365 size, paddress, data );*/
366
367 return data;
368}
369/*}}}*/