www.pudn.com > noc.rar > netif_b.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
* with arbitrary length packets
*
*/
#include "netif_b.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);
}
void NETWORK_INTERFACE::register_packet_end()
{
if( rst.read() )
packet_end_reg.write(0);
else if( wr_packet_end.read() )
packet_end_reg.write(packet_end.read());
}
// FSM sending a packet
void NETWORK_INTERFACE::send_logic()
{
bool req_out_v, send_rdy_v, wr_packet_end_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;
wr_packet_end_v = false;
switch( send_current_state.read() ){
case SEND_IDLE:
// idle - wait for send signal from processor
if( send.read() ){
// send header flit
send_next_state = SEND;
next_send_flit = HEADER;
wr_packet_end_v = true; // check if the last-packet-word marker is set
}
else {
send_next_state = SEND_IDLE;
next_send_flit = NONE;
send_rdy_v = true;
}
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:
flit_type_v = 0x0;
flit_data_v = buffer_out.read().range(31,16);
break;
case TAIL:
// if its the last packet word, mark flit as trailer
flit_type_v = (packet_end_reg.read() ? 0x2 : 0x0);
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 of the word, or check if next word is there
switch( send_flit.read() ){
case HEADER:
send_next_state = SEND;
next_send_flit = DATA;
break;
case DATA:
send_next_state = SEND;
next_send_flit = TAIL;
break;
case 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() )
if( packet_end_reg.read() )
// if it was last word of the packet - goto idle
send_next_state = SEND_IDLE;
else
// otherwise - wait for processor to supply next packet word
send_next_state = NEXT_WORD;
else
send_next_state = WAIT_SEND_OFF;
break;
case NEXT_WORD:
// wait for processor to supply next word of the packet
next_send_flit = DATA;
if( send.read() ){
// send next word
send_next_state = SEND;
wr_packet_end_v = true;
}
else {
send_next_state = NEXT_WORD;
send_rdy_v = true;
}
break;
}
wr_packet_end.write(wr_packet_end_v);
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, rcv_packet_end_v;
sc_uint<2> flit_type = sc_bv<2>(data_in.read().range(17,16));
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;
rcv_packet_end_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:
buffer_in_n = 0;
next_rcv_flit = HEADER;
break;
case HEADER:
buffer_in_n = 0;
break;
case DATA:
buffer_in_n = (data_in.read().range(15,0), buffer_in.read().range(15,0));
break;
case TAIL:
buffer_in_n = (buffer_in.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
switch(rcv_flit.read()){
case HEADER:
// got header, wait for data
rcv_next_state = RCV_IDLE;
next_rcv_flit = DATA;
break;
case DATA:
// got data high, get data low
rcv_next_state = RCV_IDLE;
next_rcv_flit = TAIL;
break;
case TAIL:
// got data low - check if it's tail flit or another data follows
// and wait for the processor to read the received data
rcv_next_state = WAIT_READ;
if( flit_type == 2 ) next_rcv_flit = NONE;
else next_rcv_flit = DATA;
#ifdef NETPRINT
cout << name() << " received data " << hex << buffer_in.read().to_uint() << dec << " @ " << sc_time_stamp() << endl;
#endif
break;
}
}
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 the next expected flit is header - it's the last word of packet
rcv_packet_end_v = (rcv_flit.read() == NONE);
if( read.read() ){
#ifdef NETPRINT
cout << name() << " data read " << hex << buffer_in.read().to_uint() << dec << " @ " << sc_time_stamp() << endl;
#endif
rcv_next_state = RCV_IDLE;
}
else
rcv_next_state = WAIT_READ;
break;
}
ack_out.write(ack_out_v);
data_rdy.write(data_rdy_v);
rcv_packet_end.write(rcv_packet_end_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);
}
}