Exemple #1
0
/////////////////////////////////////////////////////////////////////////////////////
// Interface function executed when receiving a response from VCI target[id].
// It directly routes the response to the proper VCI initiator (no time filtering).
/////////////////////////////////////////////////////////////////////////////////////
tmpl(tlm::tlm_sync_enum)::nb_transport_bw( int                        id,   
                                           tlm::tlm_generic_payload   &payload,  
                                           tlm::tlm_phase             &phase,   
                                           sc_core::sc_time           &time)  
{
    // get message SRCID
    soclib_payload_extension *resp_extension_ptr;
    payload.get_extension(resp_extension_ptr);

    unsigned int	srcid = resp_extension_ptr->get_src_id();
  
#ifdef SOCLIB_MODULE_DEBUG
printf("    [%s] receive VCI RESPONSE from target %d for init %d / time = %d\n", 
        name(), id, srcid, (int)time.value() );
#endif

    // get destination
//    unsigned int dest = m_rsp_routing_table[srcid];
    unsigned int dest = srcid;

    // update the transaction time
    time = time + (m_latency*UNIT_TIME);
  
#ifdef SOCLIB_MODULE_DEBUG
printf("    [%s] send VCI RESPONSE on port %d / time = %d\n", 
        name(), dest, (int)time.value() );
#endif

    (*p_to_initiator[dest])->nb_transport_bw( payload, 
                                              phase, 
                                              time);
    return tlm::TLM_COMPLETED;
} // end nb_transport_bw 
/////////////////////////////////////////////////////////////////////////////////////
// Interface function called when receiving a VCI response
/////////////////////////////////////////////////////////////////////////////////////
tmpl (tlm::tlm_sync_enum)::nb_transport_bw    
( tlm::tlm_generic_payload           &payload,       // payload
  tlm::tlm_phase                     &phase,         // phase
  sc_core::sc_time                   &time)          // time
{
#ifdef SOCLIB_MODULE_DEBUG
  std::cout << name() << " Receive response time = " << time.value() << std::endl;
#endif

  //update local time if the command message is different to write
  soclib_payload_extension *extension_ptr;
  payload.get_extension(extension_ptr);
  if(!extension_ptr->is_null_message()){

    m_rsp_time = time;
    
    if(!extension_ptr->is_write()){
      update_time(time);
    }
  }

  m_rsp_received.notify (sc_core::SC_ZERO_TIME);
    
  return tlm::TLM_COMPLETED;
}
Exemple #3
0
/////////////////////////////////////////////////////////////////////////////////////
// Interface function executed when receiving a response on the VCI initiator port
// If it is a VCI response, the Boolean associated to the channel is set.
/////////////////////////////////////////////////////////////////////////////////////
tmpl(tlm::tlm_sync_enum)::nb_transport_bw ( tlm::tlm_generic_payload &payload, 
                                             tlm::tlm_phase           &phase,       
                                             sc_core::sc_time         &time)  
{
    // update local time and notify
    if( time.value() > m_pdes_local_time->get().value()) m_pdes_local_time->set(time);

    // test transaction type
    soclib_payload_extension *extension_pointer;
    payload.get_extension(extension_pointer);
    if( extension_pointer->is_read() or extension_pointer->is_write() )
    { 
        // get channel index 
        size_t channel = extension_pointer->get_trd_id();

        // set signal response received
        assert( ((m_state[channel] == STATE_READ_RSP) or 
                 (m_state[channel] == STATE_WRITE_RSP)) and
        "ERROR in VCI_MULTI_DMA : unexpected response received");

        m_rsp_received[channel] = true;
    }

    return tlm::TLM_COMPLETED;
}
  virtual void b_transport( tlm::tlm_generic_payload& trans, sc_time& delay )
  {
    tlm::tlm_command cmd = trans.get_command();
    unsigned char*   ptr = trans.get_data_ptr();
    unsigned int     len = trans.get_data_length();
    unsigned char*   byt = trans.get_byte_enable_ptr();
    unsigned int     bel = trans.get_byte_enable_length();

    my_extension* ext;
    trans.get_extension(ext);
    assert( ext );

    assert( len == ext->len );
    assert( bel == ext->bel );
    for (unsigned int i = 0; i < bel; i++)
      assert( byt[i] == ext->byt[i] );
    for (unsigned int i = 0; i < len; i++)
      assert( ptr[i] == ext->ptr[i] );

    if (cmd == tlm::TLM_READ_COMMAND)
    {
      for (unsigned int i = 0; i < len; i++)
      {
        data[i] = rand() % 256;
        ptr[i]  = data[i];
      }
      ext->ptr = data;
    }

    trans.set_dmi_allowed( true );
    trans.set_response_status( tlm::TLM_OK_RESPONSE );
  }
