InOrder Resource-Request Model
Resources consists of any CPU object that an instruction wants to access. This could be a branch predictor, a cache, a execution unit, etc. In the InOrder CPU model we abstract what a resource is into a generic "Resource" class that all specific resources must derive from. In any given pipeline stage, an instruction will request that a resource perform a specific operation on it's behalf. If an instruction can complete all it's resource requests for a given stage, then it may pass to the next stage.
Relevant source files:
Ideally, resources can used by instructions as a black box that will perform specific operation.The basic steps between an instruction and resource are as follows:
- An instruction accesses a resource by generating a resource-request that contains:
- The ID of the resource to be accessed
- A command for the resource to perform
- After generating a resource-request, an instruction sends the request to the Resource Pool which will forward the request to the appropriate resource.
- Once a resource receives a request, it will:
- Check to see if there is room (i.e. bandwidth) to process that resource request. If there is room, a slot is allocated to that instruction
- Attempt to process the command that the instruction requests of it.
- If that command is successful, the resource mark the request as completed and return it back to the instruction.
- If that command is unsuccessful, the resource will mark the request as not completed before returning it back to the instruction.
Each Resource contains a enumerated list of commands that it recognizes. The execute() function expects an instruction to request a resource to perform one of the commands on this list for processing.
Slots represent the bandwidth of the resource (or how many concurrent instructions can access the resource). Each time an instruction makes a request to a resource, the resource allocates a slot to that instruction to represent the resources' bandwidth being used.
Once an instruction is allocated a slot, it is eligible to be executed within that resource. The execute function read the command from the resource-request and then tries to perform the appropriate operation. If the operation isnt completed successfully, execute() will mark the completed variable "false" and if the the operation is successful, the completed variable for that resource-request will marked as true.
The following pipeline resources are defined for InOrderCPU:
- Fetch Unit
- Instruction Cache (I-Cache)
- Branch Prediction Unit (BPred Unit)
- Register File Manager (RF Manager)
- Address Generation Unit (AGen Unit)
- Execution Unit (EXU)
- Integer Multiply and Divide Unit (Int MDU)
- Data Cache (D-Cache)
- Graduation Unit (Grad Unit)
Defining Your Own Resources
The easiest way to define your own resource is to find a resource that is similar to what you are trying to create, and then use that as a template for your design.
More specifically, you'll need to derive from the "Resource" class and then define your own resource-specific "execute" function. In the simplest case, where your resource is of zero (same-cycle) latency, then this should do the trick. If you resource processes requests on multiple cycles, then a good example of that is the instruction buffer, the caches, or the multiply/divide units.
Also note, for an instruction to use your resource, you need to :
- Add the resource to the resource pool
- Add the resource to that instruction's instruction schedule