Esempio n. 1
0
    def test_conditional_instructions_incorrect_prediction_no_commit(self):
        """Test that Conditional Instructions with incorrect predicate do not commit."""
        # Initialize units.
        root = FlushableLog()
        rs = FeedLog()
        lsq = FeedLog()
        rob = ReorderBuffer(self.rf, rs, lsq, capacity=32)
        rob.set_pipeline_flush_root(root)
        rob.WIDTH = 4
        self.rf['r4'] = 0
        self.rf['r5'] = 10

        # Initialize instructions to be fed.
        cond = Blth('r4', 'r5', 100)
        cond.branch_info = BranchInfo(False, 100, 1, None)
        cond.DELAY = 0
        add = AddI('r1', 'r1', 1)
        add.DELAY = 0

        # Feed pairs of (cond, add) instructions.
        n_pairs = 5
        for i in range(n_pairs):
            rob.feed(cond)
            rob.feed(add)
        rob.tick()  # Insert into current queue.

        # Receive result for each pair in turn.
        for i in range(0, n_pairs, 2):
            rob.receive(Result(rs.log[i].tag, True))
            rob.receive(Result(rs.log[i + 1].tag, 0))
            rob.tick()
            self.assertEqual(self.rf['r1'], 0)
        self.assertEqual(self.rf['pc'], 100)
Esempio n. 2
0
 def test_execute(self):
     ins = Binary('ROB10', lambda o1, o2: o1 + o2, 'ROB3', 'ROB4')
     with self.assertRaises(ValueError):
         ins.execute()
     ins.receive(Result('ROB3', 5))
     ins.receive(Result('ROB4', 7))
     self.assertEqual(ins.execute(), Result('ROB10', 12))
Esempio n. 3
0
    def test_conditional_instructions_correct_prediction_commit(self):
        """Test Conditional Instructions with correct predicate commit OK."""
        # Initialize units.
        rs = FeedLog()
        lsq = FeedLog()
        rob = ReorderBuffer(self.rf, rs, lsq, capacity=32)
        rob.WIDTH = 4
        self.rf['r4'] = 0
        self.rf['r5'] = 0

        # Initialize instructions to be fed.
        cond = Blth('r4', 'r5', 2)
        cond.branch_info = BranchInfo(False, 2, 2, None)
        cond.DELAY = 0
        add = AddI('r1', 'r1', 1)
        add.DELAY = 0

        # Feed pairs of (cond, add) instructions.
        n_pairs = 5
        for i in range(n_pairs):
            rob.feed(cond)
            rob.feed(add)
        rob.tick()  # Insert into current queue.

        # Receive result for each pair in turn.
        r1_value = 0
        for i in range(0, n_pairs, 2):
            rob.receive(Result(rs.log[i].tag, False))
            rob.receive(Result(rs.log[i + 1].tag, r1_value))
            rob.tick()
            self.assertEqual(self.rf['r1'], r1_value)
            r1_value += 1
Esempio n. 4
0
 def test_load_execute(self):
     memory = Memory(64)
     memory[10] = 5
     load = Load('ROB1', 'ROB2')
     with self.assertRaises(ValueError):
         load.execute(memory)
     load.receive(Result('ROB2', 10))
     self.assertEqual(load.execute(memory), Result('ROB1', 5))
Esempio n. 5
0
 def test_store_execute(self):
     memory = Memory(64)
     memory[10] = 0
     store = Store('ROB1', 'ROB3', 'ROB4')
     for result in [Result('ROB3', 10), Result('ROB4', 5)]:
         with self.assertRaises(ValueError):
             store.execute(memory)
         store.receive(result)
     store.execute(memory)
     self.assertEqual(memory[10], 5)
Esempio n. 6
0
    def test_receive_and_can_dispatch(self):
        ins = Unconditional('ROB1', 'ROB2')
        self.assertFalse(ins.can_dispatch())

        ins.receive(Result('ROB4', 0))
        self.assertFalse(ins.can_dispatch())

        ins.receive(Result('ROB2', 5))
        self.assertTrue(ins.can_dispatch())

        ins.receive(Result('ROB3', 0))
        self.assertTrue(ins.can_dispatch())
