
import sys
import argparse
import subprocess
from pprint import pprint

import m5
from m5.objects import *
from m5.util import *

addToPath('../')

from common import MemConfig
from common import HMC


def add_options(parser):
    parser.add_argument("--external-memory-system", default=0, action="store",
                        type=int, help="External memory system")
    # TLM related options, currently optional in configs/common/MemConfig.py
    parser.add_argument("--tlm-memory", action="store_true", help="use\
                        external port for SystemC TLM co-simulation. Default:\
                        no")
    # Elastic traces related options, currently optional in
    # configs/common/MemConfig.py
    parser.add_argument("--elastic-trace-en", action="store_true",
                        help="enable capture of data dependency and\
                        instruction fetch traces using elastic trace\
                        probe.\nDefault: no")
    # Options related to traffic generation
    parser.add_argument("--num-tgen", default=4, action="store", type=int,
                        choices=[4], help="number of traffic generators.\
                        Right now this script supports only 4.\nDefault: 4")
    parser.add_argument("--tgen-cfg-file",
                        default="./configs/example/hmc_tgen.cfg",
                        type=str, help="Traffic generator(s) configuration\
                        file. Note: this script uses the same configuration\
                        file for all traffic generators")


# considering 4GB HMC device with following parameters
# hmc_device_size = '4GB'
# hmc_vault_size = '256MB'
# hmc_stack_size = 8
# hmc_bank_in_stack = 2
# hmc_bank_size = '16MB'
# hmc_bank_in_vault = 16
def build_system(options):
    # create the system we are going to simulate
    system = System()
    # use timing mode for the interaction between requestor-responder ports
    system.mem_mode = 'timing'
    # set the clock fequency of the system
    clk = '100GHz'
    vd = VoltageDomain(voltage='1V')
    system.clk_domain = SrcClockDomain(clock=clk, voltage_domain=vd)
    # add traffic generators to the system
    system.tgen = [TrafficGen(config_file=options.tgen_cfg_file) for i in
                   range(options.num_tgen)]
    # Config memory system with given HMC arch
    MemConfig.config_mem(options, system)
    # Connect the traffic generatiors
    if options.arch == "distributed":
        for i in range(options.num_tgen):
            system.tgen[i].port = system.membus.cpu_side_ports
        # connect the system port even if it is not used in this example
        system.system_port = system.membus.cpu_side_ports
    if options.arch == "mixed":
        for i in range(int(options.num_tgen/2)):
            system.tgen[i].port = system.membus.cpu_side_ports
        hh = system.hmc_host
        if options.enable_global_monitor:
            system.tgen[2].port = hh.lmonitor[2].cpu_side_port
            hh.lmonitor[2].mem_side_port = hh.seriallink[2].cpu_side_port
            system.tgen[3].port = hh.lmonitor[3].cpu_side_port
            hh.lmonitor[3].mem_side_port = hh.seriallink[3].cpu_side_port
        else:
            system.tgen[2].port = hh.seriallink[2].cpu_side_port
            system.tgen[3].port = hh.seriallink[3].cpu_side_port
        # connect the system port even if it is not used in this example
        system.system_port = system.membus.cpu_side_ports
    if options.arch == "same":
        hh = system.hmc_host
        for i in range(options.num_links_controllers):
            if options.enable_global_monitor:
                system.tgen[i].port = hh.lmonitor[i].cpu_side_port
            else:
                system.tgen[i].port = hh.seriallink[i].cpu_side_port
    # set up the root SimObject
    root = Root(full_system=False, system=system)
    return root


def main():
    parser = argparse.ArgumentParser(description="Simple system using HMC as\
                                     main memory")
    HMC.add_options(parser)
    add_options(parser)
    options = parser.parse_args()
    # build the system
    root = build_system(options)
    # instantiate all of the objects we've created so far
    m5.instantiate()
    print("Beginning simulation!")
    event = m5.simulate(10000000000)
    m5.stats.dump()
    print('Exiting @ tick %i because %s (exit code is %i)' % (m5.curTick(),
                                                              event.getCause(),
                                                              event.getCode()))
    print("Done")


if __name__ == "__m5_main__":
    main()
