1/*
2 * Copyright (c) 2016-2018 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Copyright (c) 2004-2005 The Regents of The University of Michigan
15 * Copyright (c) 2013 Advanced Micro Devices, Inc.
16 * All rights reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions are
20 * met: redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer;
22 * redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution;
25 * neither the name of the copyright holders nor the names of its
26 * contributors may be used to endorse or promote products derived from
27 * this software without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 * Authors: Kevin Lim
42 *          Gabe Black
43 *          Steve Reinhardt
44 */
45
46#include "cpu/o3/regfile.hh"
47
48#include "cpu/o3/free_list.hh"
49#include "arch/generic/types.hh"
50#include "cpu/o3/free_list.hh"
51
52PhysRegFile::PhysRegFile(unsigned _numPhysicalIntRegs,
53                         unsigned _numPhysicalFloatRegs,
54                         unsigned _numPhysicalVecRegs,
55                         unsigned _numPhysicalVecPredRegs,
56                         unsigned _numPhysicalCCRegs,
57                         VecMode vmode)
58    : intRegFile(_numPhysicalIntRegs),
59      floatRegFile(_numPhysicalFloatRegs),
60      vectorRegFile(_numPhysicalVecRegs),
61      vecPredRegFile(_numPhysicalVecPredRegs),
62      ccRegFile(_numPhysicalCCRegs),
63      numPhysicalIntRegs(_numPhysicalIntRegs),
64      numPhysicalFloatRegs(_numPhysicalFloatRegs),
65      numPhysicalVecRegs(_numPhysicalVecRegs),
66      numPhysicalVecElemRegs(_numPhysicalVecRegs *
67                             NumVecElemPerVecReg),
68      numPhysicalVecPredRegs(_numPhysicalVecPredRegs),
69      numPhysicalCCRegs(_numPhysicalCCRegs),
70      totalNumRegs(_numPhysicalIntRegs
71                   + _numPhysicalFloatRegs
72                   + _numPhysicalVecRegs
73                   + _numPhysicalVecRegs * NumVecElemPerVecReg
74                   + _numPhysicalVecPredRegs
75                   + _numPhysicalCCRegs),
76      vecMode(vmode)
77{
78    PhysRegIndex phys_reg;
79    PhysRegIndex flat_reg_idx = 0;
80
81    if (TheISA::NumCCRegs == 0 && _numPhysicalCCRegs != 0) {
82        // Just make this a warning and go ahead and allocate them
83        // anyway, to keep from having to add checks everywhere
84        warn("Non-zero number of physical CC regs specified, even though\n"
85             "    ISA does not use them.\n");
86    }
87    // The initial batch of registers are the integer ones
88    for (phys_reg = 0; phys_reg < numPhysicalIntRegs; phys_reg++) {
89        intRegIds.emplace_back(IntRegClass, phys_reg, flat_reg_idx++);
90    }
91
92    // The next batch of the registers are the floating-point physical
93    // registers; put them onto the floating-point free list.
94    for (phys_reg = 0; phys_reg < numPhysicalFloatRegs; phys_reg++) {
95        floatRegIds.emplace_back(FloatRegClass, phys_reg, flat_reg_idx++);
96    }
97
98    // The next batch of the registers are the vector physical
99    // registers; put them onto the vector free list.
100    for (phys_reg = 0; phys_reg < numPhysicalVecRegs; phys_reg++) {
101        vectorRegFile[phys_reg].zero();
102        vecRegIds.emplace_back(VecRegClass, phys_reg, flat_reg_idx++);
103    }
104    // The next batch of the registers are the vector element physical
105    // registers; they refer to the same containers as the vector
106    // registers, just a different (and incompatible) way to access
107    // them; put them onto the vector free list.
108    for (phys_reg = 0; phys_reg < numPhysicalVecRegs; phys_reg++) {
109        for (ElemIndex eIdx = 0; eIdx < NumVecElemPerVecReg; eIdx++) {
110            vecElemIds.emplace_back(VecElemClass, phys_reg,
111                    eIdx, flat_reg_idx++);
112        }
113    }
114
115    // The next batch of the registers are the predicate physical
116    // registers; put them onto the predicate free list.
117    for (phys_reg = 0; phys_reg < numPhysicalVecPredRegs; phys_reg++) {
118        vecPredRegIds.emplace_back(VecPredRegClass, phys_reg, flat_reg_idx++);
119    }
120
121    // The rest of the registers are the condition-code physical
122    // registers; put them onto the condition-code free list.
123    for (phys_reg = 0; phys_reg < numPhysicalCCRegs; phys_reg++) {
124        ccRegIds.emplace_back(CCRegClass, phys_reg, flat_reg_idx++);
125    }
126
127    // Misc regs have a fixed mapping but still need PhysRegIds.
128    for (phys_reg = 0; phys_reg < TheISA::NumMiscRegs; phys_reg++) {
129        miscRegIds.emplace_back(MiscRegClass, phys_reg, 0);
130    }
131}
132
133
134void
135PhysRegFile::initFreeList(UnifiedFreeList *freeList)
136{
137    // Initialize the free lists.
138    int reg_idx = 0;
139
140    // The initial batch of registers are the integer ones
141    for (reg_idx = 0; reg_idx < numPhysicalIntRegs; reg_idx++) {
142        assert(intRegIds[reg_idx].index() == reg_idx);
143    }
144    freeList->addRegs(intRegIds.begin(), intRegIds.end());
145
146    // The next batch of the registers are the floating-point physical
147    // registers; put them onto the floating-point free list.
148    for (reg_idx = 0; reg_idx < numPhysicalFloatRegs; reg_idx++) {
149        assert(floatRegIds[reg_idx].index() == reg_idx);
150    }
151    freeList->addRegs(floatRegIds.begin(), floatRegIds.end());
152
153    /* The next batch of the registers are the vector physical
154     * registers; put them onto the vector free list. */
155    for (reg_idx = 0; reg_idx < numPhysicalVecRegs; reg_idx++) {
156        assert(vecRegIds[reg_idx].index() == reg_idx);
157        for (ElemIndex elemIdx = 0; elemIdx < NumVecElemPerVecReg; elemIdx++) {
158            assert(vecElemIds[reg_idx * NumVecElemPerVecReg +
159                    elemIdx].index() == reg_idx);
160            assert(vecElemIds[reg_idx * NumVecElemPerVecReg +
161                    elemIdx].elemIndex() == elemIdx);
162        }
163    }
164
165    /* depending on the mode we add the vector registers as whole units or
166     * as different elements. */
167    if (vecMode == Enums::Full)
168        freeList->addRegs(vecRegIds.begin(), vecRegIds.end());
169    else
170        freeList->addRegs(vecElemIds.begin(), vecElemIds.end());
171
172    // The next batch of the registers are the predicate physical
173    // registers; put them onto the predicate free list.
174    for (reg_idx = 0; reg_idx < numPhysicalVecPredRegs; reg_idx++) {
175        assert(vecPredRegIds[reg_idx].index() == reg_idx);
176    }
177    freeList->addRegs(vecPredRegIds.begin(), vecPredRegIds.end());
178
179    // The rest of the registers are the condition-code physical
180    // registers; put them onto the condition-code free list.
181    for (reg_idx = 0; reg_idx < numPhysicalCCRegs; reg_idx++) {
182        assert(ccRegIds[reg_idx].index() == reg_idx);
183    }
184    freeList->addRegs(ccRegIds.begin(), ccRegIds.end());
185}
186
187auto
188PhysRegFile::getRegElemIds(PhysRegIdPtr reg) -> IdRange
189{
190    panic_if(!reg->isVectorPhysReg(),
191            "Trying to get elems of a %s register", reg->className());
192    auto idx = reg->index();
193    return std::make_pair(
194                vecElemIds.begin() + idx * NumVecElemPerVecReg,
195                vecElemIds.begin() + (idx+1) * NumVecElemPerVecReg);
196}
197
198auto
199PhysRegFile::getRegIds(RegClass cls) -> IdRange
200{
201    switch (cls)
202    {
203      case IntRegClass:
204        return std::make_pair(intRegIds.begin(), intRegIds.end());
205      case FloatRegClass:
206        return std::make_pair(floatRegIds.begin(), floatRegIds.end());
207      case VecRegClass:
208        return std::make_pair(vecRegIds.begin(), vecRegIds.end());
209      case VecElemClass:
210        return std::make_pair(vecElemIds.begin(), vecElemIds.end());
211      case VecPredRegClass:
212        return std::make_pair(vecPredRegIds.begin(), vecPredRegIds.end());
213      case CCRegClass:
214        return std::make_pair(ccRegIds.begin(), ccRegIds.end());
215      case MiscRegClass:
216        return std::make_pair(miscRegIds.begin(), miscRegIds.end());
217    }
218    /* There is no way to make an empty iterator */
219    return std::make_pair(PhysIds::iterator(),
220                          PhysIds::iterator());
221}
222
223PhysRegIdPtr
224PhysRegFile::getTrueId(PhysRegIdPtr reg)
225{
226    switch (reg->classValue()) {
227    case VecRegClass:
228        return &vecRegIds[reg->index()];
229    case VecElemClass:
230        return &vecElemIds[reg->index() * NumVecElemPerVecReg +
231            reg->elemIndex()];
232    default:
233        panic_if(!reg->isVectorPhysElem(),
234            "Trying to get the register of a %s register", reg->className());
235    }
236    return nullptr;
237}
238
239