1/*
2 * Copyright (c) 2013-2014 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 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 * Authors: Andrew Bardsley
38 */
39
40#include "cpu/minor/func_unit.hh"
41
42#include <iomanip>
43#include <sstream>
44#include <typeinfo>
45
46#include "debug/MinorTiming.hh"
47#include "enums/OpClass.hh"
48
49MinorOpClass *
50MinorOpClassParams::create()
51{
52    return new MinorOpClass(this);
53}
54
55MinorOpClassSet *
56MinorOpClassSetParams::create()
57{
58    return new MinorOpClassSet(this);
59}
60
61MinorFUTiming *
62MinorFUTimingParams::create()
63{
64    return new MinorFUTiming(this);
65}
66
67MinorFU *
68MinorFUParams::create()
69{
70    return new MinorFU(this);
71}
72
73MinorFUPool *
74MinorFUPoolParams::create()
75{
76    return new MinorFUPool(this);
77}
78
79MinorOpClassSet::MinorOpClassSet(const MinorOpClassSetParams *params) :
80    SimObject(params),
81    opClasses(params->opClasses),
82    /* Initialise to true for an empty list so that 'fully capable' is
83     *  the default */
84    capabilityList(Num_OpClasses, (opClasses.empty() ? true : false))
85{
86    for (unsigned int i = 0; i < opClasses.size(); i++)
87        capabilityList[opClasses[i]->opClass] = true;
88}
89
90MinorFUTiming::MinorFUTiming(
91    const MinorFUTimingParams *params) :
92    SimObject(params),
93    mask(params->mask),
94    match(params->match),
95    description(params->description),
96    suppress(params->suppress),
97    extraCommitLat(params->extraCommitLat),
98    extraCommitLatExpr(params->extraCommitLatExpr),
99    extraAssumedLat(params->extraAssumedLat),
100    srcRegsRelativeLats(params->srcRegsRelativeLats),
101    opClasses(params->opClasses)
102{ }
103
104namespace Minor
105{
106
107void
108QueuedInst::reportData(std::ostream &os) const
109{
110    inst->reportData(os);
111}
112
113FUPipeline::FUPipeline(const std::string &name, const MinorFU &description_,
114    ClockedObject &timeSource_) :
115    FUPipelineBase(name, "insts", description_.opLat),
116    description(description_),
117    timeSource(timeSource_),
118    nextInsertCycle(Cycles(0))
119{
120    /* Issue latencies are set to 1 in calls to addCapability here.
121     * Issue latencies are associated with the pipeline as a whole,
122     * rather than instruction classes in Minor */
123
124    /* All pipelines should be able to execute No_OpClass instructions */
125    addCapability(No_OpClass, description.opLat, 1);
126
127    /* Add the capabilities listed in the MinorFU for this functional unit */
128    for (unsigned int i = 0; i < description.opClasses->opClasses.size();
129         i++)
130    {
131        addCapability(description.opClasses->opClasses[i]->opClass,
132            description.opLat, 1);
133    }
134
135    for (unsigned int i = 0; i < description.timings.size(); i++) {
136        MinorFUTiming &timing = *(description.timings[i]);
137
138        if (DTRACE(MinorTiming)) {
139            std::ostringstream lats;
140
141            unsigned int num_lats = timing.srcRegsRelativeLats.size();
142            unsigned int j = 0;
143            while (j < num_lats) {
144                lats << timing.srcRegsRelativeLats[j];
145
146                j++;
147                if (j != num_lats)
148                    lats << ',';
149            }
150
151            DPRINTFS(MinorTiming, static_cast<Named *>(this),
152                "Adding extra timing decode pattern %d to FU"
153                " mask: %016x match: %016x srcRegLatencies: %s\n",
154                i, timing.mask, timing.match, lats.str());
155        }
156    }
157
158    const std::vector<unsigned> &cant_forward =
159        description.cantForwardFromFUIndices;
160
161    /* Setup the bit vector cantForward... with the set indices
162     *  specified in the parameters */
163    for (auto i = cant_forward.begin(); i != cant_forward.end(); ++i) {
164        cantForwardFromFUIndices.resize((*i) + 1, false);
165        cantForwardFromFUIndices[*i] = true;
166    }
167}
168
169Cycles
170FUPipeline::cyclesBeforeInsert()
171{
172    if (nextInsertCycle == 0 || timeSource.curCycle() > nextInsertCycle)
173        return Cycles(0);
174    else
175        return nextInsertCycle - timeSource.curCycle();
176}
177
178bool
179FUPipeline::canInsert() const
180{
181    return nextInsertCycle == 0 || timeSource.curCycle() >= nextInsertCycle;
182}
183
184void
185FUPipeline::advance()
186{
187    bool was_stalled = stalled;
188
189    /* If an instruction was pushed into the pipeline, set the delay before
190     *  the next instruction can follow */
191    if (alreadyPushed()) {
192        if (nextInsertCycle <= timeSource.curCycle()) {
193            nextInsertCycle = timeSource.curCycle() + description.issueLat;
194        }
195    } else if (was_stalled && nextInsertCycle != 0) {
196        /* Don't count stalled cycles as part of the issue latency */
197        ++nextInsertCycle;
198    }
199    FUPipelineBase::advance();
200}
201
202MinorFUTiming *
203FUPipeline::findTiming(const StaticInstPtr &inst)
204{
205#if THE_ISA == ARM_ISA
206    /* This should work for any ISA with a POD mach_inst */
207    TheISA::ExtMachInst mach_inst = inst->machInst;
208#else
209    /* Just allow extra decode based on op classes */
210    uint64_t mach_inst = 0;
211#endif
212
213    const std::vector<MinorFUTiming *> &timings =
214        description.timings;
215    unsigned int num_timings = timings.size();
216
217    for (unsigned int i = 0; i < num_timings; i++) {
218        MinorFUTiming &timing = *timings[i];
219
220        if (timing.provides(inst->opClass()) &&
221            (mach_inst & timing.mask) == timing.match)
222        {
223            DPRINTFS(MinorTiming, static_cast<Named *>(this),
224                "Found extra timing match (pattern %d '%s')"
225                " %s %16x (type %s)\n",
226                i, timing.description, inst->disassemble(0), mach_inst,
227                typeid(inst).name());
228
229            return &timing;
230        }
231    }
232
233    if (num_timings != 0) {
234        DPRINTFS(MinorTiming, static_cast<Named *>(this),
235            "No extra timing info. found for inst: %s"
236            " mach_inst: %16x\n",
237            inst->disassemble(0), mach_inst);
238    }
239
240    return NULL;
241}
242
243}
244