www.pudn.com > noc.rar > inctrl.cpp
/*
* TU Eindhoven
* Eindhoven, The Netherlands
*
* Name : inctrl.cpp
*
* Author : A.S.Slusarczyk@tue.nl
*
* Date : 13-09-2003
*
* Function : Input controller of the e-cube router
*
*
*/
#include "inctrl.h"
void INPUT_CTRL::dlatch()
{
if( latch.read() )
data_latch.write(data.read());
}
void INPUT_CTRL::control_logic()
{
bool ack_v, out_req_v, header_select_v, request_switch_v, latch_v;
ack_v = false;
out_req_v = false;
header_select_v = false;
request_switch_v = false;
latch_v = false;
next_state = IDLE;
switch( current_state.read() )
{
case IDLE:
// waiting for a next packet to start
if( req.read() )
{
latch_v = true;
next_state = OPEN;
header_select_v = true;
}
else
next_state = IDLE;
break;
case OPEN:
// opening connection and forwarding header flit
#ifdef ROUTEPRINT
cout << name() << " got start of packet " << hex << data_latch.read().to_uint() << dec << " (addr=" << data_latch.read().range(15,8).to_uint() << ',' << data_latch.read().range(7,0).to_uint() << ") @" << sc_time_stamp() << endl;
#endif
request_switch_v = true;
header_select_v = true;
ack_v = out_ack.read();
out_req_v = req.read();
if( out_ack.read() ){
next_state = WAIT_ACK;
}
else{
next_state = OPEN;
}
break;
case WAIT_ACK:
request_switch_v = true;
if( out_ack.read() )
next_state = WAIT_ACK;
else
next_state = NEXT;
break;
case NEXT:
request_switch_v = true;
// waiting for next flit of the packet
if( req.read() )
{
next_state = SEND;
header_select_v = false;
latch_v = true;
//ack_v = out_ack.read();
//out_req_v = req.read();
}
else {
next_state = NEXT;
}
break;
case SEND:
// sending a flit
#ifdef ROUTEPRINT
cout << name() << " got flit 0x" << hex << data_latch.read().to_uint() << dec << " @" << sc_time_stamp() << endl;
#endif
request_switch_v = true;
header_select_v = false;
ack_v = out_ack.read();
out_req_v = req.read();
if( out_ack.read() ){ // flit was acknowledged
if( end_of_packet.read() ) // it's EOP, go idle
next_state = WAIT_END;
else // not a last flit - wait for the next
next_state = WAIT_ACK;
}
else{ // waiting for ACK
next_state = SEND;
}
break;
case WAIT_END:
request_switch_v = true;
if( out_ack.read() )
next_state = WAIT_END;
else
next_state = IDLE;
break;
}
ack.write(ack_v);
out_req.write(out_req_v);
header_select.write(header_select_v);
request_switch.write(request_switch_v);
latch.write(latch_v);
}
void INPUT_CTRL::control_change_state()
{
if( rst.read() )
current_state = IDLE;
else
current_state = next_state;
}
void INPUT_CTRL::route_select()
{
sc_uint my_addr = my_address.read();
sc_bv d = (latch.read() ? data.read() : data_latch.read() );
sc_bv bvaddr = d.range(X_ADDR_START,X_ADDR_START-ADDRESS_LEN+1);
sc_uint still_to_go = bvaddr;
out_select_n = 0;
if( still_to_go == 0 ){
// end-of-route - direct packet to data processor (or next dim. router)
out_select_n = 3;
}
else if( (my_addr == 0 && ch0.read()) || ch1.read() ){
// this is zero-channel of 0-router - switch to channel #1
// also if packet is on 1-channel, it will stay on it
out_select_n = 2;
}
else {
// otherwise - route to output channel 0
out_select_n = 1;
}
}
void INPUT_CTRL::switch_out_select(){
if( header_select.read() )
out_select.write(out_select_n.read());
}
void INPUT_CTRL::header_adjust()
{
// all of this is irrelevant if it's not the header flit, but this decision
// is made by data_select
// extract flit type and x-address and y-address
sc_bv bFT = data_latch.read().range(FT_START,FT_START-FLIT_TYPE_LEN+1);
sc_bv<8> bXA = data_latch.read().range(X_ADDR_START,X_ADDR_START-ADDRESS_LEN+1),
bYA = data_latch.read().range(Y_ADDR_START,Y_ADDR_START-ADDRESS_LEN+1);
sc_uint flit_type = bFT;
sc_uint xaddr = bXA, yaddr = bYA;
sc_bv bXAout, bYAout;
sc_uint xaddr_out, yaddr_out;
if( xaddr == 0 ){
// if it's end of route, strip x address and replace it with y address
end_of_route.write(true);
xaddr_out = yaddr;
yaddr_out = 0;
}
else{
// otherwise, decrement the address
end_of_route.write(false);
xaddr_out = xaddr-1;
yaddr_out = yaddr;
}
// recognize flit type
switch( flit_type ){
case 1 : start_of_packet.write(true); end_of_packet.write(false); break;
case 2 : start_of_packet.write(false); end_of_packet.write(true); break;
default : start_of_packet.write(false); end_of_packet.write(false); break;
};
// construct the output flit
bXAout = xaddr_out;
bYAout = yaddr_out;
sc_bv hout;
hout.range(FT_START,FT_START-FLIT_TYPE_LEN+1) = bFT;
hout.range(X_ADDR_START,X_ADDR_START-ADDRESS_LEN+1) = bXAout;
hout.range(Y_ADDR_START,Y_ADDR_START-ADDRESS_LEN+1) = bYAout;
header.write( hout );
}
void INPUT_CTRL::data_select()
{
if( header_select.read() )
data_out.write( header.read() );
else
data_out.write( data_latch.read() );
}