Exemple #1
0
 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()
Exemple #9
0
 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()
Exemple #13
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
    [    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()
Exemple #14
0
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()
Exemple #16
0
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()
 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())
Exemple #21
0
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