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