1# -*- coding: utf-8 -*-
2# Copyright (c) 2017 Jason Power
3# All rights reserved.
4#
5# Redistribution and use in source and binary forms, with or without
6# modification, are permitted provided that the following conditions are
7# met: redistributions of source code must retain the above copyright
8# notice, this list of conditions and the following disclaimer;
9# redistributions in binary form must reproduce the above copyright
10# notice, this list of conditions and the following disclaimer in the
11# documentation and/or other materials provided with the distribution;
12# neither the name of the copyright holders nor the names of its
13# contributors may be used to endorse or promote products derived from
14# this software without specific prior written permission.
15#
16# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27#
28# Authors: Jason Power
29
30""" This file creates a set of Ruby caches, the Ruby network, and a simple
31point-to-point topology for the RubyRandomTester to use.
32See Part 3 in the Learning gem5 book: learning.gem5.org/book/part3
33
34IMPORTANT: If you modify this file, it's likely that the Learning gem5 book
35           also needs to be updated. For now, email Jason <jason@lowepower.com>
36
37"""
38
39from __future__ import print_function
40from __future__ import absolute_import
41
42from m5.defines import buildEnv
43from m5.util import fatal
44
45from m5.objects import *
46
47from msi_caches import L1Cache, DirController, MyNetwork
48
49class TestCacheSystem(RubySystem):
50
51    def __init__(self):
52        if buildEnv['PROTOCOL'] != 'MSI':
53            fatal("This system assumes MSI from learning gem5!")
54
55        super(TestCacheSystem, self).__init__()
56
57    def setup(self, system, tester, mem_ctrls):
58        """Set up the Ruby cache subsystem. Note: This can't be done in the
59           constructor because many of these items require a pointer to the
60           ruby system (self). This causes infinite recursion in initialize()
61           if we do this in the __init__.
62           Setting up for running the RubyRandomTester is a little different
63           than when we're using CPUs.
64        """
65        num_testers = tester.num_cpus
66
67        # Ruby's global network.
68        self.network = MyNetwork(self)
69
70        # MSI uses 3 virtual networks
71        self.number_of_virtual_networks = 3
72        self.network.number_of_virtual_networks = 3
73
74        self.controllers = \
75            [L1Cache(system, self, self) for i in range(num_testers)] + \
76            [DirController(self, system.mem_ranges, mem_ctrls)]
77
78        self.sequencers = [RubySequencer(version = i,
79                              # I/D cache is combined and grab from ctrl
80                              icache = self.controllers[i].cacheMemory,
81                              dcache = self.controllers[i].cacheMemory,
82                              clk_domain = self.clk_domain,
83                              ) for i in range(num_testers)]
84
85        for i,c in enumerate(self.controllers[0:len(self.sequencers)]):
86            c.sequencer = self.sequencers[i]
87
88        self.num_of_sequencers = len(self.sequencers)
89
90        # Create the network and connect the controllers.
91        # NOTE: This is quite different if using Garnet!
92        self.network.connectControllers(self.controllers)
93        self.network.setup_buffers()
94
95        # Set up a proxy port for the system_port. Used for load binaries and
96        # other functional-only things.
97        self.sys_port_proxy = RubyPortProxy()
98        system.system_port = self.sys_port_proxy.slave
99
100        # Connect up the sequencers to the random tester
101        for seq in self.sequencers:
102            if seq.support_data_reqs and seq.support_inst_reqs:
103                tester.cpuInstDataPort = seq.slave
104            elif seq.support_data_reqs:
105                tester.cpuDataPort = seq.slave
106            elif seq.support_inst_reqs:
107                tester.cpuInstDataPort = seq.slave
108
109            # Do not automatically retry stalled Ruby requests
110            seq.no_retry_on_stall = True
111
112            # Tell each sequencer this is the ruby tester so that it
113            # copies the subblock back to the checker
114            seq.using_ruby_tester = True
115