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);
  }
}