timing

package
v1.7.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 26, 2019 License: MIT Imports: 16 Imported by: 0

Documentation

Overview

Package timing provides an implementation of detailed Compute Unit modeling.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AllocStatus

type AllocStatus byte

AllocStatus represents the allocation status of SGPRs, VGPRs, or LDS units

const (
	AllocStatusFree      AllocStatus = iota
	AllocStatusToReserve             // A value that is used for reservation caculation
	AllocStatusReserved              // Work-Group mapped, but wavefront not dispatched
	AllocStatusUsed                  // Currently in use
)

A list of possible status for CU binded storage allocation

type BranchUnit

type BranchUnit struct {
	// contains filtered or unexported fields
}

A BranchUnit performs branch operations

func NewBranchUnit

func NewBranchUnit(
	cu *ComputeUnit,
	scratchpadPreparer ScratchpadPreparer,
	alu emu.ALU,
) *BranchUnit

NewBranchUnit creates a new branch unit, injecting the dependency of the compute unit.

func (*BranchUnit) AcceptWave

func (u *BranchUnit) AcceptWave(
	wave *wavefront.Wavefront,
	now akita.VTimeInSec,
)

AcceptWave moves one wavefront into the read buffer of the branch unit

func (*BranchUnit) CanAcceptWave

func (u *BranchUnit) CanAcceptWave() bool

CanAcceptWave checks if the buffer of the read stage is occupied or not

func (*BranchUnit) Flush

func (u *BranchUnit) Flush()

func (*BranchUnit) IsIdle

func (u *BranchUnit) IsIdle() bool

func (*BranchUnit) Run

func (u *BranchUnit) Run(now akita.VTimeInSec) bool

Run executes three pipeline stages that are controlled by the BranchUnit

type Builder

type Builder struct {
	Engine    akita.Engine
	Freq      akita.Freq
	CUName    string
	SIMDCount int
	VGPRCount []int
	SGPRCount int

	Decoder            emu.Decoder
	ScratchpadPreparer ScratchpadPreparer
	ALU                emu.ALU

	InstMem          akita.Port
	ScalarMem        akita.Port
	VectorMemModules cache.LowModuleFinder

	ConnToInstMem   akita.Connection
	ConnToScalarMem akita.Connection
	ConnToVectorMem akita.Connection
	// contains filtered or unexported fields
}

A Builder can construct a fully functional ComputeUnit to the outside world. It simplify the compute unit building process.

func MakeBuilder

func MakeBuilder() Builder

NewBuilder returns a default builder object

func (*Builder) Build

func (b *Builder) Build() *ComputeUnit

Build returns a newly constructed compute unit according to the configuration

func (Builder) WithVisTracer

func (b Builder) WithVisTracer(t tracing.Tracer) Builder

type CUComponent

type CUComponent interface {
	CanAcceptWave() bool
	AcceptWave(wave *wavefront.Wavefront, now akita.VTimeInSec)
	Run(now akita.VTimeInSec) bool
	IsIdle() bool
	Flush()
}

A CUComponent is an element installed in the compute unit

type ComputeUnit

type ComputeUnit struct {
	*akita.TickingComponent

	WGMapper     WGMapper
	WfDispatcher WfDispatcher
	Decoder      emu.Decoder

	WfPools      []*WavefrontPool
	WfToDispatch map[*kernels.Wavefront]*WfDispatchInfo

	InFlightInstFetch       []*InstFetchReqInfo
	InFlightScalarMemAccess []*ScalarMemAccessInfo
	InFlightVectorMemAccess []VectorMemAccessInfo

	Scheduler        Scheduler
	BranchUnit       CUComponent
	VectorMemDecoder CUComponent
	VectorMemUnit    CUComponent
	ScalarDecoder    CUComponent
	VectorDecoder    CUComponent
	LDSDecoder       CUComponent
	ScalarUnit       CUComponent
	SIMDUnit         []CUComponent
	LDSUnit          CUComponent
	SRegFile         RegisterFile
	VRegFile         []RegisterFile

	InstMem          akita.Port
	ScalarMem        akita.Port
	VectorMemModules cache.LowModuleFinder

	ToACE akita.Port

	ToInstMem   akita.Port
	ToScalarMem akita.Port
	ToVectorMem akita.Port

	ToCP akita.Port
	// contains filtered or unexported fields
}

