def __init__(self, initialPC=Bus(64), IMem=Memory(True), DMem=Memory(False)): self.ALU = ALU() self.IMem = IMem self.DMem = DMem self.signExtender = SignExtender() self.regFile = RegisterFile() self.Control = Control() self.nextPCLogic = NextPCLogic() self.PC = initialPC self.aluZero = 0
def test_regfile_2R2W( dump_vcd, test_verilog ): # Test vectors test_vectors = [ # ---read 0--- ---read 1--- -----write 0----- -----write 1----- # addr data addr data en addr data en addr data [ 10, '?', 14, '?', 0, 10, 0x0000, 0, 10, 0x0000], [ 13, '?', 14, '?', 1, 14, 0x0005, 0, 14, 0x0005], [ 12, '?', 14, 0x0005, 0, 10, 0x0006, 1, 12, 0x0006], [ 12, 0x0006, 12, 0x0006, 0, 13, 0x0008, 1, 13, 0x0009], [ 12, 0x0006, 12, 0x0006, 0, 13, 0x0007, 0, 13, 0x000a], [ 17, '?', 13, 0x0009, 0, 17, 0x0090, 1, 17, 0x0010], [ 14, 0x0005, 17, 0x0010, 0, 17, 0x0090, 0, 17, 0x0020], [ 16, '?', 17, 0x0010, 1, 17, 0x0090, 1, 16, 0x0090], [ 16, 0x0090, 17, 0x0090, 1, 17, 0x0011, 0, 16, 0x0011], [ 16, 0x0090, 17, 0x0011, 0, 10, 0x0000, 0, 10, 0x0000], ] # Instantiate and elaborate the model model = RegisterFile( dtype=16, nregs=32, rd_ports=2, wr_ports=2 ) model.vcd_file = dump_vcd if test_verilog: model = TranslationTool( model, verilator_xinit=test_verilog ) model.elaborate() # Define functions mapping the test vector to ports in model def tv_in( model, test_vector ): model.rd_addr[0].value = test_vector[0] model.rd_addr[1].value = test_vector[2] model.wr_en [0].value = test_vector[4] model.wr_addr[0].value = test_vector[5] model.wr_data[0].value = test_vector[6] model.wr_en [1].value = test_vector[7] model.wr_addr[1].value = test_vector[8] model.wr_data[1].value = test_vector[9] def tv_out( model, test_vector ): if test_vector[1] != '?': assert model.rd_data[0].value == test_vector[1] if test_vector[3] != '?': assert model.rd_data[1].value == test_vector[3] # Run the test sim = TestVectorSimulator( model, test_vectors, tv_in, tv_out ) sim.run_test()
def __init__(self, memory, start_address): self.memory = memory self.start_address = start_address self.register_file = RegisterFile() self.data_memory_key_fn = lambda: -777 self.data_memory = defaultdict(self.data_memory_key_fn) self.cycle_count = 0 self.instr_count = 0 self.PC = 0 self.fetch_input_buffer = FetchInputBuffer({ 'PC': self.start_address, 'instr_count': self.instr_count, }) self.fetcher_buffer = FetcherBuffer() self.fetch_stage = FetchStage(self.memory, self.fetch_input_buffer, self.fetcher_buffer) self.decoder_buffer = DecoderBuffer() self.decode_stage = DecodeStage(self.fetcher_buffer, self.decoder_buffer, self.register_file) self.executer_buffer = ExecuterBuffer() self.execute_stage = ExecuteStage(self.decoder_buffer, self.executer_buffer) self.memory_buffer = MemoryBuffer() self.memory_stage = MemoryStage(self.executer_buffer, self.memory_buffer, self.data_memory) self.write_back_stage = WriteBackStage(self.memory_buffer, self.register_file)
def test_regfile_1R1W( dump_vcd, test_verilog ): # Test vectors test_vectors = [ # rd_addr0 rd_data0 wr_en wr_addr wr_data [ 0, '?', 0, 0, 0x0000 ], [ 1, '?', 0, 1, 0x0008 ], # Write followed by Read [ 3, '?', 1, 2, 0x0005 ], [ 2, 0x0005, 0, 2, 0x0000 ], # Simultaneous Write and Read [ 3, '?', 1, 3, 0x0007 ], [ 3, 0x0007, 1, 7, 0x0090 ], [ 7, 0x0090, 1, 3, 0x0007 ], # Write to zero [ 0, '?', 1, 0, 0x0FFF ], [ 0, 0x0FFF, 1, 4, 0x0FFF ], [ 0, 0x0FFF, 0, 4, 0x0BBB ], [ 0, 0x0FFF, 0, 4, 0x0FFF ], [ 4, 0x0FFF, 0, 0, 0x0000 ], ] # Instantiate and elaborate the model model = RegisterFile( dtype = 16, nregs = 8, rd_ports = 1 ) model.vcd_file = dump_vcd if test_verilog: model = TranslationTool( model, verilator_xinit=test_verilog ) model.elaborate() # Define functions mapping the test vector to ports in model def tv_in( model, test_vector ): model.rd_addr[0].value = test_vector[0] model.wr_en.value = test_vector[2] model.wr_addr.value = test_vector[3] model.wr_data.value = test_vector[4] def tv_out( model, test_vector ): if test_vector[1] != '?': assert model.rd_data[0].value == test_vector[1] # Run the test sim = TestVectorSimulator( model, test_vectors, tv_in, tv_out ) sim.run_test()
class WriteBackStageTest(unittest.TestCase): def setUp(self): self.register_file = RegisterFile() def tearDown(self): pass def set_up_write_back_stage(self, instruction_string): """Set up WriteBackStage with the appropriate memory_buffer, etc. """ self.instruction_string = instruction_string self.instr = Instruction.Instruction (self.instruction_string.strip().split()) self.memory = Memory.Memory([self.instruction_string.strip().split()]) self.memory_buffer = Processor.Processor.get_stage_output( self.memory, self.register_file, 0, 0, 'memory') self.write_back_stage = write_back_stage.WriteBackStage( self.memory_buffer, self.register_file) def test_write_back_no_instr(self): self.set_up_write_back_stage('R ADD R1 R2 R3') self.memory_buffer.instr = None self.write_back_stage.write_back() self.assertEqual(self.write_back_stage.memory_buffer, self.memory_buffer) def test_write_back_R(self): self.set_up_write_back_stage('R ADD R1 R2 R3') expected_reg_value = self.memory_buffer.rd[1] self.write_back_stage.write_back() self.assertEqual(self.write_back_stage.memory_buffer, MemoryBuffer()) self.assertEqual( self.write_back_stage.register_file[self.instr.rd], expected_reg_value) self.assertTrue(self.register_file.isClean(self.instr.rd)) def test_write_back_I(self): self.set_up_write_back_stage('I LW R2 R5 4') self.write_back_stage.write_back() self.assertEqual(self.write_back_stage.memory_buffer, MemoryBuffer()) self.assertTrue(self.register_file.isClean(self.instr.rt))
class WriteBackStageTest(unittest.TestCase): def setUp(self): self.register_file = RegisterFile() def tearDown(self): pass def set_up_write_back_stage(self, instruction_string): """Set up WriteBackStage with the appropriate memory_buffer, etc. """ self.instruction_string = instruction_string self.instr = Instruction.Instruction( self.instruction_string.strip().split()) self.memory = Memory.Memory([self.instruction_string.strip().split()]) self.memory_buffer = Processor.Processor.get_stage_output( self.memory, self.register_file, 0, 0, 'memory') self.write_back_stage = write_back_stage.WriteBackStage( self.memory_buffer, self.register_file) def test_write_back_no_instr(self): self.set_up_write_back_stage('R ADD R1 R2 R3') self.memory_buffer.instr = None self.write_back_stage.write_back() self.assertEqual(self.write_back_stage.memory_buffer, self.memory_buffer) def test_write_back_R(self): self.set_up_write_back_stage('R ADD R1 R2 R3') expected_reg_value = self.memory_buffer.rd[1] self.write_back_stage.write_back() self.assertEqual(self.write_back_stage.memory_buffer, MemoryBuffer()) self.assertEqual(self.write_back_stage.register_file[self.instr.rd], expected_reg_value) self.assertTrue(self.register_file.isClean(self.instr.rd)) def test_write_back_I(self): self.set_up_write_back_stage('I LW R2 R5 4') self.write_back_stage.write_back() self.assertEqual(self.write_back_stage.memory_buffer, MemoryBuffer()) self.assertTrue(self.register_file.isClean(self.instr.rt))
def __init__(self, infile, outfile, num_registers=32): self.__disassembler = Disassembler() self.__input_file = infile self.__output_file = outfile self.__f = open('team13_out_pipeline.txt', 'w') self.__pc = 96 self.__cycle = 0 self.__memory = {} self.__last_inst = 0 self.pre_issue_size = 4 self.pre_alu_size = 2 self.pre_mem_size = 2 self.post_alu_size = 1 self.post_mem_size = 1 self.__pre_issue_buffer = deque(maxlen=self.pre_issue_size) self.__pre_mem_buffer = deque(maxlen=self.pre_mem_size) self.__pre_alu_buffer = deque(maxlen=self.pre_alu_size) self.__post_mem_buffer = deque(maxlen=self.post_mem_size) self.__post_alu_buffer = deque(maxlen=self.post_alu_size) self.__cache_to_load = deque(maxlen=2) self.__register_file = RegisterFile(num_registers) self.__wb = WriteBackUnit(self.__register_file) self.__cache = Cache(self.__memory) self.__alu = ALU() self.__mem = MemoryUnit(self.__cache) self.__if = IFUnit(self.__cache, self.__register_file) self.__iu = IssueUnit(self.__register_file, self.__pre_issue_buffer, self.__pre_mem_buffer, self.__pre_alu_buffer, self.__post_mem_buffer, self.__post_alu_buffer) self.__read_file()
def test_regfile_1R1Wconst0( dump_vcd, test_verilog ): # Test vectors test_vectors = [ # rd_addr0 rd_data0 wr_en wr_addr wr_data [ 0, 0x0000, 0, 0, 0x0000 ], [ 0, 0x0000, 1, 0, 0x0005 ], [ 0, 0x0000, 0, 0, 0x0000 ], [ 1, '?', 0, 1, 0x0000 ], [ 1, '?', 1, 1, 0x0015 ], [ 1, 0x0015, 0, 1, 0x0000 ], [ 1, 0x0015, 0, 1, 0x0000 ], ] # Instantiate and elaborate the model model = RegisterFile( dtype = 16, nregs = 8, rd_ports = 1, const_zero=True ) model.vcd_file = dump_vcd if test_verilog: model = TranslationTool( model, verilator_xinit=test_verilog ) model.elaborate() # Define functions mapping the test vector to ports in model def tv_in( model, test_vector ): model.rd_addr[0].value = test_vector[0] model.wr_en.value = test_vector[2] model.wr_addr.value = test_vector[3] model.wr_data.value = test_vector[4] def tv_out( model, test_vector ): if test_vector[1] != '?': assert model.rd_data[0].value == test_vector[1] # Run the test sim = TestVectorSimulator( model, test_vectors, tv_in, tv_out ) sim.run_test()
def __init__(self, data_store, instruction_store, start_address, number_of_ways, reservation_stations_types, reservation_station_cycles, reorder_buffer_size): self.data_store = data_store self.instruction_store = instruction_store self.cycles = 0 self.stopped = False self.register_file = RegisterFile(self.NUMBER_OF_REGISTERS) self.pc = start_address self.start_address = start_address self.instructions_count = 0 self.number_of_ways = number_of_ways self.register_stat = RegisterStat(self.NUMBER_OF_REGISTERS) self.reorder_buffer = ReorderBuffer(reorder_buffer_size) self.reservation_stations = ReservationStations(reservation_stations_types, reservation_station_cycles, self.reorder_buffer, self) self.read_more_instructions = True self.mispredictions = 0 self.predections = 0
def setUp(self): instruction_list = [ 'I ADDI R1 R1 1', 'I ADDI R2 R2 2', 'I ADDI R5 R5 89', 'I BEQ R2 R5 4', 'R ADD R1 R2 R3', 'R ADD R2 R0 R1', 'R ADD R3 R0 R2', 'J J 3', 'I ADDI R9 R9 999', ] instruction_list = [ instruction_string.split() for instruction_string in instruction_list ] self.memory = Memory.Memory(instruction_list) self.register_file = RegisterFile() self.processor = Processor.Processor(self.memory, 0)
def test_regfile_2R2W(dump_vcd, test_verilog): # Test vectors test_vectors = [ # ---read 0--- ---read 1--- -----write 0----- -----write 1----- # addr data addr data en addr data en addr data [10, '?', 14, '?', 0, 10, 0x0000, 0, 10, 0x0000], [13, '?', 14, '?', 1, 14, 0x0005, 0, 14, 0x0005], [12, '?', 14, 0x0005, 0, 10, 0x0006, 1, 12, 0x0006], [12, 0x0006, 12, 0x0006, 0, 13, 0x0008, 1, 13, 0x0009], [12, 0x0006, 12, 0x0006, 0, 13, 0x0007, 0, 13, 0x000a], [17, '?', 13, 0x0009, 0, 17, 0x0090, 1, 17, 0x0010], [14, 0x0005, 17, 0x0010, 0, 17, 0x0090, 0, 17, 0x0020], [16, '?', 17, 0x0010, 1, 17, 0x0090, 1, 16, 0x0090], [16, 0x0090, 17, 0x0090, 1, 17, 0x0011, 0, 16, 0x0011], [16, 0x0090, 17, 0x0011, 0, 10, 0x0000, 0, 10, 0x0000], ] # Instantiate and elaborate the model model = RegisterFile(dtype=16, nregs=32, rd_ports=2, wr_ports=2) model.vcd_file = dump_vcd if test_verilog: model = TranslationTool(model, verilator_xinit=test_verilog) model.elaborate() # Define functions mapping the test vector to ports in model def tv_in(model, test_vector): model.rd_addr[0].value = test_vector[0] model.rd_addr[1].value = test_vector[2] model.wr_en[0].value = test_vector[4] model.wr_addr[0].value = test_vector[5] model.wr_data[0].value = test_vector[6] model.wr_en[1].value = test_vector[7] model.wr_addr[1].value = test_vector[8] model.wr_data[1].value = test_vector[9] def tv_out(model, test_vector): if test_vector[1] != '?': assert model.rd_data[0].value == test_vector[1] if test_vector[3] != '?': assert model.rd_data[1].value == test_vector[3] # Run the test sim = TestVectorSimulator(model, test_vectors, tv_in, tv_out) sim.run_test()
def test_regfile_1R1W(dump_vcd, test_verilog): # Test vectors test_vectors = [ # rd_addr0 rd_data0 wr_en wr_addr wr_data [0, '?', 0, 0, 0x0000], [1, '?', 0, 1, 0x0008], # Write followed by Read [3, '?', 1, 2, 0x0005], [2, 0x0005, 0, 2, 0x0000], # Simultaneous Write and Read [3, '?', 1, 3, 0x0007], [3, 0x0007, 1, 7, 0x0090], [7, 0x0090, 1, 3, 0x0007], # Write to zero [0, '?', 1, 0, 0x0FFF], [0, 0x0FFF, 1, 4, 0x0FFF], [0, 0x0FFF, 0, 4, 0x0BBB], [0, 0x0FFF, 0, 4, 0x0FFF], [4, 0x0FFF, 0, 0, 0x0000], ] # Instantiate and elaborate the model model = RegisterFile(dtype=16, nregs=8, rd_ports=1) model.vcd_file = dump_vcd if test_verilog: model = TranslationTool(model, verilator_xinit=test_verilog) model.elaborate() # Define functions mapping the test vector to ports in model def tv_in(model, test_vector): model.rd_addr[0].value = test_vector[0] model.wr_en.value = test_vector[2] model.wr_addr.value = test_vector[3] model.wr_data.value = test_vector[4] def tv_out(model, test_vector): if test_vector[1] != '?': assert model.rd_data[0].value == test_vector[1] # Run the test sim = TestVectorSimulator(model, test_vectors, tv_in, tv_out) sim.run_test()
def test_regfile_2R2W( dump_vcd, test_verilog ): # Test vectors test_vectors = [ # ---read 0--- ---read 1--- -----write 0----- -----write 1----- # addr data addr data en addr data en addr data [ 0, 0x0000, 4, 0x0000, 0, 0, 0x0000, 0, 0, 0x0000], [ 3, 0x0000, 4, 0x0000, 1, 4, 0x0005, 0, 4, 0x0005], [ 2, 0x0000, 4, 0x0005, 0, 0, 0x0006, 1, 2, 0x0006], [ 2, 0x0006, 2, 0x0006, 0, 3, 0x0007, 0, 3, 0x0007], [ 7, 0x0000, 3, 0x0000, 0, 7, 0x0090, 1, 7, 0x0010], [ 4, 0x0005, 7, 0x0010, 0, 7, 0x0090, 0, 7, 0x0020], [ 6, 0x0000, 7, 0x0010, 1, 7, 0x0090, 1, 6, 0x0090], [ 6, 0x0090, 7, 0x0090, 1, 7, 0x0011, 0, 6, 0x0011], [ 6, 0x0090, 7, 0x0011, 0, 0, 0x0000, 0, 0, 0x0000], ] # Instantiate and elaborate the model model = RegisterFile( dtype=16, nregs=8, rd_ports=2, wr_ports=2 ) model.vcd_file = dump_vcd if test_verilog: model = TranslationTool( model ) model.elaborate() # Define functions mapping the test vector to ports in model def tv_in( model, test_vector ): model.rd_addr[0].value = test_vector[0] model.rd_addr[1].value = test_vector[2] model.wr_en [0].value = test_vector[4] model.wr_addr[0].value = test_vector[5] model.wr_data[0].value = test_vector[6] model.wr_en [1].value = test_vector[7] model.wr_addr[1].value = test_vector[8] model.wr_data[1].value = test_vector[9] def tv_out( model, test_vector ): assert model.rd_data[0].value == test_vector[1] assert model.rd_data[1].value == test_vector[3] # Run the test sim = TestVectorSimulator( model, test_vectors, tv_in, tv_out ) sim.run_test()
def test_regfile_2R1W( dump_vcd, test_verilog ): # Test vectors test_vectors = [ # rd_addr0 rd_data0 rd_addr0 rd_data0 wr_en wr_addr wr_data [ 0, 0x0000, 1, 0x0000, 0, 0, 0x0000 ], [ 3, 0x0000, 4, 0x0000, 1, 4, 0x0005 ], [ 3, 0x0000, 4, 0x0005, 1, 2, 0x0006 ], [ 4, 0x0005, 2, 0x0006, 0, 3, 0x0007 ], [ 4, 0x0005, 4, 0x0005, 0, 7, 0x0090 ], [ 4, 0x0005, 7, 0x0000, 0, 7, 0x0090 ], [ 4, 0x0005, 7, 0x0000, 1, 7, 0x0090 ], [ 4, 0x0005, 7, 0x0090, 1, 7, 0x0090 ], ] # Instantiate and elaborate the model model = RegisterFile( dtype=16, nregs=8, rd_ports=2 ) model.vcd_file = dump_vcd if test_verilog: model = TranslationTool( model ) model.elaborate() # Define functions mapping the test vector to ports in model def tv_in( model, test_vector ): model.rd_addr[0].value = test_vector[0] model.rd_addr[1].value = test_vector[2] model.wr_en.value = test_vector[4] model.wr_addr.value = test_vector[5] model.wr_data.value = test_vector[6] def tv_out( model, test_vector ): assert model.rd_data[0].value == test_vector[1] assert model.rd_data[1].value == test_vector[3] # Run the test sim = TestVectorSimulator( model, test_vectors, tv_in, tv_out ) sim.run_test()
def test_regfile_1R1Wconst0(dump_vcd, test_verilog): # Test vectors test_vectors = [ # rd_addr0 rd_data0 wr_en wr_addr wr_data [0, 0x0000, 0, 0, 0x0000], [0, 0x0000, 1, 0, 0x0005], [0, 0x0000, 0, 0, 0x0000], [1, '?', 0, 1, 0x0000], [1, '?', 1, 1, 0x0015], [1, 0x0015, 0, 1, 0x0000], [1, 0x0015, 0, 1, 0x0000], ] # Instantiate and elaborate the model model = RegisterFile(dtype=16, nregs=8, rd_ports=1, const_zero=True) model.vcd_file = dump_vcd if test_verilog: model = TranslationTool(model, verilator_xinit=test_verilog) model.elaborate() # Define functions mapping the test vector to ports in model def tv_in(model, test_vector): model.rd_addr[0].value = test_vector[0] model.wr_en.value = test_vector[2] model.wr_addr.value = test_vector[3] model.wr_data.value = test_vector[4] def tv_out(model, test_vector): if test_vector[1] != '?': assert model.rd_data[0].value == test_vector[1] # Run the test sim = TestVectorSimulator(model, test_vectors, tv_in, tv_out) sim.run_test()
class Processor: def __init__(self, initialPC=Bus(64), IMem=Memory(True), DMem=Memory(False)): self.ALU = ALU() self.IMem = IMem self.DMem = DMem self.signExtender = SignExtender() self.regFile = RegisterFile() self.Control = Control() self.nextPCLogic = NextPCLogic() self.PC = initialPC self.aluZero = 0 def runCycle(self): #fetch the instruction from IMem instruction = self.IMem.performOp(self.PC, None, 1, 0) #get control signals self.Control.performOp(instruction.slice(31, 21)) #reg file Source1Loc = instruction.slice(9, 5) Source2UpperBound = [20] Source2LowerBound = [16] if (self.Control.reg2loc): Source2UpperBound = [4] Source2LowerBound = [0] Source2Loc = instruction.slice(Source2UpperBound[0], Source2LowerBound[0]) Source1, Source2 = self.regFile.performOp(0, Source1Loc, Source2Loc, None, None) #sign extension Imm26 = instruction.slice(25, 0) extendedImmediate = self.signExtender.performOp( self.Control.signop, Imm26) #ALU writeData = deepcopy(Source2) if (self.Control.alusrc): Source2 = extendedImmediate ALUOutput, self.aluZero = self.ALU.performOp(self.Control.aluop, Source1, Source2) #DMem DMemOutput = self.DMem.performOp(ALUOutput, writeData, self.Control.memread, self.Control.memwrite) #Write back to reg file writeReg = instruction.slice(4, 0) writeData = ALUOutput if (self.Control.mem2reg): writeData = DMemOutput self.regFile.performOp(self.Control.regwrite, Bus(5), Bus(5), writeReg, writeData) #NextPC self.PC = self.nextPCLogic.performOp(self.Control.uncondbranch, self.Control.branch, self.aluZero, extendedImmediate, self.PC) return (self.PC, DMemOutput)
class SimplifiedSuperScalarSimulator: def __init__(self, infile, outfile, num_registers=32): self.__disassembler = Disassembler() self.__input_file = infile self.__output_file = outfile self.__f = open('team13_out_pipeline.txt', 'w') self.__pc = 96 self.__cycle = 0 self.__memory = {} self.__last_inst = 0 self.pre_issue_size = 4 self.pre_alu_size = 2 self.pre_mem_size = 2 self.post_alu_size = 1 self.post_mem_size = 1 self.__pre_issue_buffer = deque(maxlen=self.pre_issue_size) self.__pre_mem_buffer = deque(maxlen=self.pre_mem_size) self.__pre_alu_buffer = deque(maxlen=self.pre_alu_size) self.__post_mem_buffer = deque(maxlen=self.post_mem_size) self.__post_alu_buffer = deque(maxlen=self.post_alu_size) self.__cache_to_load = deque(maxlen=2) self.__register_file = RegisterFile(num_registers) self.__wb = WriteBackUnit(self.__register_file) self.__cache = Cache(self.__memory) self.__alu = ALU() self.__mem = MemoryUnit(self.__cache) self.__if = IFUnit(self.__cache, self.__register_file) self.__iu = IssueUnit(self.__register_file, self.__pre_issue_buffer, self.__pre_mem_buffer, self.__pre_alu_buffer, self.__post_mem_buffer, self.__post_alu_buffer) self.__read_file() def __read_file(self): """ Reads the designated input file and stores each line as a decimal integer """ pc = 96 with open(self.__input_file, 'r') as f: for line in f: self.__memory[pc] = int(line, 2) if int(line, 2) == Disassembler.break_inst: self.__last_inst = pc pc += 4 def __update_space(self): self.__pre_issue_space = self.pre_issue_size - len( self.__pre_issue_buffer) self.__pre_alu_space = self.pre_alu_size - len(self.__pre_alu_buffer) self.__pre_mem_space = self.pre_mem_size - len(self.__pre_mem_buffer) self.__post_alu_space = self.post_alu_size - len( self.__post_alu_buffer) self.__post_mem_space = self.post_mem_size - len( self.__post_mem_buffer) def __are_buffers_empty(self): self.__update_space() # print self.__pre_issue_space, \ # self.__pre_alu_space, \ # self.__pre_mem_space, \ # self.__post_alu_space, \ # self.__post_mem_space return self.__pre_issue_space == 4 and \ self.__pre_alu_space == 2 and \ self.__pre_mem_space == 2 and \ self.__post_alu_space == 1 and \ self.__post_mem_space == 1 def run(self): run = True while run: run = False self.__cycle += 1 print self.__cycle # Run WriteBackUnit if len(self.__post_mem_buffer) > 0: wb_in = self.__post_mem_buffer.popleft() self.__wb.run(wb_in, 'mem') if len(self.__post_alu_buffer) > 0: wb_in = self.__post_alu_buffer.popleft() self.__wb.run(wb_in, 'alu') self.__update_space() # Run ALU # If pre-buffer not empty and post-buffer not full if len(self.__pre_alu_buffer) > 0 and self.__post_alu_space > 0: alu_in = self.__pre_alu_buffer.popleft() alu_out = self.__alu.run(alu_in) self.__post_alu_buffer.append(alu_out) run = True self.__update_space() # Run MemoryUnit # If pre-buffer not empty and post-buffer not full if len(self.__pre_mem_buffer) > 0 and self.__post_mem_space > 0: mem_in = self.__pre_mem_buffer.popleft() mem_out = self.__mem.run(mem_in) if not mem_out: self.__cache_to_load.append(mem_in['rn_val'] + mem_in['offset']) elif mem_out is not None: self.__post_mem_buffer.append(mem_out) run = True self.__update_space() # Run Issue Unit (twice) # TODO Hazard detection if len(self.__pre_issue_buffer) > 0: self.__iu.run(self.__pre_mem_space, self.__pre_alu_space) run = True self.__update_space() # Run IF Unit # If pre-issue buffer not full result = True if self.__pc < self.__last_inst: if self.__pre_issue_space == 0: continue elif self.__pre_issue_space == 1: result = self.__if.run(self.__pc, 1) else: result = self.__if.run(self.__pc, 2) if not result: self.__cache_to_load.append(self.__pc) else: insts = result[0] self.__pc = result[1] for inst in insts: self.__pre_issue_buffer.append(inst) run = True self.__update_space() self.__print_state() while len(self.__cache_to_load) > 0: address = self.__cache_to_load.popleft() self.__cache.load(address) def __print_buffer(self, buffer): for i in range(buffer.maxlen): try: item = '[' + buffer[i]['assembly'] + ']' except IndexError: item = '' if item == '': self.__f.write('\tEntry {}:\n'.format(i, item)) else: self.__f.write('\tEntry {}:\t{}\n'.format(i, item)) def __print_buffers(self): self.__f.write('Pre-Issue Buffer:\n') self.__print_buffer(self.__pre_issue_buffer) self.__f.write('Pre_ALU Queue:\n') self.__print_buffer(self.__pre_alu_buffer) self.__f.write('Post_ALU Queue:\n') self.__print_buffer(self.__post_alu_buffer) self.__f.write('Pre_MEM Queue:\n') self.__print_buffer(self.__pre_mem_buffer) self.__f.write('Post_MEM Queue:\n') self.__print_buffer(self.__post_mem_buffer) self.__f.write('\n') def __print_registers(self): self.__f.write('Registers\n') for i in range(4): self.__f.write('R{:02d}:'.format(i * 8)) for j in range(8): value = self.__register_file.read_register(i * 8 + j) self.__f.write('\t{}'.format(value)) self.__f.write('\n') self.__f.write('\n') def __print_cache(self): self.__f.write('Cache\n') for s, set in enumerate(self.__cache.get_cache()): self.__f.write('Set {}: LRU={}\n'.format(s, set['lru'])) for b, block in enumerate(set['blocks']): valid = int(block['valid']) dirty = int(block['dirty']) tag = int(block['tag']) if block['tag'] is not None else '0' content1 = '{0:032b}'.format(block['content'][0]) if ( block['content'][0] != 0 and block['content'][0] is not None) else '0' content2 = '{0:032b}'.format(block['content'][1]) if ( block['content'][1] != 0 and block['content'][1] is not None) else '0' self.__f.write('\tEntry {}:[({},{},{})<{},{}>]\n'.format( b, valid, dirty, tag, content1, content2)) self.__f.write('\n') def __print_memory(self): self.__f.write('Data\n') # Filter data out of memory data = dict(self.__memory) for a in range(96, self.__last_inst + 4, 4): del data[a] # Fix stupid formatting, thanks Greg if len(data) > 0: # Add 0s from beginning to first first_data = min(data.keys()) for a in range(self.__last_inst + 4, first_data, 4): data[a] = 0 # Add 0s from last to end of line last_data = max(data.keys()) a = last_data + 4 while (a - first_data) % 8 != 0: data[a] = 0 a += 4 # Print useful information addresses = list(data.keys()) addresses.sort() for i, addr in enumerate(addresses): if i % 8 == 0: self.__f.write('\n{}:\t{}'.format(addr, data[addr])) else: self.__f.write('\t{}'.format(data[addr])) self.__f.write('\n' * 2) def __print_state(self): self.__f.write('-' * 20 + '\n') self.__f.write('Cycle:{}\n\n'.format(self.__cycle)) self.__print_buffers() self.__print_registers() self.__print_cache() self.__print_memory()
def setUp(self): self.register_file = RegisterFile()
class DecodeStageTest(unittest.TestCase): def setUp(self): self.register_file = RegisterFile() def tearDown(self): pass def set_up_decode_stage(self, instruction_string): """Set up Decode Stage with the appropriate fetcher_buffer, etc. Arguments: - `instruction_string`: """ self.instruction_string = instruction_string self.instr = Instruction.Instruction (self.instruction_string.strip().split()) self.memory = Memory.Memory([self.instruction_string.strip().split()]) self.fetcher_buffer = Processor.Processor.get_stage_output( self.memory, self.register_file, 0, 0, 'fetch') self.decoder_buffer = DecoderBuffer() self.decode_stage = decode_stage.DecodeStage(self.fetcher_buffer, self.decoder_buffer, self.register_file) def test_decode_R_instruction(self): self.set_up_decode_stage('R ADD R1 R2 R3') self.register_file.setClean(self.instr.rs) self.register_file.setClean(self.instr.rt) decoder_buffer = DecoderBuffer({ 'instr': self.instr, 'rs': [self.instr.rs, self.register_file[self.instr.rs]], 'rt': [self.instr.rt, self.register_file[self.instr.rt]], 'npc': self.fetcher_buffer.npc, }) self.decode_stage.decode_R_instruction() self.assertFalse(self.decode_stage.is_stalled) self.assertEqual(self.decode_stage.decoder_buffer, decoder_buffer) self.assertTrue(self.decode_stage.register_file.isDirty(self.instr.rd)) self.assertEqual(self.decode_stage.fetcher_buffer, FetcherBuffer()) def test_decode_R_instruction_dirty_reg(self): self.set_up_decode_stage('R ADD R1 R2 R3') self.register_file.setDirty(self.instr.rt) decoder_buffer = DecoderBuffer({ 'rt': [2, None], 'rs': [1, 0], 'instr': Instruction.Instruction('R ADD R1 R2 R3'.split()), 'npc': 4, 'PC': None }) self.decode_stage.decode_R_instruction() # self.assertTrue(self.decode_stage.is_stalled) self.assertFalse(self.decode_stage.is_stalled) self.assertEqual(self.decode_stage.decoder_buffer, decoder_buffer) self.assertTrue(self.decode_stage.register_file.isDirty(self.instr.rd)) self.assertEqual(self.decode_stage.fetcher_buffer, FetcherBuffer()) def test_decode_I_instruction_funct_and_load(self): self.set_up_decode_stage('I ADDI R1 R1 1') self.register_file.setClean(self.instr.rs) decoder_buffer = DecoderBuffer({ 'instr': self.instr, 'rs': [self.instr.rs, self.register_file [self.instr.rs]], 'npc': self.fetcher_buffer.npc, 'immediate': self.instr.immediate, }) self.decode_stage.decode_I_instruction() self.assertFalse(self.decode_stage.is_stalled) self.assertEqual(self.decode_stage.decoder_buffer, decoder_buffer) self.assertTrue(self.register_file.isDirty(self.instr.rt)) self.assertEqual(self.decode_stage.fetcher_buffer, FetcherBuffer()) def test_decode_I_instruction_funct_and_load_dirty_reg(self): self.set_up_decode_stage('I ADDI R1 R1 1') self.register_file.setDirty(self.instr.rs) decoder_buffer = DecoderBuffer({ 'rt': None, 'rs': [1, None], 'instr': Instruction.Instruction('I ADDI R1 R1 1'.split()), 'npc': 4, 'PC': None, 'immediate': 1 }) self.decode_stage.decode_I_instruction() self.assertFalse(self.decode_stage.is_stalled) self.assertEqual(self.decode_stage.decoder_buffer, decoder_buffer) self.assertTrue(self.register_file.isDirty(self.instr.rt)) self.assertEqual(self.decode_stage.fetcher_buffer, self.fetcher_buffer) def test_decode_I_instruction_store_and_branch(self): self.set_up_decode_stage('I BEQ R2 R5 4') self.register_file.setClean(self.instr.rs) self.register_file.setClean(self.instr.rt) decoder_buffer = DecoderBuffer({ 'instr': self.instr, 'rs': [self.instr.rs, self.register_file [self.instr.rs]], 'rt': [self.instr.rt, self.register_file [self.instr.rt]], 'npc': self.fetcher_buffer.npc, 'immediate': self.instr.immediate, }) self.decode_stage.decode_I_instruction() self.assertFalse(self.decode_stage.is_stalled) self.assertEqual(self.decode_stage.decoder_buffer, decoder_buffer) self.assertEqual(self.decode_stage.fetcher_buffer, FetcherBuffer()) def test_decode_I_instruction_store_and_branch_dirty_reg(self): self.set_up_decode_stage('I BEQ R2 R5 4') self.register_file.setDirty(self.instr.rs) decoder_buffer = DecoderBuffer({ 'rt': [5, 0], 'rs': [2, None], 'instr': Instruction.Instruction('I BEQ R2 R5 4'.split()), 'npc': 4, 'PC': None, 'immediate': 4 }) self.decode_stage.decode_I_instruction() self.assertFalse(self.decode_stage.is_stalled) self.assertEqual(self.decode_stage.decoder_buffer, decoder_buffer) self.assertEqual(self.decode_stage.fetcher_buffer, FetcherBuffer()) def test_get_jump_address(self): instruction_string = 'J J 3' instr = Instruction.Instruction (instruction_string.strip().split()) npc = 4 self.assertEqual(decode_stage.DecodeStage.get_jump_address(npc, instr), 12) def test_decode_J_instruction(self): self.set_up_decode_stage('J J 3') # decoder_buffer = DecoderBuffer({ # 'instr': self.instr, # 'npc': self.fetcher_buffer.npc, # 'PC': 12, # }) decoder_buffer = DecoderBuffer() self.decode_stage.decode_J_instruction() self.assertEqual(self.decode_stage.decoder_buffer, decoder_buffer) self.assertEqual(self.decode_stage.fetcher_buffer, FetcherBuffer()) def test_decodeInstruction(self): self.set_up_decode_stage('R ADD R1 R2 R3') self.decode_stage.decode_instruction(True) self.assertEqual( self.decode_stage.decoder_buffer, DecoderBuffer()) self.fetcher_buffer.instr = None self.decode_stage.decode_instruction() self.assertEqual( self.decode_stage.decoder_buffer, DecoderBuffer())
class Processor: NUMBER_OF_REGISTERS = 8 def __init__(self, data_store, instruction_store, start_address, number_of_ways, reservation_stations_types, reservation_station_cycles, reorder_buffer_size): self.data_store = data_store self.instruction_store = instruction_store self.cycles = 0 self.stopped = False self.register_file = RegisterFile(self.NUMBER_OF_REGISTERS) self.pc = start_address self.start_address = start_address self.instructions_count = 0 self.number_of_ways = number_of_ways self.register_stat = RegisterStat(self.NUMBER_OF_REGISTERS) self.reorder_buffer = ReorderBuffer(reorder_buffer_size) self.reservation_stations = ReservationStations(reservation_stations_types, reservation_station_cycles, self.reorder_buffer, self) self.read_more_instructions = True self.mispredictions = 0 self.predections = 0 def progress(self): #pdb.set_trace() if self.stopped: return False self.cycles += 1 common_data_bus_empty = True can_commit = True any_change = False # Update Reservation Stations for i in self.reservation_stations.entries.keys(): for j in range(len(self.reservation_stations.entries[i])): reservation_station = self.reservation_stations.entries[i][j] if reservation_station.busy: any_change = True if reservation_station.progress == InstructionProgress.issue: if reservation_station.type_ in [ FunctionalUnit.load, FunctionalUnit.store ]: if reservation_station.qj == -1: # Ready to calculate address reservation_station.address += reservation_station.vj reservation_station.progress = InstructionProgress.execute reservation_station.start() elif reservation_station.operation in [InstructionType.return_, InstructionType.jump_and_link ]: if reservation_station.qj == -1: # Ready to calculate address reservation_station.address = reservation_station.vj reservation_station.progress = InstructionProgress.execute reservation_station.start() elif reservation_station.operation == InstructionType.jump: if reservation_station.qj == -1: # Ready to calculate address reservation_station.address += reservation_station.pc + reservation_station.vj + 2 reservation_station.progress = InstructionProgress.execute reservation_station.start() elif reservation_station.qj == -1 and reservation_station.qk == -1: if reservation_station.operation == InstructionType.branch_if_equal: self.predections += 1 if reservation_station.address < 0: reservation_station.predicted_taken = True self.reorder_buffer.clear_after((reservation_station.get_reorder_buffer().get_id() + 1) % self.reorder_buffer.get_size()) self.set_pc(self.pc + 2 + reservation_station.address) else: reservation_station.predicted_taken = False reservation_station.progress = InstructionProgress.execute reservation_station.start() reservation_station.progress_single_cycle() elif reservation_station.progress == InstructionProgress.execute: reservation_station.progress_single_cycle() if reservation_station.finished(): reservation_station.execute() reservation_station.progress = InstructionProgress.write if reservation_station.operation == InstructionType.branch_if_equal: if reservation_station.result == 0 ^ reservation_station.predicted_taken: self.inc_mispredictions() self.reorder_buffer.clear_after(reservation_station.get_reorder_buffer().get_id()) self.set_pc(reservation_station.pc + 2) else: reservation_station.get_reorder_buffer().clear() reservation_station.clear() elif reservation_station.progress == InstructionProgress.write: if common_data_bus_empty: common_data_bus_empty = False b = reservation_station.get_reorder_buffer().get_id() for q in self.reservation_stations.entries.keys(): for w in range(len(self.reservation_stations.entries[q])): tmp = self.reservation_stations.entries[q][w] if tmp.qj == b: tmp.vj = reservation_station.result tmp.qj = -1 for q in self.reservation_stations.entries.keys(): for w in range(len(self.reservation_stations.entries[q])): tmp = self.reservation_stations.entries[q][w] if tmp.qk == b: tmp.vk = reservation_station.result tmp.qk = -1 rob = reservation_station.get_reorder_buffer() rob.value = reservation_station.result rob.set_ready(True) if self.reorder_buffer.get_head() is reservation_station.get_reorder_buffer(): can_commit = False reservation_station.clear() if self.reorder_buffer.get_head().is_ready() and can_commit: any_change = True rob = self.reorder_buffer.get_head() d = rob.dest self.register_file.set(d, rob.value) rob.clear() if self.register_stat.get(d) == rob.get_id(): self.register_stat.clear(d) self.reorder_buffer.inc_head() #pdb.set_trace() # Issue new instructions if self.read_more_instructions: any_change = True for i in range(self.number_of_ways): inst = self.instruction_store.get_address(self.pc)[1] instruction = InstructionParser.parse(inst) if instruction.type_ == InstructionType.halt: self.read_more_instructions = False break if self.can_issue(instruction): self.instructions_count += 1 print "\nIssuing : " + inst self.issue(instruction) self.pc += 2 else: break print "\nReservation Stations :" print self.reservation_stations print "Reorder Buffers :" print self.reorder_buffer print "\nRegister Status :" print self.register_stat if not any_change: self.stopped = True print "" print "Data Cache : " self.data_store.print_logs(0) print "" print "Instructions Count : " + str(self.instructions_count) print "" print "Number of mispredictions : " + str(self.mispredictions) print "" print "Number of predictions : " + str(self.predections) def execute_all(self): while self.progress() != False: pass def can_issue(self, instruction): return self.reservation_stations.can_hold(self.get_functional_unit(instruction)) and not self.reorder_buffer.is_full() def issue(self, instruction): functional_unit = self.get_functional_unit(instruction) current_rob = self.reorder_buffer.get_current_empty() current_reservation_station = self.reservation_stations.get(functional_unit) if self.register_stat.busy(instruction.rs): h = self.register_stat.get(instruction.rs) if self.reorder_buffer.get(h).is_ready(): current_reservation_station.vj = self.reorder_buffer.get(h).value current_reservation_station.qj = -1 else: current_reservation_station.qj = h else: current_reservation_station.vj = self.register_file.get(instruction.rs) current_reservation_station.qj = -1 current_reservation_station.set_busy(True) current_reservation_station.dest = current_rob.get_id() current_reservation_station.operation = instruction.type_ current_reservation_station.pc = self.get_pc() current_rob.type_ = functional_unit current_rob.dest = instruction.rd current_rob.set_ready(False) current_rob.set_empty(False) current_rob.reservation_station = current_reservation_station if functional_unit in [ FunctionalUnit.add, FunctionalUnit.mult, FunctionalUnit.logical, FunctionalUnit.store ] or instruction.type_ == InstructionType.jump_and_link: if current_reservation_station.operation == InstructionType.add_immediate: current_reservation_station.vk = instruction.imm current_reservation_station.qk = -1 elif current_reservation_station.operation == InstructionType.branch_if_equal: current_reservation_station.address = instruction.imm else: if self.register_stat.busy(instruction.rt): h = self.register_stat.get(instruction.rt) if self.reorder_buffer.get(h).is_ready(): current_reservation_station.vk = self.reorder_buffer.get(h).value current_reservation_station.qk = -1 else: current_reservation_station.qk = h else: current_reservation_station.vk = self.register_file.get(instruction.rt) current_reservation_station.qk = -1 if functional_unit in [ FunctionalUnit.load ] : current_reservation_station.address = instruction.imm self.register_stat.set(instruction.rd, current_rob.get_id()) elif functional_unit in [ FunctionalUnit.store ]: current_reservation_station.address = instruction.imm elif functional_unit in [ FunctionalUnit.branches ]: if instruction.type_ == InstructionType.jump: current_reservation_station.address = instruction.imm elif functional_unit in [ FunctionalUnit.add, FunctionalUnit.mult, FunctionalUnit.logical ] and current_reservation_station.operation != InstructionType.branch_if_equal: self.register_stat.set(instruction.rd, current_rob.get_id()) current_reservation_station.progress = InstructionProgress.issue def execute_instruction(self, instruction): if instruction.type_ == InstructionType.store: self.store(instruction.reg_a, instruction.reg_b, instruction.imm) if instruction.type_ == InstructionType.jump: self.jump(instruction.reg_a, instruction.imm) if instruction.type_ == InstructionType.branch_if_equal: self.branch_if_equal(instruction.reg_a, instruction.reg_b, instruction.imm) if instruction.type_ == InstructionType.jump_and_link: self.jump_and_link(instruction.reg_a, instruction.reg_b) if instruction.type_ == InstructionType.return_: self.return_(instruction.reg_a) def get_functional_unit(self, instruction): if instruction.type_ == InstructionType.load : return FunctionalUnit.load if instruction.type_ == InstructionType.store: return FunctionalUnit.store if instruction.type_ == InstructionType.jump: return FunctionalUnit.branches if instruction.type_ == InstructionType.branch_if_equal: return FunctionalUnit.add if instruction.type_ == InstructionType.jump_and_link: return FunctionalUnit.branches if instruction.type_ == InstructionType.return_: return FunctionalUnit.branches if instruction.type_ == InstructionType.add: return FunctionalUnit.add if instruction.type_ == InstructionType.subtract: return FunctionalUnit.add if instruction.type_ == InstructionType.add_immediate: return FunctionalUnit.add if instruction.type_ == InstructionType.nand: return FunctionalUnit.logical if instruction.type_ == InstructionType.multiply: return FunctionalUnit.mult if instruction.type_ == InstructionType.halt: return FunctionalUnit.halt def store(self, source, base_address_register, offset): base_address = self.register_file.get(base_address_register) s = self.register_file.get(source) latency = self.data_store.write_in_address(base_address + offset, s) self.busy_for += latency def jump(self, base_address_register, offset): base_address = self.register_file.get(base_address_register) self.pc = self.pc + base_address + offset def branch_if_equal(self, source1, source2, address): s1 = self.register_file.get(source1) s2 = self.register_file.get(source2) if s1 == s2: self.pc = self.pc + address def jump_and_link(self, store_register, address_register): self.register_file.set(store_register, self.pc) s1 = self.register_file.get(address_register) self.pc = s1 def return_(self, source): self.pc = self.register_file.get(source) def get_instruction_number(self): return (self.pc - self.start_address) / 2 def get_pc(self): return self.pc def set_pc(self, value): self.pc = value def inc_mispredictions(self): self.mispredictions += 1