2 * Copyright (c) 2007 MIPS Technologies, Inc.
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.
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.
28 * Authors: Korey Sewell
35 #include "arch/isa_traits.hh"
36 #include "config/the_isa.hh"
37 #include "cpu/inorder/resources/use_def.hh"
38 #include "cpu/inorder/cpu.hh"
39 #include "cpu/inorder/pipeline_traits.hh"
42 using namespace TheISA
;
43 using namespace ThePipeline
;
45 UseDefUnit::UseDefUnit(string res_name
, int res_id
, int res_width
,
46 int res_latency
, InOrderCPU
*_cpu
,
47 ThePipeline::Params
*params
)
48 : Resource(res_name
, res_id
, res_width
, res_latency
, _cpu
),
49 maxSeqNum((InstSeqNum
)-1)
51 for (ThreadID tid
= 0; tid
< ThePipeline::MaxThreads
; tid
++) {
52 nonSpecInstActive
[tid
] = &cpu
->nonSpecInstActive
[tid
];
53 nonSpecSeqNum
[tid
] = &cpu
->nonSpecSeqNum
[tid
];
55 outReadSeqNum
[tid
] = maxSeqNum
;
56 outWriteSeqNum
[tid
] = maxSeqNum
;
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() + ".regFileReads")
73 .desc("Number of Reads from Register File");
76 .name(name() + ".regForwards")
77 .desc("Number of Registers Read Through Forwarding Logic");
80 .name(name() + ".regFileWrites")
81 .desc("Number of Writes to Register File");
84 .name(name() + ".regFileAccesses")
85 .desc("Number of Total Accesses (Read+Write) to the Register File");
86 regFileAccs
= regFileReads
+ regFileWrites
;
94 // Set Up Resource Events to Appropriate Resource BandWidth
96 resourceEvent
= new ResourceEvent
[width
];
101 for (int i
= 0; i
< width
; i
++) {
102 reqs
[i
] = new UseDefRequest(this);
109 UseDefUnit::getRequest(DynInstPtr inst
, int stage_num
, int res_idx
,
110 int slot_num
, unsigned cmd
)
112 UseDefRequest
*ud_req
= dynamic_cast<UseDefRequest
*>(reqs
[slot_num
]);
113 ud_req
->setRequest(inst
, stage_num
, id
, slot_num
, cmd
,
114 inst
->curSkedEntry
->idx
);
120 UseDefUnit::findRequest(DynInstPtr inst
)
122 for (int i
= 0; i
< width
; i
++) {
123 UseDefRequest
* ud_req
=
124 dynamic_cast<UseDefRequest
*>(reqs
[i
]);
128 ud_req
->getInst() == inst
&&
129 ud_req
->cmd
== inst
->curSkedEntry
->cmd
&&
130 ud_req
->useDefIdx
== inst
->curSkedEntry
->idx
) {
139 UseDefUnit::execute(int slot_idx
)
141 // After this is working, change this to a reinterpret cast
142 // for performance considerations
143 UseDefRequest
* ud_req
= dynamic_cast<UseDefRequest
*>(reqs
[slot_idx
]);
146 DynInstPtr inst
= ud_req
->inst
;
147 ThreadID tid
= inst
->readTid();
148 InstSeqNum seq_num
= inst
->seqNum
;
149 int ud_idx
= ud_req
->useDefIdx
;
151 // If there is a non-speculative instruction
152 // in the pipeline then stall instructions here
153 if (*nonSpecInstActive
[tid
] == true &&
154 seq_num
> *nonSpecSeqNum
[tid
]) {
155 DPRINTF(InOrderUseDef
, "[tid:%i]: [sn:%i] cannot execute because"
156 "there is non-speculative instruction [sn:%i] has not "
157 "graduated.\n", tid
, seq_num
, *nonSpecSeqNum
[tid
]);
159 } else if (inst
->isNonSpeculative()) {
160 *nonSpecInstActive
[tid
] = true;
161 *nonSpecSeqNum
[tid
] = seq_num
;
168 int reg_idx
= inst
->_srcRegIdx
[ud_idx
];
170 DPRINTF(InOrderUseDef
, "[tid:%i]: Attempting to read source "
171 "register idx %i (reg #%i).\n",
172 tid
, ud_idx
, reg_idx
);
174 // Ask register dependency map if it is OK to read from Arch.
176 if (regDepMap
[tid
]->canRead(reg_idx
, inst
)) {
178 uniqueRegMap
[reg_idx
] = true;
180 if (inst
->seqNum
<= outReadSeqNum
[tid
]) {
181 if (reg_idx
< FP_Base_DepTag
) {
182 DPRINTF(InOrderUseDef
, "[tid:%i]: Reading Int Reg %i"
183 "from Register File:%i.\n",
186 cpu
->readIntReg(reg_idx
,inst
->readTid()));
187 inst
->setIntSrc(ud_idx
,
188 cpu
->readIntReg(reg_idx
,
190 } else if (reg_idx
< Ctrl_Base_DepTag
) {
191 reg_idx
-= FP_Base_DepTag
;
192 DPRINTF(InOrderUseDef
, "[tid:%i]: Reading Float Reg %i"
193 "from Register File:%x (%08f).\n",
196 cpu
->readFloatRegBits(reg_idx
,
198 cpu
->readFloatReg(reg_idx
,
201 inst
->setFloatSrc(ud_idx
,
202 cpu
->readFloatReg(reg_idx
,
205 reg_idx
-= Ctrl_Base_DepTag
;
206 DPRINTF(InOrderUseDef
, "[tid:%i]: Reading Misc Reg %i "
207 "from Register File:%i.\n",
210 cpu
->readMiscReg(reg_idx
,
212 inst
->setIntSrc(ud_idx
,
213 cpu
->readMiscReg(reg_idx
,
217 outReadSeqNum
[tid
] = maxSeqNum
;
221 DPRINTF(InOrderUseDef
, "[tid:%i]: Unable to read because "
222 "of [sn:%i] hasnt read it's registers yet.\n",
223 tid
, outReadSeqNum
[tid
]);
224 DPRINTF(InOrderStall
, "STALL: [tid:%i]: waiting for "
225 "[sn:%i] to write\n",
226 tid
, outReadSeqNum
[tid
]);
231 // Look for forwarding opportunities
232 DynInstPtr forward_inst
= regDepMap
[tid
]->canForward(reg_idx
,
237 if (inst
->seqNum
<= outReadSeqNum
[tid
]) {
239 forward_inst
->getDestIdxNum(reg_idx
);
241 if (reg_idx
< FP_Base_DepTag
) {
242 DPRINTF(InOrderUseDef
, "[tid:%i]: Forwarding dest."
243 " reg value 0x%x from "
244 "[sn:%i] to [sn:%i] source #%i.\n",
246 forward_inst
->readIntResult(dest_reg_idx
),
247 forward_inst
->seqNum
,
248 inst
->seqNum
, ud_idx
);
249 inst
->setIntSrc(ud_idx
,
251 readIntResult(dest_reg_idx
));
252 } else if (reg_idx
< Ctrl_Base_DepTag
) {
253 DPRINTF(InOrderUseDef
, "[tid:%i]: Forwarding dest."
254 " reg value 0x%x from "
255 "[sn:%i] to [sn:%i] source #%i.\n",
257 forward_inst
->readFloatResult(dest_reg_idx
),
258 forward_inst
->seqNum
, inst
->seqNum
, ud_idx
);
259 inst
->setFloatSrc(ud_idx
,
261 readFloatResult(dest_reg_idx
));
263 DPRINTF(InOrderUseDef
, "[tid:%i]: Forwarding dest."
264 " reg value 0x%x from "
265 "[sn:%i] to [sn:%i] source #%i.\n",
267 forward_inst
->readIntResult(dest_reg_idx
),
268 forward_inst
->seqNum
,
269 inst
->seqNum
, ud_idx
);
270 inst
->setIntSrc(ud_idx
,
272 readIntResult(dest_reg_idx
));
275 outReadSeqNum
[tid
] = maxSeqNum
;
279 DPRINTF(InOrderUseDef
, "[tid:%i]: Unable to read "
280 "because of [sn:%i] hasnt read it's"
281 " registers yet.\n", tid
, outReadSeqNum
[tid
]);
282 DPRINTF(InOrderStall
, "STALL: [tid:%i]: waiting for "
283 "[sn:%i] to forward\n",
284 tid
, outReadSeqNum
[tid
]);
288 DPRINTF(InOrderUseDef
, "[tid:%i]: Source register idx: %i"
289 "is not ready to read.\n",
291 DPRINTF(InOrderStall
, "STALL: [tid:%i]: waiting to read "
292 "register (idx=%i)\n",
294 outReadSeqNum
[tid
] = inst
->seqNum
;
303 int reg_idx
= inst
->_destRegIdx
[ud_idx
];
305 if (regDepMap
[tid
]->canWrite(reg_idx
, inst
)) {
306 DPRINTF(InOrderUseDef
, "[tid:%i]: Flattening register idx %i &"
307 "Attempting to write to Register File.\n",
309 uniqueRegMap
[reg_idx
] = true;
310 if (inst
->seqNum
<= outReadSeqNum
[tid
]) {
311 if (reg_idx
< FP_Base_DepTag
) {
312 DPRINTF(InOrderUseDef
, "[tid:%i]: Writing Int. Result "
313 "0x%x to register idx %i.\n",
314 tid
, inst
->readIntResult(ud_idx
), reg_idx
);
316 // Remove Dependencies
317 regDepMap
[tid
]->removeFront(reg_idx
, inst
);
319 cpu
->setIntReg(reg_idx
,
320 inst
->readIntResult(ud_idx
),
322 } else if(reg_idx
< Ctrl_Base_DepTag
) {
323 // Remove Dependencies
324 regDepMap
[tid
]->removeFront(reg_idx
, inst
);
326 reg_idx
-= FP_Base_DepTag
;
328 if (inst
->resultType(ud_idx
) ==
329 InOrderDynInst::Integer
) {
330 DPRINTF(InOrderUseDef
, "[tid:%i]: Writing FP-Bits "
331 "Result 0x%x (bits:0x%x) to register "
334 inst
->readFloatResult(ud_idx
),
335 inst
->readIntResult(ud_idx
),
338 // Check for FloatRegBits Here
339 cpu
->setFloatRegBits(reg_idx
,
340 inst
->readIntResult(ud_idx
),
342 } else if (inst
->resultType(ud_idx
) ==
343 InOrderDynInst::Float
) {
344 DPRINTF(InOrderUseDef
, "[tid:%i]: Writing Float "
345 "Result 0x%x (bits:0x%x) to register "
347 tid
, inst
->readFloatResult(ud_idx
),
348 inst
->readIntResult(ud_idx
),
351 cpu
->setFloatReg(reg_idx
,
352 inst
->readFloatResult(ud_idx
),
354 } else if (inst
->resultType(ud_idx
) ==
355 InOrderDynInst::Double
) {
356 DPRINTF(InOrderUseDef
, "[tid:%i]: Writing Double "
357 "Result 0x%x (bits:0x%x) to register "
360 inst
->readFloatResult(ud_idx
),
361 inst
->readIntResult(ud_idx
),
364 // Check for FloatRegBits Here
365 cpu
->setFloatReg(reg_idx
,
366 inst
->readFloatResult(ud_idx
),
369 panic("Result Type Not Set For [sn:%i] %s.\n",
370 inst
->seqNum
, inst
->instName());
374 DPRINTF(InOrderUseDef
, "[tid:%i]: Writing Misc. 0x%x "
375 "to register idx %i.\n",
376 tid
, inst
->readIntResult(ud_idx
), reg_idx
);
378 // Remove Dependencies
379 regDepMap
[tid
]->removeFront(reg_idx
, inst
);
381 reg_idx
-= Ctrl_Base_DepTag
;
383 cpu
->setMiscReg(reg_idx
,
384 inst
->readIntResult(ud_idx
),
388 outWriteSeqNum
[tid
] = maxSeqNum
;
392 DPRINTF(InOrderUseDef
, "[tid:%i]: Unable to write because "
393 "of [sn:%i] hasnt read it's"
394 " registers yet.\n", tid
, outReadSeqNum
);
395 DPRINTF(InOrderStall
, "STALL: [tid:%i]: waiting for "
401 DPRINTF(InOrderUseDef
, "[tid:%i]: Dest. register idx: %i is "
402 "not ready to write.\n",
404 DPRINTF(InOrderStall
, "STALL: [tid:%i]: waiting to write "
405 "register (idx=%i)\n",
407 outWriteSeqNum
[tid
] = inst
->seqNum
;
414 fatal("Unrecognized command to %s", resName
);
420 UseDefUnit::squash(DynInstPtr inst
, int stage_num
, InstSeqNum squash_seq_num
,
423 DPRINTF(InOrderUseDef
, "[tid:%i]: Updating Due To Squash After [sn:%i].\n",
424 tid
, squash_seq_num
);
426 for (int i
= 0; i
< width
; i
++) {
427 ResReqPtr req_ptr
= reqs
[i
];
429 if (req_ptr
->valid
&&
430 req_ptr
->getInst()->readTid() == tid
&&
431 req_ptr
->getInst()->seqNum
> squash_seq_num
) {
433 DPRINTF(InOrderUseDef
, "[tid:%i]: Squashing [sn:%i].\n",
434 req_ptr
->getInst()->readTid(),
435 req_ptr
->getInst()->seqNum
);
437 int req_slot_num
= req_ptr
->getSlot();
442 unscheduleEvent(req_slot_num
);
445 freeSlot(req_slot_num
);
449 if (outReadSeqNum
[tid
] >= squash_seq_num
) {
450 DPRINTF(InOrderUseDef
, "[tid:%i]: Outstanding Read Seq Num Reset.\n",
452 outReadSeqNum
[tid
] = maxSeqNum
;
453 } else if (outReadSeqNum
[tid
] != maxSeqNum
) {
454 DPRINTF(InOrderUseDef
, "[tid:%i]: No need to reset Outstanding Read "
456 tid
, outReadSeqNum
[tid
]);
459 if (outWriteSeqNum
[tid
] >= squash_seq_num
) {
460 DPRINTF(InOrderUseDef
, "[tid:%i]: Outstanding Write Seq Num Reset.\n",
462 outWriteSeqNum
[tid
] = maxSeqNum
;
463 } else if (outWriteSeqNum
[tid
] != maxSeqNum
) {
464 DPRINTF(InOrderUseDef
, "[tid:%i]: No need to reset Outstanding Write "
466 tid
, outWriteSeqNum
[tid
]);
471 UseDefUnit::updateAfterContextSwitch(DynInstPtr inst
, ThreadID tid
)
473 uniqueRegsPerSwitch
= uniqueRegMap
.size();
474 uniqueRegMap
.clear();