A ComputeUnit in the timing package provides a detailed and accurate simulation of a GCN3 ComputeUnit

func NewComputeUnit

func NewComputeUnit(
	name string,
	engine akita.Engine,
) *ComputeUnit

NewComputeUnit returns a newly constructed compute unit

func (*ComputeUnit) Handle

func (cu *ComputeUnit) Handle(evt akita.Event) error

Handle processes that events that are scheduled on the ComputeUnit

func (*ComputeUnit) Tick

func (cu *ComputeUnit) Tick(now akita.VTimeInSec) bool

func (*ComputeUnit) UpdatePCAndSetReady

func (cu *ComputeUnit) UpdatePCAndSetReady(wf *wavefront.Wavefront)

type DecodeUnit

type DecodeUnit struct {
	ExecUnits []CUComponent // Execution units, index by SIMD number
	// contains filtered or unexported fields
}

A DecodeUnit is any type of decode unit that takes one cycle to decode

func NewDecodeUnit

func NewDecodeUnit(cu *ComputeUnit) *DecodeUnit

NewDecodeUnit creates a new decode unit

func (*DecodeUnit) AcceptWave

func (du *DecodeUnit) AcceptWave(
	wave *wavefront.Wavefront,
	now akita.VTimeInSec,
)

AcceptWave takes a wavefront and decode the instruction in the next cycle

func (*DecodeUnit) AddExecutionUnit

func (du *DecodeUnit) AddExecutionUnit(cuComponent CUComponent)

AddExecutionUnit registers an executions unit to the decode unit, so that the decode unit knows where to send the instruction to after decoding. This function has to be called in the order of SIMD number.

func (*DecodeUnit) CanAcceptWave

func (du *DecodeUnit) CanAcceptWave() bool

CanAcceptWave checks if the DecodeUnit is ready to decode another instruction

func (*DecodeUnit) Flush

func (du *DecodeUnit) Flush()

func (*DecodeUnit) IsIdle

func (du *DecodeUnit) IsIdle() bool

func (*DecodeUnit) Run

func (du *DecodeUnit) Run(now akita.VTimeInSec) bool

Run decodes the instruction and sends the instruction to the next pipeline stage

type FetchArbiter

type FetchArbiter struct {
	InstBufByteSize int
}

A FetchArbiter can decide which wavefront in a scheduler can fetch instructions

func (*FetchArbiter) Arbitrate

func (a *FetchArbiter) Arbitrate(
	wfPools []*WavefrontPool,
) []*wavefront.Wavefront

Arbitrate decide which wavefront can fetch the next instruction

type ISADebugger

type ISADebugger struct {
	akita.LogHookBase
	// contains filtered or unexported fields
}

ISADebugger is a logger hook that can dump the wavefront status after each instruction execution

func NewISADebugger

func NewISADebugger(logger *log.Logger) *ISADebugger

NewISADebugger creates a new ISADebugger.

func (*ISADebugger) Func

func (d *ISADebugger) Func(
	ctx akita.HookCtx,
)

Func defines the action that the ISADebugger takes

type InstFetchReqInfo

type InstFetchReqInfo struct {
	Req       *mem.ReadReq
	Wavefront *wavefront.Wavefront
	Address   uint64
}

type IssueArbiter

type IssueArbiter struct {
	// contains filtered or unexported fields
}

An IssueArbiter decides which wavefront can issue instruction

func NewIssueArbiter

func NewIssueArbiter() *IssueArbiter

NewIssueArbiter returns a newly created IssueArbiter

func (*IssueArbiter) Arbitrate

func (a *IssueArbiter) Arbitrate(
	wfPools []*WavefrontPool,
) []*wavefront.Wavefront

Arbitrate will take a round-robin fashion at SIMD level. For wavefronts in each SIMD, oldest first.

type LDSUnit

type LDSUnit struct {
	// contains filtered or unexported fields
}

A LDSUnit performs Scalar operations

func NewLDSUnit

func NewLDSUnit(
	cu *ComputeUnit,
	scratchpadPreparer ScratchpadPreparer,
	alu emu.ALU,
) *LDSUnit