Exemple #5
0
/////////////////////////////////////////////////////////////////////////////////////
// Interface function executed when receiving a command from VCI initiator[id].
// It registers the command in the central buffer.
// The initiator thread is desceduled if the buffer is full.
/////////////////////////////////////////////////////////////////////////////////////
tmpl(tlm::tlm_sync_enum)::nb_transport_fw( int                         id,          
                                           tlm::tlm_generic_payload    &payload,    
                                           tlm::tlm_phase              &phase,     
                                           sc_core::sc_time            &time)     
{

#ifdef SOCLIB_MODULE_DEBUG
printf( "    [%s] receive COMMAND from init %d / time = %d \n", 
       name(), id, (int)time.value() );
#endif

    bool push = false;
    do
    {
        // try to push a transaction in the central buffer
        push = m_central_buffer.push( id, 
                                      payload, 
                                      phase, 
                                      time );
        if( not push )
        {

#ifdef SOCLIB_MODULE_DEBUG
printf("######    [init %d] cannot push into VGMN buffer => deschedule \n", id);
#endif
            ///////////////////////////////////////
            sc_core::wait( sc_core::SC_ZERO_TIME );
            ///////////////////////////////////////

#ifdef SOCLIB_MODULE_DEBUG
printf("######    [init %d] wake up \n", id);
#endif

        }
        else
        {

#ifdef SOCLIB_MODULE_DEBUG
soclib_payload_extension *extension_ptr;
payload.get_extension(extension_ptr);
if( extension_ptr->is_active() || extension_ptr->is_inactive() )
{
    m_push_activity_count++;
    printf( "    [%s] push ACTIVITY command into buffer\n", name() );
}
else if( extension_ptr->is_null_message() )
{
    m_push_null_count++;
    printf( "    [%s] push NULL command into buffer\n", name() );
}
else
{
    m_push_vci_count++;
    printf( "    [%s] push VCI command into buffer\n", name() );
}
#endif
            // notify to wake up the thread
            m_cmd_received.notify( sc_core::SC_ZERO_TIME );
        }
    } while ( not push );

    return  tlm::TLM_COMPLETED;

} //end nb_transport_fw
//=============================================================================
// nb_transport_fw implementation calls from initiators 
//
//=============================================================================
tlm::tlm_sync_enum                                  // synchronization state
at_target_4_phase::nb_transport_fw                  // non-blocking transport call through Bus
( tlm::tlm_generic_payload &gp                      // generic payoad pointer
, tlm::tlm_phase           &phase                   // transaction phase
, sc_core::sc_time         &delay_time)             // time it should take for transport
{
  std::ostringstream  msg;                          // log message
  
  tlm::tlm_sync_enum  return_status = tlm::TLM_COMPLETED;
  
  #if (  defined ( USING_EXTENSION_OPTIONAL  ) )
  
  extension_initiator_id *extension_pointer;
  
  gp.get_extension ( extension_pointer );
  
  msg.str("");
  msg << "Target: " << m_ID              
      << " extension ";
  
  if ( extension_pointer )
  {
    msg << "data: " << extension_pointer->m_initiator_id;

    REPORT_INFO ( filename,  __FUNCTION__, msg.str() );
  }
  
  #endif  /* USING_EXTENSION_OPTIONAL */

  msg.str("");
  msg << "Target: " << m_ID               
      << " nb_transport_fw (GP, " 
      << report::print(phase) << ", "
      << delay_time << ")";
 
//-----------------------------------------------------------------------------
// decode phase argument 
//-----------------------------------------------------------------------------
  switch (phase)
  {
//=============================================================================
    case tlm::BEGIN_REQ: 
    {	
      sc_core::sc_time PEQ_delay_time = delay_time + m_accept_delay;
      
      m_end_request_PEQ.notify(gp, PEQ_delay_time); // put transaction in the PEQ
           
      return_status = tlm::TLM_ACCEPTED;   
       
      msg << endl << "      "
        << "Target: " << m_ID  
        << " " << report::print(return_status) <<  " (GP, "
        << report::print(phase) << ", "
        << delay_time << ")" ;
      REPORT_INFO(filename,  __FUNCTION__, msg.str());
      
      break;
      } // end BEGIN_REQ

//=============================================================================
    case tlm::END_RESP:
    { 
      m_end_resp_rcvd_event.notify (delay_time);
      return_status = tlm::TLM_COMPLETED;         // indicate end of transaction     
      break;
    }
    
//=============================================================================
    case tlm::END_REQ:
    case tlm::BEGIN_RESP:
    { 
      msg << "Target: " << m_ID 
          << " Illegal phase received by target -- END_REQ or BEGIN_RESP";
      REPORT_FATAL(filename, __FUNCTION__, msg.str()); 
      return_status = tlm::TLM_ACCEPTED;
      break;
    }
   
//=============================================================================
    default:
    { 
      return_status = tlm::TLM_ACCEPTED; 
      if(!m_nb_trans_fw_prev_warning)
        {
        msg << "Target: " << m_ID 
            << " unknown phase " << phase << " encountered";
        REPORT_WARNING(filename, __FUNCTION__, msg.str()); 
        m_nb_trans_fw_prev_warning = true;
        }
      break;
    }
  }
  
  return return_status;  
} //end nb_transport_fw
Exemple #7
0
////////////////////////////////////////////////////////////////////////////////////
// Interface function used when receiving a VCI command on the target port
// As the dated transactions on the VCI target port are used to update the local
// time when all DMA channels are IDLE, this component requires periodical
// NULL messages from the interconnect. 
////////////////////////////////////////////////////////////////////////////////////
tmpl(tlm::tlm_sync_enum)::nb_transport_fw ( tlm::tlm_generic_payload &payload,
                                            tlm::tlm_phase           &phase, 
                                            sc_core::sc_time         &time)   
{
    size_t  cell;
    size_t  reg;
    size_t  channel;

    soclib_payload_extension* extension_pointer;
    payload.get_extension(extension_pointer);
    
    // Compute global state
    bool all_idle = true;
    for( size_t k = 0 ; k < m_channels ; k++ )
    {
        if( m_state[k] != STATE_IDLE ) all_idle = false;
    }

    // update local time if all channels IDLE 
    if ( all_idle and  (m_pdes_local_time->get().value() < time.value()) )
    {
        m_pdes_local_time->set( time );
    }

    // No other action on NULL messages
    if ( extension_pointer->is_null_message() ) 
    {

#if SOCLIB_MODULE_DEBUG
std::cout << "[" << name() << "] time = "  << time.value() 
          << " Receive NULL message" << std::endl;
#endif
        return tlm::TLM_COMPLETED;
    }

    // address and length checking for a VCI command
    bool	one_flit = (payload.get_data_length() == 4);
    addr_t	address = payload.get_address();

    if ( m_segment.contains(address) && one_flit )
    {
        cell    = (size_t)((address - m_segment.baseAddress()) >> 2);
        reg     = cell % DMA_SPAN;
        channel = cell / DMA_SPAN;

        // checking channel overflow
        if ( channel < m_channels ) payload.set_response_status(tlm::TLM_OK_RESPONSE);
        else             payload.set_response_status(tlm::TLM_GENERIC_ERROR_RESPONSE);

        if ( extension_pointer->get_command() == VCI_READ_COMMAND )
        {

#if SOCLIB_MODULE_DEBUG
std::cout << "[" << name() << "] time = "  << time.value() 
          << " Receive VCI read command : address = " << std::hex << address
          << " / channel = " << std::dec << channel
          << " / reg = "  << reg << std::endl;
#endif
        
            if ( reg == DMA_SRC )
            {
                utoa( m_source[channel], payload.get_data_ptr(), 0 );
            }
            else if ( reg == DMA_DST )
            {
                utoa( m_destination[channel], payload.get_data_ptr(), 0 );
            }
            else if ( reg == DMA_LEN )
            {
                utoa( m_state[channel], payload.get_data_ptr(), 0 );
            }
            else if ( reg == DMA_IRQ_DISABLED ) 
            {
                utoa( (int)(m_irq_disabled[channel]), payload.get_data_ptr(), 0 );
            }
            else    payload.set_response_status(tlm::TLM_GENERIC_ERROR_RESPONSE);
        } // end read

        else if (extension_pointer->get_command() == VCI_WRITE_COMMAND)
        {
            uint32_t data = atou(payload.get_data_ptr(), 0);

#if SOCLIB_MODULE_DEBUG
std::cout << "[" << name() << "] time = "  << time.value() 
          << " Receive VCI write command : address = " << std::hex << address
          << " / channel = " << std::dec << channel
          << " / reg = "  << reg 
          << " / data = " << data << std::endl;
#endif
            // configuration command other than soft reset
            // are ignored when the DMA channel is active
            if ( reg == DMA_RESET )
            {
                m_stop[channel] = true;
            }
            else if ( m_state[channel] != STATE_IDLE )
            {
                if      ( reg == DMA_SRC )  m_source[channel]      = data;
                else if ( reg == DMA_DST )  m_destination[channel] = data;
                else if ( reg == DMA_LEN ) 
                {
                    m_length[channel] = data;
                    m_stop[channel]   = false;
                    m_event.notify();
                }
                else if ( cell == DMA_IRQ_DISABLED )  m_irq_disabled[channel] = (data != 0);
                else    payload.set_response_status(tlm::TLM_GENERIC_ERROR_RESPONSE);
            }
            else
            {
                std::cout << name() 
                << " warning: receiving a new command while busy, ignored" << std::endl;
            }
        } // end if write
        else // illegal command
        {
            payload.set_response_status(tlm::TLM_GENERIC_ERROR_RESPONSE);
        }
    } // end if legal address 
Exemple #8
0
// Instruction interface to functional part of the model
void mmu_cache::exec_instr(tlm::tlm_generic_payload& trans, sc_core::sc_time& delay, bool is_dbg) {

  // Vars for payload decoding
  tlm::tlm_command cmd = trans.get_command();
  sc_dt::uint64 addr   = trans.get_address();
  unsigned char * ptr  = trans.get_data_ptr();

  // Log instruction reads for power monitoring
  if (m_pow_mon) {
    dyn_reads += (trans.get_data_length() >> 2) + 1;
  }

  // Extract extension
  icio_payload_extension * iext;
  trans.get_extension(iext);

  unsigned int *debug;
  unsigned int flush;

  // Check/extract instruction payload extension
  if (iext!=NULL) {

    debug = iext->debug;
    flush = iext->flush;

  } else {

    // No iext
    debug = NULL;
    flush = 0;

    v::error << name() << "IEXT Payload extension missing" << v::endl;
  }

  // Flush instruction
  if (flush) {

    v::debug << name() << "Received flush instruction - flushing both caches" << v::endl;

    // Simultaneous flush of both caches
    icache->flush(&delay, debug, is_dbg);
    dcache->flush(&delay, debug, is_dbg);

    trans.set_response_status(tlm::TLM_OK_RESPONSE);

    return;

  }

  if (cmd == tlm::TLM_READ_COMMAND) {

    assert( 1 ); // fix asi -> priv / unpriv

    mmu_cache_base::exec_instr(addr, ptr, 0x8, debug, flush, delay, is_dbg); // ToDo: fix ASI! 0x8 -> unprivileged instruction

    // Set response status
    trans.set_response_status(tlm::TLM_OK_RESPONSE);

  } else {

    v::error << name() << " Command not valid for instruction cache (tlm_write)" << v::endl;
    // Set response status
    trans.set_response_status(tlm::TLM_COMMAND_ERROR_RESPONSE);

  }
}