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
32 #include "cpu/inorder/resource_pool.hh"
33 #include "cpu/inorder/resources/resource_list.hh"
39 using namespace ThePipeline
;
41 ResourcePool::ResourcePool(InOrderCPU
*_cpu
, ThePipeline::Params
*params
)
44 //@todo: use this function to instantiate the resources in resource pool. This will help in the
45 //auto-generation of this pipeline model.
46 //ThePipeline::addResources(resources, memObjects);
48 // Declare Resource Objects
49 // name - id - bandwidth - latency - CPU - Parameters
50 // --------------------------------------------------
51 resources
.push_back(new FetchSeqUnit("Fetch-Seq-Unit", FetchSeq
, StageWidth
* 2, 0, _cpu
, params
));
53 memObjects
.push_back(ICache
);
54 resources
.push_back(new CacheUnit("icache_port", ICache
, StageWidth
* MaxThreads
, 0, _cpu
, params
));
56 resources
.push_back(new DecodeUnit("Decode-Unit", Decode
, StageWidth
, 0, _cpu
, params
));
58 resources
.push_back(new BranchPredictor("Branch-Predictor", BPred
, StageWidth
, 0, _cpu
, params
));
60 resources
.push_back(new InstBuffer("Fetch-Buffer-T0", FetchBuff
, 4, 0, _cpu
, params
));
62 resources
.push_back(new UseDefUnit("RegFile-Manager", RegManager
, StageWidth
* MaxThreads
, 0, _cpu
, params
));
64 resources
.push_back(new AGENUnit("AGEN-Unit", AGEN
, StageWidth
, 0, _cpu
, params
));
66 resources
.push_back(new ExecutionUnit("Execution-Unit", ExecUnit
, StageWidth
, 0, _cpu
, params
));
68 resources
.push_back(new MultDivUnit("Mult-Div-Unit", MDU
, 5, 0, _cpu
, params
));
70 memObjects
.push_back(DCache
);
71 resources
.push_back(new CacheUnit("dcache_port", DCache
, StageWidth
* MaxThreads
, 0, _cpu
, params
));
73 resources
.push_back(new GraduationUnit("Graduation-Unit", Grad
, StageWidth
* MaxThreads
, 0, _cpu
, params
));
75 resources
.push_back(new InstBuffer("Fetch-Buffer-T1", FetchBuff2
, 4, 0, _cpu
, params
));
81 for (int i
=0; i
< resources
.size(); i
++) {
82 DPRINTF(Resource
, "Initializing resource: %s.\n", resources
[i
]->name());
91 return cpu
->name() + ".ResourcePool";
96 ResourcePool::regStats()
98 DPRINTF(Resource
, "Registering Stats Throughout Resource Pool.\n");
100 int num_resources
= resources
.size();
102 for (int idx
= 0; idx
< num_resources
; idx
++) {
103 resources
[idx
]->regStats();
108 ResourcePool::getPort(const std::string
&if_name
, int idx
)
110 DPRINTF(Resource
, "Binding %s in Resource Pool.\n", if_name
);
112 for (int i
= 0; i
< memObjects
.size(); i
++) {
113 int obj_idx
= memObjects
[i
];
114 Port
*port
= resources
[obj_idx
]->getPort(if_name
, idx
);
116 DPRINTF(Resource
, "%s set to resource %s(#%i) in Resource Pool.\n", if_name
,
117 resources
[obj_idx
]->name(), obj_idx
);
126 ResourcePool::getPortIdx(const std::string
&port_name
)
128 DPRINTF(Resource
, "Finding Port Idx for %s.\n", port_name
);
130 for (int i
= 0; i
< memObjects
.size(); i
++) {
131 unsigned obj_idx
= memObjects
[i
];
132 Port
*port
= resources
[obj_idx
]->getPort(port_name
, obj_idx
);
134 DPRINTF(Resource
, "Returning Port Idx %i for %s.\n", obj_idx
, port_name
);
143 ResourcePool::getResIdx(const std::string
&res_name
)
145 DPRINTF(Resource
, "Finding Resource Idx for %s.\n", res_name
);
147 int num_resources
= resources
.size();
149 for (int idx
= 0; idx
< num_resources
; idx
++) {
150 if (resources
[idx
]->name() == res_name
)
158 ResourcePool::request(int res_idx
, DynInstPtr inst
)
160 //Make Sure This is a valid resource ID
161 assert(res_idx
>= 0 && res_idx
< resources
.size());
163 return resources
[res_idx
]->request(inst
);
167 ResourcePool::squash(DynInstPtr inst
, int res_idx
, InstSeqNum done_seq_num
, int tid
)
169 resources
[res_idx
]->squash(inst
, ThePipeline::NumStages
-1, done_seq_num
, tid
);
173 ResourcePool::slotsAvail(int res_idx
)
175 return resources
[res_idx
]->slotsAvail();
179 ResourcePool::slotsInUse(int res_idx
)
181 return resources
[res_idx
]->slotsInUse();
185 ResourcePool::scheduleEvent(InOrderCPU::CPUEventType e_type
, DynInstPtr inst
,
186 int delay
, int res_idx
, int tid
)
192 case InOrderCPU::ActivateThread
:
194 DPRINTF(Resource
, "Scheduling Activate Thread Resource Pool Event for tick %i.\n",
196 ResPoolEvent
*res_pool_event
= new ResPoolEvent(this,
199 inst
->squashingStage
,
202 mainEventQueue
.schedule(res_pool_event
, curTick
+ cpu
->ticks(delay
));
206 case InOrderCPU::SuspendThread
:
207 case InOrderCPU::DeallocateThread
:
210 DPRINTF(Resource
, "Scheduling Deactivate Thread Resource Pool Event for tick %i.\n",
212 ResPoolEvent
*res_pool_event
= new ResPoolEvent(this,
215 inst
->squashingStage
,
219 mainEventQueue
.schedule(res_pool_event
, curTick
+ cpu
->ticks(delay
));
224 case ResourcePool::InstGraduated
:
226 DPRINTF(Resource
, "Scheduling Inst-Graduated Resource Pool Event for tick %i.\n",
228 ResPoolEvent
*res_pool_event
= new ResPoolEvent(this,e_type
,
230 inst
->squashingStage
,
233 mainEventQueue
.schedule(res_pool_event
, curTick
+ cpu
->ticks(delay
));
238 case ResourcePool::SquashAll
:
240 DPRINTF(Resource
, "Scheduling Squash Resource Pool Event for tick %i.\n",
242 ResPoolEvent
*res_pool_event
= new ResPoolEvent(this,e_type
,
244 inst
->squashingStage
,
247 mainEventQueue
.schedule(res_pool_event
, curTick
+ cpu
->ticks(delay
));
252 DPRINTF(Resource
, "Ignoring Unrecognized CPU Event (%s).\n", InOrderCPU::eventNames
[e_type
]);
253 ; // If Resource Pool doesnt recognize event, we ignore it.
258 ResourcePool::unscheduleEvent(int res_idx
, DynInstPtr inst
)
260 resources
[res_idx
]->unscheduleEvent(inst
);
264 ResourcePool::squashAll(DynInstPtr inst
, int stage_num
, InstSeqNum done_seq_num
, unsigned tid
)
266 DPRINTF(Resource
, "[tid:%i] Stage %i squashing all instructions above [sn:%i].\n",
267 stage_num
, tid
, done_seq_num
);
269 int num_resources
= resources
.size();
271 for (int idx
= 0; idx
< num_resources
; idx
++) {
272 resources
[idx
]->squash(inst
, stage_num
, done_seq_num
, tid
);
277 ResourcePool::activateAll(unsigned tid
)
279 DPRINTF(Resource
, "[tid:%i] Broadcasting Thread Activation to all resources.\n",
282 int num_resources
= resources
.size();
284 for (int idx
= 0; idx
< num_resources
; idx
++) {
285 resources
[idx
]->activateThread(tid
);
290 ResourcePool::deactivateAll(unsigned tid
)
292 DPRINTF(Resource
, "[tid:%i] Broadcasting Thread Deactivation to all resources.\n",
295 int num_resources
= resources
.size();
297 for (int idx
= 0; idx
< num_resources
; idx
++) {
298 resources
[idx
]->deactivateThread(tid
);
303 ResourcePool::instGraduated(InstSeqNum seq_num
,unsigned tid
)
305 DPRINTF(Resource
, "[tid:%i] Broadcasting [sn:%i] graduation to all resources.\n",
308 int num_resources
= resources
.size();
310 for (int idx
= 0; idx
< num_resources
; idx
++) {
311 resources
[idx
]->instGraduated(seq_num
, tid
);
315 ResourcePool::ResPoolEvent::ResPoolEvent(ResourcePool
*_resPool
)
316 : Event(CPU_Tick_Pri
), resPool(_resPool
),
317 eventType((InOrderCPU::CPUEventType
) Default
)
320 ResourcePool::ResPoolEvent::ResPoolEvent(ResourcePool
*_resPool
,
321 InOrderCPU::CPUEventType e_type
,
326 : Event(CPU_Tick_Pri
), resPool(_resPool
),
327 eventType(e_type
), inst(_inst
), seqNum(seq_num
),
328 stageNum(stage_num
), tid(_tid
)
333 ResourcePool::ResPoolEvent::process()
337 case InOrderCPU::ActivateThread
:
338 resPool
->activateAll(tid
);
341 case InOrderCPU::SuspendThread
:
342 case InOrderCPU::DeallocateThread
:
343 resPool
->deactivateAll(tid
);
346 case ResourcePool::InstGraduated
:
347 resPool
->instGraduated(seqNum
, tid
);
350 case ResourcePool::SquashAll
:
351 resPool
->squashAll(inst
, stageNum
, seqNum
, tid
);
355 fatal("Unrecognized Event Type");
358 resPool
->cpu
->cpuEventRemoveList
.push(this);
363 ResourcePool::ResPoolEvent::description()
365 return "Resource Pool event";
368 /** Schedule resource event, regardless of its current state. */
370 ResourcePool::ResPoolEvent::scheduleEvent(int delay
)
373 mainEventQueue
.reschedule(this,curTick
+ resPool
->cpu
->ticks(delay
));
374 else if (!scheduled())
375 mainEventQueue
.schedule(this,curTick
+ resPool
->cpu
->ticks(delay
));
378 /** Unschedule resource event, regardless of its current state. */
380 ResourcePool::ResPoolEvent::unscheduleEvent()