NewLDSUnit creates a new Scalar unit, injecting the dependency of the compute unit.

func (*LDSUnit) AcceptWave

func (u *LDSUnit) AcceptWave(wave *wavefront.Wavefront, now akita.VTimeInSec)

AcceptWave moves one wavefront into the read buffer of the Scalar unit

func (*LDSUnit) CanAcceptWave

func (u *LDSUnit) CanAcceptWave() bool

CanAcceptWave checks if the buffer of the read stage is occupied or not

func (*LDSUnit) Flush

func (u *LDSUnit) Flush()

func (*LDSUnit) IsIdle

func (u *LDSUnit) IsIdle() bool

CanAcceptWave checks if the buffer of the read stage is occupied or not

func (*LDSUnit) Run

func (u *LDSUnit) Run(now akita.VTimeInSec) bool

Run executes three pipeline stages that are controlled by the LDSUnit

type RegisterAccess

type RegisterAccess struct {
	Time       akita.VTimeInSec
	Reg        *insts.Reg
	RegCount   int
	LaneID     int
	WaveOffset int
	Data       []byte
	OK         bool
}

A RegisterAccess is an incidence of reading or writing the register

type RegisterFile

type RegisterFile interface {
	Read(access RegisterAccess)
	Write(access RegisterAccess)
}

A RegisterFile provides the communication interface for a set of registers.

type ResourceMask

type ResourceMask struct {
	// contains filtered or unexported fields
}

A ResourceMask is data structure to mask the status of some resources

func NewResourceMask

func NewResourceMask(size int) *ResourceMask

NewResourceMask returns a newly created ResourceMask with a given size.

func (*ResourceMask) ConvertStatus

func (m *ResourceMask) ConvertStatus(from, to AllocStatus)

ConvertStatus change all the element of one status to another

func (*ResourceMask) NextRegion

func (m *ResourceMask) NextRegion(
	length int,
	statusReq AllocStatus,
) (int, bool)

NextRegion finds a region that is masked by the resourceMask in the state define by statusReq. This function returns the offset of the starting point of the region. It also returns a boolean value that tells if a region is found

func (*ResourceMask) SetStatus

func (m *ResourceMask) SetStatus(offset, length int, status AllocStatus)

SetStatus alters the status from the position of offset to offset + length

func (*ResourceMask) StatusCount

func (m *ResourceMask) StatusCount(status AllocStatus) int

StatusCount returns the number of element that is in the target status

type SIMDUnit

type SIMDUnit struct {
	akita.HookableBase

	NumSinglePrecisionUnit int
	// contains filtered or unexported fields
}

A SIMDUnit performs branch operations

func NewSIMDUnit

func NewSIMDUnit(
	cu *ComputeUnit,
	name string,
	scratchpadPreparer ScratchpadPreparer,
	alu emu.ALU,
) *SIMDUnit

NewSIMDUnit creates a new branch unit, injecting the dependency of the compute unit.

func (*SIMDUnit) AcceptWave

func (u *SIMDUnit) AcceptWave(wave *wavefront.Wavefront, now akita.VTimeInSec)

AcceptWave moves one wavefront into the read buffer of the branch unit

func (*SIMDUnit) CanAcceptWave

func (u *SIMDUnit) CanAcceptWave() bool

CanAcceptWave checks if the buffer of the read stage is occupied or not

func (*SIMDUnit) Flush

func (u *SIMDUnit) Flush()

func (*SIMDUnit) IsIdle

func (u *SIMDUnit) IsIdle() bool

CanAcceptWave checks if the buffer of the read stage is occupied or not

func (*SIMDUnit) Name

func (u *SIMDUnit) Name() string

func (*SIMDUnit) Run

func (u *SIMDUnit) Run(now akita.VTimeInSec) bool

Run executes three pipeline stages that are controlled by the SIMDUnit

type ScalarMemAccessInfo

type ScalarMemAccessInfo struct {
	Req       *mem.ReadReq
	Wavefront *wavefront.Wavefront
	DstSGPR   *insts.Reg
	Inst      *wavefront.Inst
}

type ScalarUnit

