Esempio n. 1
0
  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 );
  }
Esempio n. 2
0
    //Method used for receiving acknowledgements of interrupts; the ack consists of
    //uninteresting data and the address corresponds to the interrupt signal to
    //be lowered
    //As a response, I lower the interrupt by sending a NULL pointer on the init_socket
    void b_transport(tlm::tlm_generic_payload& trans, sc_time& delay) {
        if(this->lastIrq < 0) {
            THROW_EXCEPTION("Error, lowering an interrupt which hasn't been raised yet!!");
        }
        tlm::tlm_command cmd = trans.get_command();
        sc_dt::uint64    adr = trans.get_address();
        unsigned char*   ptr = trans.get_data_ptr();
        if(trans.get_command() == tlm::TLM_READ_COMMAND) {
            THROW_EXCEPTION("Error, the read request is not currently supported by external PINs");
        }
        else if(cmd == tlm::TLM_WRITE_COMMAND) {
            if(this->lastIrq != adr) {
                THROW_EXCEPTION("Error, lowering interrupt " << std::hex << std::showbase << (unsigned)adr << " while " << std::hex << std::showbase << this->lastIrq << " was raised");
            }
            else {
                //finally I can really lower the interrupt: I send 0 on
                //the initSocked
                unsigned char data = 0;
                trans.set_data_ptr(&data);
                trans.set_dmi_allowed(false);
                trans.set_response_status( tlm::TLM_INCOMPLETE_RESPONSE );
                sc_time delay;
                this->init_socket->b_transport(trans, delay);
                if(trans.is_response_error()) {
                    std::string errorStr("Error in b_transport of PIN, response status = " + trans.get_response_string());
                    SC_REPORT_ERROR("TLM-2", errorStr.c_str());
                }

                this->lastIrq = -1;
            }
        }

        trans.set_response_status(tlm::TLM_OK_RESPONSE);
    }
