Address.hh revision 6239
1/*
2 * Copyright (c) 1999 Mark D. Hill and David A. Wood
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#ifndef ADDRESS_H
30#define ADDRESS_H
31
32#include <iomanip>
33#include "mem/ruby/common/Global.hh"
34#include "mem/ruby/config/RubyConfig.hh"
35#include "mem/ruby/system/NodeID.hh"
36#include "mem/ruby/system/MachineID.hh"
37
38const int ADDRESS_WIDTH = 64; // address width in bytes
39
40class Address;
41typedef Address PhysAddress;
42typedef Address VirtAddress;
43
44class Address {
45public:
46  // Constructors
47  Address() { m_address = 0; }
48  explicit Address(physical_address_t address) { m_address = address; }
49
50  Address(const Address& obj);
51  Address& operator=(const Address& obj);
52
53  // Destructor
54  //  ~Address();
55
56  // Public Methods
57
58  void setAddress(physical_address_t address) { m_address = address; }
59  physical_address_t getAddress() const {return m_address;}
60  // selects bits inclusive
61  physical_address_t bitSelect(int small, int big) const;
62  physical_address_t maskLowOrderBits(int number) const;
63  physical_address_t maskHighOrderBits(int number) const;
64  physical_address_t shiftLowOrderBits(int number) const;
65  physical_address_t getLineAddress() const
66    { return bitSelect(RubyConfig::dataBlockBits(), ADDRESS_WIDTH); }
67  physical_address_t getOffset() const
68    { return bitSelect(0, RubyConfig::dataBlockBits()-1); }
69
70  void makeLineAddress() { m_address = maskLowOrderBits(RubyConfig::dataBlockBits()); }
71  // returns the next stride address based on line address
72  void makeNextStrideAddress( int stride) {
73    m_address = maskLowOrderBits(RubyConfig::dataBlockBits())
74      + RubyConfig::dataBlockBytes()*stride;
75  }
76  void makePageAddress() { m_address = maskLowOrderBits(RubyConfig::pageSizeBits()); }
77  int getBankSetNum() const;
78  int getBankSetDist() const;
79
80  Index memoryModuleIndex() const;
81
82  void print(ostream& out) const;
83  void output(ostream& out) const;
84  void input(istream& in);
85
86  void setOffset( int offset ){
87    // first, zero out the offset bits
88    makeLineAddress();
89    m_address |= (physical_address_t) offset;
90  }
91
92private:
93  // Private Methods
94
95  // Private copy constructor and assignment operator
96  //  Address(const Address& obj);
97  //  Address& operator=(const Address& obj);
98
99  // Data Members (m_ prefix)
100  physical_address_t m_address;
101};
102
103inline
104Address line_address(const Address& addr) { Address temp(addr); temp.makeLineAddress(); return temp; }
105
106inline
107Address next_stride_address(const Address& addr, int stride) {
108  Address temp = addr;
109  temp.makeNextStrideAddress(stride);
110  temp.setAddress(temp.maskHighOrderBits(ADDRESS_WIDTH-RubyConfig::memorySizeBits()));  // surpress wrap-around problem
111  return temp;
112}
113
114inline
115Address page_address(const Address& addr) { Address temp(addr); temp.makePageAddress(); return temp; }
116
117// Output operator declaration
118ostream& operator<<(ostream& out, const Address& obj);
119// comparison operator declaration
120bool operator==(const Address& obj1, const Address& obj2);
121bool operator!=(const Address& obj1, const Address& obj2);
122bool operator<(const Address& obj1, const Address& obj2);
123/* Address& operator=(const physical_address_t address); */
124
125inline
126bool operator<(const Address& obj1, const Address& obj2)
127{
128  return obj1.getAddress() < obj2.getAddress();
129}
130
131// ******************* Definitions *******************
132
133// Output operator definition
134inline
135ostream& operator<<(ostream& out, const Address& obj)
136{
137  obj.print(out);
138  out << flush;
139  return out;
140}
141
142inline
143bool operator==(const Address& obj1, const Address& obj2)
144{
145  return (obj1.getAddress() == obj2.getAddress());
146}
147
148inline
149bool operator!=(const Address& obj1, const Address& obj2)
150{
151  return (obj1.getAddress() != obj2.getAddress());
152}
153
154inline
155physical_address_t Address::bitSelect(int small, int big) const // rips bits inclusive
156{
157  physical_address_t mask;
158  assert(big >= small);
159
160  if (big >= ADDRESS_WIDTH - 1) {
161    return (m_address >> small);
162  } else {
163    mask = ~((physical_address_t)~0 << (big + 1));
164    // FIXME - this is slow to manipulate a 64-bit number using 32-bits
165    physical_address_t partial = (m_address & mask);
166    return (partial >> small);
167  }
168}
169
170inline
171physical_address_t Address::maskLowOrderBits(int number) const
172{
173  physical_address_t mask;
174
175  if (number >= ADDRESS_WIDTH - 1) {
176    mask = ~0;
177  } else {
178    mask = (physical_address_t)~0 << number;
179  }
180  return (m_address & mask);
181}
182
183inline
184physical_address_t Address::maskHighOrderBits(int number) const
185{
186  physical_address_t mask;
187
188  if (number >= ADDRESS_WIDTH - 1) {
189    mask = ~0;
190  } else {
191    mask = (physical_address_t)~0 >> number;
192  }
193  return (m_address & mask);
194}
195
196inline
197physical_address_t Address::shiftLowOrderBits(int number) const
198{
199  return (m_address >> number);
200}
201
202inline
203integer_t Address::memoryModuleIndex() const
204{
205  integer_t index = bitSelect(RubyConfig::dataBlockBits()+RubyConfig::memoryBits(), ADDRESS_WIDTH);
206  assert (index >= 0);
207  if (index >= RubyConfig::memoryModuleBlocks()) {
208    cerr << " memoryBits: " << RubyConfig::memoryBits() << " memorySizeBits: " << RubyConfig::memorySizeBits()
209         << " Address: " << "[" << hex << "0x" << m_address << "," << " line 0x" << maskLowOrderBits(RubyConfig::dataBlockBits()) << dec << "]" << flush
210         << "error: limit exceeded. " <<
211      " dataBlockBits: " << RubyConfig::dataBlockBits() <<
212      " memoryModuleBlocks: " << RubyConfig::memoryModuleBlocks() <<
213      " index: " << index << endl;
214  }
215  assert (index < RubyConfig::memoryModuleBlocks());
216  return index;
217
218  //  Index indexHighPortion = address.bitSelect(MEMORY_SIZE_BITS-1, PAGE_SIZE_BITS+NUMBER_OF_MEMORY_MODULE_BITS);
219  //  Index indexLowPortion  = address.bitSelect(DATA_BLOCK_BITS, PAGE_SIZE_BITS-1);
220
221  //Index index = indexLowPortion | (indexHighPortion << (PAGE_SIZE_BITS - DATA_BLOCK_BITS));
222
223  /*
224  Round-robin mapping of addresses, at page size granularity
225
226ADDRESS_WIDTH    MEMORY_SIZE_BITS        PAGE_SIZE_BITS  DATA_BLOCK_BITS
227  |                    |                       |               |
228 \ /                  \ /                     \ /             \ /       0
229  -----------------------------------------------------------------------
230  |       unused        |xxxxxxxxxxxxxxx|       |xxxxxxxxxxxxxxx|       |
231  |                     |xxxxxxxxxxxxxxx|       |xxxxxxxxxxxxxxx|       |
232  -----------------------------------------------------------------------
233                        indexHighPortion         indexLowPortion
234                                        <------->
235                               NUMBER_OF_MEMORY_MODULE_BITS
236  */
237}
238
239inline
240void Address::print(ostream& out) const
241{
242  out << "[" << hex << "0x" << m_address << "," << " line 0x" << maskLowOrderBits(RubyConfig::dataBlockBits()) << dec << "]" << flush;
243}
244
245class Address;
246namespace __gnu_cxx {
247  template <> struct hash<Address>
248  {
249    size_t operator()(const Address &s) const { return (size_t) s.getAddress(); }
250  };
251}
252namespace std {
253  template <> struct equal_to<Address>
254  {
255    bool operator()(const Address& s1, const Address& s2) const { return s1 == s2; }
256  };
257}
258
259#endif //ADDRESS_H
260
261