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 }
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() } }