type ScalarUnit struct {
	// contains filtered or unexported fields
}

A ScalarUnit performs Scalar operations

func NewScalarUnit

func NewScalarUnit(
	cu *ComputeUnit,
	scratchpadPreparer ScratchpadPreparer,
	alu emu.ALU,
) *ScalarUnit

NewScalarUnit creates a new Scalar unit, injecting the dependency of the compute unit.

func (*ScalarUnit) AcceptWave

func (u *ScalarUnit) AcceptWave(wave *wavefront.Wavefront, now akita.VTimeInSec)

AcceptWave moves one wavefront into the read buffer of the Scalar unit

func (*ScalarUnit) CanAcceptWave

func (u *ScalarUnit) CanAcceptWave() bool

CanAcceptWave checks if the buffer of the read stage is occupied or not

func (*ScalarUnit) Flush

func (u *ScalarUnit) Flush()

func (*ScalarUnit) IsIdle

func (u *ScalarUnit) IsIdle() bool

CanAcceptWave checks if the buffer of the read stage is occupied or not

func (*ScalarUnit) Run

func (u *ScalarUnit) Run(now akita.VTimeInSec) bool

Run executes three pipeline stages that are controlled by the ScalarUnit

type Scheduler

type Scheduler interface {
	Run(now akita.VTimeInSec) bool
	Pause()
	Resume()
	Flush()
}

type SchedulerImpl

type SchedulerImpl struct {
	// contains filtered or unexported fields
}

A Scheduler is the controlling unit of a compute unit. It decides which wavefront to fetch and to issue.

func NewScheduler

func NewScheduler(
	cu *ComputeUnit,
	fetchArbiter WfArbiter,
	issueArbiter WfArbiter,
) *SchedulerImpl

NewScheduler returns a newly created scheduler, injecting dependency of the compute unit, the fetch arbiter, and the issue arbiter.

func (*SchedulerImpl) DecodeNextInst

func (s *SchedulerImpl) DecodeNextInst(now akita.VTimeInSec) bool

func (*SchedulerImpl) DoFetch

func (s *SchedulerImpl) DoFetch(now akita.VTimeInSec) bool

DoFetch function of the scheduler will fetch instructions from the instruction memory

func (*SchedulerImpl) DoIssue

func (s *SchedulerImpl) DoIssue(now akita.VTimeInSec) bool

DoIssue function of the scheduler issues fetched instruction to the decoding units

func (*SchedulerImpl) EvaluateInternalInst

func (s *SchedulerImpl) EvaluateInternalInst(now akita.VTimeInSec) bool

EvaluateInternalInst updates the status of the instruction being executed in the scheduler.

func (*SchedulerImpl) Flush

func (s *SchedulerImpl) Flush()

func (*SchedulerImpl) Pause

func (s *SchedulerImpl) Pause()

func (*SchedulerImpl) Resume

func (s *SchedulerImpl) Resume()

func (*SchedulerImpl) Run

func (s *SchedulerImpl) Run(now akita.VTimeInSec) bool

type ScratchpadPreparer

type ScratchpadPreparer interface {
	Prepare(instEmuState emu.InstEmuState, wf *wavefront.Wavefront)
	Commit(instEmuState emu.InstEmuState, wf *wavefront.Wavefront)
}

type ScratchpadPreparerImpl

type ScratchpadPreparerImpl struct {
	// contains filtered or unexported fields
}

ScratchpadPreparerImpl reads and write registers for the emulator

func NewScratchpadPreparerImpl

func NewScratchpadPreparerImpl(cu *ComputeUnit) *ScratchpadPreparerImpl

NewScratchpadPreparerImpl returns a newly created ScratchpadPreparerImpl, injecting the dependency of the RegInterface.

func (*ScratchpadPreparerImpl) Commit

func (p *ScratchpadPreparerImpl) Commit(
	instEmuState emu.InstEmuState,
	wf *wavefront.Wavefront,
)

Commit write to the register file according to the scratchpad layout

func (*ScratchpadPreparerImpl) Prepare

func (p *ScratchpadPreparerImpl) Prepare(
	instEmuState emu.InstEmuState,
	wf *wavefront.Wavefront,
)

