/*

           |------|   |------|   |-----|   |-----|
           | cpu  |   | iram |   | rom |   | dma |
           |------|   |------|   |-----|   |-----|
              |           |         |         |
              ---------------------------------  sys_bus
                               |
                          |--------|
                          | secbus |
                          |--------|
                               |
               -------------------------------  mem_bus
               |         |         |         |
            |------|  |-----|  |-------|  |-----|
            | XICU |  | TTY |  | BLOCK |  | MEM |
            |------|  |-----|  |-------|  |-----|

*/ 

#include <systemc>
#include <limits>
#include <sstream>
#include <sys/time.h>
#include <time.h>

//#define TRACES
//#define DEBUG

#include "config.h"

//#ifdef DEBUG
#include "gdbserver.h"
//#include "memchecker.h"

//#endif

#include "vci_signals.h"
#include "vci_param.h"
#include "vci_secbus_v2.h"

#include "mapping_table.h"
#include "vci_vgmn.h"
#include "vci_xcache.h"
#include "mips32.h"
//#include "arm.h"
#include "vci_multi_tty.h"
#include "vci_xicu.h"
#include "vci_dma.h"
#include "vci_ram.h"
#include "vci_block_device.h"
#include "vci_shutdown.h"

//MEMCHECKER_GLOBALS;

// SRCID system vgmn definition
#define SRCID_S_PROC1     0
#define SRCID_S_DMA       1

// SRCID mem vgmn definition
#define SRCID_M_SEC       0
#define SRCID_M_EEP       1
#define SRCID_M_DMA       2

// TGTID system vgmn definition
#define TGTID_S_ROM       0
#define TGTID_S_IRA       1
#define TGTID_S_RAM       2
#define TGTID_S_DMA       3
#define TGTID_S_HAL       4
#define TGTID_S_SEC       5

// TGTID mem vgmn definition
#define TGTID_M_RAM       0
#define TGTID_M_TTY       1
#define TGTID_M_XICU      2
#define TGTID_M_EEP       3
#define TGTID_M_DMA       4
#define TGTID_M_ROM       5

// VCI fields width definition
#define CELL_SIZE       4
#define PLEN_SIZE       8 
#define ADDR_SIZE       32
#define RERROR_SIZE     1
#define CLEN_SIZE       1
#define RFLAG_SIZE      1
#define SRCID_SIZE      12 
#define TRDID_SIZE      4
#define PKTID_SIZE      4
#define WRPLEN_SIZE     1

