OpenCores
URL https://opencores.org/ocsvn/an-fpga-implementation-of-low-latency-noc-based-mpsoc/an-fpga-implementation-of-low-latency-noc-based-mpsoc/trunk

Subversion Repositories an-fpga-implementation-of-low-latency-noc-based-mpsoc

[/] [an-fpga-implementation-of-low-latency-noc-based-mpsoc/] [trunk/] [mpsoc/] [src_verilator/] [simulator.cpp] - Rev 56

Compare with Previous | Blame | View Log

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <limits.h>
#include <ctype.h>
#include <stdint.h>
#include <inttypes.h>
#include <verilated.h>          // Defines common routines
 
#include "Vtraffic.h"
#include "Vpck_inj.h"
#include <thread>
#include <vector>
#include <atomic>
 
 
#include <cstdint>
#include <cstdlib>
#include <iostream>
 
 
#include "simulator.h"
 
 
 
 
int main(int argc, char** argv) {
    char change_injection_ratio=0;
    int i,j,x,y;//,report_delay_counter=0;
 
    char deafult_out[] = {"result"};
    NEw=Log2(NE);
    for(i=0;i<NE;i++)   custom_traffic_table[i]=INJECT_OFF; //off
    Verilated::commandArgs(argc, argv);   // Remember args
    processArgs ( argc,  argv );
    allocate_rsv_pck_counters();
    if (class_percentage==NULL) {
            class_percentage =   (int *) malloc(sizeof(int));
            class_percentage[0]=100;
    }
 
 
    Vrouter_new();
    if (ENDP_TYPE == PCK_INJECTOR)    for(i=0;i<NE;i++)    pck_inj[i]  = new Vpck_inj;
    else                            for(i=0;i<NE;i++)    traffic[i]  = new Vtraffic;
 
 
 
    FIXED_SRC_DST_PAIR = strcmp (TRAFFIC,"RANDOM") &  strcmp(TRAFFIC,"HOTSPOT") & strcmp(TRAFFIC,"random") & strcmp(TRAFFIC,"hot spot") & strcmp(TRAFFIC,"TASK");
 
 
    /********************
    *    initialize input
    *********************/
    reset=1;
    reset_active_high=1;
    reset_all_register();
    start_i=0;
 
    mcast_init();
 
 
 
    topology_init();
    if( TRAFFIC_TYPE == NETRACE){
        netrace_init(netrace_file); // should be called first to initiate header
        pck_inj_init((int)header->num_nodes);
    }
    else if (TRAFFIC_TYPE ==SYNFUL) {
        pck_inj_init(SYNFUL_ENDP_NUM); //should be called first to initiate node mapping needed by synful lib
        synful_init(synful_file,synful_SSExit,synful_random_seed,sim_end_clk_num,end_sim_pck_num);
    }
    else     traffic_gen_init();
 
 
 
    main_time=0;
    print_parameter();
    if( thread_num>1) initial_threads();
 
    while (!Verilated::gotFinish()) {
        if(main_time - saved_time < 50) {//set reset and start
            reset_active_high = ((router1[0]->router_event[0] & ACTIVE_HIGH_RST)==1)? 1 : 0;
            if (main_time-saved_time >= 10 ) reset = (reset_active_high)? 0 :1;           
            else reset = reset_active_high;     ;//keep system in reset
 
            if(main_time == saved_time+21){ count_en=1; start_i=1;}
            if(main_time == saved_time+23) start_i=0;
        }
 
        if(TRAFFIC_TYPE==NETRACE) netrace_posedge_event();
        else if(TRAFFIC_TYPE ==SYNFUL) synful_posedge_event();
        else traffic_clk_posedge_event();
 
 
        //The valus of all registers and input ports valuse change @ posedge of the clock. Once clk is deasserted,  as multiple modules are connected inside the testbench we need several eval for propogating combinational logic values
        //between modules when the clock .
        for (i=0;i<SMART_MAX+2;i++) {
            if(TRAFFIC_TYPE==NETRACE) netrace_negedge_event();
            else if(TRAFFIC_TYPE ==SYNFUL) synful_negedge_event();
            else traffic_clk_negedge_event( );
        }
 
        if(simulation_done){
 
            if( TRAFFIC_TYPE == NETRACE) netrace_final_report();
            else if(TRAFFIC_TYPE ==SYNFUL) synful_final_report();
            else traffic_gen_final_report();
            sim_final_all();
            return 0;
        }
 
        main_time++;
 
    }//Simulating is done
 
    sim_final_all();
    return 0;
 
}
 
 
#define __FILENAME__ (__FILE__ + SOURCE_PATH_SIZE)
 
void  usage(char * bin_name){
    printf("Usage:\n"
" %s -t <synthetic Traffic Pattern name> [synthetic Traffic options]\n"
" %s -f <Task file> [Task options]\n"
" %s -F <netrace file> [Netrace options] \n"
" %s -S <synful model file> [synful options]\n\n"
"synthetic Traffic options:\n"
"  -t <Traffic Pattern>        \"HOTSPOT\", \"RANDOM\", \"BIT_COMPLEMENT\" , \"BIT_REVERSE\",\n"
"                              \"TORNADO\", \"TRANSPOSE1\", \"TRANSPOSE2\", \"SHUFFEL\", \"CUSTOM\"\n"
"  -m <Packet size info>       packet size format  Random-Range or Random-discrete:\n"
"                              Random-Range : \"R,MIN,MAX\" : The injected packets' size in flits are\n"
"                              randomly selected in range MIN <= PCK_size <=MAX \n"
"                              Random-discrete: \"D,S1,S2,..Sn,P,P1,P2,P3,...Pn\": Si are the discrete\n"
"                              set of numbers representing packet size. The injected packet size is\n"
"                              randomly selected among these discrete values according to associated\n"
"                              probability values.\n"
"  -c <sim_end_clk_num>        The simulation will stop when the simulation clock number reaches this value\n"
"  -n <sim_end_pck_num>        The simulation will stop when the total sent packets to the NoC reaches this number\n"
"  -i <injection ratio>        flit injection ratio in percentage\n"
"  -p <class traffic ratios>   The percentage of traffic injected for each class. Represented in\n"
"                              comma-separated string format:\"n0,n1,n2..\" \n"
"  -h <HOTSPOT traffic format> represented in a string with the following format:\n"
"                              total number of hotspot nodes, first hotspot node ID, first hotspot node\n"
"                              send enable(1 or 0),first hotspot node percentage x10,second hotspot node ...\n"
"  -H <custom traffic pattern> custom traffic pattern: represented in a string with following format:\n"
"                              \"SRC1,DEST1, SRC2,DEST2, .., SRCn, DESTn\"   \n"
"  -T <thread-num>             total number of threads. The default is one (no-thread).\n"
"  -u <Multi/Broadcast format> represented in a string with following format:\n"
"                              \"ratio,min_pck_size,max_pck_size\"\n"
"                              ratio:The percentage of Multicast/broadcast packets against total injected \n"
"                              traffic. The Multicast/Broadcast packet size is randomly selected\n"
"                              between min_pck_size and max_pck_size. The max_pck_size must be smaller or equal\n"
"                              to the router buffer width. This filed is only valid when the NoC is configured\n"
"                              with the Multicast/Broadcast feature support.\n"
//"  -Q                          Quick (fast) simulation. ignore evaluating non-active routers \n"
//"                              to speed up simulation time"
"\nTrace options:\n"
"  -f <Task file>              Path to the task file. any custom task file can be generated using ProNoC gui\n"
"  -c <sim_end_clk_num>        Simulation will stop when simulation clock number reach this value \n"
"  -T <thread-num>             Total number of threads. The default is one (no-thread).\n"
//"  -Q                          Quick (fast) simulation. ignore evaluating non-active routers \n"
//"                              to speed up simulation time"
"\nNetrace options:\n"
"  -F <Netrace file>           Path to the task file. any custom task file can be generated using ProNoC gui\n"
"  -n <sim_end_pck_num>        The simulation will stop when the total sent packets to the NoC reaches this number\n"
"  -d                          ignore dependencies\n"
"  -r <start region>           Start region\n"
"  -l                          Reader throttling\n"
"  -v <level>                  Verbosity level. 0: off, 1:display a live number of injected packets,\n"
"                              3: print injected/ejected packets details, The default value is 1\n"
"  -T <thread-num>             Total number of threads. The default is one (no-thread).\n"
"  -s <speed-up-num>           The speed-up-num  is the ratio of netrace frequency to pronoc.The higher value\n"
"                              results in higher injection ratio to the NoC. Default is one\n"
//"  -Q                          Quick (fast) simulation. ignore evaluating non-active routers \n"
//"                              to speed up simulation time"
"\nsynful options:\n"
"  -S <model file>             Path to the synful application model file\n"
"  -r <seed value>             Seed value for random function\n"
"  -c <sim_end_clk_num>        The simulation will stop when the simulation clock number reaches this value \n"
"  -s                          Exit at steady state\n"
"  -n <sim_end_pck_num>        The simulation will stop when the total of sent packets to the NoC reaches this number\n"
"  -T <thread-num>             Total number of threads. The default is one (no-thread).\n"
"  -v <level>                  Verbosity level. 0: off, 1:display a live number of injected packets,\n"
"  -w <flit-size>              The synful flit size in Byte. It defines the number of flits that should be set to\n"
"                              ProNoC for each synful packets. The ProNoC packet size is:\n"
"                              Ceil(synful packet size/synful flit size).\n"
"                              3: print injected/ejected packets details, The default value is 1\n",
bin_name,bin_name,bin_name,bin_name
);
 
}
 
 
 
