blob: 623eb03c9f47a417c6d3e7f0ee92ac97fb6ee65f [file] [log] [blame]
# -*- coding: utf-8 -*-
# Copyright (c) 2016 Jason Lowe-Power
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met: redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer;
# redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution;
# neither the name of the copyright holders nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Authors: Jason Lowe-Power
import m5
from m5.objects import *
from m5.util import convert
import x86
from caches import *
class MySystem(LinuxX86System):
def __init__(self, opts):
super(MySystem, self).__init__()
self._opts = opts
# Set up the clock domain and the voltage domain
self.clk_domain = SrcClockDomain()
self.clk_domain.clock = '3GHz'
self.clk_domain.voltage_domain = VoltageDomain()
# For x86, there is an I/O gap from 3GB to 4GB.
# We can have at most 3GB of memory unless we do something special
# to account for this I/O gap. For simplicity, this is omitted.
mem_size = '512MB'
self.mem_ranges = [AddrRange(mem_size),
AddrRange(0xC0000000, size=0x100000), # For I/0
]
# Create the main memory bus
# This connects to main memory
self.membus = SystemXBar()
self.membus.badaddr_responder = BadAddr()
self.membus.default = self.membus.badaddr_responder.pio
# Set up the system port for functional access from the simulator
self.system_port = self.membus.slave
# This will initialize most of the x86-specific system parameters
# This includes things like the I/O, multiprocessor support, BIOS...
x86.init_fs(self, self.membus)
# Change this path to point to the kernel you want to use
# Kernel from http://www.m5sim.org/dist/current/x86/x86-system.tar.bz2
self.kernel = 'binaries/x86_64-vmlinux-2.6.22.9'
# Options specified on the kernel command line
boot_options = ['earlyprintk=ttyS0', 'console=ttyS0', 'lpj=7999923',
'root=/dev/hda1']
self.boot_osflags = ' '.join(boot_options)
# Replace these paths with the path to your disk images.
# The first disk is the root disk. The second could be used for swap
# or anything else.
# Disks from http://www.m5sim.org/dist/current/x86/x86-system.tar.bz2
self.setDiskImage('disks/linux-x86.img')
# Create the CPU for our system.
self.createCPU()
# Create the cache heirarchy for the system.
self.createCacheHierarchy()
# Create the memory controller for the sytem
self.createMemoryControllers()
# Set up the interrupt controllers for the system (x86 specific)
self.setupInterrupts()
def createCPU(self):
""" Create a CPU for the system """
# This defaults to one simple atomic CPU. Using other CPU models
# and using timing memory is possible as well.
# Also, changing this to using multiple CPUs is also possible
# Note: If you use multiple CPUs, then the BIOS config needs to be
# updated as well.
self.cpu = X86AtomicSimpleCPU()
self.mem_mode = 'atomic'
self.cpu.createThreads()
def setDiskImage(self, img_path):
""" Set the disk image
@param img_path path on the host to the image file for the disk
"""
# Can have up to two master disk images.
# This can be enabled with up to 4 images if using master-slave pairs
disk0 = CowDisk(img_path)
self.pc.south_bridge.ide.disks = [disk0]
def createCacheHierarchy(self):
""" Create a simple cache heirarchy with the caches from part1 """
# Create an L1 instruction and data caches and an MMU cache
# The MMU cache caches accesses from the inst and data TLBs
self.cpu.icache = L1ICache(self._opts)
self.cpu.dcache = L1DCache(self._opts)
# Connect the instruction, data, and MMU caches to the CPU
self.cpu.icache.connectCPU(self.cpu)
self.cpu.dcache.connectCPU(self.cpu)
# Hook the CPU ports up to the membus
self.cpu.icache.connectBus(self.membus)
self.cpu.dcache.connectBus(self.membus)
# Connect the CPU TLBs directly to the mem.
self.cpu.itb.walker.port = self.membus.slave
self.cpu.dtb.walker.port = self.membus.slave
def createMemoryControllers(self):
""" Create the memory controller for the system """
# Just create a controller for the first range, assuming the memory
# size is < 3GB this will work. If it's > 3GB or if you want to use
# mulitple or interleaved memory controllers then this should be
# updated accordingly
self.mem_cntrl = DDR3_1600_8x8(range = self.mem_ranges[0],
port = self.membus.master)
def setupInterrupts(self):
""" Create the interrupt controller for the CPU """
# create the interrupt controller for the CPU, connect to the membus
self.cpu.createInterruptController()
# For x86 only, make sure the interrupts are connected to the memory
# Note: these are directly connected to the memory bus, not cached
self.cpu.interrupts[0].pio = self.membus.master
self.cpu.interrupts[0].int_master = self.membus.slave
self.cpu.interrupts[0].int_slave = self.membus.master
class CowDisk(IdeDisk):
""" Wrapper class around IdeDisk to make a simple copy-on-write disk
for gem5. Creates an IDE disk with a COW read/write disk image.
Any data written to the disk in gem5 is saved as a COW layer and
thrown away on the simulator exit.
"""
def __init__(self, filename):
""" Initialize the disk with a path to the image file.
@param filename path to the image file to use for the disk.
"""
super(CowDisk, self).__init__()
self.driveID = 'master'
self.image = CowDiskImage(child=RawDiskImage(read_only=True),
read_only=False)
self.image.child.image_file = filename