OpenCores
URL https://opencores.org/ocsvn/noc/noc/trunk

Subversion Repositories noc

[/] [noc/] [src/] [router.cc] - Rev 4

Compare with Previous | Blame | View Log

/*
 * =====================================================================================
 *
 *       Filename:  router.cc
 *
 *    Description:  router 
 *
 *        Version:  1.0
 *        Created:  03/25/2009 12:42:15 PM
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Soontea Kwon (), Kwonst@skku.edu
 *        Company:  Mobile Electronics Lab
 *
 * =====================================================================================
 */
#include "router.h"
 
char router :: direction_decision(char dst_x, char dst_y, char router_x, char router_y)
{
	if(dst_x < router_x){			//outgoing west.
		return WEST_ADDRESS;
	}
	else if(dst_x > router_x){		//outgoing east.
		return EAST_ADDRESS;
	}
	else{
		if(dst_y > router_y){		//outgoing north.
			return SOUTH_ADDRESS;
		}
		else if(dst_y < router_y){	//outgoing sourth.
			return NORTH_ADDRESS;
		}
		else{						//outgoing core.
			return CORE_ADDRESS;
		}
	}
}
 
char router :: header_decoder(sc_uint<8> addr){
 
	HEAD_FLIT *head_flit;
	sc_uint<6>	dst_x, dst_y, router_x, router_y;
	sc_uint<16> temp;
	sc_uint<2>	ch_temp = 0;
	unsigned short temp_s;
 
	temp = rbuffer[addr].range(15,0);
	temp_s = temp;
	head_flit = (HEAD_FLIT *)&temp_s;
 
	if(head_flit->type == _HEAD_FLIT){
		//Header flit.
		dst_x = head_flit->dst_addr % x_num;
		dst_y = head_flit->dst_addr / y_num;
		router_x = router_id % x_num;
		router_y = router_id / y_num;
		port[addr].outport = direction_decision(dst_x, dst_y, router_x, router_y);
#ifdef ROUTER_DEC_DEBUG
		cout << "Head flit" << endl;
		cout << "packet dst_y: " << dst_y << ", dst_x: " << dst_x << endl;
		cout << "router x: " << router_x << ", y: " << router_y << endl;
 
		switch(port[addr].outport){
			case WEST_ADDRESS : cout << "WEST" << endl;
								break;
			case EAST_ADDRESS : cout << "EAST" << endl;
								break;
			case SOUTH_ADDRESS : cout << "SOUTH" << endl;
								 break;
			case NORTH_ADDRESS : cout << "NORTH" << endl;
								 break;
			case CORE_ADDRESS : cout << "CORE" << endl;
								break;
		}
#endif
 
		for(int i = 0; i < 3; i++){		
			if(!(tbuffer_state & (1 << (port[addr].outport + i)))){
				port[addr].out_ch = i;
				port[addr].set = 1;
				tbuffer_state |= (1 << (port[addr].outport + i));
 
				if(head_flit->conn_type == EIs){
					return EIs;
				}
				else if(head_flit->conn_type == OIs){
					return OIs;
				}					
			}
		}
	}
	return FAIL;
}
 
#ifdef ROUTER_DEBUG
void router :: transfer_data(sc_out<bool> *data_out, sc_out<sc_uint<2> > *router_to_fifo_sel, 
							 sc_out<bool> *write_n, sc_in<sc_uint<3> > *full, sc_uint<8> address,
							 char *debug_string, unsigned char debug_en)
#else
 
void router :: transfer_data(sc_out<bool> *data_out, sc_out<sc_uint<2> > *router_to_fifo_sel, 
							 sc_out<bool> *write_n, sc_in<sc_uint<3> > *full, sc_uint<8> address)
