Esempio n. 1
0
func New(assemblyFileName string, config *config.Config) (*Processor, error) {

	p := &Processor{
		&processor{
			done:                  false,
			instructionsFetched:   []string{},
			instructionsCompleted: []uint32{},
			dataLog:               map[uint32][]LogEvent{},

			branchHistoryTable:    map[uint32]uint32{},
			conditionalBranches:   0,
			unconditionalBranches: 0,
			mispredictedBranches:  0,
			noTakenBranches:       0,
			branchPredictorBits:   0,
			speculativeJumps:      0,

			instructionsMap: map[uint32]string{},
			instructionsSet: set.Init(),
			config:          config,

			programCounter:    0,
			registerMemory:    memory.New(config.RegistersMemorySize()),
			instructionMemory: memory.New(config.InstructionsMemorySize()),
			dataMemory:        memory.New(config.DataMemorySize()),
		},
	}

	logger.Print(config.ToString())

	// Instanciate functional units
	instructionsFinished := func() bool {
		return p.processor.done && p.InstructionsFetchedCounter() == p.InstructionsCompletedCounter() && p.SpeculativeJumps() == 0
	}
	p.processor.clockUnit = clock.New(config.CyclePeriod(), instructionsFinished)

	err := p.loadInstructionsMemory(assemblyFileName)
	if err != nil {
		return p, err
	}
	return p, nil
}
Esempio n. 2
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()
	}
}