from optparse import OptionParser
from subprocess import Popen, PIPE
from os import getcwd, cpu_count
from time import sleep

bench_dir = "/root/gem5/benchmark"
gem5_img = "gem5-gfortran3"
arch = "X86"
mode = "debug"

def addOption():
    parser = OptionParser()
    parser.add_option("-p", action="store_true", default=False, dest="parse")
    parser.add_option("-b", action="store_true", default=False, dest="build")
    parser.add_option("-k", action="store_true", default=False, dest="kill")
    (options, args) = parser.parse_args()
    return options

def shell(cmd):
    p = Popen(cmd, stdout=PIPE, stderr=PIPE, shell=True)
    (stdout, stderr) = p.communicate()
    return str(stdout, "utf-8"), str(stderr, "utf-8")

def popen(cmd):
    return Popen(cmd, stdout=PIPE, stderr=PIPE, shell=True)

def getDockerCmd(gem5_cmd):
    docker_cmd = \
    "docker run -u $UID:$GID \
    --volume " + getcwd() + ":/gem5 \
    --volume " + bench_dir + ":/bench \
    --rm " + gem5_img + " bash -c \
    'cd gem5; " + gem5_cmd + "'"
    return docker_cmd

def getListHwp():
    prefetchers = [None]
    (out, err) = shell(getDockerCmd("./build/" + arch + "/gem5." + mode + " configs/example/se.py --list-hwp-types"))
    check = False
    for line in out.split("\n"):
        if check:
            prefetcher = line.split()
            if len(prefetcher) > 0:
                prefetchers.append(prefetcher[0])
        if "Available BasePrefetcher classes:" in line:
            check = True
    return prefetchers

def buildDocker():
    dockerFile = """
    FROM gcr.io/gem5-test/ubuntu-20.04_all-dependencies
    RUN echo "deb http://gb.archive.ubuntu.com/ubuntu/ bionic main universe" >> /etc/apt/sources.list
    RUN apt-get update
    RUN apt-get install -y g++-6
    RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-6 6
    RUN apt-get install -y libgfortran3
    """
    f = open("Dockerfile", "w")
    f.write(dockerFile)
    f.close()
    shell("docker build -t gem5-gfortran3 .")
    shell("rm Dockerfile")

def build():
    (out, err) = shell("docker images")
    if gem5_img not in out:
        buildDocker()
    shell(getDockerCmd("scons build/" + arch + "/gem5." + mode + " -j" + str(int(cpu_count()*2/3))))

def kill():
    (out, err) = shell("ps -e | grep gem5.debug")
    pids = []
    for line in out.split("\n"):
        tmp = line.split()
        if len(tmp) > 0:
            pids.append(tmp[0])
    shell("kill -9 " + " ".join(pids))

def run():
    cmd = [
        "./build/" + arch + "/gem5." + mode,
        "", # [1] --outdir=
        "configs/example/se.py \
        -c tests/test-progs/hello/bin/x86/linux/hello \
        --cpu-type=TimingSimpleCPU \
        --num-cpus=8 \
        --num-cores-socket=4 \
        --num-sockets-server=2 \
        --num-cores-l2=2 \
        --caches --l1d_size=64kB --l1i_size=64kB \
        --l2cache --l2_size=1MB \
        --l3cache --l3_size=32MB \
        --l4cache --l4_size=512MB \
        --mem-size=8GB \
        --cxl --cxl-mem-size=8GB",
        "", # [3] --l2-hwp-type=
    ]

    prefetchers = getListHwp()
    for prefetcher in prefetchers:
        if prefetcher:
            cmd[1] = "--outdir=m5out/" + prefetcher
            cmd[3] = "--l2-hwp-type=" + prefetcher
        else:
            cmd[1] = "--outdir=m5out/" + "None"
            cmd[3] = ""
        popen(getDockerCmd(" ".join(cmd)))

def parse():
    prefetchers = getListHwp()
    stats = {
        "real_time": [], # m
        "exec_time": [], # ms
        "wss": [], # MiB
        "l1_miss": [], # %
        "l2_miss": [], # %
    }
    for i in range(len(prefetchers)):
        if prefetchers[i]:
            f = open("m5out/" + prefetchers[i] + "/stats.txt", "r")
            print("")
            print(prefetchers[i])
        else:
            f = open("m5out/" + "None" + "/stats.txt", "r")
            print("")
            print("None")
        for line in f:
            if "hostSeconds" in line:
                stats["real_time"].append(float(line.split()[1])/60)
            if "simTicks" in line:
                stats["exec_time"].append(float(line.split()[1])/1000/1000)
            if "hostMemory" in line:
                stats["wss"].append(float(line.split()[1])/1024/1024)
            if "dcache.demandMissRate::total" in line:
                stats["l1_miss"].append(float(line.split()[1])*100)
            if "l20.demandMissRate::total" in line:
                stats["l2_miss"].append(float(line.split()[1])*100)
        print("real_time: " + str(stats["real_time"][i]) + " m")
        print("exec_time: " + str(stats["exec_time"][i]) + " ms")
        print("wss: " + str(stats["wss"][i]) + " MiB")
        print("l1_miss: " + str(stats["l1_miss"][i]) + " %")
        print("l2_miss: " + str(stats["l2_miss"][i]) + " %")
        f.close()

if __name__ == "__main__":
    options = addOption()
    if options.parse:
        parse()
    elif options.build:
        build()
    elif options.kill:
        kill()
    else:
        run()

from optparse import OptionParser
from subprocess import Popen, PIPE
from os import getcwd, cpu_count
from time import sleep

bench_dir = "/root/gem5/benchmark"
gem5_img = "gem5-gfortran3"
arch = "X86"
mode = "debug"

