# Copyright (c) 2021 The Regents of the University of California
# 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.

import m5
from m5.objects import *
from os import path

# For downloading the disk image
from gem5.resources.resource import Resource

import argparse

def generateMemNode(state, mem_range):
    node = FdtNode("memory@%x" % int(mem_range.start))
    node.append(FdtPropertyStrings("device_type", ["memory"]))
    node.append(FdtPropertyWords("reg",
        state.addrCells(mem_range.start) +
        state.sizeCells(mem_range.size()) ))
    return node

def generateDtb(system):
    """
    Autogenerate DTB. Arguments are the folder where the DTB
    will be stored, and the name of the DTB file.
    """
    state = FdtState(addr_cells=2, size_cells=2, cpu_cells=1)
    root = FdtNode('/')
    root.append(state.addrCellsProperty())
    root.append(state.sizeCellsProperty())
    root.appendCompatible(["riscv-virtio"])

    for mem_range in system.mem_ranges:
        root.append(generateMemNode(state, mem_range))

    sections = [*system.cpu, system.platform]

    for section in sections:
        for node in section.generateDeviceTree(state):
            if node.get_name() == root.get_name():
                root.merge(node)
            else:
                root.append(node)

    fdt = Fdt()
    fdt.add_rootnode(root)
    fdt.writeDtsFile(path.join(m5.options.outdir, 'device.dts'))
    fdt.writeDtbFile(path.join(m5.options.outdir, 'device.dtb'))

def createHiFivePlatform(system):
    # Since the latency from CPU to the bus was set in SST, additional latency
    # is undesirable.
    system.membus = NoncoherentXBar(
        frontend_latency = 0, forward_latency = 0, response_latency = 0,
        header_latency = 0, width = 64
    )
    system.membus.badaddr_responder = BadAddr()
    system.membus.default = \
        system.membus.badaddr_responder.pio

    system.memory_outgoing_bridge = OutgoingRequestBridge()
    system.memory_outgoing_bridge.port = system.membus.mem_side_ports
    for cpu in system.cpu:
        cpu.createThreads()
        cpu.icache_port = system.membus.cpu_side_ports
        cpu.dcache_port = system.membus.cpu_side_ports

        cpu.mmu.connectWalkerPorts(
            system.membus.cpu_side_ports, system.membus.cpu_side_ports)


    system.platform = HiFive()

    system.platform.pci_host.pio = system.membus.mem_side_ports

    system.platform.rtc = RiscvRTC(frequency=Frequency("100MHz"))
    system.platform.clint.int_pin = system.platform.rtc.int_pin

    system.pma_checker = PMAChecker(
        uncacheable=[
            *system.platform._on_chip_ranges(),
            *system.platform._off_chip_ranges(),
        ]
    )

    system.iobus = IOXBar()
    system.bridge = Bridge(delay='50ns')
    system.bridge.mem_side_port = system.iobus.cpu_side_ports
    system.bridge.cpu_side_port = system.membus.mem_side_ports
    system.bridge.ranges = system.platform._off_chip_ranges()

    system.platform.setNumCores(1)

    system.platform.attachOnChipIO(system.membus)
    system.platform.attachOffChipIO(system.iobus)

    system.platform.attachPlic()

parser = argparse.ArgumentParser()
parser.add_argument('--cpu-clock-rate', type=str,
                     help='CPU clock rate, e.g. 3GHz')
parser.add_argument('--memory-size', type=str, help='Memory size, e.g. 4GiB')

args = parser.parse_args()
cpu_clock_rate = args.cpu_clock_rate
memory_size = args.memory_size

# Try downloading the Resource
bbl_resource = Resource("riscv-boot-exit-nodisk")
bbl_path = bbl_resource.get_local_path()

system = System()

system.clk_domain = SrcClockDomain(
    clock=cpu_clock_rate, voltage_domain=VoltageDomain()
)

system.mem_ranges = [AddrRange(start=0x80000000, size=memory_size)]

system.cpu = [TimingSimpleCPU(cpu_id=i) for i in range(1)]
system.mem_mode = 'timing'

createHiFivePlatform(system)

system.system_outgoing_bridge = OutgoingRequestBridge()
system.system_port = system.system_outgoing_bridge.port
generateDtb(system)
system.workload = RiscvLinux()
system.workload.addr_check = False
system.workload.object_file = bbl_path
system.workload.dtb_filename = path.join(m5.options.outdir, 'device.dtb')
system.workload.dtb_addr = 0x87e00000
kernel_cmd = [
    # specifying Linux kernel boot options
    "console=ttyS0"
]
system.workload.command_line = " ".join(kernel_cmd)

for cpu in system.cpu:
    cpu.createInterruptController()

root = Root(full_system = True, system = system)

