Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / cpus / vonk / n2 / lib / csr / src / N2_Csr.cc
CommitLineData
920dae64
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: N2_Csr.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/************************************************************************
22**
23** Copyright (C) 2006, Sun Microsystems, Inc.
24**
25** Sun considers its source code as an unpublished, proprietary
26** trade secret and it is available only under strict license provisions.
27** This copyright notice is placed here only to protect Sun in the event
28** the source is deemed a published work. Disassembly, decompilation,
29** or other means of reducing the object code to human readable form
30** is prohibited by the license agreement under which this code is
31** provided to the user or company in possession of this copy.
32**
33*************************************************************************/
34#include "N2_Csr.h"
35#include "N2_Model.h"
36#include "N2_Strand.h"
37
38using namespace std;
39
40const int N2_Csr::PA_BITS = 40;
41const uint64_t N2_Csr::IO_MASK = 0x1ULL << (PA_BITS - 1);
42const int N2_Csr::IO_OFFSET = 32;
43const uint64_t N2_Csr::IO_RANGE = 0xffULL << IO_OFFSET;
44
45N2_Model* N2_Csr::model = NULL;
46
47//=============================================================================
48// return SS_Io::NOT_HANDLED will pass the operation to SS_Memory
49//=============================================================================
50int N2_Csr::access_io(void* obj, int sid, int access, SS_Paddr addr, uint32_t size, uint64_t* data, uint64_t bitmask)/*{{{*/
51{
52 // filter out non-io address ---> this should never happen as only I/O addr
53 // get here
54 if ((addr & IO_MASK) == 0x0)
55 return SS_Io::NOT_HANDLED;
56
57 // CSR access should be 8-byte bound
58 if ((size % 8) != 0)
59 return SS_Io::NOT_HANDLED;
60
61 N2_Csr *csr = (N2_Csr*)obj;
62
63 csr->set_followme(false);
64 int ret = csr->address_map(addr, access, sid);
65 int prev_ret = -1;
66 if (ret == SS_Io::OK)
67 {
68 int count = size / 8;
69 for (int i = 0; i < count; i++)
70 {
71 if (access & MemoryTransaction::WRITE)
72 ret = csr->write64((addr+i*8), data[i], access, sid);
73 else
74 ret = csr->read64((addr+i*8), &data[i], access, sid);
75
76 // make sure the entire block has the same return state
77 if (prev_ret == -1)
78 prev_ret = ret;
79 else if (prev_ret != ret)
80 {
81 fprintf(stderr, "ERROR: N2_Csr::access_io(): addr=%#llx, i=%d, prev_ret=%d, ret=%d\n", addr, i, prev_ret, ret);
82 assert(0);
83 }
84 else if (ret == SS_Io::FOLLOWME)
85 csr->set_followme(true);
86 }
87 if (csr->get_followme())
88 return SS_Io::FOLLOWME;
89 else
90 return ret;
91 }
92 else
93 {
94 if (access & MemoryTransaction::READ)
95 {
96 // address not allowed for read
97 *data = 0xDEADDEADDEADDEADLLU;
98 // tell msync not to change this value
99 return SS_Io::FOLLOWME;
100 }
101 else
102 return ret;
103 }
104}
105/*}}}*/
106
107//=============================================================================
108//=============================================================================
109SS_Io::access_io_status N2_Csr::address_map( SS_Paddr paddr, int access, int sid)/*{{{*/
110{
111 // when IO address CSRs are added, make sure there is no conflict on
112 // address range, when there is one, CSR has the higher priority.
113
114 bool write = (access & MemoryTransaction::WRITE) ? true : false;
115 bool internal = (access & MemoryTransaction::INTERNAL) ? true : false;
116 bool mem_slam = (access & MemoryTransaction::MEM_SLAM) ? true : false;
117
118 uint64_t range = (paddr & IO_RANGE) >> IO_OFFSET;
119
120 // if it is an instruction fetch to I/O space other than 0xff,
121 // throw illegal instruction.
122 //TODO the current setup does not provide any information regarding whether
123 // the access is an instr fetch or not.
124 //TODO if (type == INSTR_ACCESS) && (range != 0xff) && !write && !internal
125 // ===> trap( illegal_instruction )
126
127 if (range == RANGE_RNG)
128 {
129 // 0x82: // RNG (Random Number Generator) IGNORE writes
130 if (write && !(internal || mem_slam))
131 {
132 // silently drop the write
133 return SS_Io::NOP;
134 }
135 else
136 {
137 return SS_Io::OK;
138 }
139 }
140 else if (((range == 0x87) ||
141 ((range >= 0x8a) && (range <= 0x8f)) ||
142 ((range >= 0x91) && (range <= 0x9f) && (paddr != 0x9a00000000)) ||
143 ((range >= 0xd0) && (range <= 0xfe))))
144 {
145 // 0x87: // TAP to L2 CSR (not supported) ERROR on read
146 // 0x91-0x9F: // Reserved ERROR on read
147 // xA0-0xBF: // L2 CSR (never comes to NCU) ERROR on read
148 // ---> 0xA0-0xBF: (Jeff) This range is read/write from a Riesling
149 // perspective and a "should never happen"
150 // from the NCU perspective.
151 // 0xD0-0xFE: // Reserved ERROR on read
152 if (!write)
153 {
154 if (!internal)
155 {
156 //TODO throw data_access_error 0x32 (12.9) on read
157 // if (seter->getPSCCE() && cerer->getL2U_SOCU())
158 // ===> trap( data_access_error )
159 //TODO if seter & cerer are provided through ASI follow-me, then make
160 // sure we use those follow-me values
161 return SS_Io::NOP;
162 }
163 else
164 {
165 return SS_Io::FOLLOWME;
166 }
167 }
168 else
169 {
170 return SS_Io::OK;
171 }
172 }
173 else
174 {
175 return SS_Io::OK;
176 }
177}
178/*}}}*/
179
180//=============================================================================
181// return NOT_HANDLED means should re-try the operation in SS_Memory
182//=============================================================================
183int N2_Csr::read64( SS_Paddr paddr, uint64_t *value, int access, int sid)/*{{{*/
184{
185 int range = (int)((paddr & IO_RANGE) >> IO_OFFSET);
186 switch (range)
187 {
188 case RANGE_NCU:
189 case RANGE_NCU_2:
190 // NCU R/W allowed
191 return ncu_.read64(paddr, value, access, sid);
192 break;
193 case RANGE_NIU:
194 // NIU R/W allowed
195 return niu_.read64(paddr, value, access, sid);
196 break;
197 case RANGE_MCU:
198 // MCUs R/W allowed
199 return mcu_.read64(paddr, value, access, sid);
200 break;
201 case RANGE_L2_TAP:
202 // TAP to L2 CSR (not supported) ERROR on read
203 // should be filtered out by addressMap()
204 if (internal)
205 return SS_Io::NOT_HANDLED;
206 else
207 {
208 fprintf(stderr, "ERROR: N2_Csr::read64( addr=%#llx ) not allowed\n", paddr);
209 return SS_Io::NOP;
210 }
211 break;
212 case RANGE_PIU:
213 // DMU CSR R/W allowed
214 return piu_.read64(paddr, value, access, sid);
215 break;
216 case RANGE_RST:
217 // RST R/W allowed
218 return rst_.read64(paddr, value, access, sid);
219 break;
220 case RANGE_SSI:
221 // SSI (boot ROM) IGNORE writes
222 return ssi_.read64(paddr, value, access, sid);
223 break;
224 default:
225 if (range >= RANGE_L2_LOW && range <= RANGE_L2_HIGH)
226 {
227 // L2 CSR
228 return l2_.read64(paddr, value, access, sid);
229 }
230 else if (range >= RANGE_PCIE_LOW && range <= RANGE_PCIE_HIGH)
231 {
232 // PCIE (64GB) / DMUPIO R/W allowed
233 return pcie_.read64(paddr, value, access, sid);
234 }
235 else
236 {
237 return SS_Io::NOT_HANDLED;
238 }
239 break;
240 }
241
242 return SS_Io::NOT_HANDLED;
243}
244/*}}}*/
245
246//=============================================================================
247// return NOT_HANDLED means should re-try the operation in SS_Memory
248//=============================================================================
249int N2_Csr::write64( SS_Paddr paddr, uint64_t value, int access, int sid)/*{{{*/
250{
251 int range = (int)((paddr & IO_RANGE) >> IO_OFFSET);
252 switch (range)
253 {
254 case RANGE_NCU:
255 case RANGE_NCU_2:
256 // NCU R/W allowed
257 return ncu_.write64(paddr, value, access, sid);
258 break;
259 case RANGE_NIU:
260 // NIU R/W allowed
261 return niu_.write64(paddr, value, access, sid);
262 break;
263 case RANGE_RNG:
264 // RNG (Random Number Generator) IGNORE writes
265 // should be filtered out by addressMap()
266 // we can get here if msync does an memSlam write, have to take it.
267 if (access & MemoryTransaction::MEM_SLAM)
268 return SS_Io::NOT_HANDLED;
269 else
270 return SS_Io::NOP;
271 break;
272 case RANGE_MCU:
273 // MCUs R/W allowed
274 return mcu_.write64(paddr, value, access, sid);
275 break;
276 case RANGE_PIU:
277 // DMU CSR R/W allowed
278 return piu_.write64(paddr, value, access, sid);
279 break;
280 case RANGE_RST:
281 {
282 // RST R/W allowed
283 if (((paddr == 0x8900000808) || (paddr == 0x8900000810)) &&
284 (access & MemoryTransaction::MEM_SLAM))
285 {
286 access |= MemoryTransaction::INTERNAL;
287 }
288 int ret = rst_.write64(paddr, value, access, sid);
289 if (paddr == 0x8900000808)
290 {
291 uint64_t data;
292 int ret2 = rst_.read64(paddr, &data, (access|MemoryTransaction::READ|MemoryTransaction::INTERNAL|SS_BaseCsr::NO_FOLLOW_ME), sid);
293 // if reset_gen is set to non-zero, raise reset_gen trap if in
294 // standalone mode, if in cosim mode, wait for testbench INTP command
295 //TODO if (data > 0) && !cosim ===> raise reset_gen trap
296 if ((data > 0) && (sid >= 0))
297 {
298 if (!(model->strand_ptr(sid)->sim_state.cosim()))
299 {
300 fprintf(stderr, "ERROR: N2_Csr::write64(): addr=%#llx, sid=%d, should raise a reset_gen trap\n", paddr, sid);
301 assert(0);
302 }
303 }
304 }
305 return ret;
306 break;
307 }
308 case RANGE_SSI:
309 // SSI (boot ROM)
310 return ssi_.write64(paddr, value, access, sid);
311 break;
312 default:
313 if (range >= RANGE_L2_LOW && range <= RANGE_L2_HIGH)
314 {
315 // L2 CSR
316 return l2_.write64(paddr, value, access, sid);
317 }
318 else if (range >= RANGE_PCIE_LOW && range <= RANGE_PCIE_HIGH)
319 {
320 // PCIE (64GB) / DMUPIO R/W allowed
321 return pcie_.write64(paddr, value, access, sid);
322 }
323 else
324 {
325 return SS_Io::NOT_HANDLED;
326 }
327 break;
328 }
329
330 return SS_Io::NOT_HANDLED;
331}
332/*}}}*/