示例#1
0
int SIM_router_init(SIM_router_info_t *info, SIM_router_power_t *router_power, SIM_router_area_t *router_area)
{
    u_int line_width;
    int share_buf, outdrv;

    /* PHASE 1: set parameters */
    /* general parameters */
    info->n_in = PARM(in_port);
    info->n_cache_in = PARM(cache_in_port);//0 in our case
    info->n_mc_in = PARM(mc_in_port);//0 in our case
    info->n_io_in = PARM(io_in_port);//0 in our case
    info->n_total_in = PARM(in_port) + PARM(cache_in_port) + PARM(mc_in_port) + PARM(io_in_port);//equal to in_port
    info->n_out = PARM(out_port);
    info->n_cache_out = PARM(cache_out_port);//0 here
    info->n_mc_out = PARM(mc_out_port);//0 here
    info->n_io_out = PARM(io_out_port);//0 here
    info->n_total_out = PARM(out_port) + PARM(cache_out_port) + PARM(mc_out_port) + PARM(io_out_port);//equal to out_port
    info->flit_width = FLITSIZE*8;//FLITSIZE is defined in defaults.h and can be specified in nirgam.config in bytes

    /* virtual channel parameters */
    info->n_v_channel = MAX(PARM(v_channel), 1);
    info->n_v_class = MAX(PARM(v_class), 1);
    info->cache_class = MAX(PARM(cache_class), 1);//0 here
    info->mc_class = MAX(PARM(mc_class), 1); //0 here
    info->io_class = MAX(PARM(io_class), 1);//0 here
    /* shared buffer implies buffer has tags */
    /* separate buffer & shared switch implies buffer has tri-state output driver*/
    if (info->n_v_class * info->n_v_channel > 1)  //no sharing in our case
    {
        info->in_share_buf = PARM(in_share_buf);
        info->out_share_buf = PARM(out_share_buf);
        info->in_share_switch = PARM(in_share_switch);
        info->out_share_switch = PARM(out_share_switch);
    }
    else
    {
        info->in_share_buf = 0;
        info->out_share_buf = 0;
        info->in_share_switch = 0;
        info->out_share_switch = 0;
    }

    /* crossbar */
    info->crossbar_model = PARM(crossbar_model);
    info->degree = PARM(crsbar_degree);
    info->connect_type = PARM(connect_type);
    info->trans_type = PARM(trans_type);
    info->xb_in_seg = PARM(xb_in_seg);
    info->xb_out_seg = PARM(xb_out_seg);
    info->crossbar_in_len = PARM(crossbar_in_len);
    info->crossbar_out_len = PARM(crossbar_out_len);
    /* HACK HACK HACK */
    info->exp_xb_model = PARM(exp_xb_model);
    info->exp_in_seg = PARM(exp_in_seg);
    info->exp_out_seg = PARM(exp_out_seg);

    /* input buffer */
    info->in_buf = PARM(in_buf);//have i/p buffer or not, we have
    info->in_buffer_model = PARM(in_buffer_type);//can be SRAM or REGISTER
    if (info->in_buf)
    {
        outdrv = !info->in_share_buf && info->in_share_switch;//outdrv ??
        //NUM_BUFS is buffer depth, the 2nd parameter specifies whether buffer is fifo or not(1 means it is fifo)
        //parameters: router address, isfifo, no. of read ports, no. of write ports, buffer depth, data width in bits, outdrv, buffer model(SRAM or REGISTER)

        SIM_array_init(&info->in_buf_info, 1, PARM(in_buf_rport), 1, NUM_BUFS, FLITSIZE*8, outdrv, info->in_buffer_model);
        //this function in SIM_array_l.cpp
    }
    //no need for nirgam config.
    if (PARM(cache_in_port))
    {
        info->cache_in_buf = PARM(cache_in_buf);

        if (info->cache_in_buf)
        {
            if (PARM(cache_class) > 1)
            {
                share_buf = info->in_share_buf;
                outdrv = !share_buf && info->in_share_switch;
            }
            else
            {
                outdrv = share_buf = 0;
            }
            SIM_array_init(&info->cache_in_buf_info, 1, PARM(cache_in_buf_rport), 1, PARM(cache_in_buf_set), FLITSIZE*8, outdrv, SRAM);
        }
    }
    //no need for nirgam config.
    if (PARM(mc_in_port))
    {
        info->mc_in_buf = PARM(mc_in_buf);

        if (info->mc_in_buf)
        {
            if (PARM(mc_class) > 1)
            {
                share_buf = info->in_share_buf;
                outdrv = !share_buf && info->in_share_switch;
            }
            else
            {
                outdrv = share_buf = 0;
            }
            SIM_array_init(&info->mc_in_buf_info, 1, PARM(mc_in_buf_rport), 1, PARM(mc_in_buf_set),FLITSIZE*8, outdrv, SRAM);
        }
    }
    //not needed
    if (PARM(io_in_port))
    {
        info->io_in_buf = PARM(io_in_buf);

        if (info->io_in_buf)
        {
            if (PARM(io_class) > 1)
            {
                share_buf = info->in_share_buf;
                outdrv = !share_buf && info->in_share_switch;
            }
            else
            {
                outdrv = share_buf = 0;
            }
            SIM_array_init(&info->io_in_buf_info, 1, PARM(io_in_buf_rport), 1, PARM(io_in_buf_set), FLITSIZE*8, outdrv, SRAM);
        }
    }

    /* output buffer */
    info->out_buf = PARM(out_buf);
    info->out_buffer_model = PARM(out_buffer_type);
    if (info->out_buf)
    {
        /* output buffer has no tri-state buffer anyway */
        SIM_array_init(&info->out_buf_info, 1, 1, PARM(out_buf_wport), PARM(out_buf_set), FLITSIZE*8, 0, info->out_buffer_model);
    }
    //not needed
    /* central buffer */
    info->central_buf = PARM(central_buf);
    if (info->central_buf)
    {
        info->pipe_depth = PARM(pipe_depth);
        /* central buffer is no FIFO */
        SIM_array_init(&info->central_buf_info, 0, PARM(cbuf_rport), PARM(cbuf_wport), PARM(cbuf_set), PARM(cbuf_width) * FLITSIZE*8, 0, SRAM);
        /* dirty hack */
        info->cbuf_ff_model = NEG_DFF;
    }

    /* switch allocator input port arbiter */
    if (info->n_v_class * info->n_v_channel > 1)
    {
        if (info->sw_in_arb_model = PARM(sw_in_arb_model))
        {
            if (PARM(sw_in_arb_model) == QUEUE_ARBITER)
            {
                SIM_array_init(&info->sw_in_arb_queue_info, 1, 1, 1, info->n_v_class*info->n_v_channel, SIM_logtwo(info->n_v_class*info->n_v_channel), 0, REGISTER);
                if (info->cache_class > 1)
                    SIM_array_init(&info->cache_in_arb_queue_info, 1, 1, 1, info->cache_class, SIM_logtwo(info->cache_class), 0, REGISTER);
                if (info->mc_class > 1)
                    SIM_array_init(&info->mc_in_arb_queue_info, 1, 1, 1, info->mc_class, SIM_logtwo(info->mc_class), 0, REGISTER);
                if (info->io_class > 1)
                    SIM_array_init(&info->io_in_arb_queue_info, 1, 1, 1, info->io_class, SIM_logtwo(info->io_class), 0, REGISTER);

                info->sw_in_arb_ff_model = SIM_NO_MODEL;
            }
            else
                info->sw_in_arb_ff_model = PARM(sw_in_arb_ff_model);
        }
        else
            info->sw_in_arb_ff_model = SIM_NO_MODEL;
    }
    else
    {
        info->sw_in_arb_model = SIM_NO_MODEL;
        info->sw_in_arb_ff_model = SIM_NO_MODEL;
    }

    /* switch allocator output port arbiter */
    if (info->n_total_in > 2)
    {
        info->sw_out_arb_model = PARM(sw_out_arb_model);
        if (info->sw_out_arb_model)
        {
            if (info->sw_out_arb_model == QUEUE_ARBITER)
            {
                line_width = SIM_logtwo(info->n_total_in - 1);
                SIM_array_init(&info->sw_out_arb_queue_info, 1, 1, 1, info->n_total_in - 1, line_width, 0, REGISTER);
                info->sw_out_arb_ff_model = SIM_NO_MODEL;
            }
            else
            {
                info->sw_out_arb_ff_model = PARM(sw_out_arb_ff_model);
            }
        }
        else
        {
            info->sw_out_arb_ff_model = SIM_NO_MODEL;
        }
    }
    else
    {
        info->sw_out_arb_model = SIM_NO_MODEL;
        info->sw_out_arb_ff_model = SIM_NO_MODEL;
    }

    /* virtual channel allocator type */
    if (info->n_v_channel > 1)
    {
        info->vc_allocator_type = PARM(vc_allocator_type);
    }
    else
        info->vc_allocator_type = SIM_NO_MODEL;

    /* virtual channel allocator input port arbiter */
    if ( info->n_v_channel > 1 && info->n_in > 1)
    {
        if (info->vc_in_arb_model = PARM(vc_in_arb_model))
        {
            if (PARM(vc_in_arb_model) == QUEUE_ARBITER)
            {
                SIM_array_init(&info->vc_in_arb_queue_info, 1, 1, 1, info->n_v_channel, SIM_logtwo(info->n_v_channel), 0, REGISTER);
                info->vc_in_arb_ff_model = SIM_NO_MODEL;
            }
            else
            {
                info->vc_in_arb_ff_model = PARM(vc_in_arb_ff_model);
            }
        }
        else
        {
            info->vc_in_arb_ff_model = SIM_NO_MODEL;
        }
    }
    else
    {
        info->vc_in_arb_model = SIM_NO_MODEL;
        info->vc_in_arb_ff_model = SIM_NO_MODEL;
    }

    /* virtual channel allocator output port arbiter */
    if (info->n_in > 1 && info->n_v_channel > 1)
    {
        info->vc_out_arb_model = PARM(vc_out_arb_model);
        if (info->vc_out_arb_model)
        {
            if (info->vc_out_arb_model == QUEUE_ARBITER)
            {
                line_width = SIM_logtwo((info->n_total_in - 1)*info->n_v_channel);
                SIM_array_init(&info->vc_out_arb_queue_info, 1, 1, 1, (info->n_total_in -1) * info->n_v_channel, line_width, 0, REGISTER);
                info->vc_out_arb_ff_model = SIM_NO_MODEL;
            }
            else
            {
                info->vc_out_arb_ff_model = PARM(vc_out_arb_ff_model);
            }
        }
        else
        {
            info->vc_out_arb_ff_model = SIM_NO_MODEL;
        }
    }
    else
    {
        info->vc_out_arb_model = SIM_NO_MODEL;
        info->vc_out_arb_ff_model = SIM_NO_MODEL;
    }

    /*virtual channel allocation vc selection model */

    // for NIRGAM
    //total number of entries = Number of Vcs
    //total cell width =log2(num_vcs) bit
    //in nirgam, we have assumed a list of available VCs(no. of Vcs) .
    info->vc_select_buf_type = PARM(vc_select_buf_type);
    if (info->vc_allocator_type == VC_SELECT && info->n_v_channel > 1 && info->n_in > 1)
    {
        info->vc_select_buf_type = PARM(vc_select_buf_type);
        SIM_array_init(&info->vc_select_buf_info, 1, 1, 1, info->n_v_channel, SIM_logtwo(info->n_v_channel), 0, info->vc_select_buf_type);
    }
    else
    {
        info->vc_select_buf_type = SIM_NO_MODEL;
    }


    /* redundant fields */
    if (info->in_buf)
    {
        if (info->in_share_buf)
            info->in_n_switch = info->in_buf_info.read_ports;
        else if (info->in_share_switch)
            info->in_n_switch = 1;
        else
            info->in_n_switch = info->n_v_class * info->n_v_channel;
    }
    else
        info->in_n_switch = 1;

    if (info->cache_in_buf)
    {
        if (info->in_share_buf)
            info->cache_n_switch = info->cache_in_buf_info.read_ports;
        else if (info->in_share_switch)
            info->cache_n_switch = 1;
        else
            info->cache_n_switch = info->cache_class;
    }
    else
        info->cache_n_switch = 1;

    if (info->mc_in_buf)
    {
        if (info->in_share_buf)
            info->mc_n_switch = info->mc_in_buf_info.read_ports;
        else if (info->in_share_switch)
            info->mc_n_switch = 1;
        else
            info->mc_n_switch = info->mc_class;
    }
    else
        info->mc_n_switch = 1;

    if (info->io_in_buf)
    {
        if (info->in_share_buf)
            info->io_n_switch = info->io_in_buf_info.read_ports;
        else if (info->in_share_switch)
            info->io_n_switch = 1;
        else
            info->io_n_switch = info->io_class;
    }
    else
        info->io_n_switch = 1;

    info->n_switch_in = info->n_in * info->in_n_switch + info->n_cache_in * info->cache_n_switch +
                        info->n_mc_in * info->mc_n_switch + info->n_io_in * info->io_n_switch;

    /* no buffering for local output ports */
    info->n_switch_out = info->n_cache_out + info->n_mc_out + info->n_io_out;
    if (info->out_buf)
    {
        if (info->out_share_buf)
            info->n_switch_out += info->n_out * info->out_buf_info.write_ports;
        else if (info->out_share_switch)
            info->n_switch_out += info->n_out;
        else
            info->n_switch_out += info->n_out * info->n_v_class * info->n_v_channel;
    }
    else
        info->n_switch_out += info->n_out;

    /* clock related parameters */
    info->pipelined = PARM(pipelined);
    info->H_tree_clock = PARM(H_tree_clock);
    info->router_diagonal = PARM(router_diagonal);

    if (info->pipelined || info->H_tree_clock)
    {
        info->clock_enabled = 1;
    }

    /* PHASE 2: initialization */
    if (router_power)
    {
        SIM_router_power_init(info, router_power);
    }

    if (router_area)
    {
        SIM_router_area_init(info, router_area);
    }

    return 0;
}
示例#2
0
int SIM_router_area_init(SIM_router_info_t *info, SIM_router_area_t *router_area)
{
	double bitline_len, wordline_len, xb_in_len, xb_out_len;
	double depth, nMUX, boxArea;
	int req_width;
	router_area->buffer = 0;
	router_area->crossbar = 0;
	router_area->vc_allocator = 0;
	router_area->sw_allocator = 0;

	/* buffer area */
	/* input buffer area */
	if (info->in_buf) {
		switch (info->in_buffer_model) {
			case SRAM:
				bitline_len = info->in_buf_info.n_set * (RegCellHeight + 2 * WordlineSpacing);
				wordline_len = info->flit_width * (RegCellWidth + 2 * (info->in_buf_info.read_ports 
							+ info->in_buf_info.write_ports) * BitlineSpacing);

				/* input buffer area */
				router_area->buffer = info->n_in * info->n_v_class * (bitline_len * wordline_len) *
										(info->in_share_buf ? 1 : info->n_v_channel );
				break;

			case REGISTER:
				router_area->buffer = AreaDFF * info->n_in * info->n_v_class * info->flit_width *
					info->in_buf_info.n_set * (info->in_share_buf ? 1 : info->n_v_channel );
				break;

			default: printf ("error input buffer area\n");  /* some error handler */
		}
	}

	/* output buffer area */
	if (info->out_buf) {
		switch (info->out_buffer_model) {
			case SRAM:
				bitline_len = info->out_buf_info.n_set * (RegCellHeight + 2 * WordlineSpacing);
				wordline_len = info->flit_width * (RegCellWidth + 2 * (info->out_buf_info.read_ports 
							+ info->out_buf_info.write_ports) * BitlineSpacing);

				/* output buffer area */
				router_area->buffer += info->n_out * info->n_v_class * (bitline_len * wordline_len) *
									(info->out_share_buf ? 1 : info->n_v_channel );
				break;

			case REGISTER:
				router_area->buffer += AreaDFF * info->n_out * info->n_v_class * info->flit_width * 
					info->out_buf_info.n_set * (info->out_share_buf ? 1 : info->n_v_channel ) ; 
				break;

			default: printf ("error output buffer area\n");  /* some error handler */
		}
	}

	/* crossbar area */
	if (info->crossbar_model && info->crossbar_model < CROSSBAR_MAX_MODEL) {
		switch (info->crossbar_model) {
			case MATRIX_CROSSBAR:
				xb_in_len = info->n_switch_in * info->flit_width * CrsbarCellWidth;  
				xb_out_len = info->n_switch_out * info->flit_width * CrsbarCellHeight;  
				router_area->crossbar = xb_in_len * xb_out_len;
				break;

			case MULTREE_CROSSBAR:
				if(info->degree == 2) {
					depth = ceil((log(info->n_switch_in) / log(2)));  
					nMUX = pow(2,depth) - 1;
					boxArea = 1.5 *nMUX * AreaMUX2;
					router_area->crossbar = info->n_switch_in * info->flit_width *boxArea * info->n_switch_out; 
				}
				else if( info->degree == 3 ) {
					depth = ceil((log(info->n_switch_in) / log(3))); 
					nMUX = ((pow(3,depth) - 1) / 2);
					boxArea = 1.5 * nMUX * AreaMUX3;
					router_area->crossbar = info->n_switch_in * info->flit_width *boxArea * info->n_switch_out; 
				}
				else if( info->degree == 4 ) {
					depth = ceil((log(info->n_switch_in) / log(4)));
					nMUX = ((pow(4,depth) - 1) / 3);
					boxArea = 1.5 * nMUX * AreaMUX4;
					router_area->crossbar = info->n_switch_in * info->flit_width * boxArea * info->n_switch_out; 
				}
				break;

			default: printf ("error crossbar area\n");  /* some error handler */

		}
	}

	if (info->exp_xb_model){ //only support for MATRIX_CROSSBAR type
		xb_in_len = (2 *info->n_switch_in - 1) * info->flit_width * CrsbarCellWidth; 
		xb_out_len = (2 * info->n_switch_out - 1) * info->flit_width * CrsbarCellHeight; 
		router_area->crossbar = xb_in_len * xb_out_len;
	}

	/* switch allocator area */
	if (info->sw_in_arb_model) {
		req_width = info->n_v_channel * info->n_v_class;

		switch (info->sw_in_arb_model) {	
			case MATRIX_ARBITER:  //assumes 30% spacing for each arbiter
				router_area->sw_allocator += ((AreaNOR * 2 * (req_width - 1) * req_width) + (AreaINV * req_width) 
						+ (AreaDFF * (req_width * (req_width - 1)/2))) * 1.3 * info->in_n_switch * info->n_in;
				break;

			case RR_ARBITER: //assumes 30% spacing for each arbiter
				router_area->sw_allocator += ((6 *req_width * AreaNOR) + (2 * req_width * AreaINV) 
											+ (req_width * AreaDFF)) * 1.3 * info->in_n_switch * info->n_in;
				break;

			case QUEUE_ARBITER: 
				router_area->sw_allocator += AreaDFF * info->sw_in_arb_queue_info.n_set * info->sw_in_arb_queue_info.data_width
					* info->in_n_switch * info->n_in;

				break;

			default: printf ("error switch allocator area\n");  /* some error handler */	
		}
	}

	if (info->sw_out_arb_model) {
		req_width = info->n_total_in - 1;

		switch (info->sw_out_arb_model) {
			case MATRIX_ARBITER: //assumes 30% spacing for each arbiter
				router_area->sw_allocator += ((AreaNOR * 2 * (req_width - 1) * req_width) + (AreaINV * req_width)
						+ (AreaDFF * (req_width * (req_width - 1)/2))) * 1.3 * info->n_switch_out;
				break;

			case RR_ARBITER: //assumes 30% spacing for each arbiter
				router_area->sw_allocator += ((6 *req_width * AreaNOR) + (2 * req_width * AreaINV) + (req_width * AreaDFF)) * 1.3 * info->n_switch_out;
				break;

			case QUEUE_ARBITER:
				router_area->sw_allocator += AreaDFF * info->sw_out_arb_queue_info.data_width
					* info->sw_out_arb_queue_info.n_set * info->n_switch_out;
				break;

			default: printf ("error sw arb\n");  /* some error handler */  


		}
	}


	/* virtual channel allocator area */
	if(info->vc_allocator_type == ONE_STAGE_ARB && info->n_v_channel > 1 && info->n_in > 1){
		if (info->vc_out_arb_model){
			req_width = (info->n_in - 1) * info->n_v_channel;
			switch (info->vc_out_arb_model){
				case MATRIX_ARBITER: //assumes 30% spacing for each arbiter
					router_area->vc_allocator = ((AreaNOR * 2 * (req_width - 1) * req_width) + (AreaINV * req_width)
							+ (AreaDFF * (req_width * (req_width - 1)/2))) * 1.3 * info->n_out * info->n_v_channel * info->n_v_class;
					break;

				case RR_ARBITER: //assumes 30% spacing for each arbiter
					router_area->vc_allocator = ((6 *req_width * AreaNOR) + (2 * req_width * AreaINV) + (req_width * AreaDFF)) * 1.3  
												* info->n_out * info->n_v_channel * info->n_v_class;
					break;

				case QUEUE_ARBITER:
					router_area->vc_allocator = AreaDFF * info->vc_out_arb_queue_info.data_width 
						* info->vc_out_arb_queue_info.n_set * info->n_out * info->n_v_channel * info->n_v_class;

					break;

				default: printf ("error vc allocator area - 1\n");  /* some error handler */
			}
		}

	}
	else if(info->vc_allocator_type == TWO_STAGE_ARB && info->n_v_channel > 1 && info->n_in > 1){
		if (info->vc_in_arb_model && info->vc_out_arb_model){
			/*first stage*/
			req_width = info->n_v_channel;
			switch (info->vc_in_arb_model) {
				case MATRIX_ARBITER: //assumes 30% spacing for each arbiter
					router_area->vc_allocator = ((AreaNOR * 2 * (req_width - 1) * req_width) + (AreaINV * req_width)
							+ (AreaDFF * (req_width * (req_width - 1)/2))) * 1.3 * info->n_in * info->n_v_channel * info->n_v_class;
					break;

				case RR_ARBITER: //assumes 30% spacing for each arbiter
					router_area->vc_allocator = ((6 *req_width * AreaNOR) + (2 * req_width * AreaINV) + (req_width * AreaDFF)) * 1.3 
										* info->n_in * info->n_v_channel * info->n_v_class ;
					break;

				case QUEUE_ARBITER:
					router_area->vc_allocator = AreaDFF * info->vc_in_arb_queue_info.data_width
						* info->vc_in_arb_queue_info.n_set * info->n_in * info->n_v_channel * info->n_v_class ; 

					break;

				default: printf ("error vc allocator area - 2\n");  /* some error handler */
			}

			/*second stage*/
			req_width = (info->n_in - 1) * info->n_v_channel;
			switch (info->vc_out_arb_model) {
				case MATRIX_ARBITER: //assumes 30% spacing for each arbiter
				router_area->vc_allocator += ((AreaNOR * 2 * (req_width - 1) * req_width) + (AreaINV * req_width)
						+ (AreaDFF * (req_width * (req_width - 1)/2))) * 1.3 * info->n_out * info->n_v_channel * info->n_v_class;
				break;

				case RR_ARBITER: //assumes 30% spacing for each arbiter
				router_area->vc_allocator += ((6 *req_width * AreaNOR) + (2 * req_width * AreaINV) + (req_width * AreaDFF)) * 1.3
										* info->n_out * info->n_v_channel * info->n_v_class;
				break;

				case QUEUE_ARBITER:
				router_area->vc_allocator += AreaDFF * info->vc_out_arb_queue_info.data_width
					* info->vc_out_arb_queue_info.n_set * info->n_out * info->n_v_channel * info->n_v_class;

				break;

				default: printf ("error second stage - 1\n");  /* some error handler */
			}


		}
	}
	else if(info->vc_allocator_type == VC_SELECT && info->n_v_channel > 1) {
		switch (info->vc_select_buf_type) {
			case SRAM:
				bitline_len = info->n_v_channel * (RegCellHeight + 2 * WordlineSpacing);
				wordline_len = SIM_logtwo(info->n_v_channel) * (RegCellWidth + 2 * (info->vc_select_buf_info.read_ports
							+ info->vc_select_buf_info.write_ports) * BitlineSpacing);
				router_area->vc_allocator = info->n_out * info->n_v_class * (bitline_len * wordline_len);

				break;

			case REGISTER:
				router_area->vc_allocator = AreaDFF * info->n_out * info->n_v_class* info->vc_select_buf_info.data_width
					* info->vc_select_buf_info.n_set;

				break;

			default: printf ("error second stage - 2\n");  /* some error handler */

		}
	}

	return 0;

}
示例#3
0
int SIM_router_init(SIM_router_info_t *info, SIM_router_power_t *router_power, SIM_router_area_t *router_area)
{
	u_int line_width;
	int share_buf, outdrv;

	/* PHASE 1: set parameters */
	/* general parameters */
	info->n_in = PARM(in_port);
	info->n_cache_in = PARM(cache_in_port);
	info->n_mc_in = PARM(mc_in_port);
	info->n_io_in = PARM(io_in_port);
	info->n_total_in = PARM(in_port) + PARM(cache_in_port) + PARM(mc_in_port) + PARM(io_in_port);
	info->n_out = PARM(out_port);
	info->n_cache_out = PARM(cache_out_port);
	info->n_mc_out = PARM(mc_out_port);
	info->n_io_out = PARM(io_out_port);
	info->n_total_out = PARM(out_port) + PARM(cache_out_port) + PARM(mc_out_port) + PARM(io_out_port);
	info->flit_width = PARM(flit_width);

	/* virtual channel parameters */
	info->n_v_channel = MAX(PARM(v_channel), 1);
	info->n_v_class = MAX(PARM(v_class), 1); 
	info->cache_class = MAX(PARM(cache_class), 1);
	info->mc_class = MAX(PARM(mc_class), 1);
	info->io_class = MAX(PARM(io_class), 1);
	/* shared buffer implies buffer has tags */
	/* separate buffer & shared switch implies buffer has tri-state output driver*/
	if (info->n_v_class * info->n_v_channel > 1) {
		info->in_share_buf = PARM(in_share_buf);
		info->out_share_buf = PARM(out_share_buf);
		info->in_share_switch = PARM(in_share_switch);
		info->out_share_switch = PARM(out_share_switch);
	}
	else {
		info->in_share_buf = 0;
		info->out_share_buf = 0;
		info->in_share_switch = 0;
		info->out_share_switch = 0;
	}

	/* crossbar */
	info->crossbar_model = PARM(crossbar_model);
	info->degree = PARM(crsbar_degree);
	info->connect_type = PARM(connect_type);
	info->trans_type = PARM(trans_type);
	info->xb_in_seg = PARM(xb_in_seg);
	info->xb_out_seg = PARM(xb_out_seg);
	info->crossbar_in_len = PARM(crossbar_in_len);
	info->crossbar_out_len = PARM(crossbar_out_len);
	/* HACK HACK HACK */
	info->exp_xb_model = PARM(exp_xb_model);
	info->exp_in_seg = PARM(exp_in_seg);
	info->exp_out_seg = PARM(exp_out_seg);

	/* input buffer */
	info->in_buf = PARM(in_buf);
	info->in_buffer_model = PARM(in_buffer_type);
	if(info->in_buf){
		outdrv = !info->in_share_buf && info->in_share_switch;
		SIM_array_init(&info->in_buf_info, 1, PARM(in_buf_rport), 1, PARM(in_buf_set), PARM(flit_width), outdrv, info->in_buffer_model);
	}

	if (PARM(cache_in_port)){
    	info->cache_in_buf = PARM(cache_in_buf);

		if (info->cache_in_buf){
			if (PARM(cache_class) > 1){
    			share_buf = info->in_share_buf;
    			outdrv = !share_buf && info->in_share_switch;
			}	
			else{
    			outdrv = share_buf = 0;
			}
    		SIM_array_init(&info->cache_in_buf_info, 1, PARM(cache_in_buf_rport), 1, PARM(cache_in_buf_set), PARM(flit_width), outdrv, SRAM);
		}
	}

	if (PARM(mc_in_port)){
    	info->mc_in_buf = PARM(mc_in_buf);

		if (info->mc_in_buf){
			if (PARM(mc_class) > 1){
    			share_buf = info->in_share_buf;
    			outdrv = !share_buf && info->in_share_switch;
			}
			else{
    			outdrv = share_buf = 0;
			}
    		SIM_array_init(&info->mc_in_buf_info, 1, PARM(mc_in_buf_rport), 1, PARM(mc_in_buf_set), PARM(flit_width), outdrv, SRAM);
		}
	}

	if (PARM(io_in_port)){
    	info->io_in_buf = PARM(io_in_buf);

		if (info->io_in_buf){
			if (PARM(io_class) > 1){
    			share_buf = info->in_share_buf;
    			outdrv = !share_buf && info->in_share_switch;
			}
			else{
    			outdrv = share_buf = 0;
			}
    		SIM_array_init(&info->io_in_buf_info, 1, PARM(io_in_buf_rport), 1, PARM(io_in_buf_set), PARM(flit_width), outdrv, SRAM);
		}
	}

	/* output buffer */
	info->out_buf = PARM(out_buf);
	info->out_buffer_model = PARM(out_buffer_type);
	if (info->out_buf){
		/* output buffer has no tri-state buffer anyway */
		SIM_array_init(&info->out_buf_info, 1, 1, PARM(out_buf_wport), PARM(out_buf_set), PARM(flit_width), 0, info->out_buffer_model);
	}

	/* central buffer */
	info->central_buf = PARM(central_buf);
	if (info->central_buf){
		info->pipe_depth = PARM(pipe_depth);
		/* central buffer is no FIFO */
		SIM_array_init(&info->central_buf_info, 0, PARM(cbuf_rport), PARM(cbuf_wport), PARM(cbuf_set), PARM(cbuf_width) * PARM(flit_width), 0, SRAM);
		/* dirty hack */
		info->cbuf_ff_model = NEG_DFF;
	}

	/* switch allocator input port arbiter */
	if (info->n_v_class * info->n_v_channel > 1) {
		if (info->sw_in_arb_model = PARM(sw_in_arb_model)) {
			if (PARM(sw_in_arb_model) == QUEUE_ARBITER) {
				SIM_array_init(&info->sw_in_arb_queue_info, 1, 1, 1, info->n_v_class*info->n_v_channel, SIM_logtwo(info->n_v_class*info->n_v_channel), 0, REGISTER);
				if (info->cache_class > 1)
					SIM_array_init(&info->cache_in_arb_queue_info, 1, 1, 1, info->cache_class, SIM_logtwo(info->cache_class), 0, REGISTER);
				if (info->mc_class > 1)
					SIM_array_init(&info->mc_in_arb_queue_info, 1, 1, 1, info->mc_class, SIM_logtwo(info->mc_class), 0, REGISTER);
				if (info->io_class > 1)
					SIM_array_init(&info->io_in_arb_queue_info, 1, 1, 1, info->io_class, SIM_logtwo(info->io_class), 0, REGISTER);

				info->sw_in_arb_ff_model = SIM_NO_MODEL;
			}
			else
				info->sw_in_arb_ff_model = PARM(sw_in_arb_ff_model);
		}
		else
			info->sw_in_arb_ff_model = SIM_NO_MODEL;
	}
	else {
		info->sw_in_arb_model = SIM_NO_MODEL;
		info->sw_in_arb_ff_model = SIM_NO_MODEL;
	}

	/* switch allocator output port arbiter */
	if(info->n_total_in > 2){
		info->sw_out_arb_model = PARM(sw_out_arb_model);
		if (info->sw_out_arb_model) {
			if (info->sw_out_arb_model == QUEUE_ARBITER) {
				line_width = SIM_logtwo(info->n_total_in - 1);
				SIM_array_init(&info->sw_out_arb_queue_info, 1, 1, 1, info->n_total_in - 1, line_width, 0, REGISTER);
				info->sw_out_arb_ff_model = SIM_NO_MODEL;
			}
			else{
				info->sw_out_arb_ff_model = PARM(sw_out_arb_ff_model);
			}
		}
		else{
			info->sw_out_arb_ff_model = SIM_NO_MODEL;
		}
	}
	else{
		info->sw_out_arb_model = SIM_NO_MODEL;
		info->sw_out_arb_ff_model = SIM_NO_MODEL;
	}

	/* virtual channel allocator type */
	if (info->n_v_channel > 1) {
		info->vc_allocator_type = PARM(vc_allocator_type);
	} 
	else
		info->vc_allocator_type = SIM_NO_MODEL;

	/* virtual channel allocator input port arbiter */
	if ( info->n_v_channel > 1 && info->n_in > 1) {
		if (info->vc_in_arb_model = PARM(vc_in_arb_model)) {
			if (PARM(vc_in_arb_model) == QUEUE_ARBITER) { 
				SIM_array_init(&info->vc_in_arb_queue_info, 1, 1, 1, info->n_v_channel, SIM_logtwo(info->n_v_channel), 0, REGISTER);
				info->vc_in_arb_ff_model = SIM_NO_MODEL;
			}
			else{
				info->vc_in_arb_ff_model = PARM(vc_in_arb_ff_model);
			}
		}
		else {
			info->vc_in_arb_ff_model = SIM_NO_MODEL;
		}
	}
	else {
		info->vc_in_arb_model = SIM_NO_MODEL;
		info->vc_in_arb_ff_model = SIM_NO_MODEL;
	}

	/* virtual channel allocator output port arbiter */
	if(info->n_in > 1 && info->n_v_channel > 1){
		info->vc_out_arb_model = PARM(vc_out_arb_model);
		if (info->vc_out_arb_model) {
			if (info->vc_out_arb_model == QUEUE_ARBITER) {
				line_width = SIM_logtwo((info->n_total_in - 1)*info->n_v_channel);
				SIM_array_init(&info->vc_out_arb_queue_info, 1, 1, 1, (info->n_total_in -1) * info->n_v_channel, line_width, 0, REGISTER);
				info->vc_out_arb_ff_model = SIM_NO_MODEL;
			}
			else{
				info->vc_out_arb_ff_model = PARM(vc_out_arb_ff_model);
			}
		}
		else{
			info->vc_out_arb_ff_model = SIM_NO_MODEL;
		}
	}
	else{
		info->vc_out_arb_model = SIM_NO_MODEL;
		info->vc_out_arb_ff_model = SIM_NO_MODEL;
	}

	/*virtual channel allocation vc selection model */
	info->vc_select_buf_type = PARM(vc_select_buf_type);
	if(info->vc_allocator_type == VC_SELECT && info->n_v_channel > 1 && info->n_in > 1){
		info->vc_select_buf_type = PARM(vc_select_buf_type);
		SIM_array_init(&info->vc_select_buf_info, 1, 1, 1, info->n_v_channel, SIM_logtwo(info->n_v_channel), 0, info->vc_select_buf_type);
	}
	else{
		info->vc_select_buf_type = SIM_NO_MODEL;
	}


	/* redundant fields */
	if (info->in_buf) {
		if (info->in_share_buf)
			info->in_n_switch = info->in_buf_info.read_ports;
		else if (info->in_share_switch)
			info->in_n_switch = 1;
		else
			info->in_n_switch = info->n_v_class * info->n_v_channel;
	}
	else
		info->in_n_switch = 1;

	if (info->cache_in_buf) {
		if (info->in_share_buf)
			info->cache_n_switch = info->cache_in_buf_info.read_ports;
		else if (info->in_share_switch)
			info->cache_n_switch = 1;
		else
			info->cache_n_switch = info->cache_class;
	}
	else
		info->cache_n_switch = 1;

	if (info->mc_in_buf) {
		if (info->in_share_buf)
			info->mc_n_switch = info->mc_in_buf_info.read_ports;
		else if (info->in_share_switch)
			info->mc_n_switch = 1;
		else
			info->mc_n_switch = info->mc_class;
	}
	else
		info->mc_n_switch = 1;

	if (info->io_in_buf) {
		if (info->in_share_buf)
			info->io_n_switch = info->io_in_buf_info.read_ports;
		else if (info->in_share_switch)
			info->io_n_switch = 1;
		else
			info->io_n_switch = info->io_class;
	}
	else
		info->io_n_switch = 1;

	info->n_switch_in = info->n_in * info->in_n_switch + info->n_cache_in * info->cache_n_switch +
		info->n_mc_in * info->mc_n_switch + info->n_io_in * info->io_n_switch;

	/* no buffering for local output ports */
	info->n_switch_out = info->n_cache_out + info->n_mc_out + info->n_io_out;
	if (info->out_buf) {
		if (info->out_share_buf)
			info->n_switch_out += info->n_out * info->out_buf_info.write_ports;
		else if (info->out_share_switch)
			info->n_switch_out += info->n_out;
		else
			info->n_switch_out += info->n_out * info->n_v_class * info->n_v_channel;
	}
	else
		info->n_switch_out += info->n_out;

	/* clock related parameters */	
    info->pipeline_stages = PARM(pipeline_stages);
    info->H_tree_clock = PARM(H_tree_clock);
    info->router_diagonal = PARM(router_diagonal);

	/* PHASE 2: initialization */
	if(router_power){
		SIM_router_power_init(info, router_power);
	}

	if(router_area){
		SIM_router_area_init(info, router_area);
	}

	return 0;
}