www.pudn.com > noc.rar > oarbiter.cpp


/*
 *  TU Eindhoven
 *  Eindhoven, The Netherlands
 *
 *  Name            :   oarbiter.cpp
 *
 *  Author          :   A.S.Slusarczyk@tue.nl
 *
 *  Date            :   13-09-2003
 *
 *  Function        :   Link access arbiter for e-cube router
 *
 *
 */

#include "oarbiter.h"


void ARBITER_CHANNEL_CTRL::logic()
{
  bool reqout_v, arb_req_v;
  
  reqout_v = false;
  arb_req_v = false;
  next_state = IDLE;
  
  switch(current_state.read())
    {
    case IDLE:
      // wait for queue to request channel
      if( reqin.read() ){
        next_state = REQUEST_CHANNEL;
        arb_req_v = true; // request link from arbiter 
      }
      else
        next_state = IDLE;
      break;
      
    case REQUEST_CHANNEL:
      // wait for arbiter to grant the link
      arb_req_v = true;
      if( arb_grant.read() ){
        // link was granted - the data will be output on the link
        // output request to the network
        reqout_v = true; 
        next_state = WAIT_REQ_OFF;
      }
      else{
        arb_req_v = true;
        next_state = REQUEST_CHANNEL;
      }
      break;
      
    case WAIT_REQ_OFF:
      // wait for queue to withdraw req
      if( reqin.read() ) {
        reqout_v = true;
        next_state = WAIT_REQ_OFF;
      }
      else 
        next_state = IDLE;
      break;
    }
  reqout.write(reqout_v);
  arb_req.write(arb_req_v);
}

void ARBITER_CHANNEL_CTRL::change_state()
{
  if( rst.read() )
    current_state = IDLE;
  else
    current_state = next_state;
}

// ack received from the network is permanently forwarded to the queue
void ARBITER_CHANNEL_CTRL::forward_ack()
{
  ackout.write( ackin.read() );
}


void ARBITER_SELECT_CHANNEL::select()
{
  bool r0 = req0.read(), r1 = req1.read();
  
  bool ch_bsy = channel_busy.read();
  
  if( ch_bsy ){
    // if link is busy and the requesting channel has withdrawn request
    // - free the link
    if( selected_channel.read() && !r1 
        ||
        !selected_channel.read() && !r0 
        ) 
      ch_bsy = false;
  }
  
  
  if( !ch_bsy )
    {
      // link is free - assign it to a requesting channel
      if( r0 ) { // ch0 has priority
        selected_channel.write(false);
        ch_bsy = true;
      }
      else if( r1 ){
        selected_channel.write(true);
        ch_bsy = true;
      }
    }
  
  channel_busy.write( ch_bsy );
}

void ARBITER_SELECT_CHANNEL::output()
{
  // multiplex virtual channel data on the link
  dataout.write( selected_channel.read() ? data1.read() : data0.read() );
  // grant link
  grant0.write( channel_busy.read() && ! selected_channel.read() );
  grant1.write( channel_busy.read() && selected_channel.read() );  
}