#endif
{
	sc_uint<FIFO_DEEP>      tr_fc;          //fifo deep counter.
	sc_uint<FIFO_DEEP>      buff;
	sc_uint<FIFO_DEEP>      f_ct[3];
	sc_uint<3>              channel = 0;
	sc_uint<3>              sel = 0;
	bool                    stop_flag = 0;
	bool                    temp = 0;
	bool                    ready = 0;
 
	while(true){
		if(!reset_n.read()){
			stop_flag = 0;
			f_ct[0] = f_ct[1] = f_ct[2] = 0;
		}
		else{
			if(clk.read()){
				write_n->write(true);
				if(((full->read()&0x01) != 0x01) && ((tbuffer[address+0] & WEN) == WEN)){
					sel = 1;
					channel = 0;
					stop_flag = 0;
					f_ct[channel]++;
				}
				else if(((full->read()&0x02) != 0x02)&&((tbuffer[address+1] & WEN) == WEN)){
					sel = 2;
					channel = 1;
					stop_flag = 0;
					f_ct[channel]++;
				}
				else if(((full->read()&0x04) != 0x04)&&((tbuffer[address+2] & WEN) == WEN)){
					sel = 3;
					channel = 2;
					stop_flag = 0;
					f_ct[channel]++;
				}
				else{
					sel = 0x00;
					stop_flag = 1;
				}
				router_to_fifo_sel->write(sel);
				ready = 1;
			}
			else if((ready == 1) && (stop_flag == 0)){
				if(((f_ct[channel] - 1) < FIFO_DEEP)){
					buff = tbuffer[address+channel].range(15,0);
					temp =(bool)((buff >> (f_ct[channel] - 1)) & 0x0001);
					data_out->write(temp);
					write_n->write(false);
					ready = 0;
					EI_POWER;
				}
				if((f_ct[channel]) >= (FIFO_DEEP)){
					f_ct[channel] = 0;
					tbuffer[address+channel] &= ~WEN;
					tbuffer[address+channel] = 0;
					if(tbuffer[address+channel].range(15,14) & _TAIL_FLIT){
#ifdef ROUTER_DEBUG
						cout << "Tail flit" << endl;
#endif
						port[address+channel].set = 0;
						port[address+channel].inport = 0;
						port[address+channel].outport = 0;
						port[address+channel].in_ch = 0;
						port[address+channel].out_ch = 0;
						tbuffer_state &= ~(1 << address + channel);
					}
					EI_POWER;
#ifdef ROUTER_DEBUG
	//			cout << "Router [" << router_id << "] " << debug_string << " output channel: " << channel << endl;
#endif
				}
			}
		}
		wait();
	}
}
#ifdef ROUTER_DEBUG
void router :: receive_data(sc_in<bool> *data_in, sc_out<sc_uint<2> > *fifo_to_router_sel,
							sc_out<bool> *read_n, sc_in<sc_uint<3> > *empty, sc_uint<8> address,
							char *debug_string, unsigned char debug_en)
#else
void router :: receive_data(sc_in<bool> *data_in, sc_out<sc_uint<2> > *fifo_to_router_sel,
							sc_out<bool> *read_n, sc_in<sc_uint<3> > *empty, sc_uint<8> address)
#endif
{
	sc_uint<FIFO_DEEP>  rec_buff = 0;
	sc_uint<FIFO_DEEP>	rec_fc = 0;         //fifo deep counter.
	sc_uint<FIFO_DEEP>  f_ct[3];         //fifo deep counter.
	sc_uint<2>			sel = 0;
	sc_uint<2>			channel = 0;
	bool temp = 0;
	bool ready = 0;
 
	f_ct[0] = f_ct[1] = f_ct[2] = 0;
	rbuffer[0] = rbuffer[1] = rbuffer[2] = 0;
 
	read_n->write(true);
 
	while(true){
		wait();
		if(!reset_n.read())
		{
			rbuffer[0] = rbuffer[1] = rbuffer[2] = 0;
			f_ct[0] = f_ct[1] = f_ct[2] = 0;
			read_n->write(true);
		}
		else{
			if(clk.read()){
				read_n->write(true);
				if(((empty->read()&0x01) != 0x01) && (rbuffer[address+0]&REN) != REN){
					channel = 0;
					sel = 1;
					f_ct[channel]++;
					ready = 1;
				}
				else if(((empty->read()&0x02) != 0x02) && ((rbuffer[address+1]&REN) != REN)){
					channel = 1;
					sel = 2;
					f_ct[channel]++;
					ready = 1;
				}
				else if(((empty->read()&0x04) != 0x04) && ((rbuffer[address+2]&REN) != REN)){
					channel = 2;
					sel = 3;
					f_ct[channel]++;
					ready = 1;
				}
				else{
					ready = 0;
					sel = 0;
				}
				fifo_to_router_sel->write(sel);
			}
			else if(ready == 1){ 
				if((f_ct[channel]) < FIFO_DEEP+1){
					read_n->write(false);
					wait(2,SC_NS);
					temp = data_in->read();
					rbuffer[address+channel] |= (temp << (f_ct[channel]-1));
					ready = 0;
					EI_POWER;
				}
				if((f_ct[channel]) == (FIFO_DEEP)){
					f_ct[channel] = 0;
					rbuffer[address+channel] |= REN;
					EI_POWER;
					EI_DELAY;
#ifdef ROUTER_DEBUG
					if(debug_en == 1){
						unsigned short debug_temp = 0;
						for(int dc = 0; dc <= FIFO_DEEP; dc++){
							debug_temp = rbuffer[address+channel];
							debug_temp = debug_temp >> dc;
							debug_temp &= 0x0001;
							if(dc  == 0){
								cout << "router [" << router_id << "] channel[" 
									<< channel << "] " << debug_string << " receive data: \t";
								cout << debug_temp;
							}
							else if(dc < FIFO_DEEP){
								cout << debug_temp;
							}
						}
						cout << endl;
					}
#endif
				}
			}
		}
	}
}
 