void netrace_processArgs (int argc, char **argv )
{
   char c;
 
   /* don't want getopt to moan - I can do that just fine thanks! */
   opterr = 0;
   if (argc < 2)  usage(argv[0]);
   while ((c = getopt (argc, argv, "F:dr:lv:T:n:s:")) != -1)
   {
     switch (c)
     {
         case 'F':
             TRAFFIC_TYPE=NETRACE;
             TRAFFIC=(char *) "NETRACE";
             ENDP_TYPE = PCK_INJECTOR;
             netrace_file = optarg;
             break;
         case 'd':
             ignore_dependencies=1;
             break;
         case 'r':
            start_region=atoi(optarg);
             break;
         case 'l':
             reader_throttling=1;
             break;
         case 'v':
             verbosity= atoi(optarg);
             break;
         case 'T':
            thread_num = atoi(optarg);
            break;
         case 'n':
             end_sim_pck_num=atoi(optarg);
             break;
         case 's':
             netrace_speed_up=atoi(optarg);
 
             break;
         case '?':
             if (isprint (optopt))
                 fprintf (stderr, "Unknown option `-%c'.\n", optopt);
             else
                 fprintf (stderr,  "Unknown option character `\\x%x'.\n",  optopt);
         default:
                usage(argv[0]);
                exit(1);
      }
    }
}
 
 
 
void synthetic_task_processArgs (int argc, char **argv )
{
   char c;
   int p;
   int array[10];
   float f;
 
   /* don't want getopt to moan - I can do that just fine thanks! */
   opterr = 0;
   if (argc < 2)  usage(argv[0]);
   while ((c = getopt (argc, argv, "t:m:n:c:i:p:h:H:f:T:u:Q")) != -1)
      {
     switch (c)
        {
         case 'f':
             TRAFFIC_TYPE=TASK;
             TRAFFIC=(char *) "TASK";
             task_traffic_init(optarg);
             break;
        case 't':
            TRAFFIC=optarg;
            total_active_routers=-1;
            break;
        case 's':
            MIN_PACKET_SIZE=atoi(optarg);
            break;
        case 'n':
             end_sim_pck_num=atoi(optarg);
             break;
        case 'c':
             sim_end_clk_num=atoi(optarg);
             break;
        case 'i':
             f=atof(optarg);
             f*=(MAX_RATIO/100);
             ratio= (int) f;
             break;
        case 'p':
            p= parse_string (optarg, array);
            if (p==0) {
                printf("Warning: class setting is ignored!\n");
                break;
            }
            class_percentage =   (int *) malloc( p * sizeof(int));
            for(int k=0;k<p;k++){
                class_percentage[k]=array[k];
            }
            if(p >1 && p>C){
                printf("Warning: the number of given class %u is larger than the number of message classes in ProNoC (C=%u)!\n",p,C);
            }
            break;
        case 'm':
            update_pck_size(optarg);
 
            break;
        case 'H':
            update_custom_traffic(optarg);
            break;
        case 'h':
            update_hotspot(optarg);
            break;
        case  'T':
            thread_num = atoi(optarg);
            break;
        case 'Q':
            //Quick_sim_en=1;
            fprintf (stderr, "Unknown option `-%c'.\n", optopt);
            usage(argv[0]);
            exit(1);
            break;
        case 'u':
            update_mcast_traffic(optarg);
            break;
        case '?':
           if (isprint (optopt))
          fprintf (stderr, "Unknown option `-%c'.\n", optopt);
           else
          fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt);
        default:
           usage(argv[0]);
           exit(1);
        }
      }
}
 
 
 
 
void synful_processArgs (int argc, char **argv)
{
   char c;
   /* don't want getopt to moan - I can do that just fine thanks! */
   opterr = 0;
   if (argc < 2)  usage(argv[0]);
   while ((c = getopt (argc, argv, "S:c:sn:v:T:r:w:")) != -1)
   {
     switch (c)
     {
         case 'S':
             TRAFFIC_TYPE=SYNFUL;
             TRAFFIC=(char *) "SYNFUL";
             synful_file = optarg;
             ENDP_TYPE   =PCK_INJECTOR;
             break;
         case 'c':
             sim_end_clk_num=atoi(optarg);
             break;
         case 's':
             synful_SSExit =true;
             break;
         case 'n':
             end_sim_pck_num=atoi(optarg);
             break;
         case 'v':
              verbosity= atoi(optarg);
              break;
         case 'w':
              synful_flitw= atoi(optarg);
              break;
         case 'T':
             thread_num = atoi(optarg);
             break;
         case 'r':
             synful_random_seed = atoi(optarg);
             break;
         case '?':
             if (isprint (optopt)) fprintf (stderr, "Unknown option `-%c'.\n", optopt);
             else fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt);
         default:
              usage(argv[0]);
              exit(1);
     }//switch
   }//while
}
 
 
 
