Greetings ITC Techies, As per an action item requested of Duaine and me, the following e-mail presents possible scenarios for how one might implement DPI over VHDL purely in a software simulator environment. It does not describe scenarios for synthesis of DPI based code to an emulator environment. However, for this case, function calls can conceivably be replaced with synthesizeable infrastructure layered over SCE-MI 1.1 macros where message input and output ports are used to carry function input and output messages across the communication link. In the text below, imported and exported 0-time functions are described separately. Specifically VHDL is described is it makes the case that DPI-like interfaces can be implemented over a language that does not natively support DPI without requiring extensions to the language itself. Rather, legal, compliant attributes are used to alert the language compiler and/or SCE-MI infrastructure linker to generate extra infrastructure to support the DPI call interface. It is important to note that this does not present any new requirements for SCE-MI that were not already there for SCE-MI 1.1 macros in terms of infrastructure linker support. In fact, in some cases it has proven to be easy to implement a function call based interface since, on most industrial HDL software simulators, some capability already exists for function call type interfaces - such as foreign functions in VHDL and PLI user defined tasks in Verilog. -------------------------------------------------------------- Imported 0-time functions Imported functions can be declared in VHDL as procedures and can be called from user clocked RTL processes. Here is an example of a simple user application written in VHDL that makes use of the proposed DPI imported function interface: entity PipelineEgressTransactor is port( TokenOut: in std_logic_vector(127 downto 0); Clock, Reset: in std_logic); end PipelineEgressTransactor; architecture DPI of PipelineEgressTransactor is --This is a Imported Function declaration-- procedure UploadEgressTransaction( signal countOut : in std_logic_vector (31 downto 0) signal dataOut : in std_logic_vector (63 downto 0); signal statusOut : in std_logic_vector (31 downto 0)) is begin end procedure; attribute foreign of UploadEgressTransaction: procedure is "sce_mi import DPI-C"; begin process (Clock) begin if(Reset /= '1' and IsStdLogicVectorZero(TokenOut) = '0') then UploadEgressTransaction( TokenOut(31 downto 0), TokenOut(95 downto 32), TokenOut(127 downto 96)); end if; end process; end DPI; There are a number of scenarios in which an implementation can implement the "guts" of the empty placeholder function, UploadEgressTransaction(). By no means do we try to dictate any one of those ways here. We only want to suggest possibilities for implementation. Different vendors would most likely choose different solutions depending on what is optimal in their environment. 3 of those possibilities are mentioned here: 1. The vendor can modify their compiler so that the empty procedure is automatically replaced directly with generated native code that hooks into an infrastructure implementation that directly communicates to C using whatever VHDL foreign language interface (FLI) that is supported by that vendor. This foreign language interfacing mechanism would look similar to the one that SCE-MI 1.1 macros would have to use today. Note: No source code transformation is required with this approach as the extra infrastructure is emitted directly into the native code output unit. 2. VHDL foreign functions - this is similar to 1 above. If a vendor has created a mechanism in their simulator to implement "foreign functions" as designated by the `FOREIGN attribute as described in the LRM, this mechanism can be easily be leveraged to implement imported DPI functions. In fact, a very good case can be made that such an implementation could be relatively easy since this feature already supports function calling semantics and most vendor have already have some sort of support for foreign functions. Using the `FOREIGN attribute syntax shown in the example above (which is also consistent with LRM recommended uses of this attribute to denote foreign functions), the vendor could directly implement DPI imported functions as foreign functions using their vendor specific mechanism that is already in place for foreign functions. 3. If the vendor simulator is mixed language and already supports a SystemVerilog DPI interface, the internals of the VHDL call could be a wrapper that directly calls a SystemVerilog DPI imported call. This option is similar to 2 except it utilizes existing DPI capability rather than existing foreign function capability. The modified internals for the VHDL call could either be directly generated as native code (as described in 1 above) or the user's source code could be slightly transformed to give the empty placeholder function a body that calls the DPI function. ------------------------------------------------------------------------- Exported 0-Time Functions The SCE-MI 2 DPI proposal states that 0-time procedures in VHDL can be attributed as exported DPI functions and called from C. Exported functions can potentially do the following: 1. C->HDL message passing or config ops (input args) 2. C->HDL query ops (output args) The exported function would be a VHDL procedure that can do assignments of input formal argument values to surrounding signals for passing input messages and can do assignments of surrounding signal values to output formal arguments for passing output messages. To achieve this, an exported function can be declared as a specially attributed procedure in the declarative region of an architecture. In the following user VHDL application example, the exported function, 'ServiceIngressTransaction()' assigns to signals 'serviceCallDetected', 'holdingCount', 'receivedCount', 'receivedData' and 'receivedStatus' declared in the architecture scope. -- the following is a Exported Function definition-- procedure ServiceIngressTransaction ( signal holdCountIn : in integer; signal receivedCountIn : in std_logic_vector (31 downto 0); signal dataIn : in std_logic_vector (63 downto 0); signal statusIn : in std_logic_vector (31 downto 0)) is begin serviceCallDetected <= '1'; holdingCount <= holdCountIn; receivedCount <= receivedCountIn; receivedData <= dataIn; receivedStatus <= statusIn; end procedure; attribute foreign of ServiceIngressTransaction: procedure is "sce_mi export DPI-C"; process begin wait until (Clock'event and Clock = '1'); if(serviceCallDetected = '1') then serviceCallDetected <= '0'; if (Reset /= '1') then while holdingCount > 0 loop holdingCount <= holdingCount - 1; wait until (Clock'event and Clock = '1'); end loop; TokenIn <= receivedStatus & receivedData & receivedCount; wait until (Clock'event and Clock = '1'); TokenIn <= (others => '0'); wait until (Clock'event and Clock = '1'); end if; end process; Here again are 3 possible scenarios for implementing this exported function. 1. The vendor can modify their compiler so that in addition to generating simulation code for the user's architecture and procedure, it also generates an additional process block in the same architecture scope. This process block communicates directly with the C side using special synchronization signals together with whatever VHDL foreign language interface (FLI) that is supported by that vendor. The special process block would wait until one of the synchronization signals indicates that a call to the exported function was initiated. It would then take the input data arguments passed along from the C side via the FLI and make a call to the actual exported procedure defined by the user. The output arguments of the call would be passed back to C side via the FLI. It might look something like this: -- Auxiliary process to manage calls to exported -- ServiceIngressTransaction() function ServiceIngressTransaction_wrapper: process -- These variables updated via C interface API variable holdCountIn : integer; variable receivedCountIn : std_logic_vector (31 downto 0); variable dataIn : std_logic_vector (63 downto 0); variable statusIn : std_logic_vector (31 downto 0); begin -- Wait for signal triggered via PLI, VHPI, FLI -- or similar C-API interface. wait on ServiceIngressTransaction_trigger; -- Make the actual call to the exported function (args -- are set in wrapper ServiceIngressTransaction ( holdCountIn, receivedCountIn, dataIn, statusIn ); -- Toggle trigger to notify C side (via value change callback) -- that call is complete. ServiceIngressTransaction_trigger <= ~ServiceIngressTransaction_trigger; end process ServiceIngressTransaction_wrapper; 2. In a mixed language simulator this process could be a Verilog process that is placed completely outside the user's original source unit and makes the call to the exported function using cross scope references. Using this approach would require absolutely no source code transformation and it could be implemented with no alterations to the vendor's compiler as well. Rather an extra module would be created by the infrastructure linker containing the cross scoping wrapper processes and could be compiled into its own separate database unit that is elaborated along with the rest of the design. 3. If the vendor simulator is mixed language and already supports a SystemVerilog DPI interface, an actual DPI exported function can be added as a wrapper that then calls the VHDL exported function. -- johnS ______________________________/\/ \ \ John Stickley \ \ \ Mgr., Acceleration Methodologies \ \________________ Mentor Graphics - MED \_ ________________________________________________________________Received on Thu Sep 29 06:40:03 2005
This archive was generated by hypermail 2.1.8 : Thu Sep 29 2005 - 06:40:26 PDT