def addOption():
    parser = OptionParser()
    parser.add_option("-p", action="store_true", default=False, dest="parse")
    parser.add_option("-b", action="store_true", default=False, dest="build")
    parser.add_option("-k", action="store_true", default=False, dest="kill")
    (options, args) = parser.parse_args()
    return options

def shell(cmd):
    p = Popen(cmd, stdout=PIPE, stderr=PIPE, shell=True)
    (stdout, stderr) = p.communicate()
    return str(stdout, "utf-8"), str(stderr, "utf-8")

def popen(cmd):
    return Popen(cmd, stdout=PIPE, stderr=PIPE, shell=True)

def getDockerCmd(gem5_cmd):
    docker_cmd = \
    "docker run -u $UID:$GID \
    --volume " + getcwd() + ":/gem5 \
    --volume " + bench_dir + ":/bench \
    --rm " + gem5_img + " bash -c \
    'cd gem5; " + gem5_cmd + "'"
    return docker_cmd

def getListHwp():
    prefetchers = [None]
    (out, err) = shell(getDockerCmd("./build/" + arch + "/gem5." + mode + " configs/example/se.py --list-hwp-types"))
    check = False
    for line in out.split("\n"):
        if check:
            prefetcher = line.split()
            if len(prefetcher) > 0:
                prefetchers.append(prefetcher[0])
        if "Available BasePrefetcher classes:" in line:
            check = True
    return prefetchers

def buildDocker():
    dockerFile = """
    FROM gcr.io/gem5-test/ubuntu-20.04_all-dependencies
    RUN echo "deb http://gb.archive.ubuntu.com/ubuntu/ bionic main universe" >> /etc/apt/sources.list
    RUN apt-get update
    RUN apt-get install -y g++-6
    RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-6 6
    RUN apt-get install -y libgfortran3
    """
    f = open("Dockerfile", "w")
    f.write(dockerFile)
    f.close()
    shell("docker build -t gem5-gfortran3 .")
    shell("rm Dockerfile")

def build():
    (out, err) = shell("docker images")
    if gem5_img not in out:
        buildDocker()
    shell(getDockerCmd("scons build/" + arch + "/gem5." + mode + " -j" + str(int(cpu_count()*2/3))))

def kill():
    (out, err) = shell("ps -e | grep gem5.debug")
    pids = []
    for line in out.split("\n"):
        tmp = line.split()
        if len(tmp) > 0:
            pids.append(tmp[0])
    shell("kill -9 " + " ".join(pids))

def run():
    cmd = [
        "./build/" + arch + "/gem5." + mode,
        "", # [1] --outdir=
        "configs/example/se.py \
        -c tests/test-progs/hello/bin/x86/linux/hello \
        --cpu-type=TimingSimpleCPU \
        --num-cpus=8 \
        --num-cores-socket=4 \
        --num-sockets-server=2 \
        --num-cores-l2=2 \
        --caches --l1d_size=64kB --l1i_size=64kB \
        --l2cache --l2_size=1MB \
        --l3cache --l3_size=32MB \
        --l4cache --l4_size=512MB \
        --mem-size=8GB \
        --cxl --cxl-mem-size=8GB",
        "", # [3] --l2-hwp-type=
    ]

    prefetchers = getListHwp()
    for prefetcher in prefetchers:
        if prefetcher:
            cmd[1] = "--outdir=m5out/" + prefetcher
            cmd[3] = "--l2-hwp-type=" + prefetcher
        else:
            cmd[1] = "--outdir=m5out/" + "None"
            cmd[3] = ""
        popen(getDockerCmd(" ".join(cmd)))

def parse():
    prefetchers = getListHwp()
    stats = {
        "real_time": [], # m
        "exec_time": [], # ms
        "wss": [], # MiB
        "l1_miss": [], # %
        "l2_miss": [], # %
    }
    for i in range(len(prefetchers)):
        if prefetchers[i]:
            f = open("m5out/" + prefetchers[i] + "/stats.txt", "r")
            print("")
            print(prefetchers[i])
        else:
            f = open("m5out/" + "None" + "/stats.txt", "r")
            print("")
            print("None")
        for line in f:
            if "hostSeconds" in line:
                stats["real_time"].append(float(line.split()[1])/60)
            if "simTicks" in line:
                stats["exec_time"].append(float(line.split()[1])/1000/1000)
            if "hostMemory" in line:
                stats["wss"].append(float(line.split()[1])/1024/1024)
            if "dcache.demandMissRate::total" in line:
                stats["l1_miss"].append(float(line.split()[1])*100)
            if "l20.demandMissRate::total" in line:
                stats["l2_miss"].append(float(line.split()[1])*100)
        print("real_time: " + str(stats["real_time"][i]) + " m")
        print("exec_time: " + str(stats["exec_time"][i]) + " ms")
        print("wss: " + str(stats["wss"][i]) + " MiB")
        print("l1_miss: " + str(stats["l1_miss"][i]) + " %")
        print("l2_miss: " + str(stats["l2_miss"][i]) + " %")
        f.close()

if __name__ == "__main__":
    options = addOption()
    if options.parse:
        parse()
    elif options.build:
        build()
    elif options.kill:
        kill()
    else:
        run()

FROM gcr.io/gem5-test/ubuntu-20.04_all-dependencies     RUN echo "deb http://gb.archive.ubuntu.com/ubuntu/ bionic main universe" >> /etc/apt/sources.list     RUN apt-get update     RUN apt-get install -y g++-6     RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-6 6     RUN apt-get install -y libgfortran3 # [1] --outdir= # [3] --l2-hwp-type= # m # ms # MiB # % # %