int parse_string ( char * str, int * array)
{
    int i=0;
    char *pt;
    pt = strtok (str,",");
    while (pt != NULL) {
        int a = atoi(pt);
        array[i]=a;
        i++;
        pt = strtok (NULL, ",");
    }
   return i;
}
 
 
 
 
 
 
unsigned int pck_dst_gen_unicast (     unsigned int core_num, unsigned char * inject_en) {
    if(TRAFFIC_TYPE==TASK)    return      pck_dst_gen_task_graph ( core_num, inject_en);
    if((strcmp (TOPOLOGY,"MESH")==0)||(strcmp (TOPOLOGY,"TORUS")==0))    return  pck_dst_gen_2D (core_num, inject_en);
    return pck_dst_gen_1D (core_num, inject_en);
}
 
 
void mcast_full_rnd (unsigned int core_num){
    unsigned int rnd;
    int a;
    for(;;)  {
        DEST_ADDR_ASSIGN_RAND(traffic[core_num]->dest_e_addr);
        if((strcmp (SELF_LOOP_EN,"NO")==0)) DEST_ADDR_BIT_CLR(traffic[core_num]->dest_e_addr,core_num);
        DEST_ADDR_IS_ZERO(a,traffic[core_num]->dest_e_addr);
        //rnd = rand() & ~(0x1<<core_num);
        //rnd &= ((1<<NE) -1);
        //if(rnd!=0) return rnd;
        if(a!=1) return;
    }
}
 
 
void mcast_partial_rnd (unsigned int core_num){
    unsigned int rnd;int a;
    //printf("m[%d]=%d\n",core_num,mcast_list_array[core_num]);
    if(mcast_list_array[core_num] == 1){ // the current node is located in multicast partial list
        unsigned int self_node_addr = endp_id_to_mcast_id(core_num);//current node location in multicast list
        self_node_addr++;
        for(;;){
            DEST_ADDR_ASSIGN_RAND(traffic[core_num]->dest_e_addr);
            DEST_ADDR_BIT_CLR(traffic[core_num]->dest_e_addr,0);
            if((strcmp (SELF_LOOP_EN,"NO")==0))    DEST_ADDR_BIT_CLR(traffic[core_num]->dest_e_addr,self_node_addr);
            //rnd = rand() & ~((0x1<<(self_node_addr+1))|0x1); // generate a random multicast destination. remove the current node flag and unicast_flag from destination list
            //rnd &= ((1<<(MCAST_PRTLw+1)) -1);
            //printf("rnd=%d\n",rnd);
            DEST_ADDR_IS_ZERO(a,traffic[core_num]->dest_e_addr);
            if(a!=1) return;
            //if(rnd!=0) return rnd;
        }
    }else{
        for(;;){
            DEST_ADDR_ASSIGN_RAND(traffic[core_num]->dest_e_addr);
            DEST_ADDR_BIT_CLR(traffic[core_num]->dest_e_addr,0);
            DEST_ADDR_IS_ZERO(a,traffic[core_num]->dest_e_addr);
            if(a!=1) return;
            //rnd = rand() & ~0x1;// deassert the unicast flag
            //rnd &= ((1<<(MCAST_PRTLw+1)) -1);
            //if(rnd!=0) return rnd;
        }
    }
//this function should not come here
 
}
 
 
 
 
void pck_dst_gen (     unsigned int core_num, unsigned char * inject_en) {
    unsigned int dest = pck_dst_gen_unicast (core_num, inject_en);
//    printf("inject_en=%u, core_num=%u, dest=%u\n",*inject_en, core_num,dest);
    if(IS_UNICAST){
        traffic[core_num]->dest_e_addr= dest;
        return;
    }
    else if (*inject_en==0) return;
    //multicast
    DEST_ADDR_ASSIGN_ZERO(traffic[core_num]->dest_e_addr);//reset traffic[core_num]->dest_e_addr
 
    unsigned int dest_id = endp_addr_decoder (dest);
    //*inject_en = dest_id !=core_num;
 
    unsigned int rnd = rand() % 100; // 0~99
    if(rnd >= mcast.ratio){
        //send a unicast packet
        if((strcmp (SELF_LOOP_EN,"NO")==0) && dest_id==core_num){
            *inject_en=0;
            return;
        }
        if(IS_MCAST_FULL){
            //return (0x1<<dest_id);// for mcast-full
            DEST_ADDR_BIT_SET(traffic[core_num]->dest_e_addr,dest_id);
            return;
        }
        // IS_MCAST_PARTIAL | IS_BCAST_FULL | IS_BCAST_PARTIAL
        dest = (dest << 1) | 0x1; // {dest_coded,unicast_flag}
        DEST_ADDR_ASSIGN_INT(traffic[core_num]->dest_e_addr,dest);
        return;
    }
    traffic[core_num]->pck_size_in=rnd_between(mcast.min,mcast.max);
 
    if (IS_MCAST_FULL) {
        mcast_full_rnd (core_num);
        return;
    }
    if (IS_MCAST_PARTIAL){
        mcast_partial_rnd(core_num);
        return;
    }
 
    return; //IS_BCAST_FULL | IS_BCAST_PARTIAL  traffic[core_num]->dest_e_addr=0;
}
 
 
 
void update_hotspot(char * str){
     int i;
     int array[1000];
     int p;
     int acuum=0;
     hotspot_st * new_node;
     p= parse_string (str, array);
     if (p<4){
            fprintf(stderr,"ERROR: in hotspot traffic parameters. 4 value should be given as hotspot parameter\n");
            exit(1);
     }
     HOTSPOT_NUM=array[0];
     if (p<1+HOTSPOT_NUM*3){
            fprintf(stderr,"ERROR: in hotspot traffic parameters \n");
            exit(1);
     }
     new_node =  (hotspot_st *) malloc( HOTSPOT_NUM * sizeof(hotspot_st));
     if( new_node == NULL){
         fprintf(stderr,"ERROR: cannot allocate memory for hotspot traffic\n");
           exit(1);
        }
     for (i=1;i<3*HOTSPOT_NUM; i+=3){
        new_node[i/3]. ip_num = array[i];
        new_node[i/3]. send_enable=array[i+1];
        new_node[i/3]. percentage =  acuum + array[i+2];
        acuum= new_node[i/3]. percentage;    
     }
     if(acuum> 1000){
             printf("Warning: The hotspot traffic summation %f exceed than 100 percent.  \n", (float) acuum /10);
     }
     hotspots=new_node;
}
 
void  update_mcast_traffic(char * str){
    int i;
    int array[10];
    int p;
    int max_valid =(B > LB)? LB : B;
    p= parse_string (str, array);
    if(p>0)    mcast.ratio =array[0];
    if(p>1)    mcast.min =array[1];
    if(p>2)    mcast.max =array[2];
 
    if (mcast.ratio > 100)       { printf("ERROR: The given multicast traffic ratio (%d) is larger than 100\n",mcast.ratio);     exit(1);}
    if (mcast.min < MIN_PCK_SIZE){ printf("ERROR: The given multicast minimum packet size (%d) is larger than %d minimum packet size supported by the NoC\n",mcast.min, MIN_PCK_SIZE);     exit(1);}
    if (mcast.max > max_valid)   { printf("ERROR: The given multicast maximum packet size (%d) is larger than %d maximum router buffer size\n",mcast.max, max_valid);     exit(1);};
 
 
}
 
void update_custom_traffic (char * str){
    int i;
    int array[10000];
    int p;
    p= parse_string (str, array);
    for (i=0;i<p; i+=2){
        custom_traffic_table[array[i]] = array[i+1];
    }
}
 
void update_pck_size(char *str){
    int i;
    int array[1000];
    char substring[1000];
    int p;
    char *pt,*pt2;
    MIN_PACKET_SIZE=100000;
    MAX_PACKET_SIZE=1;
 
 
    pt = strtok (str,",");
    if(*pt=='R'){//random range
        p= parse_string (str+2, array);
        if(p<2){
            fprintf(stderr,"ERROR: Wrong Packet size format %s. It should be \"R,min,max\" : \n",str);
            exit(1);
        }
 
        MIN_PACKET_SIZE=array[0];
        MAX_PACKET_SIZE=array[1];
        AVG_PACKET_SIZE=(MIN_PACKET_SIZE+MAX_PACKET_SIZE)/2;// average packet size
    }else if(*pt=='D'){//random discrete
        pck_size_sel =  RANDOM_discrete;
        pt = strtok (str+2,"P");
        pt2 = strtok (NULL,"P");
        if (pt == NULL || pt2==NULL) {
            fprintf(stderr,"ERROR: Wrong Packet size format %s. It should be \"D,s1,s2..sn,P,p1,p2..pn\". missing letter \"P\" in format  \n",str);
            exit(1);
        }
        p= parse_string (pt, array);
        if (p==0){
            fprintf(stderr,"ERROR: Wrong Packet size format %s. It should be \"D,s1,s2..sn,P,p1,p2..pn\". missing si values after letter \"D\" \"P\" in format  \n",str);
            exit(1);
        }
        int in=p;
        //alocate mmeory for pck size
        discrete_size = (int*)malloc((p) * sizeof(int));
        discrete_prob = (int*)malloc((p) * sizeof(int));
        // Check if the memory has been successfully allocated
        if (discrete_size == NULL || discrete_prob==NULL) {
            printf("ERROR: Memory not allocated.\n");
            exit(1);
        }
 
        for (i=0; i<p; i++){
 
            //printf("I[%u]=%u,\n",i,array[i]);
            discrete_size[i] = array[i];
            if(MIN_PACKET_SIZE > array[i]) MIN_PACKET_SIZE = array[i];
            if(MAX_PACKET_SIZE < array[i]) MAX_PACKET_SIZE = array[i];
        }
 
        p= parse_string (pt2+1, array);
        int sum=0;
        AVG_PACKET_SIZE=0;
        for (i=0; i<p; i++){
            //printf("P[%u]=%u,\n",i,array[i]);
            if(i<in){
                 sum+=array[i];
                 discrete_prob[i]=sum;
                 AVG_PACKET_SIZE+=discrete_size[i] * array[i];
 
            }
        }
        AVG_PACKET_SIZE/=100;
 
        if(sum!=100){
            fprintf(stderr,"ERROR: The accumulatio of the first %u probebility values is %u which is not equal to 100\n",in,sum);
            exit(1);
        }
 
    }else {
        fprintf(stderr,"ERROR: Wrong Packet size format %s. It should start with one of \"D\" or \"R\" letter\n",str);
        exit(1);
    }
 
 
}
 
