#include #include #include #include #include #include #include #include /********************************************************************* * Inclusion des modèles *********************************************************************/ #include "shared/macro.h" #include "shared/soclib_caches_interfaces.h" #include "shared/soclib_segment_table.h" #include "shared/mapping_memory.h" /********************************************************************* * Inclusion et parametrage du processeur *********************************************************************/ #include "m_cpu_configuration.h" #include "processor/M_CPU/Configuration/m_cpu_configuration.h" #include "processor/M_CPU/M_CPU.h" #include "hierarchy_memory/hierarchy_memory.h" using namespace hierarchy_memory; using namespace std; /********************************************************************* * Définitions des paramètres des composants *********************************************************************/ #define WITH_XTTY false #define NB_CONTEXT (M_CPU_NB_CLUSTER * M_CPU_NB_UL * M_CPU_NB_THREAD) // Parametre du CPU dans un fichier externe #define ICACHE_TEMPLATE LOG2_M_CPU_NB_CLUSTER + LOG2_M_CPU_NB_UL + LOG2_M_CPU_NB_THREAD+1, (LOG2_M_CPU_SIZE_IFETCH_QUEUE)+1 , M_CPU_SIZE_ADDR_INST, M_CPU_SIZE_INST,M_CPU_NB_INST_FETCH #define DCACHE_TEMPLATE LOG2_M_CPU_NB_CLUSTER + LOG2_M_CPU_NB_UL + LOG2_M_CPU_NB_THREAD+1, (LOG2_M_CPU_SIZE_LOAD_STORE_QUEUE)+1, M_CPU_SIZE_ADDR_DATA, M_CPU_SIZE_DATA //#define OFFSET_NB_LINE (power2(NB_CONTEXT)/power2(M_CPU_NB_CLUSTER)) #define OFFSET_NB_LINE 1 // nb_line, size_line, size_word, associativity, hit_latence, miss_penality #define L1_ICACHE "L1_ICACHE",(128*OFFSET_NB_LINE), 16, 4, 4, 2, 4 #define L1_DCACHE "L1_DCACHE",(128*OFFSET_NB_LINE), 16, 4, 4, 2, 4 #define L2_CACHE "L2_CACHE" , 16384, 32, 4, 8, 6, 100 #define NB_IPORT 1 #define NB_DPORT M_CPU_NB_DATA_ACCESS #define SIZE_BUFFER_IRSP 4 #define SIZE_BUFFER_DRSP 4 #define HIERARCHY_MEMORY_TEMPLATE LOG2_M_CPU_NB_CLUSTER + LOG2_M_CPU_NB_UL + LOG2_M_CPU_NB_THREAD+1, (LOG2_M_CPU_SIZE_IFETCH_QUEUE)+1 , M_CPU_SIZE_ADDR_INST, M_CPU_SIZE_INST,M_CPU_NB_INST_FETCH, (LOG2_M_CPU_SIZE_LOAD_STORE_QUEUE)+1, M_CPU_SIZE_ADDR_DATA, M_CPU_SIZE_DATA #define MAPPING_TABLE_CLUSTER_TEMPLATE LOG2_M_CPU_NB_UL, M_CPU_NB_UL, LOG2_M_CPU_NB_INST_SELECT, M_CPU_NB_INST_SELECT #define MAPPING_TABLE_UE_TEMPLATE LOG2_M_CPU_NB_CLUSTER, M_CPU_NB_CLUSTER, LOG2_M_CPU_NB_INST_SELECT, M_CPU_NB_INST_SELECT #define MAPPING_TABLE_DISPATCH_TEMPLATE LOG2_M_CPU_NB_INST_SELECT, M_CPU_NB_INST_SELECT, LOG2_M_CPU_NB_UE, M_CPU_NB_UE #define TYPE_TABLE_INST_L_TEMPLATE LOG2_NB_INST_L, NB_INST_L /********************************************************************* * Variable global *********************************************************************/ timeval time_begin; timeval time_end; unsigned int nb_cycles_simulated = 0; /******************************************************** * Déclarations des composants ********************************************************/ UE_CONFIGURATION ** ue_configuration; MAPPING_TABLE ** mapping_table_cluster; MAPPING_TABLE * mapping_table_ue; MAPPING_TABLE * mapping_table_dispatch; TYPE_TABLE * type_table_inst_l; HIERARCHY_MEMORY * memory; M_CPU * m_cpu; /********************************************************************* * print_time *********************************************************************/ void print_time (timeval time_begin, timeval time_end, unsigned int nb_cycles_simulated, unsigned int nb_cycles_current) { double average = (double)(nb_cycles_simulated) / (double)(time_end.tv_sec-time_begin.tv_sec); cout << nb_cycles_current << "\t(" << average << " cycles / seconds )" << endl; } /********************************************************************* * clean_exit *********************************************************************/ void clean_exit () { sc_stop(); gettimeofday(&time_end ,NULL); print_time(time_begin,time_end,(unsigned int)sc_simulation_time()-nb_cycles_simulated,(unsigned int)sc_simulation_time()); delete memory; for (unsigned int i = 0; i < M_CPU_NB_CLUSTER; i ++) delete mapping_table_cluster[i]; for (unsigned int i = 0; i < M_CPU_NB_UE; i ++) delete ue_configuration[i]; delete mapping_table_ue; delete mapping_table_dispatch; delete type_table_inst_l; delete m_cpu; } /********************************************************************* * handler_signal *********************************************************************/ void handler_signal(int signum) { switch (signum) { case SIGTERM : case SIGINT : { perror("Stop of simulation\n"); clean_exit(); exit(2); break; } default : { break; } }//end switch signum } /********************************************************************* * simulation *********************************************************************/ unsigned int simulation () { // Test if can continue the simulation (all thread have not send the stop signal) if (memory->stop() == true) return 0; cout << "How many cycle to simulate ? (0 to stop the simulation)" << endl; int nb_cycle; cin >> nb_cycle; cout << " ... again " << nb_cycle << " cycles" << endl; return nb_cycle; } /********************************************************************* * power2 *********************************************************************/ // return the Y=2^n with 2^(n-1) < X <= 2^n // Warning : possible bug if X > 0x80000000 uint32_t power2 (uint32_t x) { uint32_t mask; for (mask = 1; mask < x; mask <<= 1); return mask; } /********************************************************************* * usage *********************************************************************/ void usage(char * name_fct) { cerr << "usage : " << name_fct << " filename [nb_cycle]" << endl; cerr << " * filename : name of binary" << endl; cerr << " * nb_cycle : number of cycle to simulate" << endl; exit(1); } /********************************************************************* * sc_main *********************************************************************/ int sc_main(int argc, char* argv[]) { // Trap signal signal(SIGTERM, handler_signal); signal(SIGINT , handler_signal); if ( (argc != 2) && (argc != 3)) usage(argv[0]); unsigned int nb_cycles = 0; bool nb_cycles_define = false; const char * filename = argv[1]; if (argc >= 3) { nb_cycles_define = true; nb_cycles = atoi(argv[2]); } /********************************************************************* * Déclarations des variables pour la simulation *********************************************************************/ /********************************************************************* * Déclarations des signaux *********************************************************************/ sc_clock CLK ("clock",1,0.5); sc_signal NRESET; ICACHE_SIGNALS ** icache_signals; DCACHE_SIGNALS ** dcache_signals; /******************************************************** * Segment table ********************************************************/ log_printf(INFO," Table des segments\n"); SOCLIB_SEGMENT_TABLE segtable; segtable.setMSBNumber (8); segtable.setDefaultTarget(0,0); //shared data segment // Add a segment :name , address of base , size , global index , local index, uncache segtable.addSegment("text" , TEXT_BASE , TEXT_SIZE , 0 ,0 , false); segtable.addSegment("data" , DATA_CACHED_BASE , DATA_CACHED_SIZE , 0 ,0 , false); segtable.addSegment("data_unc" , DATA_UNCACHED_BASE , DATA_UNCACHED_SIZE , 0 ,0 , true ); segtable.addSegment("stack" , STACK_BASE , STACK_SIZE , 0 ,0 , false); segtable.addSegment("tty" , TTY_BASE , TTY_SIZE , 0 ,0 , true ); segtable.addSegment("sim2os" , SIM2OS_BASE , SIM2OS_SIZE , 0 ,0 , true ); segtable.addSegment("ramlock" , RAMLOCK_BASE , RAMLOCK_SIZE , 0 ,0 , true ); /******************************************************** * Déclaration des signaux ********************************************************/ log_printf(INFO," Déclaration des signaux\n"); icache_signals = new ICACHE_SIGNALS * [M_CPU_NB_CLUSTER]; dcache_signals = new DCACHE_SIGNALS * [M_CPU_NB_CLUSTER]; for (unsigned int it_m_cpu_nb_cluster = 0; it_m_cpu_nb_cluster < M_CPU_NB_CLUSTER; it_m_cpu_nb_cluster ++) { icache_signals [it_m_cpu_nb_cluster] = new ICACHE_SIGNALS [NB_IPORT]; dcache_signals [it_m_cpu_nb_cluster] = new DCACHE_SIGNALS [NB_DPORT]; } /******************************************************** * Déclaration des composants ********************************************************/ log_printf(INFO," Déclaration des composants\n"); // UE_CONFIGURATION ue_configuration = new UE_CONFIGURATION * [M_CPU_NB_UE]; for (unsigned int i = 0; i < M_CPU_NB_UE; i ++) { std::ostringstream name_ue_configuration; name_ue_configuration << "ue_configuration[" << i << "]"; ue_configuration[i] = new UE_CONFIGURATION (name_ue_configuration.str().c_str()); } // MAPPING_TABLE (CLUSTER) mapping_table_cluster = new MAPPING_TABLE * [M_CPU_NB_CLUSTER]; for (unsigned int i = 0; i < (M_CPU_NB_CLUSTER); i ++) { std::ostringstream name_mapping_table_cluster; name_mapping_table_cluster << "mapping_table_cluster[" << i << "]"; mapping_table_cluster[i] = new MAPPING_TABLE (name_mapping_table_cluster.str().c_str()); } // MAPPING_TABLE (UE) std::ostringstream name_mapping_table_ue; name_mapping_table_ue << "mapping_table_ue"; mapping_table_ue = new MAPPING_TABLE (name_mapping_table_ue.str().c_str()); // MAPPING_TABLE (DISPATCH) std::ostringstream name_mapping_table_dispatch; name_mapping_table_dispatch << "mapping_table_dispatch"; mapping_table_dispatch = new MAPPING_TABLE (name_mapping_table_dispatch.str().c_str()); std::ostringstream name_type_table_inst_l; name_type_table_inst_l << "type_table_inst_l"; type_table_inst_l = new TYPE_TABLE (name_type_table_inst_l.str().c_str()); // initialisation of internal structure ini_ue_configuration (ue_configuration); ini_mapping_table_cluster (mapping_table_cluster); ini_mapping_table_ue (mapping_table_ue); ini_mapping_table_dispatch (mapping_table_dispatch); ini_type_table_inst_l (type_table_inst_l); // ----- SYSTEM MEMORY ----- char * name_tty [NB_CONTEXT]; for (uint32_t num_context = 0; num_context < NB_CONTEXT; num_context ++) { std::ostringstream name_one_tty; name_one_tty << "tty_" << num_context; unsigned int size_name = strlen(name_one_tty.str().c_str())+1; name_tty [num_context] = new char [size_name]; strncpy(name_tty [num_context],name_one_tty.str().c_str(),size_name); } param_entity_t param_tty [1] = {param_entity_t (TTY_BASE , TTY_SIZE , tty::param_t ("tty" , NB_CONTEXT, name_tty,WITH_XTTY))}; param_entity_t param_ramlock [1] = {param_entity_t (RAMLOCK_BASE, RAMLOCK_SIZE, ramlock::param_t("ramlock", RAMLOCK_SIZE))}; param_entity_t param_sim2os = param_entity_t (SIM2OS_BASE, SIM2OS_SIZE, sim2os::param_t("sim2os",&segtable)); param_cache_t param_icache [1] = { param_cache_t (L1_ICACHE) }; param_cache_t param_dcache [1] = { param_cache_t (L1_DCACHE) }; param_cache_t param_scache [1] = { param_cache_t (L2_CACHE)}; cache::cache_multilevel::param_t param_icache_dedicated [M_CPU_NB_CLUSTER]; cache::cache_multilevel::param_t param_dcache_dedicated [M_CPU_NB_CLUSTER]; for (uint32_t num_cluster = 0; num_cluster < M_CPU_NB_CLUSTER; num_cluster ++) { std::ostringstream name_icache_dedicated; name_icache_dedicated << "icache_dedicated[" << num_cluster << "]"; param_icache_dedicated [num_cluster] = cache::cache_multilevel::param_t (name_icache_dedicated.str().c_str(),1, NB_IPORT, param_icache); std::ostringstream name_dcache_dedicated; name_dcache_dedicated << "dcache_dedicated[" << num_cluster << "]"; param_dcache_dedicated [num_cluster] = cache::cache_multilevel::param_t (name_dcache_dedicated.str().c_str(),1, NB_DPORT, param_dcache); } cache::cache_multilevel::param_t param_cache_shared ("param_cache_shared",1, M_CPU_NB_CLUSTER*(NB_IPORT+NB_DPORT), param_scache); cache::param_t param_cache ("cache" , M_CPU_NB_CLUSTER , param_icache_dedicated, param_dcache_dedicated, param_cache_shared ); std::ostringstream name_memory; name_memory << basename(argv[0]) << "_memory"; memory = new HIERARCHY_MEMORY (name_memory.str().c_str() , 0 , 0 , &segtable , M_CPU_NB_CLUSTER, NB_CONTEXT , SIZE_BUFFER_IRSP, SIZE_BUFFER_DRSP, hierarchy_memory::param_t(1,param_tty, 1,param_ramlock, param_sim2os, param_cache) ); std::ostringstream name_m_cpu; name_m_cpu << basename(argv[0]) << "_m_cpu"; m_cpu = new M_CPU (name_m_cpu.str().c_str() , ue_configuration , mapping_table_cluster , mapping_table_ue , mapping_table_dispatch , type_table_inst_l , M_CPU_PARAMETER_USE ); ////////////////////////////////////////////////////////// // Segments Initialisation ////////////////////////////////////////////////////////// log_printf(INFO," Table des segments : initialisation\n"); const char *sections_text [] = {".text",NULL}; const char *sections_data [] = {".data",".rodata",".bss",".sdata",".sbss", NULL}; const char *sections_stack [] = {".stack",NULL}; memory->init("text" , filename, sections_text); memory->init("stack" , filename, sections_stack); memory->init("data" , filename, sections_data); segtable.print(); /******************************************************** * Instanciation ********************************************************/ log_printf(INFO," Instanciation des composants\n"); log_printf(INFO," Instanciation de l'élément \"memory\"\n"); memory->CLK (CLK); memory->NRESET (NRESET); for (uint32_t x = 0; x < M_CPU_NB_CLUSTER; x ++) { for (uint32_t y = 0; y < NB_IPORT; y ++) memory->ICACHE[x][y] (icache_signals [x][y]); for (uint32_t y = 0; y < NB_DPORT; y ++) memory->DCACHE[x][y] (dcache_signals [x][y]); } log_printf(INFO," Instanciation de l'élément \"m_cpu\"\n"); m_cpu->CLK (CLK); m_cpu->NRESET (NRESET); for (unsigned int it_m_cpu_nb_cluster = 0; it_m_cpu_nb_cluster < M_CPU_NB_CLUSTER; it_m_cpu_nb_cluster++) { m_cpu->ICACHE[it_m_cpu_nb_cluster] (icache_signals[it_m_cpu_nb_cluster][0]); for (unsigned int it_nb_dport = 0; it_nb_dport < NB_DPORT; it_nb_dport++) m_cpu->DCACHE[it_m_cpu_nb_cluster][it_nb_dport] (dcache_signals[it_m_cpu_nb_cluster][it_nb_dport]); }//end it_m_cpu_nb_cluster log_printf(NONE," Successful Instanciation\n"); /******************************************************** * Simulation - Begin ********************************************************/ // Initialisation sc_start(0); // Reset NRESET.write(false); sc_start(5); NRESET.write(true); // Lunch the simulation cout << "\n<" << argv[0] << "> Simulation : Begin\n\n" << endl; nb_cycles_simulated = 0; while (1) { unsigned int nb_cycles_simulation; if (nb_cycles_define == true) { nb_cycles_simulation = nb_cycles; nb_cycles = 0; // to stop at the next loop :D } else nb_cycles_simulation = simulation(); if (nb_cycles_simulation == 0) break; gettimeofday(&time_begin ,NULL); sc_start (nb_cycles_simulation); gettimeofday(&time_end ,NULL); nb_cycles_simulated += nb_cycles_simulation; print_time(time_begin,time_end,nb_cycles_simulation,(unsigned int)sc_simulation_time()); } cout << "\n<" << argv[0] << "> Simulation : End\n\n" << endl; /******************************************************** * Simulation - End ********************************************************/ clean_exit (); return 0; }