2 * Copyright (c) 2007 MIPS Technologies, Inc.
3 * Copyright (c) 2013 Advanced Micro Devices, Inc.
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.
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.
29 * Authors: Korey Sewell
36 #include "arch/isa_traits.hh"
37 #include "config/the_isa.hh"
38 #include "cpu/inorder/resources/use_def.hh"
39 #include "cpu/inorder/cpu.hh"
40 #include "cpu/inorder/pipeline_traits.hh"
41 #include "debug/InOrderStall.hh"
42 #include "debug/InOrderUseDef.hh"
45 using namespace TheISA
;
46 using namespace ThePipeline
;
48 UseDefUnit::UseDefUnit(string res_name
, int res_id
, int res_width
,
49 Cycles res_latency
, InOrderCPU
*_cpu
,
50 ThePipeline::Params
*params
)
51 : Resource(res_name
, res_id
, res_width
, res_latency
, _cpu
)
53 for (ThreadID tid
= 0; tid
< ThePipeline::MaxThreads
; tid
++) {
54 nonSpecInstActive
[tid
] = &cpu
->nonSpecInstActive
[tid
];
55 nonSpecSeqNum
[tid
] = &cpu
->nonSpecSeqNum
[tid
];
56 serializeOnNextInst
[tid
] = false;
57 serializeAfterSeqNum
[tid
] = 0;
58 regDepMap
[tid
] = &cpu
->archRegDepMap
[tid
];
64 UseDefUnit::regStats()
67 .name(name() + ".uniqueRegsPerSwitch")
68 .desc("Number of Unique Registers Needed Per Context Switch")
69 .prereq(uniqueRegsPerSwitch
);
72 .name(name() + ".intRegFileReads")
73 .desc("Number of Reads from Int. Register File");
76 .name(name() + ".intRegFileWrites")
77 .desc("Number of Writes to Int. Register File");
80 .name(name() + ".intRegFileAccesses")
81 .desc("Total Accesses (Read+Write) to the Int. Register File");
82 intRegFileAccs
= intRegFileReads
+ intRegFileWrites
;
85 .name(name() + ".floatRegFileReads")
86 .desc("Number of Reads from FP Register File");
89 .name(name() + ".floatRegFileWrites")
90 .desc("Number of Writes to FP Register File");
93 .name(name() + ".floatRegFileAccesses")
94 .desc("Total Accesses (Read+Write) to the FP Register File");
95 floatRegFileAccs
= floatRegFileReads
+ floatRegFileWrites
;
97 //@todo: add miscreg reads/writes
98 // add forwarding by type???
101 .name(name() + ".regForwards")
102 .desc("Number of Registers Read Through Forwarding Logic");
104 Resource::regStats();
110 // Set Up Resource Events to Appropriate Resource BandWidth
111 if (latency
> Cycles(0)) {
112 resourceEvent
= new ResourceEvent
[width
];
114 resourceEvent
= NULL
;
117 for (int i
= 0; i
< width
; i
++) {
118 reqs
[i
] = new UseDefRequest(this);
125 UseDefUnit::getRequest(DynInstPtr inst
, int stage_num
, int res_idx
,
126 int slot_num
, unsigned cmd
)
128 UseDefRequest
*ud_req
= dynamic_cast<UseDefRequest
*>(reqs
[slot_num
]);
129 ud_req
->setRequest(inst
, stage_num
, id
, slot_num
, cmd
,
130 inst
->curSkedEntry
->idx
);
136 UseDefUnit::findRequest(DynInstPtr inst
)
138 for (int i
= 0; i
< width
; i
++) {
139 UseDefRequest
* ud_req
=
140 dynamic_cast<UseDefRequest
*>(reqs
[i
]);
144 ud_req
->getInst() == inst
&&
145 ud_req
->cmd
== inst
->curSkedEntry
->cmd
&&
146 ud_req
->useDefIdx
== inst
->curSkedEntry
->idx
) {
155 UseDefUnit::execute(int slot_idx
)
157 UseDefRequest
* ud_req
= dynamic_cast<UseDefRequest
*>(reqs
[slot_idx
]);
158 DynInstPtr inst
= ud_req
->inst
;
159 ThreadID tid
= inst
->readTid();
160 InstSeqNum seq_num
= inst
->seqNum
;
161 int ud_idx
= ud_req
->useDefIdx
;
163 if (serializeOnNextInst
[tid
] &&
164 seq_num
> serializeAfterSeqNum
[tid
]) {
165 inst
->setSerializeBefore();
166 serializeOnNextInst
[tid
] = false;
169 if ((inst
->isIprAccess() || inst
->isSerializeBefore()) &&
170 cpu
->instList
[tid
].front() != inst
) {
171 DPRINTF(InOrderUseDef
, "[tid:%i]: [sn:%i] Serialize before instruction encountered."
172 " Blocking until pipeline is clear.\n", tid
, seq_num
);
175 } else if (inst
->isStoreConditional() || inst
->isSerializeAfter()) {
176 DPRINTF(InOrderUseDef
, "[tid:%i]: [sn:%i] Serialize after instruction encountered."
177 " Blocking until pipeline is clear.\n", tid
, seq_num
);
178 serializeOnNextInst
[tid
] = true;
179 serializeAfterSeqNum
[tid
] = seq_num
;
182 if (inst
->fault
!= NoFault
) {
183 DPRINTF(InOrderUseDef
,
184 "[tid:%i]: [sn:%i]: Detected %s fault @ %x. Forwarding to "
185 "next stage.\n", inst
->readTid(), inst
->seqNum
, inst
->fault
->name(),
191 // If there is a non-speculative instruction
192 // in the pipeline then stall instructions here
194 if (*nonSpecInstActive
[tid
] && seq_num
> *nonSpecSeqNum
[tid
]) {
195 DPRINTF(InOrderUseDef
, "[tid:%i]: [sn:%i] cannot execute because"
196 "there is non-speculative instruction [sn:%i] has not "
197 "graduated.\n", tid
, seq_num
, *nonSpecSeqNum
[tid
]);
200 } else if (inst
->isNonSpeculative()) {
201 *nonSpecInstActive
[tid
] = true;
202 *nonSpecSeqNum
[tid
] = seq_num
;
210 RegIndex reg_idx
= inst
->_srcRegIdx
[ud_idx
];
211 RegIndex flat_idx
= cpu
->flattenRegIdx(reg_idx
, reg_type
, tid
);
212 inst
->flattenSrcReg(ud_idx
, flat_idx
);
214 if (flat_idx
== TheISA::ZeroReg
&& reg_type
== IntRegClass
) {
215 DPRINTF(InOrderUseDef
, "[tid:%i]: [sn:%i]: Ignoring Reading of ISA-ZeroReg "
216 "(Int. Reg %i).\n", tid
, inst
->seqNum
, flat_idx
);
220 DPRINTF(InOrderUseDef
, "[tid:%i]: [sn:%i]: Attempting to read source "
221 "register idx %i (reg #%i, flat#%i).\n",
222 tid
, seq_num
, ud_idx
, reg_idx
, flat_idx
);
225 if (regDepMap
[tid
]->canRead(reg_type
, flat_idx
, inst
)) {
230 uniqueIntRegMap
[flat_idx
] = true;
232 DPRINTF(InOrderUseDef
, "[tid:%i]: [sn:%i]: Reading Int Reg %i"
233 " (%i) from Register File:0x%x.\n",
236 cpu
->readIntReg(flat_idx
,inst
->readTid()));
237 inst
->setIntSrc(ud_idx
,
238 cpu
->readIntReg(flat_idx
,
246 uniqueFloatRegMap
[flat_idx
] = true;
247 DPRINTF(InOrderUseDef
, "[tid:%i]: [sn:%i]: Reading Float Reg %i"
248 " (%i) from Register File:%x (%08f).\n",
250 reg_idx
- FP_Reg_Base
, flat_idx
,
251 cpu
->readFloatRegBits(flat_idx
,
253 cpu
->readFloatReg(flat_idx
,
256 inst
->setFloatSrc(ud_idx
,
257 cpu
->readFloatReg(flat_idx
,
259 inst
->setFloatRegBitsSrc(ud_idx
,
260 cpu
->readFloatRegBits(flat_idx
,
268 uniqueMiscRegMap
[flat_idx
] = true;
269 DPRINTF(InOrderUseDef
, "[tid:%i]: [sn:%i]: Reading Misc Reg %i "
270 " (%i) from Register File:0x%x.\n",
272 reg_idx
- Misc_Reg_Base
, flat_idx
,
273 cpu
->readMiscReg(flat_idx
,
275 inst
->setIntSrc(ud_idx
,
276 cpu
->readMiscReg(flat_idx
,
282 panic("Invalid Register Type: %i", reg_type
);
287 // Look for forwarding opportunities
288 DynInstPtr forward_inst
= regDepMap
[tid
]->canForward(reg_type
,
294 forward_inst
->getDestIdxNum(flat_idx
);
300 DPRINTF(InOrderUseDef
, "[tid:%i]: Forwarding dest."
301 " reg %i (%i), value 0x%x from "
302 "[sn:%i] to [sn:%i] source #%x.\n",
303 tid
, reg_idx
, flat_idx
,
304 forward_inst
->readIntResult(dest_reg_idx
),
305 forward_inst
->seqNum
,
306 inst
->seqNum
, ud_idx
);
307 inst
->setIntSrc(ud_idx
,
309 readIntResult(dest_reg_idx
));
315 DPRINTF(InOrderUseDef
, "[tid:%i]: Forwarding dest."
316 " reg %i (%i) value 0x%x from "
317 "[sn:%i] to [sn:%i] source #%i.\n",
318 tid
, reg_idx
- FP_Reg_Base
, flat_idx
,
319 forward_inst
->readFloatResult(dest_reg_idx
),
320 forward_inst
->seqNum
, inst
->seqNum
, ud_idx
);
321 inst
->setFloatSrc(ud_idx
,
323 readFloatResult(dest_reg_idx
));
329 DPRINTF(InOrderUseDef
, "[tid:%i]: Forwarding dest."
330 " reg %i (%i) value 0x%x from "
331 "[sn:%i] to [sn:%i] source #%i.\n",
332 tid
, reg_idx
- Misc_Reg_Base
, flat_idx
,
333 forward_inst
->readIntResult(dest_reg_idx
),
334 forward_inst
->seqNum
,
335 inst
->seqNum
, ud_idx
);
336 inst
->setIntSrc(ud_idx
,
338 readIntResult(dest_reg_idx
));
343 panic("Invalid Register Type: %i", reg_type
);
349 DPRINTF(InOrderUseDef
, "[tid:%i]: Source register idx: %i "
350 "is not ready to read.\n",
352 DPRINTF(InOrderStall
, "STALL: [tid:%i]: waiting to read "
353 "register (idx=%i)\n",
364 RegIndex reg_idx
= inst
->_destRegIdx
[ud_idx
];
365 RegIndex flat_idx
= cpu
->flattenRegIdx(reg_idx
, reg_type
, tid
);
367 if (flat_idx
== TheISA::ZeroReg
&& reg_type
== IntRegClass
) {
368 DPRINTF(IntRegs
, "[tid:%i]: Ignoring Writing of ISA-ZeroReg "
369 "(Int. Reg %i)\n", tid
, flat_idx
);
374 if (regDepMap
[tid
]->canWrite(reg_type
, flat_idx
, inst
)) {
375 DPRINTF(InOrderUseDef
, "[tid:%i]: [sn:%i]: Flattening register idx %i "
376 "(%i) and Attempting to write to Register File.\n",
377 tid
, seq_num
, reg_idx
, flat_idx
);
383 uniqueIntRegMap
[flat_idx
] = true;
385 DPRINTF(InOrderUseDef
, "[tid:%i]: [sn:%i]: Writing Int. Result "
386 "0x%x to register idx %i (%i).\n",
387 tid
, seq_num
, inst
->readIntResult(ud_idx
),
390 // Remove Dependencies
391 regDepMap
[tid
]->removeFront(reg_type
, flat_idx
, inst
);
393 cpu
->setIntReg(flat_idx
,
394 inst
->readIntResult(ud_idx
),
402 uniqueFloatRegMap
[flat_idx
] = true;
404 // Remove Reg. Dependecny Block on this Register
405 regDepMap
[tid
]->removeFront(reg_type
, flat_idx
, inst
);
407 if (inst
->resultType(ud_idx
) ==
408 InOrderDynInst::FloatBits
) {
409 DPRINTF(InOrderUseDef
, "[tid:%i]: [sn:%i]: Writing FP-Bits "
410 "Result %08f (bits:0x%x) to register "
413 inst
->readFloatResult(ud_idx
),
414 inst
->readFloatBitsResult(ud_idx
),
415 reg_idx
- FP_Reg_Base
, flat_idx
);
417 // Check for FloatRegBits Here
418 cpu
->setFloatRegBits(flat_idx
,
419 inst
->readFloatBitsResult(ud_idx
),
421 } else if (inst
->resultType(ud_idx
) ==
422 InOrderDynInst::Float
) {
423 DPRINTF(InOrderUseDef
, "[tid:%i]: [sn:%i]: Writing Float "
424 "Result %08f (bits:0x%x) to register "
426 tid
, seq_num
, inst
->readFloatResult(ud_idx
),
427 inst
->readIntResult(ud_idx
),
428 reg_idx
- FP_Reg_Base
, flat_idx
);
430 cpu
->setFloatReg(flat_idx
,
431 inst
->readFloatResult(ud_idx
),
433 } else if (inst
->resultType(ud_idx
) ==
434 InOrderDynInst::Double
) {
435 DPRINTF(InOrderUseDef
, "[tid:%i]: [sn:%i]: Writing Double "
436 "Result %08f (bits:0x%x) to register "
439 inst
->readFloatResult(ud_idx
),
440 inst
->readIntResult(ud_idx
),
441 reg_idx
- FP_Reg_Base
, flat_idx
);
443 cpu
->setFloatReg(flat_idx
,
444 inst
->readFloatResult(ud_idx
),
447 panic("Result Type Not Set For [sn:%i] %s.\n",
448 inst
->seqNum
, inst
->instName());
451 floatRegFileWrites
++;
457 uniqueMiscRegMap
[flat_idx
] = true;
459 DPRINTF(InOrderUseDef
, "[tid:%i]: Writing Misc. 0x%x "
460 "to register idx %i.\n",
461 tid
, inst
->readIntResult(ud_idx
), reg_idx
- Misc_Reg_Base
);
463 // Remove Dependencies
464 regDepMap
[tid
]->removeFront(reg_type
, flat_idx
, inst
);
466 cpu
->setMiscReg(flat_idx
,
467 inst
->readIntResult(ud_idx
),
473 panic("Invalid Register Type: %i", reg_type
);
478 DPRINTF(InOrderUseDef
, "[tid:%i]: [sn:%i]: Dest. register idx: %i is "
479 "not ready to write.\n",
480 tid
, seq_num
, reg_idx
);
481 DPRINTF(InOrderStall
, "STALL: [tid:%i]: waiting to write "
482 "register (idx=%i)\n",
491 regDepMap
[tid
]->insert(inst
);
497 fatal("Unrecognized command to %s", resName
);
503 UseDefUnit::updateAfterContextSwitch(DynInstPtr inst
, ThreadID tid
)
505 uniqueRegsPerSwitch
= uniqueIntRegMap
.size() + uniqueFloatRegMap
.size()
506 + uniqueMiscRegMap
.size();
507 uniqueIntRegMap
.clear();
508 uniqueFloatRegMap
.clear();
509 uniqueMiscRegMap
.clear();