/*
 * Copyright 2020 Google, Inc.
 *
 * 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.
 */

#include "arch/arm/fastmodel/CortexR52/cortex_r52.hh"

#include "arch/arm/fastmodel/iris/cpu.hh"
#include "base/logging.hh"
#include "dev/arm/base_gic.hh"
#include "systemc/tlm_bridge/gem5_to_tlm.hh"

namespace gem5
{

namespace fastmodel
{

void
CortexR52::setCluster(CortexR52Cluster *_cluster, int _num)
{
    cluster = _cluster;
    num = _num;

    set_evs_param("CFGEND", params().CFGEND);
    set_evs_param("CFGTE", params().CFGTE);
    set_evs_param("RVBARADDR", params().RVBARADDR);
    set_evs_param("ase-present", params().ase_present);
    set_evs_param("dcache-size", params().dcache_size);
    set_evs_param("flash.enable", params().flash_enable);
    set_evs_param("icache-size", params().icache_size);
    set_evs_param("llpp.base", params().llpp_base);
    set_evs_param("llpp.size", params().llpp_size);
    set_evs_param("max_code_cache_mb", params().max_code_cache_mb);
    set_evs_param("min_sync_level", params().min_sync_level);
    set_evs_param("semihosting-A32_HLT", params().semihosting_A32_HLT);
    // Use uint32_t, since the model doesn't like setting these as uint8_t.
    set_evs_param<uint32_t>("semihosting-ARM_SVC",
            params().semihosting_ARM_SVC);
    set_evs_param<uint32_t>("semihosting-T32_HLT",
            params().semihosting_T32_HLT);
    set_evs_param<uint32_t>("semihosting-Thumb_SVC",
            params().semihosting_Thumb_SVC);
    set_evs_param("semihosting-cmd_line", params().semihosting_cmd_line);
    set_evs_param("semihosting-cwd", params().semihosting_cwd);
    set_evs_param("semihosting-enable", params().semihosting_enable);
    set_evs_param("semihosting-heap_base", params().semihosting_heap_base);
    set_evs_param("semihosting-heap_limit", params().semihosting_heap_limit);
    set_evs_param("semihosting-stack_base", params().semihosting_stack_base);
    set_evs_param("semihosting-stack_limit", params().semihosting_stack_limit);
    set_evs_param("tcm.a.enable", params().tcm_a_enable);
    set_evs_param("tcm.a.size", params().tcm_a_size);
    set_evs_param("tcm.b.size", params().tcm_b_size);
    set_evs_param("tcm.c.size", params().tcm_c_size);
    set_evs_param("vfp-dp-present", params().vfp_dp_present);
    set_evs_param("vfp-enable_at_reset", params().vfp_enable_at_reset);
}

void
CortexR52::setResetAddr(Addr addr, bool secure)
{
    evs_base_cpu->setResetAddr(num, addr, secure);
}

Port &
CortexR52::getPort(const std::string &if_name, PortID idx)
{
    if (if_name == "ppi") {
        // Since PPIs are indexed both by core and by number, modify the name
        // to hold the core number.
        return evs->gem5_getPort(csprintf("%s_%d", if_name, num), idx);
    } else if (if_name == "standbywfi") {
        // Since standbywfi is indexed by fanout, modify the name to hold the
        // core number.
        return evs->gem5_getPort(csprintf("%s_%d", if_name, num), idx);
    } else if (if_name == "amba" || if_name == "llpp" || if_name == "flash" ||
               if_name == "core_reset" || if_name == "poweron_reset" ||
               if_name == "halt") {
        // Since these ports are scalar per core, use the core number as the
        // index. Also verify that that index is not being used.
        assert(idx == InvalidPortID);
        return evs->gem5_getPort(if_name, num);
    } else {
        return SimObject::getPort(if_name, idx);
    }
}

CortexR52Cluster::CortexR52Cluster(const Params &p) :
    SimObject(p), cores(p.cores), evs(p.evs)
{
    for (int i = 0; i < p.cores.size(); i++)
        p.cores[i]->setCluster(this, i);

    Iris::BaseCpuEvs *e = dynamic_cast<Iris::BaseCpuEvs *>(evs);
    panic_if(!e, "EVS should be of type Iris::BaseCpuEvs");
    e->setCluster(this);

    set_evs_param("core.CLUSTER_ID", params().CLUSTER_ID);
    set_evs_param("core.DBGROMADDR", params().DBGROMADDR);
    set_evs_param("core.DBGROMADDRV", params().DBGROMADDRV);
    set_evs_param("core.PERIPHBASE", params().PERIPHBASE);
    set_evs_param("core.cluster_utid", params().cluster_utid);
    set_evs_param("core.cpi_div", params().cpi_div);
    set_evs_param("core.cpi_mul", params().cpi_mul);
    set_evs_param("core.dcache-prefetch_enabled",
            params().dcache_prefetch_enabled);
    set_evs_param("core.dcache-read_access_latency",
            params().dcache_read_access_latency);
    set_evs_param("core.dcache-state_modelled",
            params().dcache_state_modelled);
    set_evs_param("core.dcache-write_access_latency",
            params().dcache_write_access_latency);
    set_evs_param("core.flash_protection_enable_at_reset",
            params().flash_protection_enable_at_reset);
    set_evs_param("core.has_flash_protection", params().has_flash_protection);
    set_evs_param("core.icache-prefetch_enabled",
            params().icache_prefetch_enabled);
    set_evs_param("core.icache-read_access_latency",
            params().icache_read_access_latency);
    set_evs_param("core.icache-state_modelled",
            params().icache_state_modelled);
    set_evs_param("core.memory.ext_slave_base",
            params().memory_ext_slave_base);
    set_evs_param("core.memory.flash_base", params().memory_flash_base);
    set_evs_param("core.memory.flash_size", params().memory_flash_size);
    // Use uint32_t, since the model doesn't like setting these as uint8_t.
    set_evs_param<uint32_t>("core.num_protection_regions_s1",
            params().num_protection_regions_s1);
    set_evs_param<uint32_t>("core.num_protection_regions_s2",
            params().num_protection_regions_s2);
    set_evs_param("core.num_spi", params().num_spi);
    set_evs_param("core.ram_protection_enable_at_reset",
            params().ram_protection_enable_at_reset);
    set_evs_param("core.has_export_m_port", params().has_export_m_port);
}

Port &
CortexR52Cluster::getPort(const std::string &if_name, PortID idx)
{
    if (if_name == "spi") {
        return evs->gem5_getPort(if_name, idx);
    } else if (if_name == "ext_slave" || if_name == "top_reset" ||
               if_name == "dbg_reset" || if_name == "model_reset") {
        assert(idx == InvalidPortID);
        return evs->gem5_getPort(if_name, idx);
    } else {
        return SimObject::getPort(if_name, idx);
    }
}

} // namespace fastmodel
} // namespace gem5