//CORE
void router :: core_receive_data(){
#ifdef ROUTER_DEBUG
	receive_data(&c_data_in, &c_fifo_to_router_sel, &c_read_n, &c_empty, CORE_ADDRESS,
				 "core",1);
#else
	receive_data(&c_data_in, &c_fifo_to_router_sel, &c_read_n, &c_empty, CORE_ADDRESS);
#endif
}
void router :: core_transfer_data(){
#ifdef ROUTER_DEBUG
	transfer_data(&c_data_out, &c_router_to_fifo_sel, &c_write_n, &c_full, CORE_ADDRESS,
				 "core" , 1);
#else
	transfer_data(&c_data_out, &c_router_to_fifo_sel, &c_write_n, &c_full, CORE_ADDRESS);
#endif
}
 
//WEST
void router :: west_receive_data(){
#ifdef ROUTER_DEBUG
	receive_data(&w_data_in, &w_fifo_to_router_sel, &w_read_n, &w_empty, WEST_ADDRESS, 
				 "west", 0);
#else
	receive_data(&w_data_in, &w_fifo_to_router_sel, &w_read_n, &w_empty, WEST_ADDRESS);
#endif
 
}
void router :: west_transfer_data(){
#ifdef ROUTER_DEBUG
	transfer_data(&w_data_out, &w_router_to_fifo_sel, &w_write_n, &w_full, WEST_ADDRESS,
				  "west" , 0);
#else
	transfer_data(&w_data_out, &w_router_to_fifo_sel, &w_write_n, &w_full, WEST_ADDRESS);
#endif
}
 
//EAST
void router :: east_receive_data(){
#ifdef ROUTER_DEBUG
	receive_data(&e_data_in, &e_fifo_to_router_sel, &e_read_n, &e_empty, EAST_ADDRESS, 
				 "east", 0);
#else
	receive_data(&e_data_in, &e_fifo_to_router_sel, &e_read_n, &e_empty, EAST_ADDRESS);
#endif
}
 
void router :: east_transfer_data(){
#ifdef ROUTER_DEBUG
	transfer_data(&e_data_out, &e_router_to_fifo_sel, &e_write_n, &e_full, EAST_ADDRESS,
				  "east", 0);
#else
	transfer_data(&e_data_out, &e_router_to_fifo_sel, &e_write_n, &e_full, EAST_ADDRESS);
#endif
}
 
//NORTH
void router :: north_receive_data(){
#ifdef ROUTER_DEBUG
	receive_data(&n_data_in, &n_fifo_to_router_sel, &n_read_n, &n_empty, NORTH_ADDRESS, 
				 "north", 0);
#else
	receive_data(&n_data_in, &n_fifo_to_router_sel, &n_read_n, &n_empty, NORTH_ADDRESS);
#endif
}
 
void router :: north_transfer_data(){
#ifdef ROUTER_DEBUG
	transfer_data(&n_data_out, &n_router_to_fifo_sel, &n_write_n, &n_full, NORTH_ADDRESS,
				  "north", 0);
#else
	transfer_data(&n_data_out, &n_router_to_fifo_sel, &n_write_n, &n_full, NORTH_ADDRESS);
#endif
}
 
//SOUTH
void router :: south_receive_data(){
#ifdef ROUTER_DEBUG
	receive_data(&s_data_in, &s_fifo_to_router_sel, &s_read_n, &s_empty, SOUTH_ADDRESS, 
				 "south", 0);
#else
	receive_data(&s_data_in, &s_fifo_to_router_sel, &s_read_n, &s_empty, SOUTH_ADDRESS);
#endif
}
 
