Esempio n. 1
0
func (this *Processor) StartPipelineUnits(config *config.Config, recoveryChannel channel.Channel, operationId, address uint32) func() {

	// Initialize channels
	addressChannel := channel.New(config.InstructionsFetchedPerCycle()) // Branch Predictor -> Fetch
	instructionChannel := channel.New(config.InstructionsQueue())       // Fetch -> Decode
	operationChannel := channel.New(config.InstructionsDecodedQueue())  // Decode -> Dispatch
	executionChannels := map[info.CategoryEnum]channel.Channel{         // Dispatch -> Execute
		info.Aritmetic:     channel.New(config.AluUnits()),
		info.LoadStore:     channel.New(config.LoadStoreUnits()),
		info.Control:       channel.New(config.BranchUnits()),
		info.FloatingPoint: channel.New(config.FpuUnits()),
	}
	commonDataBusChannel := channel.New(channel.INFINITE) // Execute -> Dispatcher (RS & ROB)

	closeUnitsHandlers := []func(){}

	/////////////////////////////////////////////////////////////////////////////
	// Run stage units in parallel                                             //
	//  - Units are executed as go routines https://blog.golang.org/pipelines) //
	/////////////////////////////////////////////////////////////////////////////

	// ---------- Fetch ------------ //
	fe := fetcher.New(uint32(0), this, config.InstructionsFetchedPerCycle(), config.BranchPredictorType())
	fe.Run(addressChannel, instructionChannel)
	closeUnitsHandlers = append(closeUnitsHandlers, fe.Close)

	// ---------- Decode ------------ //
	for index := uint32(0); index < config.DecoderUnits(); index++ {
		de := decoder.New(index, this)
		de.Run(instructionChannel, operationChannel)
		closeUnitsHandlers = append(closeUnitsHandlers, de.Close)
	}

	// ----- Dispatch / RS / ROB ---- //
	di := dispatcher.New(uint32(0), this, operationId, config.TotalRegisters(),
		config.ReservationStationEntries(), config.ReorderBufferEntries(), config.InstructionsDispatchedPerCycle(),
		config.InstructionsWrittenPerCycle(), config.RegisterAliasTableEntries())
	di.Run(operationChannel, executionChannels, commonDataBusChannel, recoveryChannel)
	closeUnitsHandlers = append(closeUnitsHandlers, di.Close)

	// ------- Execute (Alu) -------- //
	for index := uint32(0); index < config.AluUnits(); index++ {
		ex := executor.New(index, this, di.Bus(), info.Aritmetic)
		ex.Run(executionChannels, commonDataBusChannel)
		closeUnitsHandlers = append(closeUnitsHandlers, ex.Close)
	}

	// ---- Execute (Load Store) ---- //
	for index := uint32(0); index < config.LoadStoreUnits(); index++ {
		ex := executor.New(index, this, di.Bus(), info.LoadStore)
		ex.Run(executionChannels, commonDataBusChannel)
		closeUnitsHandlers = append(closeUnitsHandlers, ex.Close)
	}

	// ------ Execute (Branch) ------ //
	for index := uint32(0); index < config.BranchUnits(); index++ {
		ex := executor.New(index, this, di.Bus(), info.Control)
		ex.Run(executionChannels, commonDataBusChannel)
		closeUnitsHandlers = append(closeUnitsHandlers, ex.Close)
	}

	// ------- Execute (FPU) -------- //
	for index := uint32(0); index < config.FpuUnits(); index++ {
		ex := executor.New(index, this, di.Bus(), info.FloatingPoint)
		ex.Run(executionChannels, commonDataBusChannel)
		closeUnitsHandlers = append(closeUnitsHandlers, ex.Close)
	}

	// Set instruction for fetching to start pipeline
	go addressChannel.Add(operation.New(operationId, address))

	// Return flush function for all channels
	return func() {
		// Close units & channels
		for _, closeUnitHandler := range closeUnitsHandlers {
			closeUnitHandler()
		}

		// Close channels
		addressChannel.Close()
		instructionChannel.Close()
		operationChannel.Close()
		executionChannels[info.Aritmetic].Close()
		executionChannels[info.LoadStore].Close()
		executionChannels[info.Control].Close()
		executionChannels[info.FloatingPoint].Close()
		commonDataBusChannel.Close()
	}
}