void allocate_rsv_pck_counters (void) {
    int p=(MAX_PACKET_SIZE-MIN_PACKET_SIZE)+1;
    rsv_size_array = (unsigned int*) calloc ( p , sizeof(int));
    if (rsv_size_array==NULL){
         fprintf(stderr,"ERROR: cannot allocate memory for rsv_size_array\n");
         exit(1);
    }
}
 
 
void task_traffic_init (char * str) {
    load_traffic_file(str,task_graph_data,task_graph_abstract);
    end_sim_pck_num=task_graph_total_pck_num;
    MIN_PACKET_SIZE = task_graph_min_pck_size;
    MAX_PACKET_SIZE = task_graph_max_pck_size;
    AVG_PACKET_SIZE=(MIN_PACKET_SIZE+MAX_PACKET_SIZE)/2;// average packet size
    int p=(MAX_PACKET_SIZE-MIN_PACKET_SIZE)+1;
    rsv_size_array = (unsigned int*) calloc ( p , sizeof(int));
    if (rsv_size_array==NULL){
        fprintf(stderr,"ERROR: cannot allocate (%d x int) memory for rsv_size_array. \n",p);
        exit(1);
    }
}
 
 
 
 
 
 
 
void processArgs (int argc, char **argv ){
    int i;
 
    mcast.ratio=50;
    mcast.min= MIN_PCK_SIZE;
    mcast.max= (B > LB)? LB : B;
 
    for( i = 1; i < argc; ++i ) {
        if( strcmp(argv[i], "-t") == 0 ) {
            synthetic_task_processArgs ( argc, argv );
            return;
        } else if( strcmp(argv[i], "-f") == 0 ) {
            synthetic_task_processArgs ( argc, argv );
            return;
 
        } else if( strcmp(argv[i], "-F") == 0 ) {
            netrace_processArgs (argc, argv );
            return;
        } else if ( strcmp(argv[i], "-S") == 0 ) {
            synful_processArgs (argc, argv );
            return;
        }
    }
    fprintf (stderr, "You should pass one of the Synthetic-, Task-, Synfull- or Nettrace- based simulation as input argument. \n");
    usage(argv[0]);
    exit(1);
}
 
 
int get_new_pck_size(){
        if(pck_size_sel ==  RANDOM_discrete){
                int rnd = rand() % 100; // 0~99
                int i=0;
                while( rnd > discrete_prob[i] ) i++;
                return discrete_size [i];
        }
        //random range
        return rnd_between(MIN_PACKET_SIZE,MAX_PACKET_SIZE);
}
 
 
 
 
 
 
void traffic_gen_final_report(){
    int i;
    for (i=0;i<NE;i++) if(traffic[i]->pck_number>0) total_active_endp       =     total_active_endp +1;
    printf("\nsimulation results-------------------\n");
    printf("\tSimulation clock cycles:%d\n",clk_counter);
    printf("\n\tTotal received packet in different size:\n");
    printf("\tflit_size,");
    for (i=0;i<=(MAX_PACKET_SIZE - MIN_PACKET_SIZE);i++){
        if(rsv_size_array[i]>0) printf("%u,",i+ MIN_PACKET_SIZE);
    }
    printf("\n\t#pck,");
    for (i=0;i<=(MAX_PACKET_SIZE - MIN_PACKET_SIZE);i++){
           if(rsv_size_array[i]>0) printf("%u,",rsv_size_array[i]);
    }
    printf("\n");
 
//    printf(" total received flits:%d\n",total_rsv_flit_number);
//    printf(" total sent flits:%d\n",total_sent_flit_number);
    print_statistic_new (clk_counter);
 
}
 
 
void traffic_gen_init( void ){
    int i;
    unsigned int dest_e_addr;
    for (i=0;i<NE;i++){
            unsigned char inject_en;
            random_var[i] = 100;
            traffic[i]->current_e_addr        = endp_addr_encoder(i);
            traffic[i]->start=0;
            traffic[i]->pck_class_in=  pck_class_in_gen( i);
            traffic[i]->pck_size_in=get_new_pck_size();
            pck_dst_gen (i, &inject_en);
            //traffic[i]->dest_e_addr= dest_e_addr;
            if(inject_en == 0) traffic[i]->stop=1;
            //printf("src=%u, des_eaddr=%x, dest=%x\n", i,dest_e_addr, endp_addr_decoder(dest_e_addr));
            if(inject_done) traffic[i]->stop=1;
            traffic[i]->start_delay=rnd_between(10,500);
            if(TRAFFIC_TYPE==SYNTHETIC){
                //traffic[i]->avg_pck_size_in=AVG_PACKET_SIZE;
                traffic[i]->ratio=ratio;
                traffic[i]->init_weight=1;
            }
    }
}
 
void pck_inj_init (int model_node_num){
    int i,tmp;
    for (i=0;i<NE;i++){
           pck_inj[i]->current_e_addr        = endp_addr_encoder(i);
           pck_inj[i]->pck_injct_in_ready= (0x1<<V)-1;
           pck_inj[i]->pck_injct_in_pck_wr=0;
    }
    std::cout << "Node mapping---------------------" << std::endl;
    std::cout << "\tMapping " << model_node_num << " " << TRAFFIC  << " Nodes to " << NE << " ProNoC Nodes" << std::endl;
    std::cout << "\t" << TRAFFIC  << "\tID \t<-> ProNoC ID "<< std::endl;
    traffic_model_mapping = (int *) malloc( model_node_num * sizeof(int));
    for (i=0;i<model_node_num;i++){
    //TODO mapping should be done according to number of NE and should be set by the user later
               if(NE<=model_node_num){
                   // we have less or equal number of injectors in traffic model thatn the number of modes in ProNoC
                   // So we need to map multiples injector nodes from the model to one packet injector
                   tmp = ((i* NE)/model_node_num);
                   traffic_model_mapping[i]=tmp;
               } else {
                   // we have more endpoints that what is defined in the model
                   if(i<model_node_num) traffic_model_mapping[i]=i;
               }
               std::cout<< "\t\t" << i << "\t<->\t"  << tmp << std::endl;
 
    }
    std::cout << "Node mapping---------------------" << std::endl;
}
 
/*************
 * sc_time_stamp
 *
 * **********/
double sc_time_stamp () {       // Called by $time in Verilog
    return main_time;
}
 
int pow2( int num){
    int pw;
    pw= (0x1 << num);
    return pw;
}
 
/*
volatile int *  lock;
unsigned int  nr_per_thread=0;
unsigned int  ne_per_thread=0;
 
void thread_function (int n){
    int i;
    unsigned int node=0;
    while(1){
        while(lock[n]==0) std::this_thread::yield();
        for(i=0;i<nr_per_thread;i++){
            node= (n * nr_per_thread)+i;
            if (node >= NR) break;
            single_router_eval(node);
        }
        for(i=0;i<ne_per_thread;i++){
            node= (n * ne_per_thread)+i;
            if (node >= NE) break;
            if( TRAFFIC_TYPE == NETRACE)   pck_inj[node]->eval();
            else   traffic[node]->eval();
        }
 
        //router1[n]->eval();
        //if( TRAFFIC_TYPE == NETRACE)   pck_inj[n]->eval();
        //else   traffic[n]->eval();
 
        lock[n]=0;
        if(n==0) break;//first thread is the main process
    }
}
*/
 
class alignas(64) Vthread
{
    // Access specifier
    public:
    std::atomic<bool> eval;
    std::atomic<bool> copy;
    std::atomic<bool> update;
    // Data Members
    int n;//thread num
    int nr_per_thread;
    int ne_per_thread;
    // Member Functions()
    //Parameterized Constructor
 
 
    void function ( ){
        int i;
        unsigned int node=0;
        while(1){
            while(!eval && !copy && !update) std::this_thread::yield();
            if(eval){
                //connect_clk_reset_start
                for(i=0;i<ne_per_thread;i++){
                    node= (n * ne_per_thread)+i;
                    if (node >= NE) break;
                    if(ENDP_TYPE == PCK_INJECTOR){
                        pck_inj[node]->reset= reset;
                        pck_inj[node]->clk    = clk;
                    }
                    else {
                        traffic[node]->start= start_i;
                        traffic[node]->reset= reset;
                        traffic[node]->clk    = clk;
                    }
                }//endp
                for(i=0;i<nr_per_thread;i++){
                    node= (n * nr_per_thread)+i;
                    if (node >= NR) break;
                    //if(router_is_active[node] | (Quick_sim_en==0))
                    single_router_reset_clk(node);
                }
 
                //eval
                for(i=0;i<nr_per_thread;i++){
                    node= (n * nr_per_thread)+i;
                    if (node >= NR) break;
                    //if(router_is_active[node] | (Quick_sim_en==0))
                    single_router_eval(node);
                }
                for(i=0;i<ne_per_thread;i++){
                    node= (n * ne_per_thread)+i;
                    if (node >= NE) break;
                    if(ENDP_TYPE == PCK_INJECTOR)   pck_inj[node]->eval();
                    else   traffic[node]->eval();
                }
                eval=false;
            }
 
            if(copy){
                for  (int i=0;   i<R2R_TABLE_SIZ; i++) {
                    if(
                    r2r_cnt_all[i].id1 >= (n * nr_per_thread)
                    &&
                    r2r_cnt_all[i].id1 <  ((n+1) * nr_per_thread)
                    )
                    topology_connect_r2r(i);
                }
 
 
                for(i=0;i<ne_per_thread;i++){
                    node= (n * ne_per_thread)+i;
                    if (node >= NE) break;
                    topology_connect_r2e(node);
                }
                copy=false;
            }
 
            if(update){
                for(i=0;i<nr_per_thread;i++){
                    node= (n * nr_per_thread)+i;
                    if (node >= NR) break;
                    single_router_st_update(node);
                }
                update=false;
            }
 
            //router1[n]->eval();
            //if( TRAFFIC_TYPE == NETRACE)   pck_inj[n]->eval();
            //else   traffic[n]->eval();
 
 
            if(n==0) break;//first thread is the main process
        }
    }
 