Prepare read from the register file and sets the scratchpad layout

type SimpleRegisterFile

type SimpleRegisterFile struct {

	// In vector register, each lane can have up-to 256 VGPRs. Then the offset
	// difference from v0 lane 0 to v0 lane 1 is 256*4 = 1024B. Field
	// ByteSizePerLane should be set to 1024 in vector registers.
	ByteSizePerLane int
	// contains filtered or unexported fields
}

A SimpleRegisterFile is a Register file that can always read and write registers immediately

func NewSimpleRegisterFile

func NewSimpleRegisterFile(
	byteSize uint64,
	byteSizePerLane int,
) *SimpleRegisterFile

NewSimpleRegisterFile creates and returns a new SimpleRegisterFile

func (*SimpleRegisterFile) Read

func (r *SimpleRegisterFile) Read(access RegisterAccess)

func (*SimpleRegisterFile) Write

func (r *SimpleRegisterFile) Write(access RegisterAccess)

type VectorMemAccessInfo

type VectorMemAccessInfo struct {
	Read      *mem.ReadReq
	Write     *mem.WriteReq
	Wavefront *wavefront.Wavefront
	Inst      *wavefront.Inst
	// contains filtered or unexported fields
}

type VectorMemoryUnit

type VectorMemoryUnit struct {
	SendBuf     []mem.AccessReq
	SendBufSize int

	AddrCoalescingLatency   int
	AddrCoalescingCycleLeft int
	// contains filtered or unexported fields
}

A VectorMemoryUnit performs Scalar operations

func NewVectorMemoryUnit

func NewVectorMemoryUnit(
	cu *ComputeUnit,
	scratchpadPreparer ScratchpadPreparer,
	coalescer coalescer,
) *VectorMemoryUnit

NewVectorMemoryUnit creates a new Scalar unit, injecting the dependency of the compute unit.

func (*VectorMemoryUnit) AcceptWave

func (u *VectorMemoryUnit) AcceptWave(wave *wavefront.Wavefront, now akita.VTimeInSec)

AcceptWave moves one wavefront into the read buffer of the Scalar unit

func (*VectorMemoryUnit) CanAcceptWave

func (u *VectorMemoryUnit) CanAcceptWave() bool

CanAcceptWave checks if the buffer of the read stage is occupied or not

func (*VectorMemoryUnit) Flush

func (u *VectorMemoryUnit) Flush()

func (*VectorMemoryUnit) IsIdle

func (u *VectorMemoryUnit) IsIdle() bool

IsIdle moves one wavefront into the read buffer of the Scalar unit

func (*VectorMemoryUnit) Run

func (u *VectorMemoryUnit) Run(now akita.VTimeInSec) bool

Run executes three pipeline stages that are controlled by the VectorMemoryUnit

type WGMapper

type WGMapper interface {
	MapWG(req *gcn3.MapWGReq) bool
	UnmapWG(wg *wavefront.WorkGroup)
}

WGMapper defines the behavior of how a workgroup is mapped in the compute unit.

It is responsible for allocating SIMD number, VGPRs offset, SGPRs offset and LDS offset for each wavefront in the workgroup. A WGMapper is not a component and we assume the mapping process is done within a cycle

type WGMapperImpl

type WGMapperImpl struct {
	NumWfPool       int
	WfPoolFreeCount []int

	SGprCount       int
	SGprGranularity int
	SGprMask        *ResourceMask

	VGprCount       []int
	VGprGranularity int
	VGprMask        []*ResourceMask

	LDSByteSize    int
	LDSGranularity int
	LDSMask        *ResourceMask
	// contains filtered or unexported fields
}

WGMapperImpl is a sub-component of scheduler. It is responsible for allocate and reserve resources for the incoming MapWgReq.

func NewWGMapper

func NewWGMapper(cu *ComputeUnit, numWfPool int) *WGMapperImpl

NewWGMapper returns a newly created WgMapper with default compute unit setting

func (*WGMapperImpl) MapWG

func (m *WGMapperImpl) MapWG(req *gcn3.MapWGReq) bool

MapWG uses a first fit algorithm to allocate SGPR, VGPR, and LDS resources. In terms of SIMD selection, it uses a round robin policy.

