Otawa  0.10
PERSProblem.h
Go to the documentation of this file.
1 /*
2  * $Id$
3  * This file describes the Persistence cache problem.
4  *
5  * This file is part of OTAWA
6  * Copyright (c) 2007, IRIT UPS.
7  *
8  * OTAWA is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * OTAWA is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with OTAWA; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21  * 02110-1301 USA
22  */
23 
24 #ifndef CACHE_PERSPROBLEM_H_
25 #define CACHE_PERSPROBLEM_H_
26 
27 #include <elm/io.h>
28 #include <elm/assert.h>
29 #include <otawa/prog/WorkSpace.h>
30 #include <otawa/cache/LBlockSet.h>
31 #include <otawa/hard/Cache.h>
32 #include <otawa/cfg/BasicBlock.h>
33 #include <otawa/util/HalfAbsInt.h>
34 
35 
36 namespace otawa {
37 
38 class PERSProblem {
39 
40  // Types
41  public:
42  class Item {
43  int A, size;
44 
45  public:
46  inline Item(const int _size, const int _A)
47  : A (_A), size(_size)
48  {
49  age = new int [size];
50  for (int i = 0; i < size; i++)
51  age[i] = -1;
52  }
53 
54  inline ~Item() {
55  delete [] age;
56  }
57 
58  inline Item(const Item &source) : A(source.A), size(source.size) {
59  age = new int [size];
60  for (int i = 0; i < size; i++)
61  age[i] = source.age[i];
62 
63  }
64 
65  inline Item& operator=(const Item &src) {
66  ASSERT((A == src.A) && (size == src.size));
67  for (int i = 0; i < size ; i++)
68  age[i] = src.age[i];
69  return *this;
70  }
71 
72  inline void refresh(int id, int newage) {
73  ASSERT((id >= 0) && (id < size));
74 
75  if ((newage != -1) && ((age[id] > newage) || (age[id] == -1)))
76  age[id] = newage;
77  }
78 
79  inline void lub(const Item &dom) {
80  /* ASSERT((A == dom.A) && (size == dom.size)); */
81 
82  for (int i = 0; i < size; i++) {
83  if ((age[i] == -1) || ((age[i] < dom.age[i]) && (dom.age[i] != -1)) )
84  age[i] = dom.age[i];
85  }
86  }
87 
88  inline bool equals(const Item &dom) const {
89  ASSERT((A == dom.A) && (size == dom.size));
90  for (int i = 0; i < size; i++)
91  if (age[i] != dom.age[i])
92  return false;
93  return true;
94  }
95 
96  inline void empty() {
97  for (int i = 0; i < size; i++)
98  age[i] = -1;
99 
100  }
101 
102  inline bool contains(const int id) {
103  ASSERT((id < size) && (id >= 0));
104  return(age[id] != -1);
105  }
106 
107  inline void inject(MUSTProblem::Domain *must, const int id) {
108  if (must->contains(id)) {
109  for (int i = 0; i < size; i++) {
110  if ((age[i] < age[id]) && (age[i] != -1) && (age[i] != A))
111  age[i]++;
112  }
113  age[id] = 0;
114  } else {
115  for (int i = 0; i < size; i++) {
116  if ((age[i] != -1) && (age[i] != A))
117  age[i]++;
118  }
119  }
120  age[id] = 0;
121  }
122 
123  inline bool isWiped(const int id) {
124  return(age[id] == A);
125  }
126 
127  inline bool isPersistent(const int id) {
128  return(contains(id) && !isWiped(id));
129  }
130  inline int getAge(const int id) const {
131  ASSERT((id >= 0) && (id < size));
132  return age[id];
133  }
134 
135  inline void addDamage(const int id, int damage) {
136  ASSERT((id >= 0) && (id < size));
137  if (age[id] == -1)
138  return;
139  age[id] += damage;
140  if (age[id] > A)
141  age[id] = A;
142  }
143 
144  inline void print(elm::io::Output &output) const {
145  bool first = true;
146  output << "[";
147  for (int i = 0; i < size; i++) {
148  if (age[i] != -1) {
149  if (!first) {
150  output << ", ";
151  }
152  output << i << ":" << age[i];
153  first = false;
154  }
155  }
156  output << "]";
157 
158  }
159 
160  /*
161  * For each cache block belonging to the set:
162  * age[block] represents its age, from 0 (newest) to A-1 (oldest).
163  * The value -1 means that the block is not in the set.
164  */
165  int *age;
166  };
167 
168  class Domain {
169  int A, size;
170  bool isBottom;
171  public:
172 
173  inline Domain(const int _size, const int _A)
174  : A (_A), size(_size), whole(_size, _A)
175  {
176  isBottom = true;
177  whole.empty();
178  }
179 
180  inline ~Domain() {
181  for (int i = 0; i < data.length(); i++)
182  delete data[i];
183  }
184 
185  inline Domain(const Domain &source) : A(source.A), size(source.size), isBottom(source.isBottom), whole(source.whole) {
186 
187  for (int i = 0; i < source.data.length(); i++)
188  data.add(new Item(*source.data[i]));
189  }
190 
191  inline Domain& operator=(const Domain &src) {
192  if (src.isBottom) {
193  setToBottom();
194  } else {
195  whole = src.whole;
196  isBottom = false;
197 
198  /*
199  for (int i = 0; i < src.data.length(); i++)
200  data.add(new Item(*src.data[i]));
201  */
202  int sdl = src.data.length();
203  int dl = data.length();
204  int minl = (sdl > dl) ? dl : sdl;
205  data.setLength((sdl > dl) ? dl : sdl);
206 
207  for (int i = 0; i < minl; i++)
208  *data[i] = *src.data[i];
209 
210  for (int i = dl; i < sdl; i++)
211  data.add(new Item(*src.data[i]));
212 
213 
214  }
215  return *this;
216 
217  }
218 
219  inline void lub(const Domain &dom) {
220  /*
221  * Rules for the LUB:
222  * 1. lub(anything,bottom) == anything
223  * 2. lub(dom1,dom2) where dom1 and dom2 has the same size, do the LUB of each corresponding item.
224  * 3. lub(dom1,dom2) where dom1 has less items than dom2: we discard items of dom2 (starting from outer-most loop)
225  * until it has the same size as dom1, then apply rule 2.
226  */
227  if (dom.isBottom)
228  return;
229 
230  if (isBottom) {
231  for (int i = 0; i < dom.data.length(); i++)
232  data.add(new Item(*dom.data[i]));
233  whole = dom.whole;
234  isBottom = false;
235  return;
236  }
237 
238  int dl = data.length();
239  int ddl = dom.data.length();
240  int length = (dl < ddl) ? dl : ddl;
241 
242  for (int i = dl - 1, j = ddl - 1, k = 0; k < length; i--, j--, k++) {
243  data[i]->lub(*dom.data[j]);
244  }
245 
246  for (int i = 0; i < dl - length; i++) {
247  data.remove(0);
248  }
249  whole.lub(dom.whole);
250  }
251 
252 
253  inline void lub(const Item &item) {
254  /* Special LUB: do the lub of each Item in current domain with
255  * item passed as parameter. Used for the partial analysis
256  */
257  for (int i = 0; i < data.length(); i++)
258  data[i]->lub(item);
259 
260  whole.lub(item);
261 
262  }
263 
264 
265  inline bool equals(const Domain &dom) const {
266  ASSERT(!isBottom && !dom.isBottom);
267  for (int i = 0; i < dom.data.length(); i++) {
268  if (!data[i]->equals(*dom.data[i]))
269  return false;
270  }
271  return (whole.equals(dom.whole) && (isBottom == dom.isBottom));
272  }
273 
274  inline void empty() {
275  for (int i = 0; i < data.length(); i++)
276  delete data[i];
277  data.clear();
278  whole.empty();
279  isBottom = false;
280  }
281 
282  inline void setToBottom() {
283  for (int i = 0; i < data.length(); i++)
284  delete data[i];
285  data.clear();
286  whole.empty();
287  isBottom = true;
288  }
289 
290  inline Item &getWhole() {
291  return whole;
292  }
293 
294  inline bool contains(const int id, const int index) {
295  ASSERT(!isBottom);
296  return(data[index]->contains(id));
297  }
298 
299 
300  inline void inject(MUSTProblem::Domain *must, const int id) {
301  ASSERT(!isBottom);
302  for (int i = 0; i < data.length(); i++)
303  data[i]->inject(must, id);
304  whole.inject(must, id);
305  }
306 
307  inline bool isWiped(const int id, const int index) {
308  ASSERT(!isBottom);
309  return(data[index]->isWiped(id));
310 
311  }
312 
313  inline int getAge(const int id, const int index) const {
314  ASSERT(!isBottom);
315  return(data[index]->getAge(id));
316  }
317 
318  inline bool isPersistent(const int id, const int index) {
319  ASSERT(!isBottom);
320  return(data[index]->isPersistent(id));
321 
322  }
323  inline void addDamage(const int id, const int index, int damage) {
324  ASSERT(!isBottom);
325  data[index]->addDamage(id, damage);
326  }
327 
328  inline void addDamage(const int id, int damage) {
329  ASSERT(!isBottom);
330  for (int n = 0; n < data.length(); n++)
331  data[n]->addDamage(id, damage);
332  whole.addDamage(id, damage);
333  }
334 
335  inline void refresh(const int id, const int index, int newage) {
336  ASSERT(!isBottom);
337  data[index]->refresh(id, newage);
338  }
339 
340  inline void refresh(const int id, int newage) {
341  ASSERT(!isBottom);
342  for (int n = 0; n < data.length(); n++)
343  data[n]->refresh(id, newage);
344  whole.refresh(id, newage);
345  }
346 
347  inline void print(elm::io::Output &output) const {
348  bool first = true;
349  if (isBottom) {
350  output << "BOTTOM";
351  return;
352  }
353  output << "(W=";
354  whole.print(output);
355  output << ", ";
356  for (int i = 0; i < data.length(); i++) {
357  if (!first)
358  output << "|";
359  data[i]->print(output);
360  first = false;
361  }
362  output << ")";
363  }
364 
365  inline void enterContext() {
366  ASSERT(!isBottom);
367  Item item(size, A);
368  item.empty();
369  data.push(new Item(item));
370 
371  }
372 
373  inline void leaveContext() {
374  ASSERT(!isBottom);
375  Item *ptr = data.pop();
376  delete ptr;
377  }
378 
379  inline int length() {
380  ASSERT(!isBottom);
381  return data.length();
382  }
383 
384  inline Item& getItem(const int idx) const {
385  ASSERT(!isBottom);
386  return(*data.get(idx));
387  }
388 
389 
390  private:
391 
394 
395  };
396 
397 
399 
400  private:
401 
402  // Fields
409  const int line;
410 
411 
412  public:
413  // Public fields
414 
415  // Constructors
416  PERSProblem(const int _size, LBlockSet *_lbset, WorkSpace *_fw, const hard::Cache *_cache, const int _A);
417 
418  // Destructors
419  ~PERSProblem();
420 
421  // Problem methods
422  const Domain& bottom(void) const;
423  const Domain& entry(void) const;
424 
425  inline void lub(Domain &a, const Domain &b) const {
426  a.lub(b);
427  }
428  inline void assign(Domain &a, const Domain &b) const {
429  a = b;
430  }
431  inline bool equals(const Domain &a, const Domain &b) const {
432  return (a.equals(b));
433  }
434  void update(Domain& out, const Domain& in, BasicBlock* bb);
435 
436  inline void enterContext(Domain& dom, BasicBlock *header, hai_context_t ctx) {
437 #ifndef PERFTEST
438  if (ctx == CTX_LOOP)
439  dom.enterContext();
440 #endif
441  }
442 
443  inline void leaveContext(Domain& dom, BasicBlock *header, hai_context_t ctx) {
444 #ifndef PERFTEST
445  if (ctx == CTX_LOOP)
446  dom.leaveContext();
447 #endif
448  }
449 };
450 
451 elm::io::Output& operator<<(elm::io::Output& output, const PERSProblem::Domain& dom);
452 
453 }
454 
455 #endif /* CACHE_PERSPROBLEM_H_*/
void inject(MUSTProblem::Domain *must, const int id)
Definition: PERSProblem.h:107
dtd::RefAttr< BasicBlock * > source("source", dtd::STRICT|dtd::REQUIRED)
Domain callstate
Definition: PERSProblem.h:398
WorkSpace * fw
Definition: PERSProblem.h:405
void leaveContext(Domain &dom, BasicBlock *header, hai_context_t ctx)
Definition: PERSProblem.h:443
void empty()
Definition: PERSProblem.h:96
Domain & operator=(const Domain &src)
Definition: PERSProblem.h:191
Item whole
Definition: PERSProblem.h:392
Domain bot
Definition: PERSProblem.h:407
int A
Definition: PERSProblem.h:169
Domain(const Domain &source)
Definition: PERSProblem.h:185
LBlockSet * lbset
Definition: PERSProblem.h:403
CFG * cfg
Definition: PERSProblem.h:404
Item & getItem(const int idx) const
Definition: PERSProblem.h:384
void print(elm::io::Output &output) const
Definition: PERSProblem.h:347
int length()
Definition: PERSProblem.h:379
void setToBottom()
Definition: PERSProblem.h:282
int getAge(const int id, const int index) const
Definition: PERSProblem.h:313
bool contains(const int id, const int index)
Definition: PERSProblem.h:294
sys::SystemInStream & in
~Item()
Definition: PERSProblem.h:54
void lub(const Domain &dom)
Definition: PERSProblem.h:219
void lub(Domain &a, const Domain &b) const
Definition: PERSProblem.h:425
dtd::Element bb(dtd::make("bb", _BB).attr(id).attr(address).attr(size))
void refresh(const int id, const int index, int newage)
Definition: PERSProblem.h:335
void refresh(const int id, int newage)
Definition: PERSProblem.h:340
bool isPersistent(const int id, const int index)
Definition: PERSProblem.h:318
Definition: PERSProblem.h:42
elm::io::Output & operator<<(elm::io::Output &out, Address addr)
Definition: base.cpp:188
Control Flow Graph representation.
Definition: CFG.h:42
uint32 size
Item(const int _size, const int _A)
Definition: PERSProblem.h:46
const hard::Cache * cache
Definition: PERSProblem.h:406
void enterContext(Domain &dom, BasicBlock *header, hai_context_t ctx)
Definition: PERSProblem.h:436
void assign(Domain &a, const Domain &b) const
Definition: PERSProblem.h:428
void inject(MUSTProblem::Domain *must, const int id)
Definition: PERSProblem.h:300
bool equals(const Domain &dom) const
Definition: PERSProblem.h:265
Problem for computing the PERS ACS of L-blocks.
Definition: PERSProblem.h:38
const Domain & entry(void) const
Definition: cache_PERSProblem.cpp:62
int size
Definition: PERSProblem.h:169
bool isPersistent(const int id)
Definition: PERSProblem.h:127
bool isWiped(const int id)
Definition: PERSProblem.h:123
int size
Definition: PERSProblem.h:43
void update(Domain &out, const Domain &in, BasicBlock *bb)
Definition: cache_PERSProblem.cpp:66
Item & getWhole()
Definition: PERSProblem.h:290
int A
Definition: PERSProblem.h:43
bool isBottom
Definition: PERSProblem.h:170
A workspace represents a program, its run-time and all information about WCET computation or any othe...
Definition: WorkSpace.h:67
void addDamage(const int id, int damage)
Definition: PERSProblem.h:328
int getAge(const int id) const
Definition: PERSProblem.h:130
This class contains the configuration of a level of cache of processor.
Definition: Cache.h:34
bool contains(const int id)
Definition: MUSTProblem.h:127
void leaveContext()
Definition: PERSProblem.h:373
void lub(const Item &dom)
Definition: PERSProblem.h:79
sys::SystemOutStream & out
This class represents the list of l-blocks of a task for a chosen cache row.
Definition: LBlockSet.h:38
void print(elm::io::Output &output) const
Definition: PERSProblem.h:144
hai_context_t
Definition: HalfAbsInt.h:50
void addDamage(const int id, int damage)
Definition: PERSProblem.h:135
Definition: HalfAbsInt.h:51
const Domain & bottom(void) const
Definition: cache_PERSProblem.cpp:58
bool contains(const int id)
Definition: PERSProblem.h:102
~PERSProblem()
Definition: cache_PERSProblem.cpp:55
This is the minimal definition of a basic block.
Definition: BasicBlock.h:43
void empty()
Definition: PERSProblem.h:274
PERSProblem(const int _size, LBlockSet *_lbset, WorkSpace *_fw, const hard::Cache *_cache, const int _A)
Definition: cache_PERSProblem.cpp:37
void lub(const Item &item)
Definition: PERSProblem.h:253
const int line
Definition: PERSProblem.h:409
Item(const Item &source)
Definition: PERSProblem.h:58
Item & operator=(const Item &src)
Definition: PERSProblem.h:65
genstruct::Vector< Item * > data
Definition: PERSProblem.h:393
void enterContext()
Definition: PERSProblem.h:365
Domain(const int _size, const int _A)
Definition: PERSProblem.h:173
Definition: PERSProblem.h:168
bool equals(const Item &dom) const
Definition: PERSProblem.h:88
void refresh(int id, int newage)
Definition: PERSProblem.h:72
bool equals(const Domain &a, const Domain &b) const
Definition: PERSProblem.h:431
bool isWiped(const int id, const int index)
Definition: PERSProblem.h:307
void addDamage(const int id, const int index, int damage)
Definition: PERSProblem.h:323
int * age
Definition: PERSProblem.h:165
Domain ent
Definition: PERSProblem.h:408
Definition: MUSTProblem.h:44
~Domain()
Definition: PERSProblem.h:180