    Vthread(int x,int r,int e)
    {
       n=x; nr_per_thread=r; ne_per_thread=e;
       eval=false;
       copy =false;
       update=false;
       if(n!=0) {
         std::thread th {&Vthread::function,this};
         th.detach();
       }
    }
 
 
};
 
Vthread ** thread;
 
void initial_threads (void){
    int i;
    //devide nodes equally between threads
    unsigned int  nr_per_thread=0;
    unsigned int  ne_per_thread=0;
    nr_per_thread = (NR % thread_num)?  (unsigned int)(NR/thread_num) + 1 :  (unsigned int)(NR/thread_num);
    ne_per_thread = (NE % thread_num)?  (unsigned int)(NE/thread_num) + 1 :  (unsigned int)(NE/thread_num);
 
    //std::vector<std::thread> threads(thread_num-1);
    //lock = new int[thread_num];
    //for(i=0;i<thread_num;i++) lock [i]=0;
 
    //Dynamically Allocating Memory
    thread = (Vthread **) new Vthread * [thread_num];
    for(i=0;i<thread_num;i++) thread[i] = new Vthread(i,nr_per_thread,ne_per_thread) ;
 
    //initiates (thread_num-1) number of live thread
    //for(i=0;i<thread_num-1;i++) threads[i] = std::thread(&thread_function, (i+1));
    //for (auto& th : threads)    th.detach();
 
    unsigned maxThreads = std::thread::hardware_concurrency();
    printf("Thread is initiated as following:\n"
    "\tMax hardware supported threads:%u\n"
    "\tthread_num:%u\n"
    "\trouter per thread:%u\n"
    "\tendpoint per thread:%u\n"
    ,maxThreads,thread_num,nr_per_thread,ne_per_thread);
}
 
 
 
 
void sim_eval_all (void){
    int i;
    if(thread_num>1) {
        for(i=0;i<thread_num;i++) thread[i]->eval=true;
        //thread_function (0);
        thread[0]->function();
        for(i=0;i<thread_num;i++)while(thread[i]->eval);
    }else{// no thread
 
        connect_clk_reset_start_all();
 
        //routers_eval();
        for(i=0;i<NR;i++){
            //if(router_is_active[i] | (Quick_sim_en==0))
            single_router_eval(i);
        }
        if(ENDP_TYPE == PCK_INJECTOR) for(i=0;i<NE;i++) pck_inj[i]->eval();
        else for(i=0;i<NE;i++) traffic[i]->eval();
    }
}
 
 
void topology_connect_all_nodes (void){
 
 
    int i;
    if(thread_num>1) {
        for(i=0;i<thread_num;i++) thread[i]->copy=true;
        //thread_function (0);
        thread[0]->function();
        for(i=0;i<thread_num;i++){
            while(thread[i]->copy==true);
        }
        return;
    }//no thread
    for  (int n=0; n<R2R_TABLE_SIZ; n++) {
        topology_connect_r2r(n);
    }
 
    for (int n=0;n<NE; n++){
        topology_connect_r2e(n);
    }
}
 
 
void sim_final_all (void){
    int i;
    routers_final();
    if(ENDP_TYPE == PCK_INJECTOR) for(i=0;i<NE;i++) pck_inj[i]->final();
    else for(i=0;i<NE;i++) traffic[i]->final();
    //noc->final();
}
 
void connect_clk_reset_start_all(void){
    int i;
    //noc-> clk = clk;
    //noc-> reset = reset;
    if(ENDP_TYPE == PCK_INJECTOR) {
        for(i=0;i<NE;i++)    {
            pck_inj[i]->reset= reset;
            pck_inj[i]->clk    = clk;
        }
    }else {
        for(i=0;i<NE;i++)    {
            traffic[i]->start= start_i;
            traffic[i]->reset= reset;
            traffic[i]->clk    = clk;
        }
    }
    connect_routers_reset_clk();
}
 
 
void traffic_clk_negedge_event(void){
    int i;
    clk = 0;
    //for (i=0;i<NR;i++) router_is_active [i]=0;
    topology_connect_all_nodes ();
 
    for (i=0;i<NE;i++){
        if(inject_done) traffic[i]->stop=1;
    }
 
    sim_eval_all();
}
 
void update_traffic_injector_st (unsigned int i){
    unsigned char inject_en;
    // a packet has been received
    if(traffic[i]->update & (main_time-saved_time >= 10 )){
        total_rsv_pck_num+=1;
        update_noc_statistic (i) ;
    }
    // the header flit has been sent out
    if(traffic[i]->hdr_flit_sent ){
        traffic[i]->pck_class_in=  pck_class_in_gen( i);
        traffic[i]->pck_size_in=get_new_pck_size();
        if((!FIXED_SRC_DST_PAIR)| (!IS_UNICAST)){
            pck_dst_gen (i, &inject_en);
            //traffic[i]->dest_e_addr= dest_e_addr;
            if(inject_en == 0) traffic[i]->stop=1;
            //printf("src=%u, dest=%x\n", i,endp_addr_decoder(dest_e_addr));
        }
    }
 
    if(traffic[i]->flit_out_wr==1){
        total_sent_flit_number++;
        if (!IS_UNICAST){
            total_expect_rsv_flit_num+=traffic[i]->mcast_dst_num_o;
        }else{
            total_expect_rsv_flit_num++;
        }
        #if (C>1)
            sent_stat [i][traffic[i]->flit_out_class].flit_num++;
        #else
        sent_stat [i].flit_num++;
        #endif
    }
 
    if(traffic[i]->flit_in_wr==1){
        total_rsv_flit_number++;
    }
 
    if(traffic[i]->hdr_flit_sent==1){
        total_sent_pck_num++;
        #if (C>1)
            sent_stat [i][traffic[i]->flit_out_class].pck_num++;
        #else
            sent_stat [i].pck_num++;
        #endif
    }
}
 
void update_all_traffic_injector_st(){
    for (int i=0;i<NE;i++){
            update_traffic_injector_st(i);
        }
 
}
 
 
 
void traffic_clk_posedge_event(void) {
    int i;
    unsigned int dest_e_addr;
 
    clk = 1;       // Toggle clock
    if(count_en) clk_counter++;
    inject_done= ((total_sent_pck_num >= end_sim_pck_num) || (clk_counter>= sim_end_clk_num) || total_active_routers == 0);
    //if(inject_done) printf("clk_counter=========%d\n",clk_counter);
    total_rsv_flit_number_old=total_rsv_flit_number;
    update_all_router_stat();
    update_all_traffic_injector_st();
 
    if(inject_done){
        if(total_rsv_flit_number_old == total_rsv_flit_number){
            ideal_rsv_cnt++;
            if(ideal_rsv_cnt >= NE*10){
                traffic_gen_final_report( );
                fprintf(stderr,"ERROR: The number of expected (%u) & received flits (%u) were not equal at the end of simulation\n",total_expect_rsv_flit_num, total_rsv_flit_number);
                exit(1);
            }
        }else ideal_rsv_cnt=0;
        if(total_expect_rsv_flit_num == total_rsv_flit_number ) simulation_done=1;
    }
 
    sim_eval_all();
 
}
 
 
/**********************************
 *
 *     update_noc_statistic
 *
 *
 *********************************/
 
