Greetings ITC Techies, As a follow up to the face-to-face two weeks ago, I've been busy incorporating some of the good suggestions at that meeting. One major thing I heard was some disappointment that the non-blocking fifo interface was not congruent with the pipes interface in terms of handling data shaping, variable length messaging. Initially I had thought there were some complications with combining data shaping in non-blocking interfaces. However, the more I thought about it the more I realized that we can probably have our cake and eat it too. Plus I agree that unifying the two would remove the complication of two separate use models - one for TLM/FIFO applications and the other for streaming/PIPE applications. We can still have two use models but at least a unified interface. Toward that end, I've made some improvements to the current proposal and have been able to qualify these in the prototype. Here is a summary of the changes: 1. Merging of FIFO and PIPE interfaces I've merged dpi_fifo non-blocking calls into dpi_pipe calls. Now the dpi_pipe interface supports the full blocking streaming calls and data shaping features just as it had before. Plus it now has a thread-neutral non-blocking interface as well. The non-blocking send() and receive() calls take the same argument profiles as the blocking ones so that data shaping is still supported. ---------------------------------------------------- Blocking (thread-aware calls): ---------------- C side Data transfer ops: dpi_pipe_c_send() dpi_pipe_c_receive() dpi_pipe_c_flush() ---------------- HDL side Data transfer ops: dpi_pipe_hdl_send() dpi_pipe_hdl_receive() dpi_pipe_hdl_flush() ---------------------------------------------------- Non-blocking (thread-neutral calls): ---------------- C side Data transfer ops: dpi_pipe_c_try_send() dpi_pipe_c_try_receive() dpi_pipe_c_try_flush() Query ops: dpi_pipe_c_can_send() dpi_pipe_c_can_receive() Notify ops: (dpi_pipe_notify_ok_to_send)() (dpi_pipe_notify_ok_to_receive)() ---------------- HDL side Data transfer ops: dpi_pipe_hdl_try_send() dpi_pipe_hdl_try_receive() dpi_pipe_hdl_try_flush() Query ops: dpi_pipe_hdl_can_send() dpi_pipe_hdl_can_receive() Notify ops: dpi_pipe_hdl_notify_ok_to_send() dpi_pipe_hdl_notify_ok_to_receive() 2. Notify callbacks now dynamic on the C side Per had commented at the face-to-face that the notify callbacks were hard coded function names and questioned if we should make them function pointers instead. After exploring this more, it became clear that the fixed named callbacks do not allow much flexibility in terms of implementing higher thread-aware interfaces on top of the thread-neutral calls. For example you might want one function if you're using TLM proxies but another if you're using blocking DPI ops directly. To accommodate this, it turns out to be a lot more flexible if the notify callback can be changed to different functions on a pipe by pipe basis. For this reason I've changed the notify callback to be programmable on the C side. User's will never really need to deal with these complications since they will tend to use higher level blocking calls or TLM interfaces. So this is a complication that can be potentially limited to the implementor not the user. Nonetheless I think it makes sense to make the underlying API a clear part of the standard for the implementor. To support the programmable notify callbacks two functions were added to set a callback pointer and context and to retrieve context: typedef void (*dpi_pipe_notify_callback)( void *context ); // input: C model context void *dpi_pipe_get_notify_context( void *pipe_handle ); // input: pipe handle void dpi_pipe_set_notify_callback( void *pipe_handle, // input: pipe handle dpi_pipe_notify_callback notify_callback, // input: notify callback function void *notify_context ); // input: notify context The notify callback itself is now passed the context directly which is more efficient (no longer has to do a lookup using svGetScope()/svGetUserData()). The attached examples show how these calls are used. 3. Pipe handles used in place of pipe IDs on the C side Another comment that was made a few weeks ago is that it is somewhat awkward to set the scope before each call to a pipe on the C side. It turns out, this requirement also can make implementations less efficient. I'm now proposing that we replace the pipe-id argument to all C-side calls with a pipe_handle argument instead. The pipe handle can be derived once at initialization time and reused many times without having to set scope each time and requiring the internal implementation to do a lookup based on the scope and the pipe ID to retrieve the internal data structure associated with a pipe. Doing this not only made the user application code a lot cleaner looking but made the implementation more efficient as well (fewer lookups and pointer indirections on each call). To faciliate pipe handles, a new call is added to retrieve a pipe handle for a given DPI scope and pipe ID: void *dpi_pipe_c_handle( // return: pipe handle svScope hdl_context, // input: HDL context int pipe_id, // input: intra-module pipe identifier svBit input_or_output ); // input: 1 for input pipe, // 0 for output pipe 4. Thread-neutral calls to support blocking flush op We may want to re-think this a bit but this is what I have for now. Since flush is, by definition, a blocking operation, it is thread-aware. To be consistent with providing thread-neutral API support for implementation of all blocking calls, it stands to reason we need dpi_c/hdl_try_flush() calls to compliment the dpi_c/hdl_flush() calls. So I've added this to the API. There are a couple of other possible options for this. 5. Automatic flush-on-eom Cadence suggested that, on a pipe-by-pipe basis, that there be a means to enable automatic flush when eom is specified. The committee agreed that this would be useful. A new call is added to specify automatic flush-on-eom mode for a pipe designated by a given handle. This mode configuration call is always initiated only on the C side (at initialization) for both input and output pipes: void dpi_pipe_set_eom_auto_flush( void *pipe_handle, // input: pipe handle svBit enabled ); // input: enable/disable 6. Limitless transaction sizes on the C side for data shaping At the face-to-face Shabtay expressed some disappointment that for data shaping funnels, the input transaction from the C side is limited in size to the width of the pipe as statically specified on the HDL side. Happily it turns out this is not true ! Since svBitVecVal arrays can be essentially unbounded, using data shaping (funnel) an arbitrarily large number of elements can be sent from or received to the C side in a single call. Only on the HDL side do we have a practical limitation on the number of elements that can be received or sent on any given call. As before, this is equal to the size of the statically declared data arguments on the HDL side. I've attached header files for the new calls for both the HDL and C sides. I've attached a simple example of blocking call implementations for both the C and HDL side using the thread-neutral interfaces described above. (For HDL side example see dpi_pipes.vh, for C side example see dpi_pipes_sysc.cxx). I've also attached the revised example of the TLM proxy model that is currently in the appendix of the working document. I'm ready to make these detailed updates to the working document but I want to make sure I have some degree of buyin. I can also update the distributed example to reflect the latest changes. I really think with this proposal I've addressed many of the concerns raised about pipes at the face-to-face and, with the committee's cooperation, I'd like incorporate these changes into the working document ASAP. -- johnS This email may contain material that is confidential, privileged and/or attorney work product for the sole use of the intended recipient. Any review, reliance or distribution by others or forwarding without express permission /\ is strictly prohibited. If you are /\ | \ not the intended recipient please | \ / | contact the sender and delete / \ \ all copies. /\_/ K2 \_ \_ ______________________________/\/ \ \ John Stickley \ \ \ Principal Engineer \ \________________ Mentor Graphics - MED \_ 17 E. Cedar Place \ john_stickley@mentor.com Ramsey, NJ 07446 \ Phone: (201) 818-2585 ________________________________________________________________ //=========================================================================== // dpi_pipes.h // // @(#) $Id: dpi_pipes.h,v 1.5 2005/10/03 16:38:30 jstickle Exp $ //=========================================================================== //--------------------------------------------------------------------------- // Mentor Graphics, Corp. // // (C) Copyright, Mentor Graphics, Corp. 2003-2006 // All Rights Reserved // Licensed Materials - Property of Mentor Graphics, Corp. // // No part of this file may be reproduced, stored in a retrieval system, // or transmitted in any form or by any means --- electronic, mechanical, // photocopying, recording, or otherwise --- without prior written permission // of Mentor Graphics, Corp. // // WARRANTY: // Use all material in this file at your own risk. Mentor Graphics, Corp. // makes no claims about any material contained in this file. //--------------------------------------------------------------------------- #ifndef _dpi_pipes_h #define _dpi_pipes_h #include "svdpi.h" #ifdef __cplusplus extern "C" { #endif //--------------------------------------------------------------------------- // dpi_pipe_c_handle() -- johnS 1-26-06 // // This function retreives an opaque handle representing a transaction // input or output pipe given an HDL scope and a pipe ID. //--------------------------------------------------------------------------- void *dpi_pipe_c_handle( svScope hdl_context, // input: HDL context int pipe_id, // input: intra-module pipe identifier svBit input_or_output ); // input: 1 for input pipe, 0 for output pipe //--------------------------------------------------------------------------- // dpi_pipe_c_send() -- johnS 1-26-06 // // These is the basic blocking send function for a transaction input pipe. // The passed in data is sent to the pipe. If necessary the calling thread // is suspended until there is room in the pipe. // // The eom arg is a flag which is used for user specified end-of-message (eom) // indication. It can be used for example to mark the end of a frame containing // a sequence of transactions. // // dpi_pipe_c_receive() // // This is the basic blocking receive function for a transaction output pipe. // // The eom argument for this call is an output argument. It is set to the // same settings of the flag passed on the send end of the pipe as described // above. Thus is can be used by the caller to query whether the current // read is one for which an eom was specified when the data was written on // the send end. // // Both the send() and receive() calls are thread-aware. They can be // easily implemented using a simple reference implementation that makes // use of the non-blocking thread-neutral interface decribed below // in conjunction with a selected threading system. //--------------------------------------------------------------------------- void dpi_pipe_c_send( void *pipe_handle, // input: pipe handle int bytes_per_element, // input: #bits/element int num_elements, // input: #elements to be written const svBitVecVal *data, // input: data svBit eom ); // input: end-of-message marker flag (and flush) void dpi_pipe_c_receive( void *pipe_handle, // input: pipe handle int bytes_per_element, // input: #bits/element int num_elements, // input: #elements to be read int *num_elements_read, // output: #elements actually read svBitVecVal *data, // output: data svBit *eom ); // output: end-of-message marker flag (and flush) //--------------------------------------------------------------------------- // dpi_pipe_c_flush() -- johnS 1-26-06 // // Flush pipelined data. //--------------------------------------------------------------------------- void dpi_pipe_c_flush( void *pipe_handle ); // input: pipe handle //--------------------------------------------------------------------------- // dpi_pipe_c_try_send() -- johnS 1-26-06 // // This is the basic non-blocking send function for a transaction input pipe. // If there is room in the pipe for the indicated number of elements, the // data is transferred to the pipe and a success status of 1 is returned. // Otherwise, nothing is done with the data and a status of 0 is returned. // // This function is thread-neutral can can be used to create a reference // implementation of the blocking send function (dpi_pipe_c_send) // over a selected C-based threading environment. // // dpi_pipe_c_try_receive() // // This is the basic non-blocking receive function for a transaction output // pipe. If the indicated number of elements exist in the pipe, the data is // transferred out of the pipe and a success status of 1 is returned. // Otherwise, the data in the pipe is left alone and a status of 0 is returned. // // This function is thread-neutral can can be used to create a reference // implementation of the blocking receive function (dpi_pipe_c_receive) // over a selected C-based threading environment. // //--------------------------------------------------------------------------- int dpi_pipe_c_try_send( void *pipe_handle, // input: pipe handle int bytes_per_element, // input: #bits/element int num_elements, // input: #elements to be written const svBitVecVal *data, // input: data svBit eom ); // input: end-of-message marker flag int dpi_pipe_c_try_receive( void *pipe_handle, // input: pipe handle int bytes_per_element, // input: #bits/element int num_elements, // input: #elements to be read int *num_elements_read, // output: #elements actually read svBitVecVal *data, // output: data svBit *eom ); // output: end-of-message marker flag //--------------------------------------------------------------------------- // dpi_pipe_c_try_flush() johnS 1-26-06 //--------------------------------------------------------------------------- int dpi_pipe_c_try_flush( void *pipe_handle ); // input: pipe handle //--------------------------------------------------------------------------- // dpi_pipe_c_can_send() -- johnS 1-26-06 // // This is function indicates if there is currently space in the pipe // for the indicated number of elements meaning that the next call to // dpi_pipe_c_send() will succeed without requiring a block. // // dpi_pipe_c_can_receive() // // This is function indicates if there is currently at least the indicated // number of elements in the pipe meaning that the next call to // dpi_pipe_c_receive() will succeed without requiring a block. // // For both of these calls, a return value 0 indicates that the operation // cannot succeed, 1 indicates that it can succeed. //--------------------------------------------------------------------------- int dpi_pipe_c_can_send( void *pipe_handle, // input: pipe handle int bytes_per_element, // input: #bits/element int num_elements ); // input: #elements to be written int dpi_pipe_c_can_receive( void *pipe_handle, // input: pipe handle int bytes_per_element, // input: #bits/element int num_elements ); // input: #elements to be written //--------------------------------------------------------------------------- // Notify callback support -- johnS 2-15-06 // typedef void (*dpi_pipe_notify_callback)( void *context ); // input: C model context void *dpi_pipe_get_notify_context( void *pipe_handle ); // input: pipe handle void dpi_pipe_set_notify_callback( void *pipe_handle, // input: pipe handle dpi_pipe_notify_callback notify_callback, // input: notify callback function void *notify_context ); // input: notify context //--------------------------------------------------------------------------- // EOM auto-flush support -- johnS 2-15-06 // void dpi_pipe_set_eom_auto_flush( void *pipe_handle, // input: pipe handle svBit enabled ); // input: enable/disable #ifdef __cplusplus } /* extern "C" */ #endif #endif // _dpi_pipes_h // @(#) $Id: dpi_pipes.vh,v 1.3 2006/02/21 04:20:06 jstickle Exp $ //--------------------------------------------------------------------------- // Mentor Graphics, Corp. // // (C) Copyright, Mentor Graphics, Corp. 2003-2006 // All Rights Reserved // Licensed Materials - Property of Mentor Graphics, Corp. // // No part of this file may be reproduced, stored in a retrieval system, // or transmitted in any form or by any means --- electronic, mechanical, // photocopying, recording, or otherwise --- without prior written permission // of Mentor Graphics, Corp. // // WARRANTY: // Use all material in this file at your own risk. Mentor Graphics, Corp. // makes no claims about any material contained in this file. //--------------------------------------------------------------------------- `ifdef DPI_PIPE_MAX_BITS `else `define DPI_PIPE_MAX_BITS 512 `endif `ifdef DPI_PIPE_MAX_CHANNELS `else `define DPI_PIPE_MAX_CHANNELS 32 `endif reg [`DPI_PIPE_MAX_CHANNELS-1:0] ok_to_receive; reg [`DPI_PIPE_MAX_CHANNELS-1:0] ok_to_send; initial ok_to_receive = 0; initial ok_to_send = 0; //=========================================================================== // dpi_pipe_hdl_try_receive() johnS 9-15-05 // dpi_pipe_hdl_try_send() // // Non-blocking send/receive to pipe channel from HDL endpoint. //=========================================================================== import "DPI-C" function int dpi_pipe_hdl_try_receive( input int pipe_id, // input: intra-module pipe identifier input int bytes_per_element, // input: #bytes/element input int num_elements, // input: #elements to be read output int num_elements_read, // output: #elements actually read output bit [`DPI_PIPE_MAX_BITS-1:0] data, // output: data output bit eom ); // output: end-of-message marker flag import "DPI-C" function int dpi_pipe_hdl_try_send( input int pipe_id, // input: intra-module pipe identifier input int bytes_per_element, // input: #bytes/element input int num_elements, // input: #elements to be written input bit [`DPI_PIPE_MAX_BITS-1:0] data, // input: data input bit eom ); // input: end-of-message marker flag //=========================================================================== // dpi_pipe_hdl_notify_ok_to_receive() johnS 9-15-05 // dpi_pipe_hdl_notify_ok_to_send() // // Exported functions to set "OK to send/receive" events from SystemC layer. //=========================================================================== export "DPI-C" function dpi_pipe_hdl_notify_ok_to_receive; function void dpi_pipe_hdl_notify_ok_to_receive( int pipe_id ); begin ok_to_receive[pipe_id] = 1; end endfunction export "DPI-C" function dpi_pipe_hdl_notify_ok_to_send; function void dpi_pipe_hdl_notify_ok_to_send( int pipe_id ); begin ok_to_send[pipe_id] = 1; end endfunction //=========================================================================== // dpi_pipe_hdl_receive() johnS 9-15-05 // dpi_pipe_hdl_send() // // Blocking receive/send to pipe channel from HDL endpoint. //=========================================================================== task dpi_pipe_hdl_receive( input int pipe_id, // input: intra-module pipe identifier input int bytes_per_element, // input: #bytes/element input int num_elements, // input: #elements to be read output int num_elements_read, // output: #elements actually read output bit [`DPI_PIPE_MAX_BITS-1:0] data, // output: data output bit eom ); // output: end-of-message marker flag while( !dpi_pipe_hdl_try_receive( pipe_id, bytes_per_element, num_elements, num_elements_read, data, eom ) ) begin ok_to_receive[pipe_id] = 0; wait( ok_to_receive[pipe_id] ); end endtask task dpi_pipe_hdl_send( input int pipe_id, // input: intra-module pipe identifier input int bytes_per_element, // input: #bytes/element input int num_elements, // input: #elements to be written input bit [`DPI_PIPE_MAX_BITS-1:0] data, // input: data input bit eom ); // input: end-of-message marker flag while( !dpi_pipe_hdl_try_send( pipe_id, bytes_per_element, num_elements, data, eom ) ) begin ok_to_send[pipe_id] = 0; wait( ok_to_send[pipe_id] ); end endtask //=========================================================================== // dpi_pipe_hdl_flush() johnS 9-15-05 // // Flush pipelined data //=========================================================================== import "DPI-C" function int dpi_pipe_hdl_try_flush( input int pipe_id ); // input: intra-module pipe identifier task dpi_pipe_hdl_flush( input int pipe_id ); // input: intra-module pipe identifier while( !dpi_pipe_hdl_try_flush( pipe_id ) ) begin ok_to_send[pipe_id] = 0; wait( ok_to_send[pipe_id] ); end endtask //=========================================================================== // dpi_fifos_mti.cxx // // @(#) $Id: dpi_pipes_sysc.cxx,v 1.1 2006/02/21 04:20:06 jstickle Exp $ //=========================================================================== //--------------------------------------------------------------------------- // Mentor Graphics, Corp. // // (C) Copyright, Mentor Graphics, Corp. 2003-2006 // All Rights Reserved // Licensed Materials - Property of Mentor Graphics, Corp. // // No part of this file may be reproduced, stored in a retrieval system, // or transmitted in any form or by any means --- electronic, mechanical, // photocopying, recording, or otherwise --- without prior written permission // of Mentor Graphics, Corp. // // WARRANTY: // Use all material in this file at your own risk. Mentor Graphics, Corp. // makes no claims about any material contained in this file. //--------------------------------------------------------------------------- #include <vector> #include <systemc.h> #include "dpi_pipes.h" #include "svdpi.h" //--------------------------------------------------------------------------- // notify_ok_to_send_or_receive() johnS 2-12-06 // // This is a callback function that notifies the application that there // is room for at least 1 data element in an input pipe or least one data // element in an output pipe. // // This callback function assumes it has been given a context object // that is an sc_event that can be directly posted to. //--------------------------------------------------------------------------- static void notify_ok_to_send_or_receive( void *context ){ // input: notify context sc_event *me = (sc_event *)context; me->notify(); } //--------------------------------------------------------------------------- // dpi_pipe_c_send() johnS 1-26-06 // // This is the basic blocking send function for the C endpoint of a // transaction input pipe. It first calls the non-blocking send function // (dpi_pipe_c_try_send()). If it succeeds in sending on the first try, // it returns happily. // // Otherwise continues to wait on an sc_event until there is at least the // required number of data elements in the pipe at which point the call // to dpi_pipe_c_try_send() will succeed. //--------------------------------------------------------------------------- void dpi_pipe_c_send( void *pipe_handle, // input: pipe handle int bytes_per_element, // input: #bits/element int num_elements, // input: #elements to be written const svBitVecVal *data, // input: data svBit eom ) // input: end-of-message marker flag { if( !dpi_pipe_c_try_send( pipe_handle, bytes_per_element, num_elements, data, eom ) ) { sc_event *ok_to_send = (sc_event *)dpi_pipe_get_notify_context( pipe_handle ); // if( notify ok_to_send context has not yet been set up ) ... if( ok_to_send == NULL ){ ok_to_send = new sc_event; dpi_pipe_set_notify_callback( pipe_handle, notify_ok_to_send_or_receive, ok_to_send ); } while( !dpi_pipe_c_try_send( pipe_handle, bytes_per_element, num_elements, data, eom ) ) wait( *ok_to_send ); } } //--------------------------------------------------------------------------- // dpi_pipe_c_receive() johnS 1-26-06 // // This is the basic blocking receive function for the C endpoint of a // transaction output pipe. It first calls the non-blocking receive function // (dpi_pipe_c_try_receive()). If it succeeds in receiving on the first try, // it returns happily. // // Otherwise continues to wait on an sc_event until there is at least the // required number of data elements in the pipe at which point the call // to dpi_pipe_c_try_receive() will succeed. //--------------------------------------------------------------------------- void dpi_pipe_c_receive( void *pipe_handle, // input: pipe handle int bytes_per_element, // input: #bits/element int num_elements, // input: #elements to be read int *num_elements_read, // output: #elements actually read svBitVecVal *data, // output: data svBit *eom ) // output: end-of-message marker flag { if( !dpi_pipe_c_try_receive( pipe_handle, bytes_per_element, num_elements, num_elements_read, data, eom ) ) { sc_event *ok_to_receive = (sc_event *)dpi_pipe_get_notify_context( pipe_handle ); // if( notify ok_to_receive context has not yet been set up ) ... if( ok_to_receive == NULL ){ ok_to_receive = new sc_event; dpi_pipe_set_notify_callback( pipe_handle, notify_ok_to_send_or_receive, ok_to_receive ); } while( !dpi_pipe_c_try_receive( pipe_handle, bytes_per_element, num_elements, num_elements_read, data, eom ) ) wait( *ok_to_receive ); } } //--------------------------------------------------------------------------- // dpi_pipe_c_flush() johnS 1-26-06 //--------------------------------------------------------------------------- void dpi_pipe_c_flush( void *pipe_handle ) // input: pipe handle { sc_event *ok_to_send = (sc_event *)dpi_pipe_get_notify_context( pipe_handle ); if( ok_to_send == NULL ) return; while( !dpi_pipe_c_try_flush(pipe_handle) ) wait( *ok_to_send ); } //=========================================================================== // pipeline_ingress_proxy.hxx // // @(#) $Id: pipeline_ingress_proxy.hxx,v 1.1 2006/02/21 04:09:57 jstickle Exp $ //=========================================================================== //--------------------------------------------------------------------------- // Mentor Graphics, Corp. // // (C) Copyright, Mentor Graphics, Corp. 2003-2006 // All Rights Reserved // Licensed Materials - Property of Mentor Graphics, Corp. // // No part of this file may be reproduced, stored in a retrieval system, // or transmitted in any form or by any means --- electronic, mechanical, // photocopying, recording, or otherwise --- without prior written permission // of Mentor Graphics, Corp. // // WARRANTY: // Use all material in this file at your own risk. Mentor Graphics, Corp. // makes no claims about any material contained in this file. //--------------------------------------------------------------------------- #ifndef _pipeline_ingress_proxy_hxx #define _pipeline_ingress_proxy_hxx //______________________________ _______________ // class pipeline_ingress_proxy \____________________________/ johnS 2-5-2006 // // The pipeline_ingress_proxy module consumes data received over a data channel // from producer sends it to the Pipeline DUT on the Verilog side by passing // transactions over a transaction input pipe to the // PipelineIngressTransactor. //--------------------------------------------------------------------------- template< typename T, const int NUM_WORDS > class pipeline_ingress_proxy : public sc_module, public virtual tlm_put_if<T> { public: sc_export< tlm_put_if< T > > put_export; private: void *m_pipe_handle; sc_event m_ok_to_put; static void notify_ok_to_put( void *context ){ // input: notify context sc_event *me = (sc_event *)context; me->notify(); } void pack( const T &t, svBitVecVal pipe_data[] ); public: pipeline_ingress_proxy( sc_module_name name, const char *transactor_name, int channel ) : sc_module(name) { // Bind to channel. put_export( *this ); // Establish binding to transaction input pipe. svScope hdl_context = svGetScopeFromName( transactor_name ); m_pipe_handle = dpi_pipe_c_handle( hdl_context, channel, 1 ); // Register notify "ok to put" callback dpi_pipe_set_notify_callback( m_pipe_handle, notify_ok_to_put, &m_ok_to_put ); } void put( const T &t ){ svBitVecVal pipe_data[ SV_PACKED_DATA_NELEMS(NUM_WORDS*32) ]; pack( t, pipe_data ); while( !nb_can_put() ) wait( m_ok_to_put ); assert( dpi_pipe_c_try_send( m_pipe_handle, 4, NUM_WORDS, pipe_data, 0 ) ); } bool nb_put( const T &t ){ if( !nb_can_put() ) return false; svBitVecVal pipe_data[ SV_PACKED_DATA_NELEMS(NUM_WORDS*32) ]; pack( t, pipe_data ); assert( dpi_pipe_c_try_send( m_pipe_handle, 4, NUM_WORDS, pipe_data, 0 ) ); return true; } bool nb_can_put( tlm_tag<T> *t = 0 ) const { return dpi_pipe_c_can_send( m_pipe_handle, 4, NUM_WORDS ); } const sc_event &ok_to_put( tlm_tag<T> *t = 0 ) const { return m_ok_to_put; } }; void pipeline_ingress_proxy<mytype,mytype::NUM_WORDS>::pack( const mytype &t, svBitVecVal pipe_data[] ) { pipe_data[0] = t.count; // Coerce double to long long integer. long long ll_data = (long long)t.data; pipe_data[1] = (svBitVecVal)ll_data; ll_data >>= 32; pipe_data[2] = (svBitVecVal)ll_data; pipe_data[3] = t.status; } #endif // _pipeline_ingress_proxy_hxx //=========================================================================== // mytype.hxx // // @(#) $Id: mytype.hxx,v 1.3 2006/02/21 04:20:30 jstickle Exp $ //=========================================================================== //--------------------------------------------------------------------------- // Mentor Graphics, Corp. // // (C) Copyright, Mentor Graphics, Corp. 2003-2006 // All Rights Reserved // Licensed Materials - Property of Mentor Graphics, Corp. // // No part of this file may be reproduced, stored in a retrieval system, // or transmitted in any form or by any means --- electronic, mechanical, // photocopying, recording, or otherwise --- without prior written permission // of Mentor Graphics, Corp. // // WARRANTY: // Use all material in this file at your own risk. Mentor Graphics, Corp. // makes no claims about any material contained in this file. //--------------------------------------------------------------------------- #ifndef _mytype_hxx #define _mytype_hxx using namespace sc_core; using namespace std; #include <iostream> //______________ _______________ // class mytype \____________________________________________/ johnS 1-2-2004 // // An arbitrary custom data type used to demonstrate passing of abstract data // objects among SystemC SC_MODULEs over data channels. //--------------------------------------------------------------------------- class mytype { public: enum { NUM_WORDS = 4 }; int count; double data; long status; mytype( int a_count, double a_data, long a_status ){ count = a_count; data = a_data; status = a_status; } //--------------------------------------------------------- // Mandatory Methods: johnS 1-2-2004 // mytype() // operator=() // operator==() // // Mandatory methods for custom types used with SystemC data // channels. C++ compile errors will result if these methods // are not defined for custom types used to parametrize SystemC // data channels such as sc_in<>, sc_out<>, sc_buffer<>, // sc_signal<>. This is only true when such types are passed by // value (which is safe but inefficient). When passed by // reference, the extra methods are not needed (and simulations // are more efficient). //--------------------------------------------------------- mytype(){ } // Default constructor const mytype &operator=( const mytype &a_data ){ count = a_data.count; data = a_data.data; status = a_data.status; return *this; } bool operator==( const mytype &a_data ) const{ return count == a_data.count && data == a_data.data && status == a_data.status ? true : false; } }; //--------------------------------------------------------- // Mandatory Functions: johnS 1-2-2004 // sc_trace() // operator << () // // Mandatory functions for custom types used with SystemC // data channels. See explanation above for mandatory methods. //--------------------------------------------------------- inline void sc_trace( sc_trace_file* /*tf*/, const mytype& /*object*/, const string& /*name*/ ) { } inline void sc_trace( sc_trace_file* /*tf*/, const mytype* /*object*/, const string& /*name*/ ) { } inline ostream &operator<<(ostream &out, const mytype &data){ out << data.count << " " << data.data << " " << data.status << endl; return out; } #endif // _mytype_hxxReceived on Tue Feb 21 09:49:09 2006
This archive was generated by hypermail 2.1.8 : Tue Feb 21 2006 - 09:50:06 PST