void router :: south_transfer_data(){
#ifdef ROUTER_DEBUG
	transfer_data(&s_data_out, &s_router_to_fifo_sel, &s_write_n, &s_full, SOUTH_ADDRESS,
				  "south", 0);
#else
	transfer_data(&s_data_out, &s_router_to_fifo_sel, &s_write_n, &s_full, SOUTH_ADDRESS);
#endif
}
 
void router :: oi_transfer_data()
{
	sc_uint<OI_FLIT_SIZE> temp = 0;
	sc_uint<OI_FLIT_SIZE> tc_count = 0;
	bool tr_bit_temp;
	sc_logic rc_temp = SC_LOGIC_Z;
 
	while(true){
		if(!reset_n.read()){
			c_oi_out.write(SC_LOGIC_Z);
			tc_count = 0;
		}
		else{
			if((tbuffer[OI_ADDRESS] & WEN) == WEN){
				temp = tbuffer[OI_ADDRESS].range(15,0);
				tr_bit_temp = ((temp >> tc_count) & 0x0001);
				if(tr_bit_temp == 1){
					c_oi_out.write(SC_LOGIC_1);
					tc_count++;
					TRANSMITTER_OI_POWER;
				}
				else if(tr_bit_temp == 0){
					c_oi_out.write(SC_LOGIC_0);
					tc_count++;
					TRANSMITTER_OI_POWER;
				}
				else{
					c_oi_out.write(SC_LOGIC_Z);
				}
				if(tc_count == OI_FLIT_SIZE + 1){
					c_oi_out.write(SC_LOGIC_Z);
#ifdef ROUTER_DEBUG
					short debug_temp = 0;
					for(int dc = 0; dc <= FIFO_DEEP; dc++){
						debug_temp = tbuffer[OI_ADDRESS].range(15,0);
						debug_temp = debug_temp >> dc;
						debug_temp &= 0x0001;
						if(dc  == 0){
							cout << "router [" << router_id << "] OI transfer data: \t";
							cout << debug_temp;
						}
						else if(dc < FIFO_DEEP){
							cout << debug_temp;
						}
					}
					cout << endl;
#endif
					if(tbuffer[OI_ADDRESS].range(15,14) & _TAIL_FLIT){
#ifdef ROUTER_DEBUG
						cout << "OI TR : Tail flit" << endl;
#endif
						port[OI_ADDRESS].set = 0;
						port[OI_ADDRESS].inport = 0;
						port[OI_ADDRESS].outport = 0;
						port[OI_ADDRESS].in_ch = 0;
						port[OI_ADDRESS].out_ch = 0;
						tbuffer_state &= ~(1 << OI_ADDRESS);
					}
					TRANSMITTER_OI_DELAY;
					tc_count = 0;
					tbuffer[OI_ADDRESS] = 0;
				}
			}
		}
		wait();
	}
}
 
void router :: oi_receive_data()
{
	sc_uint<OI_FLIT_SIZE> temp = 0;
	sc_uint<OI_FLIT_SIZE> oi_count = 0;
	sc_logic rc_temp = SC_LOGIC_Z;
 
	while(true){
		if(!reset_n.read()){
			oi_count = 0;
			rc_temp = SC_LOGIC_Z;
			temp = 0;
		}
		else{
			if((rbuffer[OI_ADDRESS] & REN) != REN){
				rc_temp = c_oi_in.read();
				if((rc_temp != SC_LOGIC_Z) && (rc_temp != SC_LOGIC_X)){
					if(rc_temp == SC_LOGIC_0){
						oi_count++;
						RECEIVER_OI_ENERGY;
					}
					else if(rc_temp == SC_LOGIC_1){
						temp |= (1 << oi_count);
						oi_count++;
						RECEIVER_OI_ENERGY;
					}
					if(oi_count == OI_FLIT_SIZE){
						rbuffer[OI_ADDRESS] = temp;
						rbuffer[OI_ADDRESS] |= REN;
						RECEIVER_OI_DELAY;
						oi_count = 0;
						temp = 0;
#ifdef ROUTER_DEBUG
						short debug_temp = 0;
						for(int dc = 0; dc <= FIFO_DEEP; dc++){
							debug_temp = rbuffer[OI_ADDRESS];
							debug_temp = debug_temp >> dc;
							debug_temp &= 0x0001;
							if(dc  == 0){
								cout << "router [" << router_id << "] OI receive data: \t";
								cout << debug_temp;
							}
							else if(dc < FIFO_DEEP){
								cout << debug_temp;
							}
						}
						cout << endl;
#endif
					}
				}
			}
		}
		wait();
	}
}
 