void update_rsvd_st (
        statistic_t *     rsvd_stat,
        unsigned int       clk_num_h2h,
        unsigned int    clk_num_h2t,
        unsigned int     latency,
        unsigned int    distance,
        unsigned int    pck_size
 
) {
    rsvd_stat->pck_num ++;
    rsvd_stat->flit_num+=  pck_size;
    rsvd_stat->sum_clk_h2h +=(double)clk_num_h2h;
    rsvd_stat->sum_clk_h2t +=(double)clk_num_h2t;
    rsvd_stat->sum_clk_per_hop+= ((double)clk_num_h2h/(double)distance);
    if (rsvd_stat->worst_latency < latency ) rsvd_stat->worst_latency=latency;
    if (rsvd_stat->min_latency==0          ) rsvd_stat->min_latency  =latency;
    if (rsvd_stat->min_latency   > latency ) rsvd_stat->min_latency  =latency;
    #if (STND_DEV_EN)
          rsvd_stat->sum_clk_pow2 += (double)clk_num_h2h * (double) clk_num_h2h;
    #endif
}
 
void update_sent_st (
    statistic_t *  sent_stat,
    unsigned int     latency
) {
 
    if (sent_stat->worst_latency < latency ) sent_stat->worst_latency=latency;
    if (sent_stat->min_latency==0          ) sent_stat->min_latency  =latency;
    if (sent_stat->min_latency   > latency ) sent_stat->min_latency  =latency;
 
}
 
 
void update_statistic_at_ejection (
    int    core_num,
    unsigned int       clk_num_h2h,
    unsigned int    clk_num_h2t,
    unsigned int    distance,
    unsigned int      class_num,
    unsigned int     src,
    unsigned int    pck_size
    ){
 
 
 
    if(ENDP_TYPE == TRFC_INJECTOR) {
        if( traffic[core_num]->pck_size_o >= MIN_PACKET_SIZE && traffic[core_num]->pck_size_o <=MAX_PACKET_SIZE){
              if(rsv_size_array!=NULL)     rsv_size_array[traffic[core_num]->pck_size_o-MIN_PACKET_SIZE]++;
        }
    }
 
    if(verbosity==0 && ( TRAFFIC_TYPE == NETRACE || TRAFFIC_TYPE ==SYNFUL)) if((total_rsv_pck_num & 0X1FFFF )==0 ) printf(" packet sent total=%d\n",total_rsv_pck_num);
    unsigned int latency = (strcmp (AVG_LATENCY_METRIC,"HEAD_2_TAIL")==0)? clk_num_h2t :  clk_num_h2h;
    #if(C>1)
        update_rsvd_st ( &rsvd_stat[core_num][class_num],      clk_num_h2h,   clk_num_h2t,     latency,    distance,pck_size);
        update_sent_st ( &sent_stat[src     ][class_num],      latency);
    #else
        update_rsvd_st ( &rsvd_stat[core_num], clk_num_h2h,   clk_num_h2t,     latency,    distance,pck_size);
        update_sent_st ( &sent_stat[src     ], latency);
    #endif
 
    update_rsvd_st ( &endp_to_endp[src][core_num],      clk_num_h2h,   clk_num_h2t,     latency,    distance, pck_size);
 
}
 
 
 
 
 
void update_noc_statistic (    int    core_num){
    unsigned int       clk_num_h2h =traffic[core_num]->time_stamp_h2h;
    unsigned int    clk_num_h2t =traffic[core_num]->time_stamp_h2t;
    unsigned int    distance=traffic[core_num]->distance;
    unsigned int      class_num=traffic[core_num]->pck_class_out;
    unsigned int    src_e_addr=traffic[core_num]->src_e_addr;
    unsigned int     src = endp_addr_decoder (src_e_addr);
    unsigned int    pck_size = traffic[core_num]-> pck_size_o;
    update_statistic_at_ejection ( core_num,    clk_num_h2h,  clk_num_h2t,  distance,      class_num,     src,pck_size);
 
 
}
 
avg_st_t finilize_statistic (unsigned long int total_clk, statistic_t rsvd_stat){
 
     avg_st_t avg_statistic;
     avg_statistic.avg_throughput= ((double)(rsvd_stat.flit_num*100)/NE )/total_clk;
     avg_statistic.avg_latency_flit    = rsvd_stat.sum_clk_h2h/rsvd_stat.pck_num;
     avg_statistic.avg_latency_pck       = rsvd_stat.sum_clk_h2t/rsvd_stat.pck_num;
     avg_statistic.avg_latency_per_hop = ( rsvd_stat.pck_num==0)? 0 : rsvd_stat.sum_clk_per_hop/rsvd_stat.pck_num;
     avg_statistic.avg_pck_siz        = ( rsvd_stat.pck_num==0)? 0 : (double)(rsvd_stat.flit_num / rsvd_stat.pck_num);
     #if (STND_DEV_EN)
          avg_statistic.std_dev =standard_dev( rsvd_stat.sum_clk_pow2,rsvd_stat.pck_num, avg_statistic.avg_latency_flit);
     #endif
     return avg_statistic;
}
 
template<typename T>
    void myout(T value)
    {
       std::cout << value << std::endl;
    }
template<typename First, typename ... Rest>
    void myout(First first, Rest ... rest)
    {
       std::cout << first << ",";
       myout(rest...);
    }
 
void print_st_single (unsigned long int total_clk, statistic_t rsvd_stat, statistic_t sent_stat){
 
 
 
    avg_st_t avg;
    avg=finilize_statistic (total_clk,  rsvd_stat);
 
    myout(
            sent_stat.pck_num,
            rsvd_stat.pck_num,
            sent_stat.flit_num,
            rsvd_stat.flit_num,
            sent_stat.worst_latency,
            rsvd_stat.worst_latency,
            sent_stat.min_latency,
            rsvd_stat.min_latency,
            avg.avg_latency_per_hop,
            avg.avg_latency_flit,
            avg.avg_latency_pck,
            avg.avg_throughput,
            avg.avg_pck_siz,
            #if (STND_DEV_EN)
            avg.std_dev
            #endif
    );
//    printf("\n");
 
}
 
 
void merge_statistic (statistic_t * merge_stat, statistic_t stat_in){
    merge_stat->pck_num+=stat_in.pck_num;
    merge_stat->flit_num+=stat_in.flit_num;
    if(merge_stat->worst_latency <  stat_in.worst_latency) merge_stat->worst_latency= stat_in.worst_latency;
    if(merge_stat->min_latency   == 0                       ) merge_stat->min_latency  = stat_in.min_latency;
    if(merge_stat->min_latency   > stat_in.min_latency  && stat_in.min_latency!=0   ) merge_stat->min_latency  = stat_in.min_latency;
    merge_stat->sum_clk_h2h      +=stat_in.sum_clk_h2h    ;
    merge_stat->sum_clk_h2t      +=stat_in.sum_clk_h2t    ;
    merge_stat->sum_clk_per_hop  +=stat_in.sum_clk_per_hop;
    #if (STND_DEV_EN)
        merge_stat->sum_clk_pow2 +=stat_in.sum_clk_pow2;
    #endif
 
}
 
void print_statistic_new (unsigned long int total_clk){
    int i;
 
 
    print_router_st();
    print_endp_to_endp_st("pck_num");
    print_endp_to_endp_st("flit_num");
 
    printf( "\n\tEndpoints Statistics:\n"
            "\t#EID,"
            "sent_stat.pck_num,"
            "rsvd_stat.pck_num,"
            "sent_stat.flit_num,"
            "rsvd_stat.flit_num,"
            "sent_stat.worst_latency,"
            "rsvd_stat.worst_latency,"
            "sent_stat.min_latency,"
            "rsvd_stat.min_latency,"
            "avg_latency_per_hop,"
            "avg_latency_flit,"
            "avg_latency_pck,"
            "avg_throughput(%%),"
            "avg_pck_size,"
            #if (STND_DEV_EN)
            "avg.std_dev"
            #endif
            "\n");
 
 
 
#if(C>1)
    int c;
    statistic_t sent_stat_class [NE];
    statistic_t rsvd_stat_class [NE];
    statistic_t sent_stat_per_class [C];
    statistic_t rsvd_stat_per_class [C];
 
    memset (&rsvd_stat_class,0,sizeof(statistic_t)*NE);
    memset (&sent_stat_class,0,sizeof(statistic_t)*NE);
    memset (&rsvd_stat_per_class,0,sizeof(statistic_t)*C);
    memset (&sent_stat_per_class,0,sizeof(statistic_t)*C);
 
 
    for (i=0; i<NE;i++){
        for (c=0; c<C;c++){
            merge_statistic (&rsvd_stat_class[i],rsvd_stat[i][c]);
            merge_statistic (&sent_stat_class[i],sent_stat[i][c]);
            merge_statistic (&rsvd_stat_per_class[c],rsvd_stat[i][c]);
            merge_statistic (&sent_stat_per_class[c],sent_stat[i][c]);
        }
    }
 
 
 
 
#else
    #define sent_stat_class  sent_stat
    #define rsvd_stat_class  rsvd_stat
#endif
 
 
 
 
 
    statistic_t rsvd_stat_total, sent_stat_total;
    memset (&rsvd_stat_total,0,sizeof(statistic_t));
    memset (&sent_stat_total,0,sizeof(statistic_t));
    for (i=0; i<NE;i++){
        merge_statistic (&rsvd_stat_total,rsvd_stat_class[i]);
        merge_statistic (&sent_stat_total,sent_stat_class[i]);
    }
    printf("\ttotal,");
    print_st_single (total_clk, rsvd_stat_total,sent_stat_total);
 
#if(C>1)
    for (c=0; c<C;c++){
        printf("\ttotal_class%u,",c);
        print_st_single (total_clk, rsvd_stat_per_class[c],sent_stat_per_class[c]);
    }
#endif
 
    for (i=0; i<NE;i++){
        printf("\t%u,",i);
        print_st_single (total_clk, rsvd_stat_class[i],sent_stat_class[i] );
    }
 
 
 
 
 
}
 
 
 
 
 
 
 
