Port: Stricter port bind/unbind semantics
[gem5.git] / src / cpu / o3 / rename_map.cc
1 /*
2 * Copyright (c) 2004-2005 The Regents of The University of Michigan
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 * Authors: Kevin Lim
29 */
30
31 #include <vector>
32
33 #include "cpu/o3/rename_map.hh"
34 #include "debug/Rename.hh"
35
36 using namespace std;
37
38 // @todo: Consider making inline bool functions that determine if the
39 // register is a logical int, logical fp, physical int, physical fp,
40 // etc.
41
42 SimpleRenameMap::~SimpleRenameMap()
43 {
44 }
45
46 void
47 SimpleRenameMap::init(unsigned _numLogicalIntRegs,
48 unsigned _numPhysicalIntRegs,
49 PhysRegIndex &ireg_idx,
50
51 unsigned _numLogicalFloatRegs,
52 unsigned _numPhysicalFloatRegs,
53 PhysRegIndex &freg_idx,
54
55 unsigned _numMiscRegs,
56
57 RegIndex _intZeroReg,
58 RegIndex _floatZeroReg,
59
60 int map_id,
61 bool bindRegs)
62 {
63 id = map_id;
64
65 numLogicalIntRegs = _numLogicalIntRegs;
66
67 numLogicalFloatRegs = _numLogicalFloatRegs;
68
69 numPhysicalIntRegs = _numPhysicalIntRegs;
70
71 numPhysicalFloatRegs = _numPhysicalFloatRegs;
72
73 numMiscRegs = _numMiscRegs;
74
75 intZeroReg = _intZeroReg;
76 floatZeroReg = _floatZeroReg;
77
78 DPRINTF(Rename, "Creating rename map %i. Phys: %i / %i, Float: "
79 "%i / %i.\n", id, numLogicalIntRegs, numPhysicalIntRegs,
80 numLogicalFloatRegs, numPhysicalFloatRegs);
81
82 numLogicalRegs = numLogicalIntRegs + numLogicalFloatRegs;
83
84 numPhysicalRegs = numPhysicalIntRegs + numPhysicalFloatRegs;
85
86 //Create the rename maps
87 intRenameMap.resize(numLogicalIntRegs);
88 floatRenameMap.resize(numLogicalRegs);
89
90 if (bindRegs) {
91 DPRINTF(Rename, "Binding registers into rename map %i\n",id);
92
93 // Initialize the entries in the integer rename map to point to the
94 // physical registers of the same index
95 for (RegIndex index = 0; index < numLogicalIntRegs; ++index)
96 {
97 intRenameMap[index].physical_reg = ireg_idx++;
98 }
99
100 // Initialize the entries in the floating point rename map to point to
101 // the physical registers of the same index
102 // Although the index refers purely to architected registers, because
103 // the floating reg indices come after the integer reg indices, they
104 // may exceed the size of a normal RegIndex (short).
105 for (PhysRegIndex index = numLogicalIntRegs;
106 index < numLogicalRegs; ++index)
107 {
108 floatRenameMap[index].physical_reg = freg_idx++;
109 }
110 } else {
111 DPRINTF(Rename, "Binding registers into rename map %i\n",id);
112
113 PhysRegIndex temp_ireg = ireg_idx;
114
115 for (RegIndex index = 0; index < numLogicalIntRegs; ++index)
116 {
117 intRenameMap[index].physical_reg = temp_ireg++;
118 }
119
120 PhysRegIndex temp_freg = freg_idx;
121
122 for (PhysRegIndex index = numLogicalIntRegs;
123 index < numLogicalRegs; ++index)
124 {
125 floatRenameMap[index].physical_reg = temp_freg++;
126 }
127 }
128 }
129
130 void
131 SimpleRenameMap::setFreeList(SimpleFreeList *fl_ptr)
132 {
133 freeList = fl_ptr;
134 }
135
136
137 SimpleRenameMap::RenameInfo
138 SimpleRenameMap::rename(RegIndex arch_reg)
139 {
140 PhysRegIndex renamed_reg;
141 PhysRegIndex prev_reg;
142
143 if (arch_reg < numLogicalIntRegs) {
144
145 // Record the current physical register that is renamed to the
146 // requested architected register.
147 prev_reg = intRenameMap[arch_reg].physical_reg;
148
149 // If it's not referencing the zero register, then rename the
150 // register.
151 if (arch_reg != intZeroReg) {
152 renamed_reg = freeList->getIntReg();
153
154 intRenameMap[arch_reg].physical_reg = renamed_reg;
155
156 assert(renamed_reg >= 0 && renamed_reg < numPhysicalIntRegs);
157
158 } else {
159 // Otherwise return the zero register so nothing bad happens.
160 renamed_reg = intZeroReg;
161 }
162 } else if (arch_reg < numLogicalRegs) {
163 // Record the current physical register that is renamed to the
164 // requested architected register.
165 prev_reg = floatRenameMap[arch_reg].physical_reg;
166
167 // If it's not referencing the zero register, then rename the
168 // register.
169 #if THE_ISA == ALPHA_ISA
170 if (arch_reg != floatZeroReg) {
171 #endif
172 renamed_reg = freeList->getFloatReg();
173
174 floatRenameMap[arch_reg].physical_reg = renamed_reg;
175
176 assert(renamed_reg < numPhysicalRegs &&
177 renamed_reg >= numPhysicalIntRegs);
178 #if THE_ISA == ALPHA_ISA
179 } else {
180 // Otherwise return the zero register so nothing bad happens.
181 renamed_reg = floatZeroReg;
182 }
183 #endif
184 } else {
185 // Subtract off the base offset for miscellaneous registers.
186 arch_reg = arch_reg - numLogicalRegs;
187
188 DPRINTF(Rename, "Renamed misc reg %d\n", arch_reg);
189
190 // No renaming happens to the misc. registers. They are
191 // simply the registers that come after all the physical
192 // registers; thus take the base architected register and add
193 // the physical registers to it.
194 renamed_reg = arch_reg + numPhysicalRegs;
195
196 // Set the previous register to the same register; mainly it must be
197 // known that the prev reg was outside the range of normal registers
198 // so the free list can avoid adding it.
199 prev_reg = renamed_reg;
200 }
201
202 DPRINTF(Rename, "Renamed reg %d to physical reg %d old mapping was %d\n",
203 arch_reg, renamed_reg, prev_reg);
204
205 return RenameInfo(renamed_reg, prev_reg);
206 }
207
208 PhysRegIndex
209 SimpleRenameMap::lookup(RegIndex arch_reg)
210 {
211 if (arch_reg < numLogicalIntRegs) {
212 return intRenameMap[arch_reg].physical_reg;
213 } else if (arch_reg < numLogicalRegs) {
214 return floatRenameMap[arch_reg].physical_reg;
215 } else {
216 // Subtract off the misc registers offset.
217 arch_reg = arch_reg - numLogicalRegs;
218
219 // Misc. regs don't rename, so simply add the base arch reg to
220 // the number of physical registers.
221 return numPhysicalRegs + arch_reg;
222 }
223 }
224
225 void
226 SimpleRenameMap::setEntry(RegIndex arch_reg, PhysRegIndex renamed_reg)
227 {
228 // In this implementation the miscellaneous registers do not
229 // actually rename, so this function does not allow you to try to
230 // change their mappings.
231 if (arch_reg < numLogicalIntRegs) {
232 DPRINTF(Rename, "Rename Map: Integer register %i being set to %i.\n",
233 (int)arch_reg, renamed_reg);
234
235 intRenameMap[arch_reg].physical_reg = renamed_reg;
236 } else if (arch_reg < numLogicalIntRegs + numLogicalFloatRegs) {
237 DPRINTF(Rename, "Rename Map: Float register %i being set to %i.\n",
238 (int)arch_reg - numLogicalIntRegs, renamed_reg);
239
240 floatRenameMap[arch_reg].physical_reg = renamed_reg;
241 }
242 }
243
244 int
245 SimpleRenameMap::numFreeEntries()
246 {
247 int free_int_regs = freeList->numFreeIntRegs();
248 int free_float_regs = freeList->numFreeFloatRegs();
249
250 if (free_int_regs < free_float_regs) {
251 return free_int_regs;
252 } else {
253 return free_float_regs;
254 }
255 }