www.pudn.com > noc.rar > netif.cpp
/*
* TU Eindhoven
* Eindhoven, The Netherlands
*
* Name : netif.cpp
*
* Author : A.S.Slusarczyk@tue.nl
*
* Date : 15-09-2003
*
* Function : Generic network interface module for the network of Ecube routers
*
*
*/
#include "netif.h"
// buffering packet data to send
void NETWORK_INTERFACE::buffer_out_process()
{
if( rst.read() )
buffer_out.write(0);
else if( write_data.read() )
buffer_out.write(reg_data_in);
}
// buffering destination address for the packet
void NETWORK_INTERFACE::buffer_addr_process()
{
sc_bv<2*ADDRESS_LEN> addr = reg_data_in.read().range(2*ADDRESS_LEN-1,0);
if( rst.read() )
buffer_addr.write(0);
else if( write_addr.read() )
buffer_addr.write(addr);
}
// FSM sending a packet
void NETWORK_INTERFACE::send_logic()
{
bool req_out_v, send_rdy_v;
sc_bv data_out_v;
sc_bv flit_type_v = 0;
sc_bv addrx = buffer_addr.read().range(2*ADDRESS_LEN-1,ADDRESS_LEN),
addry = buffer_addr.read().range(ADDRESS_LEN-1,0);
sc_bv<16> flit_data_v = 0;
next_send_flit = send_flit.read();
send_next_state = SEND_IDLE;
req_out_v = false;
send_rdy_v = false;
switch( send_current_state.read() ){
case SEND_IDLE:
// idle - wait for send signal from processor
if( send.read() ){
// send arrived - build header flit
send_next_state = BUILD_FLIT;
next_send_flit = HEADER;
flit_type_v = 0x1;
flit_data_v = (addrx,addry);
}
else {
send_next_state = SEND_IDLE;
next_send_flit = NONE;
send_rdy_v = true;
}
break;
case BUILD_FLIT:
// building next flit - depending on which flit - output
// the flit marker (header,data,trailer) and the appropriate data
// (address,data high,data low)
switch( send_flit.read() ){
case HEADER:
flit_type_v = 0x1;
flit_data_v = (addrx,addry);
break;
case DATA_HIGH:
flit_type_v = 0x0;
flit_data_v = buffer_out.read().range(31,16);
break;
case DATA_LOW_TAIL:
flit_type_v = 0x2;
flit_data_v = buffer_out.read().range(15,0);
break;
}
send_next_state = SEND;
break;
case SEND:
// sending - assert network request, output flit
req_out_v = true;
switch( send_flit.read() ){
case HEADER:
flit_type_v = 0x1;
flit_data_v = (addrx,addry);
break;
case DATA_HIGH:
flit_type_v = 0x0;
flit_data_v = buffer_out.read().range(31,16);
break;
case DATA_LOW_TAIL:
flit_type_v = 0x2;
flit_data_v = buffer_out.read().range(15,0);
break;
}
if( ack_in.read() ){
// flit acknowledged - can send next one
// withdraw request, wait for ack to disappear
#ifdef NETPRINT
cout << name() << " sent flit t=" << flit_type_v << " data=" << hex << flit_data_v.to_uint() << dec << " @ " << sc_time_stamp() << endl;
#endif
send_next_state = WAIT_ACK_OFF;
}
else
send_next_state = SEND;
break;
case WAIT_ACK_OFF:
// wait for ack to disappear
if( ! ack_in.read() )
{
// send next flit, or exit
switch( send_flit.read() ){
case HEADER:
send_next_state = BUILD_FLIT;
next_send_flit = DATA_HIGH;
break;
case DATA_HIGH:
send_next_state = BUILD_FLIT;
next_send_flit = DATA_LOW_TAIL;
break;
case DATA_LOW_TAIL:
send_next_state = WAIT_SEND_OFF;
next_send_flit = NONE;
send_rdy_v = true;
break;
}
}
else
send_next_state = WAIT_ACK_OFF;
break;
case WAIT_SEND_OFF:
// assert send ready, wait for send to be withdrawn
send_rdy_v = true;
if( !send.read() )
send_next_state = SEND_IDLE;
else
send_next_state = WAIT_SEND_OFF;
break;
}
req_out.write(req_out_v);
send_rdy.write(send_rdy_v);
data_out.write( (flit_type_v, flit_data_v) );
}
// state update of the sending FSM
void NETWORK_INTERFACE::send_change_state()
{
if( rst.read() ){
send_current_state = SEND_IDLE;
send_flit = NONE;
}
else{
send_current_state = send_next_state;
send_flit = next_send_flit;
}
}
// FSM receiving packets
void NETWORK_INTERFACE::rcv_logic()
{
bool ack_out_v, data_rdy_v;
// sc_bv<32> buffer_in_v;
rcv_next_state = RCV_IDLE;
next_rcv_flit = rcv_flit.read();
buffer_in_n = buffer_in.read();
ack_out_v = false;
data_rdy_v = false;
switch( rcv_current_state.read() )
{
case RCV_IDLE:
// idle - wait for request from network
if( req_in.read() ){
#ifdef NETPRINT
cout << name() << " rcv flit " << hex << data_in.read().to_uint() << dec << " @ " << sc_time_stamp() << endl;
#endif
// discard flit if it's header, store in buffer if it's data
rcv_next_state = ACK;
switch(rcv_flit.read()){
case NONE: next_rcv_flit = HEADER; break;
case HEADER:
next_rcv_flit = DATA_HIGH;
buffer_in_n = (data_in.read().range(15,0), buffer_in_n.read().range(15,0));
break;
case DATA_HIGH:
next_rcv_flit = DATA_LOW_TAIL;
buffer_in_n = (buffer_in_n.read().range(31,16), data_in.read().range(15,0));
break;
}
}
else
rcv_next_state = RCV_IDLE;
break;
case ACK:
// acknowledge flit and wait until request is withdrawn
ack_out_v = true;
if( ! req_in.read() ){
// flit transmission finished
if( rcv_flit.read() == DATA_LOW_TAIL ) {
// if it was tail flit - wait for processor to read the packet
#ifdef NETPRINT
cout << name() << " received packet " << hex << buffer_in_n.to_uint() << dec << " @ " << sc_time_stamp() << endl;
#endif
rcv_next_state = WAIT_READ;
}
else
// otherwise - wait for next flit
rcv_next_state = RCV_IDLE;
}
else
rcv_next_state = ACK;
break;
case WAIT_READ:
// assert data ready and wait for processor to read the data
data_rdy_v = true;
if( read.read() ){
#ifdef NETPRINT
cout << name() << " packet read " << hex << buffer_in.read().to_uint() << dec << " @ " << sc_time_stamp() << endl;
#endif
next_rcv_flit = NONE;
rcv_next_state = RCV_IDLE;
}
else
rcv_next_state = WAIT_READ;
break;
}
// buffer_in.write(buffer_in_v);
// reg_data_out.write(buffer_in_v);
ack_out.write(ack_out_v);
data_rdy.write(data_rdy_v);
}
// state update of the receiving FSM
void NETWORK_INTERFACE::rcv_change_state()
{
if( rst.read() ){
rcv_current_state = RCV_IDLE;
rcv_flit = NONE;
buffer_in.write(0);
}
else{
rcv_current_state = rcv_next_state;
rcv_flit = next_rcv_flit;
buffer_in.write(buffer_in_n);
}
}