func (*WGMapperImpl) SetWfPoolSizes

func (m *WGMapperImpl) SetWfPoolSizes(numWfs []int)

SetWfPoolSizes updates the number of WfPools and it number of wavefronts that a wavefront pool can handle.

func (*WGMapperImpl) UnmapWG

func (m *WGMapperImpl) UnmapWG(wg *wavefront.WorkGroup)

UnmapWG will remove all the resource reservation of a work-group

type WavefrontPool

type WavefrontPool struct {
	Capacity int

	VRegFile akita.Component
	// contains filtered or unexported fields
}

A WavefrontPool holds the wavefronts that will be scheduled in one SIMD unit

func NewWavefrontPool

func NewWavefrontPool(capacity int) *WavefrontPool

NewWavefrontPool creates and returns a new WavefrontPool

func (*WavefrontPool) AddWf

func (wfp *WavefrontPool) AddWf(wf *wavefront.Wavefront)

AddWf will add an wavefront to the wavefront pool

func (*WavefrontPool) Availability

func (wfp *WavefrontPool) Availability() int

Availability returns the number of extra Wavefront that the wavefront pool can hold

func (*WavefrontPool) RemoveWf

func (wfp *WavefrontPool) RemoveWf(wf *wavefront.Wavefront)

RemoveWf removes a wavefront from a wavefront pool

type WfArbiter

type WfArbiter interface {
	Arbitrate(wfpools []*WavefrontPool) []*wavefront.Wavefront
}

An WfArbiter can decide which wavefront can take action, in a list of wavefront pools

type WfCompletionEvent

type WfCompletionEvent struct {
	*akita.EventBase
	Wf *wavefront.Wavefront
}

A WfCompletionEvent marks the completion of a wavefront

func NewWfCompletionEvent

func NewWfCompletionEvent(
	time akita.VTimeInSec,
	handler akita.Handler,
	wf *wavefront.Wavefront,
) *WfCompletionEvent

NewWfCompletionEvent returns a newly constructed WfCompleteEvent

type WfDispatchEvent

type WfDispatchEvent struct {
	*akita.EventBase

	ManagedWf  *wavefront.Wavefront
	IsLastInWG bool
	MapWGReq   *gcn3.MapWGReq
}

WfDispatchEvent is the event that the dispatcher dispatches a wavefront

func NewWfDispatchEvent

func NewWfDispatchEvent(
	t akita.VTimeInSec,
	handler akita.Handler,
	Wf *wavefront.Wavefront,
) *WfDispatchEvent

NewWfDispatchEvent creates a new WfDispatchCompletionEvent

type WfDispatchInfo

type WfDispatchInfo struct {
	Wavefront  *kernels.Wavefront
	SIMDID     int
	VGPROffset int
	SGPROffset int
	LDSOffset  int
}

WfDispatchInfo preservers the information from a work-group mapping to guarantee a wavefront to be dispatching to its designated location

type WfDispatcher

type WfDispatcher interface {
	DispatchWf(now akita.VTimeInSec, wf *wavefront.Wavefront)
}

A WfDispatcher initialize wavefronts

type WfDispatcherImpl

type WfDispatcherImpl struct {
	Latency int
	// contains filtered or unexported fields
}

A WfDispatcherImpl will register the wavefront in wavefront pool and initialize all the registers

func NewWfDispatcher

func NewWfDispatcher(cu *ComputeUnit) *WfDispatcherImpl

NewWfDispatcher creates a default WfDispatcher

func (*WfDispatcherImpl) DispatchWf

func (d *WfDispatcherImpl) DispatchWf(
	now akita.VTimeInSec,
	wf *wavefront.Wavefront,
)

DispatchWf starts or continues a wavefront dispatching process.

Directories

Path Synopsis
caches
l1v
Package l1v provides a GCN3 GPU L1 cache implementation.
Package l1v provides a GCN3 GPU L1 cache implementation.
Package mock_timing is a generated GoMock package.
Package mock_timing is a generated GoMock package.
Package pipelines defines a pipeline timing model.
Package pipelines defines a pipeline timing model.
Package wavefront defines concepts related to a wavefront.
Package wavefront defines concepts related to a wavefront.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL