1/*
2 * Copyright (c) 2004-2005 The Regents of The University of Michigan
3 * Copyright (c) 2013 Advanced Micro Devices, Inc.
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
9 * notice, this list of conditions and the following disclaimer;
10 * redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution;
13 * neither the name of the copyright holders nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * Authors: Kevin Lim
30 */
31
32#ifndef __CPU_O3_FREE_LIST_HH__
33#define __CPU_O3_FREE_LIST_HH__
34
35#include <iostream>
36#include <queue>
37
38#include "base/misc.hh"
39#include "base/trace.hh"
40#include "cpu/o3/comm.hh"
41#include "cpu/o3/regfile.hh"
42#include "debug/FreeList.hh"
43
44/**
45 * Free list for a single class of registers (e.g., integer
46 * or floating point). Because the register class is implicitly
47 * determined by the rename map instance being accessed, all
48 * architectural register index parameters and values in this class
49 * are relative (e.g., %fp2 is just index 2).
50 */
51class SimpleFreeList
52{
53 private:
54
55 /** The actual free list */
56 std::queue<PhysRegIndex> freeRegs;
57
58 public:
59
60 SimpleFreeList() {};
61
62 /** Add a physical register to the free list */
63 void addReg(PhysRegIndex reg) { freeRegs.push(reg); }
64
65 /** Get the next available register from the free list */
66 PhysRegIndex getReg()
67 {
68 assert(!freeRegs.empty());
69 PhysRegIndex free_reg = freeRegs.front();
70 freeRegs.pop();
71 return free_reg;
72 }
73
74 /** Return the number of free registers on the list. */
75 unsigned numFreeRegs() const { return freeRegs.size(); }
76
77 /** True iff there are free registers on the list. */
78 bool hasFreeRegs() const { return !freeRegs.empty(); }
79};
80
81
82/**
83 * FreeList class that simply holds the list of free integer and floating
84 * point registers. Can request for a free register of either type, and
85 * also send back free registers of either type. This is a very simple
86 * class, but it should be sufficient for most implementations. Like all
87 * other classes, it assumes that the indices for the floating point
88 * registers starts after the integer registers end. Hence the variable
89 * numPhysicalIntRegs is logically equivalent to the baseFP dependency.
90 * Note that while this most likely should be called FreeList, the name
91 * "FreeList" is used in a typedef within the CPU Policy, and therefore no
92 * class can be named simply "FreeList".
93 * @todo: Give a better name to the base FP dependency.
94 */
95class UnifiedFreeList
96{
97 private:
98
99 /** The object name, for DPRINTF. We have to declare this
100 * explicitly because Scoreboard is not a SimObject. */
101 const std::string _name;
102
103 /** The list of free integer registers. */
104 SimpleFreeList intList;
105
106 /** The list of free floating point registers. */
107 SimpleFreeList floatList;
108
109 /** The list of free condition-code registers. */
110 SimpleFreeList ccList;
111
112 /**
113 * The register file object is used only to distinguish integer
114 * from floating-point physical register indices.
115 */
116 PhysRegFile *regFile;
117
118 /*
119 * We give UnifiedRenameMap internal access so it can get at the
120 * internal per-class free lists and associate those with its
121 * per-class rename maps. See UnifiedRenameMap::init().
122 */
123 friend class UnifiedRenameMap;
124
125 public:
126 /** Constructs a free list.
127 * @param _numPhysicalIntRegs Number of physical integer registers.
128 * @param reservedIntRegs Number of integer registers already
129 * used by initial mappings.
130 * @param _numPhysicalFloatRegs Number of physical fp registers.
131 * @param reservedFloatRegs Number of fp registers already
132 * used by initial mappings.
133 */
134 UnifiedFreeList(const std::string &_my_name, PhysRegFile *_regFile);
135
136 /** Gives the name of the freelist. */
137 std::string name() const { return _name; };
138
139 /** Returns a pointer to the condition-code free list */
140 SimpleFreeList *getCCList() { return &ccList; }
141
142 /** Gets a free integer register. */
143 PhysRegIndex getIntReg() { return intList.getReg(); }
144
145 /** Gets a free fp register. */
146 PhysRegIndex getFloatReg() { return floatList.getReg(); }
147
148 /** Gets a free cc register. */
149 PhysRegIndex getCCReg() { return ccList.getReg(); }
150
151 /** Adds a register back to the free list. */
152 void addReg(PhysRegIndex freed_reg);
153
154 /** Adds an integer register back to the free list. */
155 void addIntReg(PhysRegIndex freed_reg) { intList.addReg(freed_reg); }
156
157 /** Adds a fp register back to the free list. */
158 void addFloatReg(PhysRegIndex freed_reg) { floatList.addReg(freed_reg); }
159
160 /** Adds a cc register back to the free list. */
161 void addCCReg(PhysRegIndex freed_reg) { ccList.addReg(freed_reg); }
162
163 /** Checks if there are any free integer registers. */
164 bool hasFreeIntRegs() const { return intList.hasFreeRegs(); }
165
166 /** Checks if there are any free fp registers. */
167 bool hasFreeFloatRegs() const { return floatList.hasFreeRegs(); }
168
169 /** Checks if there are any free cc registers. */
170 bool hasFreeCCRegs() const { return ccList.hasFreeRegs(); }
171
172 /** Returns the number of free integer registers. */
173 unsigned numFreeIntRegs() const { return intList.numFreeRegs(); }
174
175 /** Returns the number of free fp registers. */
176 unsigned numFreeFloatRegs() const { return floatList.numFreeRegs(); }
177
178 /** Returns the number of free cc registers. */
179 unsigned numFreeCCRegs() const { return ccList.numFreeRegs(); }
180};
181
182inline void
183UnifiedFreeList::addReg(PhysRegIndex freed_reg)
184{
185 DPRINTF(FreeList,"Freeing register %i.\n", freed_reg);
186 //Might want to add in a check for whether or not this register is
187 //already in there. A bit vector or something similar would be useful.
188 if (regFile->isIntPhysReg(freed_reg)) {
189 intList.addReg(freed_reg);
172 } else {
173 assert(regFile->isFloatPhysReg(freed_reg));
190 } else if (regFile->isFloatPhysReg(freed_reg)) {
191 floatList.addReg(freed_reg);
192 } else {
193 assert(regFile->isCCPhysReg(freed_reg));
194 ccList.addReg(freed_reg);
195 }
196
197 // These assert conditions ensure that the number of free
198 // registers are not more than the # of total Physical Registers.
199 // If this were false, it would mean that registers
200 // have been freed twice, overflowing the free register
201 // pool and potentially crashing SMT workloads.
202 // ----
203 // Comment out for now so as to not potentially break
204 // CMP and single-threaded workloads
205 // ----
206 // assert(freeIntRegs.size() <= numPhysicalIntRegs);
207 // assert(freeFloatRegs.size() <= numPhysicalFloatRegs);
208}
209
210
211#endif // __CPU_O3_FREE_LIST_HH__