Greetings and ITC Techies, I think I might have a breakthrough for our "deadlock" on pipes. :-) That thing that seems to be bothering Shabtay the most, and perhaps with some justification, is that the pipes do not have a thread neutral API that can be used to aid implementations in adapting the user friendly pipe functions implementation to arbitrary threading systems on the C side. So, after thinking about it and looking at what we have so far, it occurs to me that what we really need is *both* of the following 1. A user-friendly, but thread-aware pipe interface (which we already have). 2. A lower level implementation-friendly, but thread-neutral pipe interface - essentailly implementation "hooks" to facilitate easy creation of adapters that allow implementation of the user-friendly API in selected C threaing environments (which Shabtay wants). Shabtay, ye ask and ye shall receive ! Here's a solution I believe can be made to work that is, 1. Compatible with the existing easy-to-use API at the user level 2. Provides thread neutral "hooks" that implementations can choose to use to create adapter layers. 3. Easy to demonstrate a reference implementation of the blocking pipe calls that uses the hook functions. In fact, the examples I'm providing today show a working source code example of such an implementation for the HDL side. So what I've done is kept the blocking user-friendly pipe functions on the C side as is: User-friendly C callins: dpi_pipe_c_send() dpi_pipe_c_receive() dpi_pipe_c_flush() A user would use only these functions. But I've added 4 new "hook" functions that only a thread specific implementation would use: C hook functions: dpi_pipe_c_try_send() - C callin dpi_pipe_c_try_receive() - C callin dpi_pipe_c_notify_ok_to_send() - C callback dpi_pipe_c_notify_ok_to_receive() - C callback The try_send() and try_receive() functions are essentially non-blocking sends that return a status as to whether there was room in the pipe (try_send()) or at least one transaction in the pipe (try_receive). The notify_ok_to_send() and notify_ok_to_receive() functions are callbacks that can be called directly or indirectly from within the thread-neutral implementation code to nofify the thread-aware implementation code (but not user code !) on the C side when it is OK to send or receive. By implementing the bodies of these functions a vendor can put in thread specific code that takes some action such as posting to an sc_event. So the key here is that the 1st 2 hook functions have thread neutral code. And the 2nd 2 hook functions are callbacks called from within thread-neutral code that can be filled in by some implementation wishing to create a thread-aware adapter that implements the send() and receive() functions. I've also defined the same functions on the HDL side for full symetry: User-friendly HDL callins: dpi_pipe_hdl_receive() dpi_pipe_hdl_send() dpi_pipe_hdl_flush() HDL hook functions: dpi_pipe_hdl_try_send() - HDL callin dpi_pipe_hdl_try_receive() - HDL callin dpi_pipe_hdl_notify_ok_to_send() - HDL callback dpi_pipe_hdl_notify_ok_to_receive() - HDL callback I've attached the C and Verilog header files that provide precise declarations of all of these functions. In fact, in there you'll also find an actual source code reference model showing how, on the HDL side, the hook functions can be used in "adapters" that implement the user friendly functions. A very similar scheme can easily be applied to any threading system on the C side. I've also uploaded the complete working example that actually uses all the new hook functions (on both sides) and simulates on any ModelSim 6.1/Linux installation. You'll find it on anonymous FTP at ftp.ikos.com under, outgoing/scemi2_demo.tgz The 32 bit binaries are built for Linux that runs on either i386 or x86_64 platforms. It was tested on an RHEL 3.0 machine. Env.script and Makefile explain setup. I hope this breaks the deadlock allows us to move forward with pipes. -- johnS //=========================================================================== // dpi_pipes.h // // @(#) $Id: dpi_pipes.h,v 1.1 2006/01/27 07:08:05 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 #ifdef __cplusplus extern "C" { #endif #include "svdpi.h" //--------------------------------------------------------------------------- // dpi_pipe_c_send() -- johnS 1-26-06 // // These is the basic blocking send function for a transaction input pipe. // // dpi_pipe_c_receive() // // This is the basic blocking receive function for a transaction output pipe. //--------------------------------------------------------------------------- void dpi_pipe_c_send( int pipe_id, // input: intra-module pipe identifier 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 void dpi_pipe_c_receive( int pipe_id, // input: intra-module pipe identifier 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_flush() -- johnS 1-26-06 // // Flush pipelined data. //--------------------------------------------------------------------------- void dpi_pipe_c_flush( int pipe_id ); // input: intra-module pipe identifier //--------------------------------------------------------------------------- // dpi_pipe_c_try_send() -- johnS 1-26-06 // // This is the basic non-blocking send function for a transaction input pipe. // 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. 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( int pipe_id, // input: intra-module pipe identifier 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( int pipe_id, // input: intra-module pipe identifier 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_notify_ok_to_send() -- johnS 1-26-06 // // This is the declaration for a callback function that is used to notify // the C side that a transaction input pipe has space. This function // is a thread neutral function that can be used by implementations // of the block send function (dpi_pipe_c_send) in adaptations to // selected C-based threading environments. // // dpi_pipe_c_notify_ok_to_receive() // // This is the declaration for a callback function that is used to notify // the C side that a transaction output pipe has space. This function // is a thread neutral function that can be used by implementations // of the block send function (dpi_pipe_c_send) in adaptations to // selected C-based threading environments. // void dpi_pipe_c_notify_ok_to_send( int pipe_id ); // input: intra-module pipe identifier void dpi_pipe_c_notify_ok_to_receive( int pipe_id ); // input: intra-module pipe identifier #ifdef __cplusplus } /* extern "C" */ #endif #endif // _dpi_pipes_h // @(#) $Id: dpi_pipes.vh,v 1.1 2006/01/27 07:08:10 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. //--------------------------------------------------------------------------- //=========================================================================== // dpi_pipe_hdl_receive() johnS 9-15-05 // dpi_pipe_hdl_send() // // Receive, send pipelined data //=========================================================================== `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_nb_get() johnS 9-15-05 // dpi_pipe_hdl_nb_put() // // 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 if( !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] ); if( !dpi_pipe_hdl_try_receive( pipe_id, bytes_per_element, num_elements, num_elements_read, data, eom ) ) $display( "ERROR: Unexpected return from dpi_pipe_hdl_try_receive()" ); 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 if( !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] ); if( !dpi_pipe_hdl_try_send( pipe_id, bytes_per_element, num_elements, data, eom ) ) $display( "ERROR: Unexpected return from dpi_pipe_hdl_try_send()" ); end endtask //=========================================================================== // dpi_pipe_hdl_flush() johnS 9-15-05 // // Flush pipelined data //=========================================================================== import "DPI-C" context task dpi_pipe_hdl_flush( input int pipe_id ); // input: intra-module pipe identifierReceived on Fri Jan 27 07:30:58 2006
This archive was generated by hypermail 2.1.8 : Fri Jan 27 2006 - 07:31:41 PST