Esempio n. 7
0
    def test_inorder_commit(self):
        """Ensure instruction Results are committed in-order."""
        for _ in range(30):
            for capacity in [1, 5, 25, 200]:
                # Initialize test components.
                self.log.reset()
                zeros = {'r%d' % i: 0 for i in range(capacity)}
                act_rf = RegisterFile(capacity, init_values=zeros)
                exp_rf = RegisterFile(capacity, init_values=zeros)
                width = random.randint(1, 2 * capacity)
                rob = ReorderBuffer(act_rf,
                                    self.log,
                                    self.lsq,
                                    capacity=capacity,
                                    width=width)

                # Feed instructions into ROB.
                n_ins = random.randint(1, capacity)
                register_names = []
                for i in range(n_ins):
                    add = self.generate_add(capacity)
                    register_names.append(add.rd)
                    rob.feed(add)
                rob.tick()

                # Generate a Result value for each fed instruction.
                result_vals = [random.randint(1, 10000) for _ in range(n_ins)]

                # Publish all but first result in reverse order to ROB. Should be
                # no updates to act_rf as the first instruction is stalled!
                for i in reversed(range(1, n_ins)):
                    rob.receive(Result(self.log.log[i].tag, result_vals[i]))
                    rob.tick()
                    self.assertEqual(exp_rf, act_rf)

                # Publish result of first instruction - all can now be comitted in
                # turn.
                rob.receive(Result(self.log.log[0].tag, result_vals[0]))

                # Group updates into ROB width chunks.
                updates = list(zip(register_names, result_vals))
                group_updates = [
                    updates[i:i + rob.width]
                    for i in range(0, len(updates), rob.width)
                ]

                # Ensure in-order commit of width instructions per tick.
                for group in group_updates:
                    rob.tick()
                    for (name, result) in group:
                        exp_rf[name] = result
                    self.assertEqual(exp_rf, act_rf)
                rob.tick()
Esempio n. 8
0
    def test_load_receive_and_can_dispatch_execute(self):
        ins = Load('ROB1', 'ROB2')
        self.assertFalse(ins.can_dispatch())

        ins.receive(Result('ROB4', 0))
        self.assertFalse(ins.can_dispatch())

        ins.receive(Result('ROB1', 0))
        self.assertFalse(ins.can_dispatch())

        ins.receive(Result('ROB2', 7))
        self.assertEqual(ins.address, 7)
        self.assertTrue(ins.can_dispatch())
Esempio n. 9
0
    def test_store_receive_and_can_dispatch_execute(self):
        ins = Store('ROB1', 'ROB7', 'ROB8')
        self.assertFalse(ins.can_dispatch())

        ins.receive(Result('ROB4', 0))
        self.assertFalse(ins.can_dispatch())

        ins.receive(Result('ROB7', 0))
        self.assertEqual(ins.address, 0)
        self.assertFalse(ins.can_dispatch())

        ins.receive(Result('ROB8', 7))
        self.assertTrue(ins.can_dispatch())
Esempio n. 10
0
    def test_result_equality(self):
        result = Result('r0', 10)

        none = Result('r1', 11)
        self.assertFalse(result == none, 'no attributes equal')

        val = Result('r2', 10)
        self.assertFalse(result == val, 'val equal but not dest')

        dest = Result('r0', 11)
        self.assertFalse(result == dest, 'dest equal but not val')

        val_dest = Result('r0', 10)
        self.assertTrue(result == val_dest, 'both attributes equal')
Esempio n. 11
0
 def test_inorder_execute(self):
     """Ensure Instructions are executed in-order."""
     capacity = 16
     lsq = LoadStoreQueue(self.memory, self.bus, capacity)
     # Fill LSQ with MemoryAccess Instructions.
     instructions = []
     for i in range(capacity):
         ins = self.generate_memory_access(capacity)
         instructions.append(ins)
         lsq.feed(ins)
     lsq.tick()
     # Ensure all execute dependencies are met.
     for i in range(capacity):
         lsq.receive(Result('ROB%d' % i, i))
     # Tick max # times req. for all Instructions to have completed.
     for _ in range(sum([ins.DELAY for ins in instructions])):
         lsq.tick()
     # Compute expected sequence of Results published by LoadStoreQueue.
     self.reset_memory()
     exp_results = []
     for ins in instructions:
         result = ins.execute(self.memory)
         if result:
             exp_results.append(result)
     self.assertListEqual(self.bus.log, exp_results)
Esempio n. 12
0
    def test_receive_and_can_dispatch(self):
        ins = Binary('ROB1', lambda o1, o2: o1 + o2, 'ROB2', 'ROB3')
        self.assertFalse(ins.can_dispatch())

        ins.receive(Result('ROB4', 0))
        self.assertFalse(ins.can_dispatch())

        ins.receive(Result('ROB2', 5))
        self.assertFalse(ins.can_dispatch())

        ins.receive(Result('ROB1', 0))
        self.assertFalse(ins.can_dispatch())

        ins.receive(Result('ROB3', 7))
        self.assertTrue(ins.can_dispatch())

        ins.receive(Result('ROB0', 0))
        self.assertTrue(ins.can_dispatch())