Esempio n. 3
0
inline void lt_target::b_transport(tlm::tlm_generic_payload& trans, sc_time& delay){

	sc_dt::uint64  adr  = trans.get_address() / 4;
	unsigned char* ptr  = trans.get_data_ptr();
	unsigned int   len  = trans.get_data_length();
	unsigned char* byt  = trans.get_byte_enable_ptr();
	unsigned int   blen = trans.get_byte_enable_length();
	unsigned int   wid  = trans.get_streaming_width();

	if (adr >= sc_dt::uint64(mem_size) ) {
		trans.set_response_status( tlm::TLM_ADDRESS_ERROR_RESPONSE );
		return;
	}
	if ( wid < len ) {
		trans.set_response_status( tlm::TLM_BURST_ERROR_RESPONSE );
		return;
	}
	
	if (trans.is_read()) {
		delay += rd_latency;
		if ( byt != 0 ) {
			for ( unsigned int i = 0; i < len; i++ )
				if ( byt[i % blen] == TLM_BYTE_ENABLED ){
					ptr[i] = (mem[adr+i/4] >> ((i&3)*8)) & 0xFF;
				}
		} else {
  // TLM-2 blocking transport method
  virtual void b_transport( tlm::tlm_generic_payload& trans, sc_time& delay )
  {
    tlm::tlm_command cmd = trans.get_command();
    sc_dt::uint64    adr = trans.get_address();
    unsigned char*   ptr = trans.get_data_ptr();
    unsigned int     len = trans.get_data_length();
    unsigned char*   byt = trans.get_byte_enable_ptr();
    unsigned int     wid = trans.get_streaming_width();

    // Obliged to check address range and check for unsupported features,
    //   i.e. byte enables, streaming, and bursts
    // Can ignore DMI hint and extensions
    // Using the SystemC report handler is an acceptable way of signalling an error

    if (adr >= sc_dt::uint64(SIZE) || byt != 0 || len > 4 || wid < len)
      SC_REPORT_ERROR("TLM-2", "Target does not support given generic payload transaction");

    // Obliged to implement read and write commands
    if ( cmd == tlm::TLM_READ_COMMAND ){
      memcpy(ptr, &mem[adr], len);
      cout << "Data: " << dec << mem[adr] << 
              " is read from Address: " << dec << adr << endl;
    }
    else if ( cmd == tlm::TLM_WRITE_COMMAND ){
      memcpy(&mem[adr], ptr, len);
      cout << "Data: " << dec << mem[adr] << 
              " is written into Address: " << dec << adr << endl;
    }

    // Obliged to set response status to indicate successful completion
    trans.set_response_status( tlm::TLM_OK_RESPONSE );
  }
Esempio n. 5
0
//==============================================================================
//  dbg_transport implementation calls from initiators
//
//=============================================================================
unsigned int model_jxz_tlm::entry_transport_dbg (tlm::tlm_generic_payload &gp)
{
  tlm::tlm_command command = gp.get_command();// memory command
  unsigned char *data = gp.get_data_ptr();// data pointer
  unsigned int length = gp.get_data_length();// data length
  gp.set_response_status(tlm::TLM_COMMAND_ERROR_RESPONSE);
  return 0;
}
Esempio n. 6
0
//==============================================================================
//  b_transport implementation calls from initiators
//
//=============================================================================
void model_jxz_tlm::entry_b_transport (tlm::tlm_generic_payload &gp, sc_core::
  sc_time &delay_time)
{
  tlm::tlm_command command = gp.get_command();// memory command
  unsigned char *data = gp.get_data_ptr();// data pointer
  unsigned int length = gp.get_data_length();// data length
  unsigned long timefactor = ((length+BUSWIDTHBYTE-1)/BUSWIDTHBYTE)-1;
  bool write_ok = true;
  gp.set_response_status(tlm::TLM_COMMAND_ERROR_RESPONSE);
  return;
}
  // TLM-2 blocking transport method
  virtual void b_transport( tlm::tlm_generic_payload& trans, sc_time& delay )
  {
    tlm::tlm_command cmd = trans.get_command();
    sc_dt::uint64    adr = trans.get_address() / 4;
    unsigned char*   ptr = trans.get_data_ptr();
    unsigned int     len = trans.get_data_length();
    unsigned char*   byt = trans.get_byte_enable_ptr();
    unsigned int     wid = trans.get_streaming_width();

    // Obliged to check address range and check for unsupported features,
    //   i.e. byte enables, streaming, and bursts
    // Can ignore extensions

    // *********************************************
    // Generate the appropriate error response
    // *********************************************

    if (adr >= sc_dt::uint64(SIZE)) {
      trans.set_response_status( tlm::TLM_ADDRESS_ERROR_RESPONSE );
      return;
    }
    if (byt != 0) {
      trans.set_response_status( tlm::TLM_BYTE_ENABLE_ERROR_RESPONSE );
      return;
    }
    if (len > 4 || wid < len) {
      trans.set_response_status( tlm::TLM_BURST_ERROR_RESPONSE );
      return;
    }

    // Obliged to implement read and write commands
    if ( cmd == tlm::TLM_READ_COMMAND )
      memcpy(ptr, &mem[adr], len);
    else if ( cmd == tlm::TLM_WRITE_COMMAND )
      memcpy(&mem[adr], ptr, len);

    // Illustrates that b_transport may block
    wait(delay);

    // Reset timing annotation after waiting
    delay = SC_ZERO_TIME;

    // *********************************************
    // Set DMI hint to indicated that DMI is supported
    // *********************************************

    trans.set_dmi_allowed(true);

    // Obliged to set response status to indicate successful completion
    trans.set_response_status( tlm::TLM_OK_RESPONSE );
  }
Esempio n. 8
0
void memory::operation
(
     tlm::tlm_generic_payload  &gp
   , sc_core::sc_time          &delay_time   ///< transaction delay
) {
    sc_dt::uint64    address   = gp.get_address();     // memory address
    tlm::tlm_command command   = gp.get_command();     // memory command
    unsigned char    *data     = gp.get_data_ptr();    // data pointer
    unsigned  int     length   = gp.get_data_length(); // data length

    tlm::tlm_response_status response_status = check_address(gp)
            ? tlm::TLM_OK_RESPONSE
            : tlm::TLM_ADDRESS_ERROR_RESPONSE;

    if (gp.get_byte_enable_ptr()) {
        gp.set_response_status(tlm::TLM_BYTE_ENABLE_ERROR_RESPONSE);
    }
    else if (gp.get_streaming_width() != gp.get_data_length()) {
        gp.set_response_status(tlm::TLM_BURST_ERROR_RESPONSE);
    }
    switch (command)
    {
        default:
        {
            gp.set_response_status(tlm::TLM_COMMAND_ERROR_RESPONSE);
            break;
        }

        case tlm::TLM_WRITE_COMMAND:
        {
            if (response_status == tlm::TLM_OK_RESPONSE) {
                for (unsigned int i = 0; i < length; i++) {
                    m_memory[address++] = data[i];        // move the data to memory
                }
            }
            break;
        }

        case tlm::TLM_READ_COMMAND: {
            if (response_status == tlm::TLM_OK_RESPONSE) {
                for (unsigned int i = 0; i < length; i++)
                {
                    data[i] = m_memory[address++];         // move the data from memory
                }
            }
            break;
        }
    } // end switch
    gp.set_response_status(response_status);
}
Esempio n. 9
0
void leon3_funclt_trap::IntrTLMPort_32::b_transport( int tag, tlm::tlm_generic_payload \
    & trans, sc_time & delay ){
    unsigned char* ptr = trans.get_data_ptr();
    sc_dt::uint64 adr = trans.get_address();
    if(*ptr == 0){
        //Lower the interrupt
        this->irqSignal = -1;
    }
    else{
        //Raise the interrupt
        this->irqSignal = adr;
    }
    trans.set_response_status(tlm::TLM_OK_RESPONSE);
}
Esempio n. 10
0
    void peq_cb(tlm::tlm_generic_payload& trans, const tlm::tlm_phase& phase){
        tlm::tlm_sync_enum status;
        sc_time delay;

        switch (phase){
            case tlm::BEGIN_REQ:
                status = send_end_req(trans);
            break;

            case tlm::END_RESP:
                //std::cerr << "tlm::END_RESP in memory peq_cb" << std::endl;
                this->transactionInProgress = false;
                this->transactionCompleted.notify();
            break;

            case tlm::END_REQ:
            case tlm::BEGIN_RESP:
                SC_REPORT_FATAL("TLM-2", "Illegal transaction phase received by target");
            break;

            default:
                if (phase == internal_ph){
                    // Execute the read or write commands
                    tlm::tlm_command cmd = trans.get_command();
                    sc_dt::uint64    adr = trans.get_address();
                    unsigned char*   ptr = trans.get_data_ptr();
                    unsigned int     len = trans.get_data_length();

                    if(cmd == tlm::TLM_READ_COMMAND){
                        for(int i = 0; i < len; i++, ptr++)
                            *ptr = this->mem[adr + i];
                    }
                    else if(cmd == tlm::TLM_WRITE_COMMAND){
                        for(int i = 0; i < len; i++, ptr++)
                            this->mem[adr + i] = *ptr;
                    }


                    trans.set_response_status(tlm::TLM_OK_RESPONSE);

                    // Target must honor BEGIN_RESP/END_RESP exclusion rule
                    // i.e. must not send BEGIN_RESP until receiving previous END_RESP or BEGIN_REQ
                    send_response(trans);
                    //std::cerr << "Memory reading address in memory " << std::hex << std::showbase << adr << std::endl;
                }
            break;
        }
    }
Esempio n. 11
0
// Data interface to functional part of the model
void mmu_cache::exec_data(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();
  unsigned int len     = trans.get_data_length();

  // Log number of reads and writes for power monitoring
  if (m_pow_mon) {

    if (cmd == tlm::TLM_READ_COMMAND) {

      dyn_reads += (len >> 2) + 1;

    } else {
Esempio n. 12
0
    virtual unsigned int transport_dbg(tlm::tlm_generic_payload & trans) {
        tlm::tlm_command cmd = trans.get_command();
        sc_dt::uint64 adr = trans.get_address() / 4;
        unsigned char* ptr = trans.get_data_ptr();
        unsigned int len = trans.get_data_length();

        // Calculate the number of bytes to be actually copied
        unsigned int num_bytes = (len < (SIZE - adr) * 4) ? len : (SIZE - adr) * 4;

        if (cmd == tlm::TLM_READ_COMMAND)
            memcpy(ptr, &mem[adr], num_bytes);
        else if (cmd == tlm::TLM_WRITE_COMMAND)
            memcpy(&mem[adr], ptr, num_bytes);

        return num_bytes;
    }
Esempio n. 13
0
void DNP_master_device::master_cb( tlm::tlm_generic_payload &arg_Req, sc_time& delay)
{
	uint32_t  addr     = (uint32_t) arg_Req.get_address();
	uint32_t  len      = (uint32_t) arg_Req.get_data_length();
	uint8_t  *data_ptr = (uint8_t *) arg_Req.get_data_ptr();

	crt_trans_id ++ ; 

	memset(recvd_data, 0, sizeof(recvd_data));

	if (arg_Req.is_read()){
		 /*
		  * Read command
		  */
		 DPRINTF("R @ 0x%08x(%d) <%d>\n", addr, len, crt_trans_id);

		 for(uint32_t i = 0; i < len; i+=4){

#ifdef DEBUG_DNP_MASTER
			  uint32_t *p = (uint32_t *)recvd_data;
#endif			  
			  send_req(crt_trans_id, (addr + i), recvd_data, 4, false);
			  
			  wait(rsp_rcvd_ev);
			  memcpy((data_ptr + i), (uint32_t *)recvd_data, 4);

			  DPRINTF("R @ 0x%08x -- %08x \n", (addr + i), *p);
		 }
	}else{
		 /*
		  * Write command
		  */
		 DPRINTF("W @ 0x%08x(%d) <%d>\n", addr, len, crt_trans_id);

		 for (uint32_t i = 0; i < len; i+=4){

#ifdef DEBUG_DNP_MASTER
			  uint32_t *p = (uint32_t *)(data_ptr + i);
#endif
			  DPRINTF("W @ 0x%08x -- %08x\n", (addr + i), *p);
			  
			  send_req(crt_trans_id, (addr + i), (data_ptr + i), 4, true);
			  wait(rsp_rcvd_ev);
		}
	}
	arg_Req.set_response_status(tlm::TLM_OK_RESPONSE);
}
Esempio n. 14
0
    // TLM-2 debug transaction method
    unsigned int transport_dbg(int tag, tlm::tlm_generic_payload& trans){
        tlm::tlm_command cmd = trans.get_command();
        sc_dt::uint64    adr = trans.get_address();
        unsigned char*   ptr = trans.get_data_ptr();
        unsigned int     len = trans.get_data_length();

        if(cmd == tlm::TLM_READ_COMMAND){
            for(int i = 0; i < len; i++, ptr++)
                *ptr = this->mem[adr + i];
        }
        else if(cmd == tlm::TLM_WRITE_COMMAND){
            for(int i = 0; i < len; i++, ptr++)
                this->mem[adr + i] = *ptr;
        }

        return len;
    }
Esempio n. 15
0
  // Called on receiving BEGIN_RESP or TLM_COMPLETED
  void check_transaction(tlm::tlm_generic_payload& trans)
  {
    if ( trans.is_response_error() )
    {
      char txt[100];
      sprintf(txt, "Transaction returned with error, response status = %s",
                   trans.get_response_string().c_str());
      SC_REPORT_ERROR("TLM-2", txt);
    }

    tlm::tlm_command cmd = trans.get_command();
    sc_dt::uint64    adr = trans.get_address();
    int*             ptr = reinterpret_cast<int*>( trans.get_data_ptr() );

    fout << hex << adr << " " << name() << " check, cmd=" << (cmd ? 'W' : 'R')
         << ", data=" << hex << *ptr << " at time " << sc_time_stamp() << endl;

    // Allow the memory manager to free the transaction object
    trans.release();
  }
Esempio n. 16
0
/////////////////////////////////////////////////////////////////////////////////////
// Interface function called when receiving an IRQ event
/////////////////////////////////////////////////////////////////////////////////////
tmpl (tlm::tlm_sync_enum)::irq_nb_transport_fw
( int                      id,       
  tlm::tlm_generic_payload &payload, 
  tlm::tlm_phase           &phase,  
  sc_core::sc_time         &time)  
{
   uint8_t	value = payload.get_data_ptr()[0];

#ifdef SOCLIB_MODULE_DEBUG
std::cout << "[" << name() << "] time = " << std::dec << time.value()
          << " receive Interrupt " << id << " / value = " << (int)value << std::endl;
#endif

    assert(time.value() >= m_pending_time[id].value() 
               && "IRQ event received with a wrong date");

    m_pending_irq[id] = ( value != 0 );
    m_pending_time[id] = time;

    return tlm::TLM_COMPLETED;
}  
Esempio n. 17
0
  // TLM-2 blocking transport method
  virtual void b_transport( tlm::tlm_generic_payload& trans, sc_time& delay )
  {
    tlm::tlm_command cmd = trans.get_command();
    sc_dt::uint64    adr = trans.get_address();
    unsigned char*   ptr = trans.get_data_ptr();
    unsigned int     len = trans.get_data_length();
    unsigned char*   byt = trans.get_byte_enable_ptr();
    unsigned int     wid = trans.get_streaming_width();

    // Obliged to check address range and check for unsupported features,
    //   i.e. byte enables, streaming, and bursts
    // Can ignore DMI hint and extensions
    // Using the SystemC report handler is an acceptable way of signalling an error

    if (adr >= sc_dt::uint64(SIZE) * 4 || adr % 4)
    {
      trans.set_response_status( tlm::TLM_ADDRESS_ERROR_RESPONSE );
      return;
    }
    else if (byt != 0)
    {
      trans.set_response_status( tlm::TLM_BYTE_ENABLE_ERROR_RESPONSE );
      return;
    }
    else if (len > 4 || wid < len)
    {
      trans.set_response_status( tlm::TLM_BURST_ERROR_RESPONSE );
      return;
    }

    // Obliged to implement read and write commands
    if ( cmd == tlm::TLM_READ_COMMAND )
      memcpy(ptr, &mem[adr/4], len);
    else if ( cmd == tlm::TLM_WRITE_COMMAND )
      memcpy(&mem[adr/4], ptr, len);

    // Obliged to set response status to indicate successful completion
    trans.set_response_status( tlm::TLM_OK_RESPONSE );
  }
Esempio n. 18
0
//! @param payload  The generic TLM payload
//! @param delay    How far the initiator is beyond baseline SystemC time.
//!                 Ignored here.
// ----------------------------------------------------------------------------
void
LoggerSC::loggerReadWrite( tlm::tlm_generic_payload &payload,
			   sc_core::sc_time         &delay )
{
  // Break out the address, mask and data pointer.
  tlm::tlm_command   comm    = payload.get_command();
  sc_dt::uint64      addr    = payload.get_address();
  unsigned char     *maskPtr = payload.get_byte_enable_ptr();
  unsigned char     *dataPtr = payload.get_data_ptr();

  // Record the payload fields (data only if it's a write)
  const char *commStr;

  switch( comm ) {
  case tlm::TLM_READ_COMMAND:   commStr = "Read";            break;
  case tlm::TLM_WRITE_COMMAND:  commStr = "Write";           break;
  case tlm::TLM_IGNORE_COMMAND: commStr = "Ignore";          break;
  default:                      commStr = "Unknown command"; break;
  }

  std::cout << "Logging" << std::endl;
  std::cout << "  Command:      "   << commStr << std::endl;
  std::cout << "  Address:      0x" << std::setw( 8 ) << std::setfill( '0' )
	    <<std::hex << (uint64_t)addr << std::endl;
  std::cout << "  Byte enables: 0x" << std::setw( 8 ) << std::setfill( '0' )
	    <<std::hex << *((uint32_t *)maskPtr) << std::endl;

  if( tlm::TLM_WRITE_COMMAND == comm ) {
    std::cout << "  Data:         0x" << std::setw( 8 ) << std::setfill( '0' )
	      <<std::hex << *((uint32_t *)dataPtr) << std::endl;
  }

  std::cout << std::endl;

  payload.set_response_status( tlm::TLM_OK_RESPONSE );  // Always OK

}	// loggerReadWrite()
Esempio n. 19
0
unsigned int memory::debug
(
     tlm::tlm_generic_payload  &gp
   , sc_core::sc_time          &delay_time   ///< transaction delay
) {
    sc_dt::uint64    address   = gp.get_address();     // memory address
    tlm::tlm_command command   = gp.get_command();     // memory command
    unsigned char    *data     = gp.get_data_ptr();    // data pointer
    unsigned  int     length   = gp.get_data_length(); // data length
    bool              ok       = check_address(gp);

    if(ok) {
        switch (command)
        {
            case tlm::TLM_WRITE_COMMAND:
                for (unsigned int i = 0; i < length; i++) {
                    m_memory[address++] = data[i];         // move the data to memory
                }
                gp.set_response_status(tlm::TLM_OK_RESPONSE);
                break;

            case tlm::TLM_READ_COMMAND:
                for (unsigned int i = 0; i < length; i++) {
                    data[i] = m_memory[address++];         // move the data from memory
                }
                gp.set_response_status(tlm::TLM_OK_RESPONSE);
                break;

            default:
                ok = 0;
                break;

        }
    } // end switch

    return ok ? length : 0;
}
Esempio n. 20
0
//=====================================================================
///  @fn dmi_memory::operation
//
///  @brief DMI read and write processing
//
///  @details
///    This routine implements dmi based read and  write operations
//
//=====================================================================
void
dmi_memory::operation
( tlm::tlm_generic_payload  &gp
, sc_core::sc_time          &delay   ///< transaction delay
)
{
  std::ostringstream  msg;
  msg.str("");

  m_address   = gp.get_address();
  m_data      = gp.get_data_ptr();    ///< data pointer
  m_length    = gp.get_data_length(); ///< data length
  m_command   = gp.get_command();
  m_is_dmi_flag = false;
  gp.set_response_status(tlm::TLM_GENERIC_ERROR_RESPONSE);

  if (is_address_dmi(gp) == false )
  {
    msg << "Iniiator:" << m_ID
        << "A GP with an address not in the allowed DMI ranges has been received"
        << endl << "       "
        << "Use check_status before passing a gp to operation";
      REPORT_INFO(filename, __FUNCTION__, msg.str());
      gp.set_response_status(tlm::TLM_COMMAND_ERROR_RESPONSE); // Need a different error
    }
 else
 {
  m_offset  = m_address - m_dmi_base_address;

  switch (m_command)
  {
    case tlm::TLM_WRITE_COMMAND:
    {
      for (unsigned int i = 0; i < m_length; i++)
       {
          m_dmi_ptr[m_offset + i] = m_data[i];
        }
      gp.set_response_status(tlm::TLM_OK_RESPONSE);

      delay = delay + m_dmi_write_latency;  // update time
      report::print(m_ID, gp, filename);

      break;
    }

    case tlm::TLM_READ_COMMAND:
    {
      // clear read buffer
      for (unsigned int i = 0; i < m_length; i++)
        {
        m_data[i] = m_dmi_ptr [m_offset + i];
        }
      gp.set_response_status(tlm::TLM_OK_RESPONSE);

      delay = delay +  m_dmi_read_latency; // update time
      report::print(m_ID, gp, filename);

      break;
    }

    default:
    {
      msg << "Target: " << m_ID
          << " Unknown GP command that could be ignorable";
      REPORT_WARNING(filename, __FUNCTION__, msg.str());
      gp.set_response_status(tlm::TLM_COMMAND_ERROR_RESPONSE);
      break;
    }

    }//end switch
  }

  return;

//==============================================================================
} // end memory_operation
Esempio n. 21
0
  void peq_cb(tlm::tlm_generic_payload& trans, const tlm::tlm_phase& phase)
  {
    tlm::tlm_sync_enum status;
    sc_time delay;

    switch (phase) {
    case tlm::BEGIN_REQ:

      #ifdef DEBUG
        fout << hex << trans.get_address() << " " << name() << " BEGIN_REQ at " << sc_time_stamp() << endl;
      #endif

      // Increment the transaction reference count
      trans.acquire();

      // Put back-pressure on initiator by deferring END_REQ until pipeline is clear
      if (n_trans == 2)
        end_req_pending = &trans;
      else
      {
        status = send_end_req(trans);
        if (status == tlm::TLM_COMPLETED) // It is questionable whether this is valid
          break;
      }

      break;

    case tlm::END_RESP:
      // On receiving END_RESP, the target can release the transaction
      // and allow other pending transactions to proceed

      #ifdef DEBUG
        fout << hex << trans.get_address() << " " << name() << " END_RESP at " << sc_time_stamp() << endl;
      #endif

      if (!response_in_progress)
        SC_REPORT_FATAL("TLM-2", "Illegal transaction phase END_RESP received by target");

      trans.release();
      n_trans--;

      // Target itself is now clear to issue the next BEGIN_RESP
      response_in_progress = false;
      if (next_response_pending)
      {
        send_response( *next_response_pending );
        next_response_pending = 0;
      }

      // ... and to unblock the initiator by issuing END_REQ
      if (end_req_pending)
      {
        status = send_end_req( *end_req_pending );
        end_req_pending = 0;
      }

      break;

    case tlm::END_REQ:
    case tlm::BEGIN_RESP:
      SC_REPORT_FATAL("TLM-2", "Illegal transaction phase received by target");
      break;

    default:
      if (phase == internal_ph)
      {
        // Execute the read or write commands

        tlm::tlm_command cmd = trans.get_command();
        sc_dt::uint64    adr = trans.get_address();
        unsigned char*   ptr = trans.get_data_ptr();
        unsigned int     len = trans.get_data_length();

        if ( cmd == tlm::TLM_READ_COMMAND )
        {
          *reinterpret_cast<int*>(ptr) = rand();
          fout << hex << adr << " " << name() << " Execute READ, target = " << name()
               << " data = " << *reinterpret_cast<int*>(ptr) << endl;
        }
        else if ( cmd == tlm::TLM_WRITE_COMMAND )
          fout << hex << adr << " " << name() << " Execute WRITE, target = " << name()
               << " data = " << *reinterpret_cast<int*>(ptr) << endl;

        trans.set_response_status( tlm::TLM_OK_RESPONSE );

        // Target must honor BEGIN_RESP/END_RESP exclusion rule
        // i.e. must not send BEGIN_RESP until receiving previous END_RESP or BEGIN_REQ
        if (response_in_progress)
        {
          // Target allows only two transactions in-flight
          if (next_response_pending)
            SC_REPORT_FATAL("TLM-2", "Attempt to have two pending responses in target");
          next_response_pending = &trans;
        }
        else
          send_response(trans);
        break;
      }
    }
  }
Esempio n. 22
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 
Esempio n. 23
0
//==============================================================================
///  @fn memory::operation
//  
///  @brief performs read and write
// 
///  @details
///    This routine implements the read and  write operations. including 
///    checking for byte_enable and streaming that are not implemented
//   
//==============================================================================
void 
memory::operation     
( tlm::tlm_generic_payload  &gp     
, sc_core::sc_time          &delay_time   ///< transaction delay 
)    
{
  /// Access the required attributes from the payload
  sc_dt::uint64    address   = gp.get_address();     // memory address
  tlm::tlm_command command   = gp.get_command();     // memory command
  unsigned char    *data     = gp.get_data_ptr();    // data pointer
  unsigned  int     length   = gp.get_data_length(); // data length
  
  std::ostringstream  msg;   
  msg.str("");
  tlm::tlm_response_status response_status = check_address(gp);
  
  if (gp.get_byte_enable_ptr())
  {
    gp.set_response_status(tlm::TLM_BYTE_ENABLE_ERROR_RESPONSE);
  }
  else if (gp.get_streaming_width() != gp.get_data_length()) 
  {
    gp.set_response_status(tlm::TLM_BURST_ERROR_RESPONSE);
  }
    
  switch (command)
  {
    default:
    {
      if (m_previous_warning == false)
      {
        msg << "Target: " << m_ID 
            << " Unsupported Command Extension";
        REPORT_INFO(filename, __FUNCTION__, msg.str());
        gp.set_response_status(tlm::TLM_COMMAND_ERROR_RESPONSE);
        delay_time = sc_core::SC_ZERO_TIME;
        m_previous_warning = true;
      }
      break;
    }
    
    /// Setup a TLM_WRITE_COMMAND Informational Message and Write the Data from
    /// the Generic Payload Data pointer to Memory
    ///
    case tlm::TLM_WRITE_COMMAND:
    {
      if (response_status == tlm::TLM_OK_RESPONSE)
        {
          for (unsigned int i = 0; i < length; i++)
          {
            m_memory[address++] = data[i];     // move the data to memory
          }
          delay_time = delay_time + m_write_delay;
          report::print(m_ID, gp, filename);
        } 
      break;     
    }

    case tlm::TLM_READ_COMMAND:
    {
      if (response_status == tlm::TLM_OK_RESPONSE)
      {
        for (unsigned int i = 0; i < length; i++)
        {
          data[i] = m_memory[address++];         // move the data to memory
        }
        delay_time = delay_time + m_read_delay;
        report::print(m_ID, gp, filename);
      }     
      break;
    }
  } // end switch

  gp.set_response_status(response_status);
  
  return;
} // end memory_operation
tlm::tlm_sync_enum BridgeClassicToAMBATLM2<BUSWIDTH>::nb_bw_transport(tlm::tlm_generic_payload & trans, tlm::tlm_phase & ph, sc_core::sc_time &delay)
{
//  		std::cout << sc_core::sc_object::name()<< ph << std::endl;
	  	amba::amba_id * m_id;
	  	amba::amba_exclusive * m_exclusive;
	    tlm::tlm_sync_enum returnVal=tlm::TLM_ACCEPTED;
	    std::ostringstream msg;
	    msg.str("");
	    if(ph == amba::BEGIN_LAST_RESP || ph == tlm::BEGIN_RESP)
		{
			//assert(trans.get_command()==tlm::TLM_READ_COMMAND && "Write Command doesn't support the response.");
			master_sock.template get_extension<amba::amba_id>(m_id,trans);
			if (trans.is_write())
			{
//				std::cout << "TLM BEHAVIOR: received BEGIN_RESP at time " << sc_core::sc_time_stamp() << std::endl;
			  assert(ph == tlm::BEGIN_RESP);
			  assert(wr_packets[m_id->value] != NULL);
			  //as per packet.cc:74 writeback never needs a response
			  if (wr_packets[m_id->value]->cmd != MemCmd::Writeback)
			  {
					if (master_sock.template get_extension<amba::amba_exclusive>(m_exclusive,trans))
					{
						if (m_exclusive->value)
						{
							wr_packets[m_id->value]->req->setExtraData(0);
						}
						else
						{
							wr_packets[m_id->value]->req->setExtraData(1);
						}
					}
				  setCurTick(sc_core::sc_time_stamp().value());
                  wr_packets[m_id->value]->busFirstWordDelay = wr_packets[m_id->value]->busLastWordDelay = 0;
				  if (bus_stalling)
					  retryQueue.push(wr_packets[m_id->value]);
				  else if (!slavePort->sendTimingResp(wr_packets[m_id->value]))
				  {
						bus_stalling=true;
						retryQueue.push(wr_packets[m_id->value]);
				  }	
#ifdef DEBUG
				  else if (_trace_transactions)
					std::cout << "In " << sc_core::sc_object::name() << " at time " << sc_time_stamp() << " sending a WS response to GEM5 with address=0x" << hex << trans.get_address() << dec << " size=" << trans.get_data_length() << std::endl;
#endif
			  }
			  master_sock.release_transaction(&trans); //now we release
			  wr_packets[m_id->value] = NULL;
				if (needWrIdRetry)
				{
					setCurTick(sc_core::sc_time_stamp().value());
					needWrIdRetry=false;
					slavePort->sendRetry();
				}
			}
           else if (ph == amba::BEGIN_LAST_RESP)
           {
//				std::cout << "TLM BEHAVIOR: received BEGIN_LAST_RESP at time " << sc_core::sc_time_stamp() << std::endl;
				assert(rd_packets[m_id->value] != NULL);
				uint8_t * data=trans.get_data_ptr();
				PacketPtr pkt = rd_packets[m_id->value];
				pkt->makeTimingResponse();
				uint32_t shadow_size=pkt->getSize();
				uint64_t shadow_addr=pkt->getAddr();
//				std::cout << sc_core::sc_object::name() << " bridge received read data for address = "  << trans.get_address()-pkt->getAddr() << " at time " << sc_time_stamp() << std::endl;
				memcpy(pkt->getPtr<uint8_t>(),data,pkt->getSize());
//				if (master_sock.template get_extension<amba::amba_exclusive>(m_exclusive,trans))
//				{
//					if (m_exclusive->value)
//						pkt->req->setExtraData(0);
//					else
//						pkt->req->setExtraData(1);
//				}
				setCurTick(sc_core::sc_time_stamp().value());
                pkt->busFirstWordDelay = pkt->busLastWordDelay = 0;
				if (bus_stalling)
					retryQueue.push(pkt);
				else if (!slavePort->sendTimingResp(pkt))
				{
					bus_stalling=true;
					retryQueue.push(pkt);
				}	
#ifdef DEBUG				  						  
				else if (_trace_transactions)
				{
					std::cout << "In " << sc_core::sc_object::name() << " at time " << sc_time_stamp() << " sending a READ response to GEM5 with address=0x" << hex << shadow_addr << dec << " size=" << shadow_size;
					std::cout << hex << " and data= [";
					for(unsigned j=0;j<shadow_size; j++)
						std::cout << "0x" << uint32_t(data[j]) << ",";
					std::cout << "]" << dec << std::endl;
				}
#endif
				rd_packets[m_id->value]=NULL;
				master_sock.release_transaction(&trans);
				if (needRdIdRetry)
				{
					setCurTick(sc_core::sc_time_stamp().value());
					needRdIdRetry=false;
					slavePort->sendRetry();
				}
			}
           else
           {
        	   //received a read data phase
           }
			//always accept directly (cf EagleNest spec)
//			std::cout << "TLM BEHAVIOR: sending  TLM_UPDATED & END_RESP at time " << sc_core::sc_time_stamp() << std::endl;
            ph=tlm::END_RESP;
			return tlm::TLM_UPDATED;
		}
	    else if(ph ==tlm::END_REQ)
	    { 
//			std::cout << "TLM BEHAVIOR: received END_REQ and returning TLM_ACCEPTED at time " << sc_core::sc_time_stamp() << std::endl;
			if (needRetry)
			{
				setCurTick(sc_core::sc_time_stamp().value());
				trans.release();
				needRetry=false;
				slavePort->sendRetry();
			}
	    }
		else if(ph== amba::END_DATA )
		{
//			std::cout << "TLM BEHAVIOR: received END_DATA and returning TLM_ACCEPTED at time " << sc_core::sc_time_stamp() << std::endl;
			if (need_wenable_event)
			{
				need_wenable_event=false;
            	wenable_event.notify();
			}
			return tlm::TLM_ACCEPTED;
		}
		else
				assert("Unexpected phase returned from AXI slave.");	
		return returnVal;
}
Esempio n. 25
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);

  }
}