void router :: direction_handle(){
	sc_uint<8> ch = 0;
	char state = 0;
 
	ch = CORE_ADDRESS;
 
	while(true){
		if(!reset_n.read()){
			control_state = 0;
		}
		else{
			for(ch = 0; ch < 16; ch++){
				if(rbuffer[ch] & REN){
					if(port[ch].set == 1){
						if(!(tbuffer[port[ch].outport + port[ch].out_ch] & WEN)){
							tbuffer[port[ch].outport + port[ch].out_ch] = rbuffer[ch].range(15,0);
							tbuffer[port[ch].outport + port[ch].out_ch] |= WEN;
							rbuffer[ch] = 0;
							rbuffer[ch] &= ~REN;
						}
					}
					else if(port[ch].set == 0){
						state = header_decoder(ch);
						if(state != FAIL){
							if(!(tbuffer[port[ch].outport + port[ch].out_ch] & WEN)){
								tbuffer[port[ch].outport + port[ch].out_ch] = rbuffer[ch].range(15,0);
								tbuffer[port[ch].outport + port[ch].out_ch] |= WEN;
								rbuffer[ch] &= ~REN;
								if(state == OIs){
									if(ch < 3){
										port[ch].outport = OI_ADDRESS;
										port[ch].out_ch = 0;
										port[ch].set = 1;
									}
 
									if(port[ch].outport == 0){
										port[15].outport = 0;
										port[15].out_ch = port[ch].out_ch;
										port[ch].set = 0;
										port[15].set = 1;
									}
									optical_sw(ch);
								}
								rbuffer[ch] = 0;
							}
						}
					}
				}
			}
		}
		wait();
	}
}
 
sc_uint<16> router :: out_direction(sc_uint<8> out_going, sc_uint<16> go_a, sc_uint<16> go_b, 
									sc_uint<16> go_c, sc_uint<16> go_d, sc_uint<16> go_e)
{
	sc_uint<16> out_temp = 0;
 
	if(out_going == EAST_ADDRESS){
		out_temp = go_a;
	}
	else if(out_going == WEST_ADDRESS){
		out_temp = go_b;
	}
	else if(out_going == NORTH_ADDRESS){
		out_temp = go_c;
	}
	else if(out_going == SOUTH_ADDRESS){
		out_temp = go_d;
	}
	else if(out_going == CORE_ADDRESS){
		out_temp = go_e;
	}
 
	return out_temp;
}
 
void router :: optical_sw(sc_uint<8> ch)
{
	sc_uint<16> out_temp = 0;
	HEAD_FLIT *head_flit;
	sc_uint<6>	dst_x, dst_y, router_x, router_y;
	sc_uint<16> temp;
	sc_uint<2>	ch_temp = 0;
	unsigned short temp_s;
	sc_uint<8> outgoing = 0;
 
	temp = rbuffer[ch].range(15,0);
	temp_s = temp;
	head_flit = (HEAD_FLIT *)&temp_s;
 
	//Header flit.
	dst_x = head_flit->dst_addr % x_num;
	dst_y = head_flit->dst_addr / y_num;
	router_x = router_id % x_num;
	router_y = router_id / y_num;
 
	outgoing = direction_decision(dst_x, dst_y, router_x, router_y);
 
	//input buffer number.
	if(ch  < 3){			//in core.
		out_temp = out_direction(outgoing, CORE_TO_EAST, CORE_TO_WEST, CORE_TO_NORTH, CORE_TO_SOUTH, 0);
	}
	else if(ch < 6){		//in west
		out_temp = out_direction(outgoing, 0, 0, WEST_TO_NORTH, WEST_TO_SOUTH, WEST_TO_CORE);
	}
	else if(ch < 9){		//in east
		out_temp = out_direction(outgoing, 0, 0, EAST_TO_NORTH, EAST_TO_SOUTH, EAST_TO_CORE);
	}
	else if(ch < 12){		//in north
		out_temp = out_direction(outgoing, NORTH_TO_EAST, NORTH_TO_WEST, 0, 0, NORTH_TO_CORE);
	}
	else if(ch < 15){		//in south
		out_temp = out_direction(outgoing, SOUTH_TO_EAST, SOUTH_TO_WEST, 0, 0, NORTH_TO_CORE);
	}
	//cout << "sel " << hex << out_temp << endl;
	control_state |= out_temp;
	oi_control.write(control_state);
	//cout << "control signal: " << hex << state_temp << endl;
}
 

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.