void print_parameter (){
    printf ("NoC parameters:---------------- \n");
    printf ("\tTopology: %s\n",TOPOLOGY);
    printf ("\tRouting algorithm: %s\n",ROUTE_NAME);
    printf ("\tVC_per port: %d\n", V);
    printf ("\tNon-local port buffer_width per VC: %d\n", B);
    printf ("\tLocal port buffer_width per VC: %d\n", LB);
 
    #if defined (IS_MESH) || defined (IS_FMESH) || defined (IS_TORUS)
        printf ("\tRouter num in row: %d \n",T1);
        printf ("\tRouter num in column: %d \n",T2);
        printf ("\tEndpoint num per router: %d\n",T3);
    #elif defined (IS_LINE) || defined (IS_RING )
        printf ("\tTotal Router num: %d \n",T1);
        printf ("\tEndpoint num per router: %d\n",T3);
    #elif defined (IS_FATTREE) || defined (IS_TREE)
        printf ("\tK: %d \n",T1);
        printf ("\tL: %d \n",T2);
    #elif defined (IS_STAR)
        printf ("\tTotal Endpoints number: %d \n",T1);
    #else//CUSTOM
        printf ("\tTotal Endpoints number: %d \n",T1);
        printf ("\tTotal Routers number: %d \n",T2);
    #endif
 
    printf ("\tNumber of Class: %d\n", C);
    printf ("\tFlit data width: %d \n", Fpay);
    printf ("\tVC reallocation mechanism: %s \n",  VC_REALLOCATION_TYPE);
    printf ("\tVC/sw combination mechanism: %s \n", COMBINATION_TYPE);
    printf ("\tAVC_ATOMIC_EN:%d \n", AVC_ATOMIC_EN);
    printf ("\tCongestion Index:%d \n",CONGESTION_INDEX);
    printf ("\tADD_PIPREG_AFTER_CROSSBAR:%d\n",ADD_PIPREG_AFTER_CROSSBAR);
    printf ("\tSSA_EN enabled:%s \n",SSA_EN);
    printf ("\tSwitch allocator arbitration type:%s \n",SWA_ARBITER_TYPE);
    printf ("\tMinimum supported packet size:%d flit(s) \n",MIN_PCK_SIZE);
    printf ("\tLoop back is enabled:%s \n",SELF_LOOP_EN);
    printf ("\tNumber of multihop bypass (SMART max):%d \n",SMART_MAX);
    printf ("\tCastying type:%s.\n",CAST_TYPE);
    if (IS_MCAST_PARTIAL){
        printf ("\tCAST LIST:%s\n",MCAST_ENDP_LIST);
    }
    printf ("NoC parameters:---------------- \n");
    printf ("\nSimulation parameters-------------\n");
    #if(DEBUG_EN)
        printf ("\tDebuging is enabled\n");
    #else
        printf ("\tDebuging is disabled\n");
    #endif   
 
    //if(strcmp (AVG_LATENCY_METRIC,"HEAD_2_TAIL")==0)printf ("\tOutput is the average latency on sending the packet header until receiving tail\n");
    //else printf ("\tOutput is the average latency on sending the packet header until receiving header flit at destination node\n");
    printf ("\tTraffic pattern:%s\n",TRAFFIC);
    size_t n = sizeof(class_percentage)/sizeof(class_percentage[0]);
    for(int p=0;p<n; p++){
        printf ("\ttraffic percentage of class %u is : %d\n",p,  class_percentage[p]);
    }
    if(strcmp (TRAFFIC,"HOTSPOT")==0){
        //printf ("\tHot spot percentage: %u\n", HOTSPOT_PERCENTAGE);
        printf ("\tNumber of hot spot cores: %d\n", HOTSPOT_NUM);
    }
    if (strcmp (CAST_TYPE,"UNICAST")){
        printf ("\tMULTICAST traffic ratio: %d(%%), min: %d, max: %d\n", mcast.ratio,mcast.min,mcast.max);
    }
 
 
    //printf ("\tTotal packets sent by one router: %u\n", TOTAL_PKT_PER_ROUTER);
    if(sim_end_clk_num!=0) printf ("\tSimulation timeout =%d\n", sim_end_clk_num);
    if(end_sim_pck_num!=0) printf ("\tSimulation ends on total packet num of =%d\n", end_sim_pck_num);
    if(TRAFFIC_TYPE!=NETRACE && TRAFFIC_TYPE!=SYNFUL){
        printf ("\tPacket size (min,max,average) in flits: (%u,%u,%u)\n",MIN_PACKET_SIZE,MAX_PACKET_SIZE,AVG_PACKET_SIZE);
        printf ("\tPacket injector FIFO width in flit:%u \n",TIMSTMP_FIFO_NUM);
    }
    if( TRAFFIC_TYPE == SYNTHETIC) printf("\tFlit injection ratio per router is =%f (flits/clk/Total Endpoint %%)\n",(float)ratio*100/MAX_RATIO);
    printf ("Simulation parameters-------------\n");
 
 
 
}
 
 
 
 
 
/************************
 *
 *     reset system
 *
 *
 * *******************/
 
void reset_all_register (void){
    int i;
     total_active_endp=0;
     total_rsv_pck_num=0;
     total_sent_pck_num=0;
     sum_clk_h2h=0;
     sum_clk_h2t=0;
     ideal_rsv_cnt=0;
#if (STND_DEV_EN)
     sum_clk_pow2=0;
#endif
 
     sum_clk_per_hop=0;
     count_en=0;
     clk_counter=0;
 
     for(i=0;i<C;i++)
     {
         total_rsv_pck_num_per_class[i]=0;
         sum_clk_h2h_per_class[i]=0;
         sum_clk_h2t_per_class[i]=0;
          sum_clk_per_hop_per_class[i]=0;
#if (STND_DEV_EN)
          sum_clk_pow2_per_class[i]=0;
#endif
 
     }  //for
     total_sent_flit_number=0;
     total_expect_rsv_flit_num=0;
 
 
}
 
 
 
 
/***********************
 *
 *     standard_dev
 *
 * ******************/
 
#if (STND_DEV_EN)
/************************
 * std_dev = sqrt[(B-A^2/N)/N]  = sqrt [(B/N)- (A/N)^2] = sqrt [B/N - mean^2]
 * A = sum of the values
 * B = sum of the squarded values
 * *************/
 
double standard_dev( double sum_pow2, unsigned int  total_num, double average){
    double std_dev;
 
    /*
    double  A, B, N;
    N= total_num;
    A= average * N;
    B= sum_pow2;
 
    A=(A*A)/N;
    std_dev = (B-A)/N;
    std_dev = sqrt(std_dev);
*/
    if(total_num==0) return 0;
 
    std_dev = sum_pow2/(double)total_num; //B/N
    std_dev -= (average*average);// (B/N) - mean^2
    std_dev = sqroot(std_dev);// sqrt [B/N - mean^2]
 
    return std_dev;
 
}
 
#endif
 
 
 
/**********************
 *
 *    pck_class_in_gen
 *
 * *****************/
 
