translation.hh (6973:a123bd350935) | translation.hh (7049:a06e95c99294) |
---|---|
1/* 2 * Copyright (c) 2002-2005 The Regents of The University of Michigan 3 * Copyright (c) 2009 The University of Edinburgh 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are 8 * met: redistributions of source code must retain the above copyright --- 21 unchanged lines hidden (view full) --- 30 * Timothy M. Jones 31 */ 32 33#ifndef __CPU_TRANSLATION_HH__ 34#define __CPU_TRANSLATION_HH__ 35 36#include "sim/tlb.hh" 37 | 1/* 2 * Copyright (c) 2002-2005 The Regents of The University of Michigan 3 * Copyright (c) 2009 The University of Edinburgh 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are 8 * met: redistributions of source code must retain the above copyright --- 21 unchanged lines hidden (view full) --- 30 * Timothy M. Jones 31 */ 32 33#ifndef __CPU_TRANSLATION_HH__ 34#define __CPU_TRANSLATION_HH__ 35 36#include "sim/tlb.hh" 37 |
38/** 39 * This class captures the state of an address translation. A translation 40 * can be split in two if the ISA supports it and the memory access crosses 41 * a page boundary. In this case, this class is shared by two data 42 * translations (below). Otherwise it is used by a single data translation 43 * class. When each part of the translation is finished, the finish 44 * function is called which will indicate whether the whole translation is 45 * completed or not. There are also functions for accessing parts of the 46 * translation state which deal with the possible split correctly. 47 */ |
|
38class WholeTranslationState 39{ 40 protected: 41 int outstanding; 42 Fault faults[2]; 43 44 public: 45 bool isSplit; 46 RequestPtr mainReq; 47 RequestPtr sreqLow; 48 RequestPtr sreqHigh; 49 uint8_t *data; 50 uint64_t *res; 51 BaseTLB::Mode mode; 52 | 48class WholeTranslationState 49{ 50 protected: 51 int outstanding; 52 Fault faults[2]; 53 54 public: 55 bool isSplit; 56 RequestPtr mainReq; 57 RequestPtr sreqLow; 58 RequestPtr sreqHigh; 59 uint8_t *data; 60 uint64_t *res; 61 BaseTLB::Mode mode; 62 |
53 /** Single translation state. */ | 63 /** 64 * Single translation state. We set the number of outstanding 65 * translations to one and indicate that it is not split. 66 */ |
54 WholeTranslationState(RequestPtr _req, uint8_t *_data, uint64_t *_res, 55 BaseTLB::Mode _mode) 56 : outstanding(1), isSplit(false), mainReq(_req), sreqLow(NULL), 57 sreqHigh(NULL), data(_data), res(_res), mode(_mode) 58 { 59 faults[0] = faults[1] = NoFault; 60 assert(mode == BaseTLB::Read || mode == BaseTLB::Write); 61 } 62 | 67 WholeTranslationState(RequestPtr _req, uint8_t *_data, uint64_t *_res, 68 BaseTLB::Mode _mode) 69 : outstanding(1), isSplit(false), mainReq(_req), sreqLow(NULL), 70 sreqHigh(NULL), data(_data), res(_res), mode(_mode) 71 { 72 faults[0] = faults[1] = NoFault; 73 assert(mode == BaseTLB::Read || mode == BaseTLB::Write); 74 } 75 |
63 /** Split translation state. */ | 76 /** 77 * Split translation state. We copy all state into this class, set the 78 * number of outstanding translations to two and then mark this as a 79 * split translation. 80 */ |
64 WholeTranslationState(RequestPtr _req, RequestPtr _sreqLow, 65 RequestPtr _sreqHigh, uint8_t *_data, uint64_t *_res, 66 BaseTLB::Mode _mode) 67 : outstanding(2), isSplit(true), mainReq(_req), sreqLow(_sreqLow), 68 sreqHigh(_sreqHigh), data(_data), res(_res), mode(_mode) 69 { 70 faults[0] = faults[1] = NoFault; 71 assert(mode == BaseTLB::Read || mode == BaseTLB::Write); 72 } 73 | 81 WholeTranslationState(RequestPtr _req, RequestPtr _sreqLow, 82 RequestPtr _sreqHigh, uint8_t *_data, uint64_t *_res, 83 BaseTLB::Mode _mode) 84 : outstanding(2), isSplit(true), mainReq(_req), sreqLow(_sreqLow), 85 sreqHigh(_sreqHigh), data(_data), res(_res), mode(_mode) 86 { 87 faults[0] = faults[1] = NoFault; 88 assert(mode == BaseTLB::Read || mode == BaseTLB::Write); 89 } 90 |
91 /** 92 * Finish part of a translation. If there is only one request then this 93 * translation is completed. If the request has been split in two then 94 * the outstanding count determines whether the translation is complete. 95 * In this case, flags from the split request are copied to the main 96 * request to make it easier to access them later on. 97 */ |
|
74 bool 75 finish(Fault fault, int index) 76 { 77 assert(outstanding); 78 faults[index] = fault; 79 outstanding--; 80 if (isSplit && outstanding == 0) { 81 82 // For ease later, we copy some state to the main request. 83 if (faults[0] == NoFault) { 84 mainReq->setPaddr(sreqLow->getPaddr()); 85 } 86 mainReq->setFlags(sreqLow->getFlags()); 87 mainReq->setFlags(sreqHigh->getFlags()); 88 } 89 return outstanding == 0; 90 } 91 | 98 bool 99 finish(Fault fault, int index) 100 { 101 assert(outstanding); 102 faults[index] = fault; 103 outstanding--; 104 if (isSplit && outstanding == 0) { 105 106 // For ease later, we copy some state to the main request. 107 if (faults[0] == NoFault) { 108 mainReq->setPaddr(sreqLow->getPaddr()); 109 } 110 mainReq->setFlags(sreqLow->getFlags()); 111 mainReq->setFlags(sreqHigh->getFlags()); 112 } 113 return outstanding == 0; 114 } 115 |
116 /** 117 * Determine whether this translation produced a fault. Both parts of the 118 * translation must be checked if this is a split translation. 119 */ |
|
92 Fault 93 getFault() const 94 { 95 if (!isSplit) 96 return faults[0]; 97 else if (faults[0] != NoFault) 98 return faults[0]; 99 else if (faults[1] != NoFault) 100 return faults[1]; 101 else 102 return NoFault; 103 } 104 | 120 Fault 121 getFault() const 122 { 123 if (!isSplit) 124 return faults[0]; 125 else if (faults[0] != NoFault) 126 return faults[0]; 127 else if (faults[1] != NoFault) 128 return faults[1]; 129 else 130 return NoFault; 131 } 132 |
133 /** Remove all faults from the translation. */ |
|
105 void 106 setNoFault() 107 { 108 faults[0] = faults[1] = NoFault; 109 } 110 | 134 void 135 setNoFault() 136 { 137 faults[0] = faults[1] = NoFault; 138 } 139 |
140 /** 141 * Check if this request is uncacheable. We only need to check the main 142 * request because the flags will have been copied here on a split 143 * translation. 144 */ |
|
111 bool 112 isUncacheable() const 113 { 114 return mainReq->isUncacheable(); 115 } 116 | 145 bool 146 isUncacheable() const 147 { 148 return mainReq->isUncacheable(); 149 } 150 |
151 /** 152 * Check if this request is a prefetch. We only need to check the main 153 * request because the flags will have been copied here on a split 154 * translation. 155 */ |
|
117 bool 118 isPrefetch() const 119 { 120 return mainReq->isPrefetch(); 121 } 122 | 156 bool 157 isPrefetch() const 158 { 159 return mainReq->isPrefetch(); 160 } 161 |
162 /** Get the physical address of this request. */ |
|
123 Addr 124 getPaddr() const 125 { 126 return mainReq->getPaddr(); 127 } 128 | 163 Addr 164 getPaddr() const 165 { 166 return mainReq->getPaddr(); 167 } 168 |
169 /** 170 * Get the flags associated with this request. We only need to access 171 * the main request because the flags will have been copied here on a 172 * split translation. 173 */ |
|
129 unsigned 130 getFlags() 131 { 132 return mainReq->getFlags(); 133 } 134 | 174 unsigned 175 getFlags() 176 { 177 return mainReq->getFlags(); 178 } 179 |
180 /** Delete all requests that make up this translation. */ |
|
135 void 136 deleteReqs() 137 { 138 delete mainReq; 139 if (isSplit) { 140 delete sreqLow; 141 delete sreqHigh; 142 } 143 } 144}; 145 | 181 void 182 deleteReqs() 183 { 184 delete mainReq; 185 if (isSplit) { 186 delete sreqLow; 187 delete sreqHigh; 188 } 189 } 190}; 191 |
192 193/** 194 * This class represents part of a data address translation. All state for 195 * the translation is held in WholeTranslationState (above). Therefore this 196 * class does not need to know whether the translation is split or not. The 197 * index variable determines this but is simply passed on to the state class. 198 * When this part of the translation is completed, finish is called. If the 199 * translation state class indicate that the whole translation is complete 200 * then the execution context is informed. 201 */ |
|
146template <class ExecContext> 147class DataTranslation : public BaseTLB::Translation 148{ 149 protected: 150 ExecContext *xc; 151 WholeTranslationState *state; 152 int index; 153 --- 4 unchanged lines hidden (view full) --- 158 } 159 160 DataTranslation(ExecContext *_xc, WholeTranslationState* _state, 161 int _index) 162 : xc(_xc), state(_state), index(_index) 163 { 164 } 165 | 202template <class ExecContext> 203class DataTranslation : public BaseTLB::Translation 204{ 205 protected: 206 ExecContext *xc; 207 WholeTranslationState *state; 208 int index; 209 --- 4 unchanged lines hidden (view full) --- 214 } 215 216 DataTranslation(ExecContext *_xc, WholeTranslationState* _state, 217 int _index) 218 : xc(_xc), state(_state), index(_index) 219 { 220 } 221 |
222 /** 223 * Finish this part of the translation and indicate that the whole 224 * translation is complete if the state says so. 225 */ |
|
166 void 167 finish(Fault fault, RequestPtr req, ThreadContext *tc, 168 BaseTLB::Mode mode) 169 { 170 assert(state); 171 assert(mode == state->mode); 172 if (state->finish(fault, index)) { 173 xc->finishTranslation(state); 174 } 175 delete this; 176 } 177}; 178 179#endif // __CPU_TRANSLATION_HH__ | 226 void 227 finish(Fault fault, RequestPtr req, ThreadContext *tc, 228 BaseTLB::Mode mode) 229 { 230 assert(state); 231 assert(mode == state->mode); 232 if (state->finish(fault, index)) { 233 xc->finishTranslation(state); 234 } 235 delete this; 236 } 237}; 238 239#endif // __CPU_TRANSLATION_HH__ |