Esempio n. 13
0
    def test_correct_result(self):
        """Test correct Result computed by IntegerUnit and published."""
        add = IntegerLogical('ROB1', lambda o1, o2: o1 + o2, 5, 6)
        add.DELAY = 1

        unit = IntegerUnit(self.bus_log)
        unit.feed(add)
        unit.trigger()
        unit.tick()
        self.assertEqual(self.bus_log.log, [Result('ROB1', 11)])
Esempio n. 14
0
    def test_instructions_receive_published_results(self):
        """Test Instructions receive published results and dispatch OK."""
        ins = IntegerLogical('ROB1', lambda o1, o2: o1 - o2, 'ROB2', 'ROB3')
        self.rs.register(self.feed_log)

        self.rs.feed(ins)
        self.rs.trigger()

        self.rs.receive(Result('ROB4', 100))
        self.rs.tick()
        self.assertListEqual(self.feed_log.log, [])

        self.rs.receive(Result('ROB3', 100))
        self.rs.tick()
        self.assertListEqual(self.feed_log.log, [])

        self.rs.receive(Result('ROB2', 50))
        self.rs.tick()
        self.assertListEqual(self.feed_log.log, [ins])
Esempio n. 15
0
    def test_instructions_receive_published_results(self):
        """Test Instructions receive published results OK."""
        load = Load('ROB1', 'ROB2')
        store = Store('ROB3', 'ROB4', 'ROB2')
        lsq = LoadStoreQueue(self.memory, self.bus, 32)
        lsq.feed(load)
        lsq.feed(store)
        lsq.tick()

        lsq.receive(Result('ROB2', 10))
        self.assertEqual(load.address, 10)
        self.assertEqual(store.value, 10)
Esempio n. 16
0
    def test_correct_result(self):
        """Test correct Result computed by BranchUnit and published."""
        tests = []

        cond = Conditional('ROB1', lambda o1, o2: o1 < o2, 5, 6)
        cond.DELAY = 1
        tests.append((cond, Result('ROB1', True, typ=Branch)))

        cond = Conditional('ROB1', lambda o1, o2: o1 < o2, 6, 6)
        cond.DELAY = 1
        tests.append((cond, Result('ROB1', False, typ=Branch)))

        uncond = Unconditional('ROB2', 10)
        uncond.DELAY = 1
        tests.append((uncond, Result('ROB2', 10, typ=Branch)))

        for ins, exp_result in tests:
            self.bus_log.reset()
            unit = BranchUnit(self.bus_log)
            unit.feed(ins)
            unit.trigger()
            unit.tick()
            self.assertListEqual(self.bus_log.log, [exp_result])
Esempio n. 17
0
 def test_instructions_removed_from_queue_on_commit(self):
     """Test that commit frees a slot in the ROB."""
     for capacity in [1, 5, 25, 200]:
         log = FeedLog()
         rob = ReorderBuffer(self.rf,
                             log,
                             self.lsq,
                             capacity=capacity,
                             width=4)
         # Half fill.
         for _ in range(capacity // 2):
             rob.feed(self.generate_add(self.n_gpr_registers))
         rob.tick()  # Instructions now in current queue.
         # Remove all fed from ROB queue by giving values.
         self.assertEqual(capacity // 2, len(log.log))
         for ins in log.log:
             rob.receive(Result(ins.tag, 5))
         for _ in range(math.ceil(capacity / rob.width)):
             rob.tick()
         # Should now be able to feed capacity instructions.
         for _ in range(capacity):
             rob.feed(self.generate_add(self.n_gpr_registers))
Esempio n. 18
0
 def execute(self):
     if not self.can_dispatch():
         raise ValueError('unable to execute: operand not available')
     return Result(self.tag, self.operand, typ=Branch)
Esempio n. 19
0
 def execute(self):
     if not self.can_dispatch():
         raise ValueError('unable to execute: operand(s) not available')
     value = self.operation(self.operand_1, self.operand_2)
     return Result(self.tag, value, typ=Branch)
Esempio n. 20
0
 def execute(self, memory):
     if not self.can_dispatch():
         raise ValueError('unable to execute: operand(s) not available')
     return Result(self.tag, memory[self.address])
Esempio n. 21
0
 def test_execute(self):
     ins = Unconditional('ROB10', 'ROB4')
     with self.assertRaises(ValueError):
         ins.execute()
     ins.receive(Result('ROB4', 7))
     self.assertEqual(ins.execute(), Result('ROB10', 7, Branch))