int _main(int argc, char *argv[])
{
    using namespace sc_core;
    using namespace soclib::caba;
    using namespace soclib::common;
/*
//#ifdef DEBUG
    typedef soclib::common::Mips32ElIss iss_t;
//    typedef soclib::common::GdbServer<soclib::common::IssMemchecker<soclib::common::Mips32ElIss> > Processor;
    typedef soclib::common::GdbServer<soclib::common::Mips32ElIss> Processor;
*/
//    typedef soclib::common::ArmIss iss_t;
//    typedef soclib::common::GdbServer<soclib::common::IssMemchecker<soclib::common::Mips32ElIss> > Processor;
//    typedef soclib::common::GdbServer<soclib::common::ArmIss> Processor;
/*#else
    typedef soclib::common::Mips32ElIss Processor;
#endif
*/
    typedef soclib::common::GdbServer<soclib::common::Mips32ElIss> Processor;
//    typedef soclib::common::Mips32ElIss Processor;

    typedef VciParams<CELL_SIZE,
                      PLEN_SIZE,
                      ADDR_SIZE,
                      RERROR_SIZE,
                      CLEN_SIZE,
                      RFLAG_SIZE,
                      SRCID_SIZE,
                      TRDID_SIZE,
                      PKTID_SIZE,
                      WRPLEN_SIZE> vci_param;

    uint64_t       ms1, ms2;
    struct timeval t1, t2;

    ///////////////////////////////////////////////////////////////
    // command line arguments
    ///////////////////////////////////////////////////////////////
    int     ncycles             = 1000000000;       // simulated cycles
    char    soft_name[256]      = "bootloader.out";  // pathname for the loader
    bool    debug_ok            = false;            // debug activated
    bool    stats_ok            = false;            // statistics activated
    int     stats_period        = 100000;           // statistics periodicity
    int     begin_stats         = 0;
    int     sys_latency         = 1;               // intrinsic NOC latency
    int     mem_latency         = 1;
    int     nb_proc             = 1;
    char    io_kernel[256]      = "kernel.bin";
    char    io_kernel_elf[256]  = "kernel.out";
    char    disk[256]           = "disk.img";
    int     icache_ways         = 8;
    int     icache_sets         = 32;
    int     icache_words        = 8;
    int     dcache_ways         = 8;
    int     dcache_sets         = 32;
    int     dcache_words        = 8;
    bool    issecbus              = true;

    if (argc > 1)
    {
        for( int n=1 ; n<argc ; n=n+2 )
        {
            if( (strcmp(argv[n],"-IWAYS") == 0) && (n+1<argc) )
            {
                icache_ways = atoi(argv[n+1]);
            }
            else if( (strcmp(argv[n],"-ISETS") == 0) && (n+1<argc) )
            {
                icache_sets = atoi(argv[n+1]);
            }
            else if( (strcmp(argv[n],"-IWORDS") == 0) && (n+1<argc) )
            {
                icache_words = atoi(argv[n+1]);
            }
            else if( (strcmp(argv[n],"-DWAYS") == 0) && (n+1<argc) )
            {
                dcache_ways = atoi(argv[n+1]);
            }
            else if( (strcmp(argv[n],"-DSETS") == 0) && (n+1<argc) )
            {
                dcache_sets = atoi(argv[n+1]);
            }
            else if( (strcmp(argv[n],"-DWORDS") == 0) && (n+1<argc) )
            {
                dcache_words = atoi(argv[n+1]);
            }
            else if( (strcmp(argv[n],"-NCYCLES") == 0) && (n+1<argc) )
            {
                ncycles = atoi(argv[n+1]);
            }
            else if( (strcmp(argv[n],"-DEBUG") == 0) && (n+1<argc) )
            {
                debug_ok = true;
            }
            else if( (strcmp(argv[n],"-STATS_BEGIN") == 0) && (n+1<argc) )
            {
                begin_stats= atoi(argv[n+1]);
            }
            else if( (strcmp(argv[n],"-STATS") == 0) && (n+1<argc) )
            {
                stats_ok = true;
                stats_period = atoi(argv[n+1]);
            }
            else if( (strcmp(argv[n],"-BOOT") == 0) && (n+1<argc) )
            {
                strcpy(soft_name, argv[n+1]) ;
            }
            else if( (strcmp(argv[n],"-KERNEL") == 0) && (n+1<argc) )
            {
                strcpy(io_kernel, argv[n+1]) ;
            }
            else if( (strcmp(argv[n],"-DISK") == 0) && (n+1<argc) )
            {
                strcpy(disk, argv[n+1]) ;
            }
            else if( (strcmp(argv[n],"-KERNEL_ELF") == 0) && (n+1<argc) )
            {
                strcpy(io_kernel_elf, argv[n+1]) ;
            }
            else if( (strcmp(argv[n],"-SYS_LATENCY") == 0) && (n+1<argc) )
            {
                sys_latency = atoi(argv[n+1]);
            }
            else if( (strcmp(argv[n],"-MEM_LATENCY") == 0) && (n+1<argc) )
            {
                mem_latency = atoi(argv[n+1]);
            }
            else if ( (strcmp(argv[n],"-PROC") == 0) && (n+1<argc) )
            {
                nb_proc = atoi(argv[n+1]);
            }
            else if ( (strcmp(argv[n], "-NOSECBUS") == 0) && (n<argc) )
            {
                issecbus = false;
            }
            else
            {
                std::cout << "   Arguments on the command line are (key,value) couples." << std::endl;
                std::cout << "   The order is not important." << std::endl;
                std::cout << "   Accepted arguments are :" << std::endl << std::endl;
                std::cout << "   -NCYCLES number_of_simulated_cycles" << std::endl;
                std::cout << "   -IOCFILE file_name" << std::endl;
                std::cout << "   -FBFSIZE number_of_pixels" << std::endl;
                std::cout << "   -BOOT bootloader elf file" << std::endl;
                std::cout << "   -KERNEL kernel binary file" << std::endl;
                std::cout << "   -KERNEL_ELF kernel elf file (only for memcheck)" << std::endl;
                std::cout << "   -DISK harddrive disk image" << std::endl;
                std::cout << "   -DEBUG debug_start_cycle" << std::endl;
                std::cout << "   -TOCYCLE debug_end_cycle" << std::endl;
                std::cout << "   -STATS statistics_period" << std::endl;
                std::cout << "   -STATS_BEGIN begin stats at" << std::endl;
                std::cout << "   -SYS_LATENCY intrinsic latency of sys vgmn" << std::endl;
                std::cout << "   -MEM_LATENCY intrinsic latency of mem vgmn" << std::endl;
                std::cout << "   -PROC number of proc" << std::endl;
                std::cout << "   -ISETS instruction cache sets" << std::endl;
                std::cout << "   -IWAYS instruction cache ways" << std::endl;
                std::cout << "   -IWORDS instruction cache words" << std::endl;
                std::cout << "   -DSETS data cache sets" << std::endl;
                std::cout << "   -DWAYS data cache ways" << std::endl;
                std::cout << "   -DWORDS data cache words" << std::endl;
                std::cout << "   -NOSECBUS remove secbus from this platform" << std::endl;
                exit(0);
            }
        }
    }
    //////////////////////////////////////////////////////////////////////////
    // Mapping Table
    //////////////////////////////////////////////////////////////////////////
    MappingTable maptab_sys(32, IntTab(12), IntTab(8), 0xf0000000);
    
    maptab_sys.add(Segment("eeprom",       CONFIG_EEPROM_BASE, CONFIG_EEPROM_SIZE, IntTab(TGTID_S_RAM), false));
    maptab_sys.add(Segment("iram",         CONFIG_IRAM_BASE,   CONFIG_IRAM_SIZE,   IntTab(TGTID_S_IRA), true));
    maptab_sys.add(Segment("boot",         CONFIG_BOOT_BASE,   CONFIG_BOOT_SIZE,   IntTab(TGTID_S_ROM), true));
    maptab_sys.add(Segment("bios",         CONFIG_BIOS_BASE,   CONFIG_BIOS_SIZE,   IntTab(TGTID_S_ROM), true));
    maptab_sys.add(Segment("mem",          CONFIG_MEM_BASE,    CONFIG_MEM_SIZE,    IntTab(TGTID_S_RAM), true));
    maptab_sys.add(Segment("idma",         CONFIG_IDMA_BASE,   CONFIG_IDMA_SIZE,   IntTab(TGTID_S_DMA), false));
    maptab_sys.add(Segment("xicu",         CONFIG_XICU_BASE,   CONFIG_XICU_SIZE,   IntTab(TGTID_S_RAM), false)); 
    maptab_sys.add(Segment("seg_tty",      CONFIG_TTY_BASE,    CONFIG_TTY_SIZE,    IntTab(TGTID_S_RAM), false));
    maptab_sys.add(Segment("dma",          CONFIG_DMA_BASE,    CONFIG_DMA_SIZE,    IntTab(TGTID_S_RAM), false));
    maptab_sys.add(Segment("fdt",          CONFIG_FDT_BASE,    CONFIG_FDT_SIZE,    IntTab(TGTID_S_ROM), false));
    maptab_sys.add(Segment("halt",         CONFIG_HALT_BASE,   CONFIG_HALT_SIZE,   IntTab(TGTID_S_HAL), false));
    if (issecbus)
    {
        maptab_sys.add(Segment("secbus",       CONFIG_SECBUS_BASE, CONFIG_SECBUS_SIZE, IntTab(TGTID_S_SEC), false));
        maptab_sys.add(Segment("masterblock",  CONFIG_MB_BASE ,    CONFIG_MB_SIZE,     IntTab(TGTID_S_RAM), false));
    }

    std::cout << std::endl << maptab_sys << std::endl;

    MappingTable maptab_mem(32, IntTab(12), IntTab(8), 0xf0000000);

    maptab_mem.add(Segment("mem",          CONFIG_MEM_BASE,    CONFIG_MEM_SIZE,    IntTab(TGTID_M_RAM), true));
    if (issecbus)
    {
        maptab_mem.add(Segment("masterblock",  CONFIG_MB_BASE ,    CONFIG_MB_SIZE,     IntTab(TGTID_M_RAM), false));
    }
    maptab_mem.add(Segment("eeprom",       CONFIG_EEPROM_BASE, CONFIG_EEPROM_SIZE, IntTab(TGTID_M_EEP), false));
    maptab_mem.add(Segment("xicu",         CONFIG_XICU_BASE,   CONFIG_XICU_SIZE,   IntTab(TGTID_M_XICU),false));
    maptab_mem.add(Segment("seg_tty",      CONFIG_TTY_BASE,    CONFIG_TTY_SIZE,    IntTab(TGTID_M_TTY), false));
    maptab_mem.add(Segment("dma",          CONFIG_DMA_BASE,    CONFIG_DMA_SIZE,    IntTab(TGTID_M_DMA), false));
//    maptab_mem.add(Segment("rom",          CONFIG_EROM_BASE,   CONFIG_EROM_SIZE,   IntTab(TGTID_M_ROM), false));


    std::cout << std::endl << maptab_mem << std::endl;

    std::cout << " Cache L1 : " << std::endl;
    int i_l1 = icache_ways*icache_words*icache_sets*4;
    int d_l1 = dcache_ways*dcache_words*dcache_sets*4;
    if (i_l1<1024)
        std::cout << "   I : " << i_l1 << "o" << std::endl;
    else
        std::cout << "   I : " << i_l1/1024 << "ko" << std::endl;
    if (d_l1<1024)
        std::cout << "   D : " << d_l1 << "o" << std::endl;
    else
        std::cout << "   D : " << d_l1/1024 << "ko" << std::endl;

    std::cout << std::endl << std::endl;

    //////////////////////////////////////////////////////////////////////////
    // Signals
    //////////////////////////////////////////////////////////////////////////
    sc_clock        signal_clk("signal_clk", sc_time( 1, SC_NS ), 0.5 );
    sc_signal<bool> signal_resetn("signal_resetn");
    
    // vci
    VciSignals<vci_param>   signal_vci_proc[nb_proc];
    VciSignals<vci_param>   signal_vci_tgt_rom("signal_vci_tgt_rom"); // vgmn_sys - rom
    VciSignals<vci_param>   signal_vci_tgt_ram("signal_vci_tgt_ram"); // vgmn_mem - ram
    VciSignals<vci_param>   signal_vci_tgt_tty("signal_vci_tgt_tty"); // vgmn_io - tty
    VciSignals<vci_param>   signal_vci_tgt_xicu("signal_vci_tgt_xicu"); // vgmn_io - xicu
//    VciSignals<vci_param>   signal_vci_tgt_coc("signal_vci_tgt_coc"); // vgmn_io - coc
    VciSignals<vci_param>   signal_vci_tgt_ira("signal_vci_tgt_ira"); // vgmn_sys - iram
    VciSignals<vci_param>   signal_vci_tgt_halt("signal_vci_tgt_halt"); // vgmn_sys - halt

    VciSignals<vci_param>   signal_vci_tgt_eep("signal_vci_tgt_eep"); // vgmn_io - eeprom
    VciSignals<vci_param>   signal_vci_ini_eep("signal_vci_ini_eep"); // eeprom - vgmn_io

    VciSignals<vci_param>   signal_vci_tgt_dma("signal_vci_tgt_dma"); // vgmn_io - dma device
    VciSignals<vci_param>   signal_vci_ini_dma("signal_vci_ini_dma"); // dma device - vgmn_io

    VciSignals<vci_param>   signal_vci_tgt_idma("signal_vci_tgt_idma"); 
    VciSignals<vci_param>   signal_vci_ini_idma("signal_vci_ini_idma"); 

    VciSignals<vci_param>   signal_vci_tgt_io("signal_vci_bridge_io_system"); // vgmn_sys - vgmn_io
    VciSignals<vci_param>   signal_vci_ini_sys("signal_vci_ini_system"); 
    VciSignals<vci_param>   signal_vci_tgt_erom("signal_vci_tgt_erom");
 
    VciSignals<vci_param>   signal_vci_tgt_sec("signal_vci_tgt_sec"); // vgmn_sys - secbus
    VciSignals<vci_param>   signal_vci_tgt_iosec("signal_vci_tgt_iosec"); // vgmn_sys - secbus
    VciSignals<vci_param>   signal_vci_ini_ram("signal_vci_ini_ram"); // secbus - vgmn_mem

    // irq
    sc_signal<bool> signal_false("signal_false");
    sc_signal<bool> signal_irq_tty("signal_irq_tty");
    sc_signal<bool> signal_irq_eep("signal_irq_eep");
    sc_signal<bool> signal_irq_dma("signal_irq_dma");
//	sc_signal<bool> signal_irq_sec("signal_irq_sec");
    sc_signal<bool> signal_irq_proc[nb_proc];
    sc_signal<bool> signal_irq_idma("signal_irq_idma");
    sc_signal<bool> signal_irq_esecbus("signal_irq_esecbus");
    sc_signal<bool> signal_irq_csecbus("signal_irq_csecbus");

//    soclib::common::Loader hackdata("hackdata.bin@0x90000000:RO");
    soclib::common::Loader loader(soft_name, "platform.dtb@0xe0000000:RO");
    loader.memory_default(0x5a);
//#ifdef DEBUG
//    soclib::common::Loader elf_loader(io_kernel_elf);
//    soclib::common::GdbServer<soclib::common::IssMemchecker<iss_t> >::set_loader(elf_loader);
//    soclib::common::IssMemchecker<iss_t>::init(maptab_sys, elf_loader ,"xicu,seg_tty,blockdevice,secbus,eeprom,fdt");
//    soclib::common::GdbServer<iss_t>::set_loader(elf_loader);
//#endif
    
    VciXcacheWrapper<vci_param, Processor >*proc[nb_proc];
    for (int i=0;i<nb_proc;i++)
    {
        std::ostringstream o;
        o << "proc" << i;
        proc[i] = new VciXcacheWrapper<vci_param,Processor>(o.str().c_str(), i,maptab_sys,IntTab(i),
                                                            icache_ways, icache_sets, icache_words,
                                                            dcache_ways, dcache_sets, dcache_words);
    }

    VciXicu<vci_param>* vcixicu;
    vcixicu = new VciXicu<vci_param>("vcixicu", maptab_mem, IntTab(TGTID_M_XICU), 1, 5, nb_proc, nb_proc);

    VciSecbusV2<vci_param>* secbus;

    if (issecbus)
    {
        secbus = new VciSecbusV2<vci_param>("secbus", maptab_sys, IntTab(TGTID_S_SEC));
    }

    VciRam<vci_param>* rom;
    rom = new VciRam<vci_param>("rom", IntTab(TGTID_S_ROM), maptab_sys, loader);

    VciBlockDevice<vci_param>* blockdevice;
    blockdevice = new VciBlockDevice<vci_param>("eeprom", maptab_mem, IntTab(SRCID_M_EEP), IntTab(TGTID_M_EEP), io_kernel/*, 512*/);
    
    VciDma<vci_param>* dma;
    dma = new VciDma<vci_param>("dma", maptab_mem, IntTab(SRCID_M_DMA), IntTab(TGTID_M_DMA), 8);

    VciDma<vci_param>* idma;
    idma = new VciDma<vci_param>("idma", maptab_sys, IntTab(SRCID_S_DMA), IntTab(TGTID_S_DMA), 8);

    VciRam<vci_param>* iram;
    iram = new VciRam<vci_param>("iram", IntTab(TGTID_S_IRA), maptab_sys, loader);

    VciShutdown<vci_param>* halt;
    halt = new VciShutdown<vci_param>("halt", IntTab(TGTID_S_HAL), maptab_sys);

/*    VciRam<vci_param>* erom;
    erom = new VciRam<vci_param>("erom", IntTab(TGTID_M_ROM), maptab_mem, hackdata);
*/
    VciRam<vci_param>* ramsec;
    ramsec = new VciRam<vci_param>("ram", IntTab(TGTID_M_RAM), maptab_mem, loader);

    VciMultiTty<vci_param>* tty;
    tty = new VciMultiTty<vci_param>("tty", IntTab(TGTID_M_TTY), maptab_mem, "tty", NULL);

    VciVgmn<vci_param>* vgmn_sys;
    vgmn_sys = new VciVgmn<vci_param>("vgmn_system", maptab_sys, nb_proc+1, 6, sys_latency, 32);
    
    VciVgmn<vci_param>* vgmn_mem;
    vgmn_mem = new VciVgmn<vci_param>("vgmn_mem", maptab_mem, 3, 5, mem_latency, 32);

    //////////////////////////////////////////////////////////////////////////
    // Net-List
    //////////////////////////////////////////////////////////////////////////
    for (int i=0;i<nb_proc;i++)
    {
      proc[i]->p_clk                 (signal_clk);
      proc[i]->p_resetn              (signal_resetn);
      proc[i]->p_vci                 (signal_vci_proc[i]);
      proc[i]->p_irq[0]              (signal_irq_proc[i]);
      proc[i]->p_irq[1]              (signal_irq_esecbus); 
      proc[i]->p_irq[2]              (signal_false);
      proc[i]->p_irq[3]              (signal_false);
      proc[i]->p_irq[4]              (signal_false);
      proc[i]->p_irq[5]              (signal_false);

      vgmn_sys->p_to_initiator[i]    (signal_vci_proc[i]);
      vcixicu->p_irq[i]              (signal_irq_proc[i]);
    }

    vcixicu->p_clk                   (signal_clk);
    vcixicu->p_resetn                (signal_resetn);
    vcixicu->p_vci                   (signal_vci_tgt_xicu);
    vcixicu->p_hwi[0]                (signal_irq_tty);
    vcixicu->p_hwi[1]                (signal_irq_eep);
    vcixicu->p_hwi[2]                (signal_irq_dma);
    vcixicu->p_hwi[3]                (signal_irq_idma);
    vcixicu->p_hwi[4]                (signal_irq_csecbus);

    rom->p_clk                       (signal_clk);
    rom->p_resetn                    (signal_resetn);
    rom->p_vci                       (signal_vci_tgt_rom);

    ramsec->p_clk                    (signal_clk);
    ramsec->p_resetn                 (signal_resetn);
    ramsec->p_vci                    (signal_vci_tgt_ram);
    
    iram->p_clk                      (signal_clk);
    iram->p_resetn                   (signal_resetn);
    iram->p_vci                      (signal_vci_tgt_ira);

    blockdevice->p_clk               (signal_clk);
    blockdevice->p_resetn            (signal_resetn);
    blockdevice->p_vci_target        (signal_vci_tgt_eep);
    blockdevice->p_vci_initiator     (signal_vci_ini_eep);
    blockdevice->p_irq               (signal_irq_eep);
     
    dma->p_clk                       (signal_clk);
    dma->p_resetn                    (signal_resetn);
    dma->p_vci_target                (signal_vci_tgt_dma);
    dma->p_vci_initiator             (signal_vci_ini_dma);
    dma->p_irq                       (signal_irq_dma);

    idma->p_clk                      (signal_clk);
    idma->p_resetn                   (signal_resetn);
    idma->p_vci_target               (signal_vci_tgt_idma);
    idma->p_vci_initiator            (signal_vci_ini_idma);
    idma->p_irq                      (signal_irq_idma);

    halt->p_clk                      (signal_clk);
    halt->p_resetn                   (signal_resetn);
    halt->p_vci                      (signal_vci_tgt_halt);

/*
    erom->p_clk                      (signal_clk);
    erom->p_resetn                   (signal_resetn);
    erom->p_vci                      (signal_vci_tgt_erom);
*/
    tty->p_clk                       (signal_clk);
    tty->p_resetn                    (signal_resetn);
    tty->p_vci                       (signal_vci_tgt_tty);
    tty->p_irq[0]                    (signal_irq_tty);

    secbus->p_clk                    (signal_clk);
    secbus->p_resetn                 (signal_resetn);
    secbus->p_vci_io_target          (signal_vci_tgt_iosec);
    secbus->p_vci_target             (signal_vci_tgt_sec);
    secbus->p_vci_initiator          (signal_vci_ini_ram);
    secbus->p_irq_e                  (signal_irq_esecbus);
    secbus->p_irq_c                  (signal_irq_csecbus);

    vgmn_sys->p_clk                  (signal_clk);
    vgmn_sys->p_resetn               (signal_resetn);
    vgmn_sys->p_to_initiator[SRCID_S_DMA](signal_vci_ini_idma);
    vgmn_sys->p_to_target[TGTID_S_ROM](signal_vci_tgt_rom);
    vgmn_sys->p_to_target[TGTID_S_IRA](signal_vci_tgt_ira);
    vgmn_sys->p_to_target[TGTID_S_DMA](signal_vci_tgt_idma);
    vgmn_sys->p_to_target[TGTID_S_RAM](signal_vci_tgt_sec);
    vgmn_sys->p_to_target[TGTID_S_SEC](signal_vci_tgt_iosec);
    vgmn_sys->p_to_target[TGTID_S_HAL](signal_vci_tgt_halt);
    
    vgmn_mem->p_clk                     (signal_clk);
    vgmn_mem->p_resetn                  (signal_resetn);
    vgmn_mem->p_to_target[TGTID_M_RAM]  (signal_vci_tgt_ram);
    vgmn_mem->p_to_initiator[SRCID_M_SEC](signal_vci_ini_ram);
    vgmn_mem->p_to_initiator[SRCID_M_EEP](signal_vci_ini_eep);
    vgmn_mem->p_to_initiator[SRCID_M_DMA](signal_vci_ini_dma);
    vgmn_mem->p_to_target[TGTID_M_TTY]   (signal_vci_tgt_tty);
    vgmn_mem->p_to_target[TGTID_M_XICU]  (signal_vci_tgt_xicu);
    vgmn_mem->p_to_target[TGTID_M_EEP]   (signal_vci_tgt_eep);
    vgmn_mem->p_to_target[TGTID_M_DMA]   (signal_vci_tgt_dma);
//    vgmn_mem->p_to_target[TGTID_M_ROM]   (signal_vci_tgt_erom);


    //////////////////////////////////////////////////////////////////////////
    // simulation
    //////////////////////////////////////////////////////////////////////////

#ifdef TRACES
   sc_trace_file *TRACEFILE;
   TRACEFILE = sc_create_vcd_trace_file("traces/vcd_traces");
   sc_trace (TRACEFILE, signal_clk, "clk");
   for (int i=0;i<nb_proc;i++)
   {
       std::ostringstream o;
       o << "proc" << i;
       sc_trace (TRACEFILE, signal_vci_proc[i], o.str().c_str());
   }
   sc_trace (TRACEFILE, signal_vci_tgt_ira, "iram");
   sc_trace (TRACEFILE, signal_vci_tgt_rom, "vci_rom");
   sc_trace (TRACEFILE, signal_vci_ini_eep, "eep");

   sc_trace (TRACEFILE, signal_vci_tgt_iosec, "vci_iosec");
   sc_trace (TRACEFILE, signal_vci_tgt_sec, "vci_sec");
   sc_trace (TRACEFILE, signal_vci_ini_ram, "vci_sec_out");

   sc_trace (TRACEFILE, signal_vci_tgt_ram, "vci_ram");
   sc_trace (TRACEFILE, signal_vci_tgt_tty, "vci_tty");
#endif

   sc_start(sc_time(0, SC_NS));
   signal_resetn = false;
   sc_start(sc_time(1, SC_NS));
   signal_resetn = true;

   if (debug_ok)
   {
     int incr = 0;
     sc_start(sc_time(4000000,SC_NS));
     while (incr<ncycles)
     {
       sc_start(sc_time(1,SC_NS));
       proc[0]->print_trace(1);
       incr++;
     }
   }
   else
   {
       if (gettimeofday(&t1, NULL) != 0) {
           perror("gettimeofday");
           return EXIT_FAILURE;
       }
       
       sc_start(10000000.0, sc_core::SC_NS);
       if (gettimeofday(&t2, NULL) != 0) {
           perror("gettimeofday");
           return EXIT_FAILURE;
       }
       ms1 = (uint64_t)t1.tv_sec * 1000ULL + (uint64_t)t1.tv_usec / 1000;
       ms2 = (uint64_t)t2.tv_sec * 1000ULL + (uint64_t)t2.tv_usec / 1000;
       std::cout << "platform clock frequency " << (double)10000000ULL / (double)(ms2 - ms1) << "Khz" << std::endl;
       
       sc_start();
   }

   sc_stop();

   delete rom;
   delete ramsec;

   delete iram;
   delete tty;
   delete vgmn_sys;
   delete vgmn_mem;
   delete vcixicu;
   delete dma;
#ifdef TRACES
   sc_close_vcd_trace_file(TRACEFILE);
#endif
   return(0);

} // end _main

int sc_main (int argc, char *argv[])
{
    try {
        return _main(argc, argv);
    } catch (std::exception &e) {
        std::cout << e.what() << std::endl;
    } catch (...) {
        std::cout << "Unknown exception occured" << std::endl;
        throw;
    }
    return 1;
}

// Local Variables:
// tab-width: 4;
// c-basic-offset: 4;
// c-file-offsets:((innamespace . 0)(inline-open . 0));
// indent-tabs-mode: nil;
// End:
//
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4

