示例#1
0
    def setUp(self):
        self.clock = Clock()
        self.bus = BusLog()

        self.memory = Memory(10)
        for i in range(len(self.memory)):
            self.memory[i] = i

        self.n_gpr = 6
        self.rf = RegisterFile(self.n_gpr, 'r',
                               init_values={'r%d' % i: i for i in range(self.n_gpr)})
        iu1 = IntegerUnit(self.bus)
        iu2 = IntegerUnit(self.bus)
        iu3 = IntegerUnit(self.bus)

        rs = ReservationStation()
        rs.register(iu1)
        rs.register(iu2)
        rs.register(iu3)

        lsq = LoadStoreQueue(self.memory, self.bus)

        self.rob = ReorderBuffer(self.rf, rs, lsq)

        self.clock.register(self.rob)
        self.clock.register(lsq)
        self.clock.register(rs)
        self.clock.register(iu3)
        self.clock.register(iu2)
        self.clock.register(iu1)

        self.bus.subscribe(self.rob)
        self.bus.subscribe(rs)
        self.bus.subscribe(lsq)
示例#2
0
class TestIntegration(unittest.TestCase):

    def setUp(self):
        self.clock = Clock()
        self.bus = BusLog()

        self.memory = Memory(10)
        for i in range(len(self.memory)):
            self.memory[i] = i

        self.n_gpr = 6
        self.rf = RegisterFile(self.n_gpr, 'r',
                               init_values={'r%d' % i: i for i in range(self.n_gpr)})
        iu1 = IntegerUnit(self.bus)
        iu2 = IntegerUnit(self.bus)
        iu3 = IntegerUnit(self.bus)

        rs = ReservationStation()
        rs.register(iu1)
        rs.register(iu2)
        rs.register(iu3)

        lsq = LoadStoreQueue(self.memory, self.bus)

        self.rob = ReorderBuffer(self.rf, rs, lsq)

        self.clock.register(self.rob)
        self.clock.register(lsq)
        self.clock.register(rs)
        self.clock.register(iu3)
        self.clock.register(iu2)
        self.clock.register(iu1)

        self.bus.subscribe(self.rob)
        self.bus.subscribe(rs)
        self.bus.subscribe(lsq)

    def test_straightline_integration(self):
        instructions = [Add('r2', 'r3', 'r4'),
                        Store('r1', 'r2'),
                        Load('r1', 'r2'),
                        AddI('r1', 'r1', 1),
                        Store('r1', 'r2')]
        for ins in instructions:
            self.rob.feed(ins)

        # Enough clock ticks to ensure completion.
        for _ in range(100):
            self.clock.tick()

        self.assertListEqual([self.rf['r%d' % i] for i in range(self.n_gpr)],
                             [0, 2, 7, 3, 4, 5])
        self.assertListEqual([self.memory[i] for i in range(len(self.memory))],
                             [0, 1, 2, 3, 4, 5, 6, 2, 8, 9])
示例#3
0
    def test_feed_full(self):
        """Test full operation when feeding Instructions."""
        for rob_capacity in [1, 5, 25, 200]:
            for rs_capacity in [1, 5, 25, 200]:
                for lsq_capacity in [1, 5, 25, 200]:
                    register_limit = min(rob_capacity, rs_capacity)
                    memory_limit = min(rob_capacity, lsq_capacity)

                    rs = ReservationStation(capacity=rs_capacity)
                    lsq = LoadStoreQueue(self.memory,
                                         self.bus,
                                         capacity=lsq_capacity)
                    rob = ReorderBuffer(self.rf,
                                        rs,
                                        lsq,
                                        capacity=rob_capacity)

                    for _ in range(register_limit):
                        ins = self.generate_add(self.n_gpr_registers)
                        self.assertFalse(
                            rob.full(ins),
                            'ReorderBuffer should not be full after < %d feeds'
                            % register_limit)
                        rob.feed(ins)
                    self.assertTrue(
                        rob.full(self.generate_add(self.n_gpr_registers)),
                        'ReorderBuffer should be full after %d feeds' %
                        register_limit)
                    with self.assertRaises(AssertionError):
                        rob.feed(self.generate_add(self.n_gpr_registers))
示例#4
0
    def test_flush(self):
        """Ensure flush of ReorderBuffer, LoadStoreQueue and ReservationStation."""
        rs = FlushableLog()
        rs.full = lambda: False
        rs.feed = lambda x: None
        lsq = FlushableLog()
        lsq.full = lambda: False
        lsq.feed = lambda x: None

        for rob_capacity in [1, 5, 25, 200]:
            for rs_capacity in [1, 5, 25, 200]:
                for lsq_capacity in [1, 5, 25, 200]:
                    register_limit = min(rob_capacity, rs_capacity)

                    rs.reset()
                    lsq.reset()
                    rob = ReorderBuffer(self.rf,
                                        rs,
                                        lsq,
                                        capacity=rob_capacity)

                    for _ in range(register_limit):
                        rob.feed(self.generate_add(self.n_gpr_registers))
                    rob.flush()
                    self.assertFalse(
                        rob.full(self.generate_add(self.n_gpr_registers)),
                        'ReorderBuffer should not be full after flush')
                    self.assertEqual(
                        rs.n_flush, 1,
                        'ReorderBuffer must flush ReservationStation')
                    self.assertEqual(
                        lsq.n_flush, 1,
                        'ReorderBuffer must flush LoadStoreQueue')
示例#5
0
 def test_get_queue_id(self):
     """Test that _get_queue_id throws an error on wrap-around."""
     for capacity in [1, 5, 25, 200]:
         rob = ReorderBuffer(self.rf, self.log, self.lsq, capacity=capacity)
         for _ in range(capacity):
             rob._get_queue_id()
         with self.assertRaises(AssertionError):
             rob._get_queue_id()
示例#6
0
文件: __main__.py 项目: samgd/procsim
if args.always_taken:
    branch_predictor = AlwaysTaken()
elif args.never_taken:
    branch_predictor = NeverTaken()
elif args.back_taken_forward_not:
    branch_predictor = BackTakenForwardNot()
elif args.branch_history_table:
    branch_predictor = BranchHistoryTable(
        n_entries=args.branch_history_table[0],
        n_prediction_bits=args.branch_history_table[1])
else:
    branch_predictor = BranchHistoryTable(n_entries=2**8, n_prediction_bits=2)

reorder_buffer = ReorderBuffer(register_file,
                               reservation_station,
                               load_store_queue,
                               branch_predictor=branch_predictor,
                               capacity=args.capacity,
                               width=args.superscalar_width)

decode = Decode(reorder_buffer,
                capacity=args.capacity,
                width=args.superscalar_width)

fetch = Fetch(register_file,
              program.PROGRAM,
              decode,
              branch_predictor,
              width=args.superscalar_width)

# Add additional connections.
broadcast_bus.subscribe(reservation_station)
示例#7
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))
示例#8
0
 def test_invalid_capacity(self):
     """Test exception thrown when initialized with invalid capacity."""
     for _ in range(100):
         invalid = random.randint(-1000, 0)
         with self.assertRaises(ValueError):
             ReorderBuffer(self.rf, self.log, self.lsq, capacity=invalid)
示例#9
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)
示例#10
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
示例#11
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()