unsigned char  pck_class_in_gen(
     unsigned int  core_num
 
) {
    unsigned char pck_class_in;
    unsigned char  rnd=rand()%100;
    int c=0;
    int sum=class_percentage[0];
    size_t n = sizeof(class_percentage)/sizeof(class_percentage[0]);
    for(;;){
        if( rnd < sum) return c;
        if( c==n-1 ) return c;
        c++;
        sum+=class_percentage[c];
    }
    return 0;
}
 
 
 
 
void update_injct_var(unsigned int src,  unsigned int injct_var){
    //printf("before%u=%u\n",src,random_var[src]);
    random_var[src]= rnd_between(100-injct_var, 100+injct_var);
    //printf("after=%u\n",random_var[src]);
}
 
unsigned int pck_dst_gen_task_graph ( unsigned int src, unsigned char * inject_en){
     task_t  task;
    float f,v;
    *inject_en=1;
    int index = task_graph_abstract[src].active_index;
 
    if(index == DISABLE){
        traffic[src]->ratio=0;
        traffic[src]->stop=1;
        *inject_en=0;
        return INJECT_OFF; //disable sending
    }
 
    if(    read(task_graph_data[src],index,&task)==0){
        traffic[src]->ratio=0;
        traffic[src]->stop=1;
        *inject_en=0;
        return INJECT_OFF; //disable sending
 
    }
 
#if (C>1)
    if(sent_stat[src][traffic[src]->flit_out_class].pck_num & 0xFF){//sent 255 packets
#else
    if(sent_stat[src].pck_num & 0xFF){//sent 255 packets
#endif
 
            //printf("uu=%u\n",task.jnjct_var);
            update_injct_var(src, task.jnjct_var);
 
        }
 
    task_graph_total_pck_num++;
    task.pck_sent = task.pck_sent +1;
    task.burst_sent= task.burst_sent+1;
    task.byte_sent = task.byte_sent + (task.avg_pck_size * (Fpay/8) );
 
    traffic[src]->pck_class_in=  pck_class_in_gen(src);
    //traffic[src]->avg_pck_size_in=task.avg_pck_size;
    traffic[src]->pck_size_in=rnd_between(task.min_pck_size,task.max_pck_size);
 
    f=  task.injection_rate;
    v= random_var[src];
    f*= (v /100);
    if(f>100) f= 100;
    f=  f * MAX_RATIO / 100;
 
    traffic[src]->ratio=(unsigned int)f;
    traffic[src]->init_weight=task.initial_weight;
 
    if (task.burst_sent >= task.burst_size){
        task.burst_sent=0;
        task_graph_abstract[src].active_index=task_graph_abstract[src].active_index+1;
        if(task_graph_abstract[src].active_index>=task_graph_abstract[src].total_index) task_graph_abstract[src].active_index=0;
 
    }
 
    update_by_index(task_graph_data[src],index,task);
 
    if (task.byte_sent  >= task.bytes){ // This task is done remove it from the queue
                remove_by_index(&task_graph_data[src],index);
                task_graph_abstract[src].total_index = task_graph_abstract[src].total_index-1;
                if(task_graph_abstract[src].total_index==0){ //all tasks are done turned off the core
                    task_graph_abstract[src].active_index=-1;
                    traffic[src]->ratio=0;
                    traffic[src]->stop=1;
                    if(total_active_routers!=0) total_active_routers--;
                    *inject_en=0;
                    return INJECT_OFF;
                }
                if(task_graph_abstract[src].active_index>=task_graph_abstract[src].total_index) task_graph_abstract[src].active_index=0;
    }
 
    return endp_addr_encoder(task.dst);
}
 
 
void update_all_router_stat(void){
    if(thread_num>1) {
        int i;
        for(i=0;i<thread_num;i++) thread[i]->update=true;
        //thread_function (0);
        thread[0]->function();
        for(i=0;i<thread_num;i++)while(thread[i]->update==true);
        return;
    }
    //no thread
    for (int i=0; i<NR; i++) single_router_st_update(i);
}
 
void update_router_st (
        unsigned int Pnum,
        unsigned int rid,
        void * event,
        size_t size
){
    unsigned int port_event;
 
    for (int p=0;p<Pnum;p++){
        if (size == sizeof(unsigned char)) {
            unsigned char * eventArr = (unsigned char *)event;
            port_event = eventArr[p];
        }
        if (size == sizeof(short int)) {
            unsigned short int * eventArr = (unsigned short int *)event;
            port_event = eventArr[p];
        }
        if (size == sizeof(int)) {
            unsigned int * eventArr = (unsigned int *)event;
            port_event = eventArr[p];
        }
 
 
        if(port_event & FLIT_IN_WR_FLG ) router_stat [rid][p].flit_num_in++;
        if(port_event & PCK_IN_WR_FLG  ) router_stat [rid][p].pck_num_in++;
        if(port_event & FLIT_OUT_WR_FLG) router_stat [rid][p].flit_num_out++;
        if(port_event & PCK_OUT_WR_FLG ) router_stat [rid][p].pck_num_out++;
        if(port_event & FLIT_IN_BYPASSED)router_stat [rid][p].flit_num_in_bypassed++;
        else if(port_event & FLIT_IN_WR_FLG){
            router_stat [rid][p].flit_num_in_buffered++;
            unsigned int bypassed_times = (port_event >> BYPASS_LSB);
            router_stat [rid][p].bypass_counter[bypassed_times]++;
        }
    }
}
 
 
void print_router_st (void) {
 
    //report router statistic
    printf("\n\n\tRouters' statistics:\n");
    printf("\t#RID, #Port,"
           "flit_in,"
           "pck_in,"
           "flit_out,"
        "pck_out,"
        "flit_in_buffered,"
        "flit_in_bypassed,"
    );
    if(SMART_MAX>0) for (int k=0;k<SMART_MAX+1;k++) printf("bypsd_%0d_times,",k);
    printf("\n");
 
    for (int i=0; i<NR; i++){
 
           for (int p=0;p<MAX_P;p++){
 
               printf("\t%u,%u,",i,p);
               printf("%d,%d,%d,%d,%d,%d,",
                router_stat [i][p].flit_num_in,
                router_stat [i][p].pck_num_in,
                router_stat [i][p].flit_num_out,
                router_stat [i][p].pck_num_out,
                router_stat [i][p].flit_num_in_buffered,
                router_stat [i][p].flit_num_in_bypassed
                );
            if(SMART_MAX>0) for (int k=0;k<SMART_MAX+1;k++) printf("%d," ,router_stat [i][p].bypass_counter[k]);
            printf("\n");
            router_stat_accum [i].flit_num_in              += router_stat [i][p].flit_num_in;
            router_stat_accum [i].pck_num_in               += router_stat [i][p].pck_num_in;
            router_stat_accum [i].flit_num_out             += router_stat [i][p].flit_num_out;
            router_stat_accum [i].pck_num_out              += router_stat [i][p].pck_num_out;
            router_stat_accum [i].flit_num_in_buffered     += router_stat [i][p].flit_num_in_buffered;
            router_stat_accum [i].flit_num_in_bypassed     += router_stat [i][p].flit_num_in_bypassed;
            if(SMART_MAX>0) for (int k=0;k<SMART_MAX+1;k++) router_stat_accum [i].bypass_counter[k]+= router_stat [i][p].bypass_counter[k];
 
           }
           printf("\t%u,total,",i);
           printf("%d,%d,%d,%d,%d,%d,",
        router_stat_accum [i].flit_num_in,
        router_stat_accum [i].pck_num_in,
        router_stat_accum [i].flit_num_out,
        router_stat_accum [i].pck_num_out,
        router_stat_accum [i].flit_num_in_buffered,
        router_stat_accum [i].flit_num_in_bypassed
           );
           if(SMART_MAX>0) for (int k=0;k<SMART_MAX+1;k++) printf("%d," , router_stat_accum [i].bypass_counter[k]);
           printf("\n");
      }
}
 
 
void print_endp_to_endp_st(const char * st)  {
    printf ("\n\tEndp_to_Endp %s:\n\t#EID,",st);
    for (int src=0; src<NE; src++) printf ("%u,",src);
    printf ("\n");
    for (int src=0; src<NE; src++){
        printf ("\t%u,",src);
        for (int dst=0;dst<NE;dst++){
            if(strcmp(st,"pck_num")==0)  printf("%u,",endp_to_endp[src][dst].pck_num);
            if(strcmp(st,"flit_num")==0) printf("%u,",endp_to_endp[src][dst].flit_num);
        }
        printf ("\n");
    }
}
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.