www.pudn.com > noc.rar > netif.h


/*
 *  TU Eindhoven
 *  Eindhoven, The Netherlands
 *
 *  Name            :   netif.h
 *
 *  Author          :   A.S.Slusarczyk@tue.nl
 *
 *  Date            :   15-09-2003
 *
 *  Function        :   Generic network interface module for the network of Ecube routers
 *
 *
 */
 
#ifndef NETIF_H_INCLUDED
#define NETIF_H_INCLUDED

#include 
#include "router.h"

SC_MODULE(NETWORK_INTERFACE)
{
  sc_in clk, rst;
  
  // processor interface
  
  // packet data or destination address
  sc_in< sc_bv<32> > reg_data_in;         
  // write reg_data_in to data buffer
  sc_in< bool > write_data;
  // write reg_data_in to address buffer
  sc_in< bool > write_addr;   
  // trigger sending
  sc_in< bool > send;
  // free the receiving buffer
  sc_in< bool > read;
  
  // contents of the receive buffer
  sc_out< sc_bv<32> > reg_data_out;
  // receive buffer contains data not confirmed with 'read'
  sc_out< bool > data_rdy;
  // previous send operation completed
  sc_out< bool > send_rdy;

  // network interface
  sc_in< sc_bv > data_in;
  sc_in< bool > req_in, ack_in;

  sc_out< sc_bv > data_out;
  sc_out< bool > req_out, ack_out;

  // buffers
  void buffer_addr_process();
  void buffer_out_process();
  sc_signal< sc_bv<2*ADDRESS_LEN> > buffer_addr;
  sc_signal< sc_bv<32> > buffer_in, buffer_out;

  sc_signal< sc_bv<32> > buffer_in_n;

  
  // control FSM for sending data
  
  // which flit (there are three flits necessary to send 32-bit data)
  enum flit_type { NONE, HEADER, DATA_HIGH, DATA_LOW_TAIL };
#ifdef VERILOG
  sc_signal send_flit, next_send_flit;
#else
  sc_signal send_flit, next_send_flit;
#endif
  
  // state of the sending process
  enum send_state { SEND_IDLE, BUILD_FLIT, SEND, WAIT_ACK_OFF, WAIT_SEND_OFF };
#ifdef VERILOG
  sc_signal send_current_state, send_next_state;
#else
  sc_signal send_current_state, send_next_state;
#endif

  void send_logic();
  void send_change_state();

  // control FSM for receiving data
  enum rcv_state { RCV_IDLE, ACK, WAIT_READ };
#ifdef VERILOG
  sc_signal rcv_flit, next_rcv_flit;
  sc_signal rcv_current_state, rcv_next_state;
#else
  sc_signal rcv_flit, next_rcv_flit;
  sc_signal rcv_current_state, rcv_next_state;
#endif
  void rcv_logic();
  void rcv_change_state();

  void forward_buffer(){
	reg_data_out.write(buffer_in.read());
  }
  
  SC_CTOR(NETWORK_INTERFACE)
	{
	  SC_METHOD(buffer_out_process);
	  sensitive_pos << clk << rst;

	  SC_METHOD(buffer_addr_process);
	  sensitive_pos << clk << rst;
	  
	  SC_METHOD(send_logic);
	  sensitive << send_current_state << send_flit << send << buffer_out << buffer_addr << ack_in;
	  
	  SC_METHOD(send_change_state);
	  sensitive_pos << clk << rst;

	  SC_METHOD(rcv_logic);
	  sensitive << rcv_current_state << rcv_flit << req_in << data_in << buffer_in << read;
	  
	  SC_METHOD(rcv_change_state);
	  sensitive_pos << clk << rst;
	  
	  SC_METHOD(forward_buffer);
	  sensitive << buffer_in;
	}
};

#ifndef VERILOG

// non-synthesizable behavioral model of a network interface client (dummy data processor)
// receive packets from the NI, send random packets
SC_MODULE(NI_RAND_DRIVER){
  
  sc_in clk, rst;
  sc_in en;
  
  sc_out< sc_bv<32> > reg_data_in;
  sc_out< bool > write_data, write_addr;
  sc_out< bool > send, read;
  
  sc_in< sc_bv<32> > reg_data_out;
  sc_in< bool > data_rdy, send_rdy;

  unsigned x,y,maxx,maxy;
  
  // the sending process
  void sending(){
	unsigned ax, ay, data;
	sc_bv<32> d;
	
	while(true){
	  
	  while( !en.read() || (rand()%10 != 0) )
		wait();
	  
	  cout << name() << " : sending " << flush;
	  // generate address
	  while(1){
		ax = rand()%(maxx+1);
		ay = rand()%(maxy+1);
		if ( ax!=x || ay !=y ) break;
	  }
	  // generate data
	  data = rand();
	  // top byte of data contains sender address (for debugging)
	  data &= 0x00ffffff;
	  data |= (x << 28);
	  data |= (y << 24);
	  	  
	  cout << " addr=(" << ax << ',' << ay << ") data=0x" << hex << data <<  " " << sc_time_stamp() << endl;
	  
	  // make address relative
	  if( ax < x ) ax = ax - x + maxx + 1; else ax -= x;
	  if( ay < y ) ay = ay - y + maxy + 1; else ay -= y;
	  
	  // write address to NI
	  d.range(15,8) = ax;
	  d.range(7,0) = ay;
	  reg_data_in = d;
	  write_addr = 1;	  

	  wait();
	  
	  // write data to NI
	  write_addr = 0;
	  d = data;
	  reg_data_in = d;
	  write_data = 1;
	  
	  wait();

	  // send data
	  write_data = 0;
	  send = 1;
	  
	  // wait for send to complete
	  wait_until(send_rdy.delayed()==true);
	  send = 0;
	  cout << '\t' << name() << " : sent (" << ax << ',' << ay << ") 0x" << hex << data << " " << sc_time_stamp() << endl;


	  wait();	  
	}
  }

  // the receiving process
  void receiving(){
	while(true){

	  while( !data_rdy.read() )
		wait();
	  
	  // read data from NI
	  cout << name() << " received 0x" << hex << reg_data_out.read().to_int() << " " << sc_time_stamp() << endl;
	  read = 1;
	  wait();

	  read = 0;
	  while( data_rdy.read() )
		wait();
	}
  }
  
  SC_CTOR(NI_RAND_DRIVER){
	SC_CTHREAD(sending, clk.pos());
	watching(rst.delayed()==true);
	
	SC_CTHREAD(receiving, clk.pos());
	watching(rst.delayed()==true);
  }
};

#endif

#endif