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__