RE: [sv-cc] Updated externexport proposal (version N+2)


Subject: RE: [sv-cc] Updated externexport proposal (version N+2)
From: Warmke, Doug (doug_warmke@mentorg.com)
Date: Thu Mar 13 2003 - 15:50:32 PST


Joao,
 
A few last-minute corrections and one issue.
 
Corrections:
1) The names svGetScopeFromName() and svGetNameFromScope()
    haven't been updated. (Not critical, but might as well fix now
    before sending to sv-ec)
 
2) My suggestion for using "put" instead of "set" was added to the
    wrong function. The names should be svPutUserData() and
    svSetScope(). Currently you have those reversed.
 
Issue:
We never agreed upon allowing unnamed function prototype arguments.
I don't think you should add that to the requirement list until SV-CC
has voted on this issue. Can you please remove it, at least as a
firm requirement on SV-EC?
 
Other:
Still need clarifications on allowability of $root as a valid
declaration
scope that would return a *non-NULL* handle. i.e. NULL handle returns
from the API functions always indicate an error.
 
Thanks and regards,
Doug
 
-----Original Message-----
From: Joao Geada [mailto:Joao.Geada@synopsys.com]
Sent: Thursday, March 13, 2003 2:36 PM
To: Swapnajit Mittra; sv-cc
Cc: Ghassan Khoory; Andrzej I Litwiniuk
Subject: [sv-cc] Updated externexport proposal (version N+2)

Swapnajit,
below is the final version of the extern/export proposal
========================================
Proposal
 ========================================

At any scope where a function declaration can occur, permit the
following
declarations:

extern "DPI" [pure|context] [<cname>=] <named_function_proto>;

export "DPI" [<cname>=] function <fname>;

This syntax does not require any new keywords: "DPI" is a string
qualifying
the type of extern/export. For SV3.1 only the string "DPI" is valid.

Note that the <named_function_proto>, as defined in SV3.1 draft3 spec
(page 233)
must be modified slightly so that the argument list permits open arrays.
Only
extern DPI functions can use this argument type. We additionally also
want to relax the
prototype syntax to permit unnamed arguments, again only for extern DPI
prototypes.
If the extern declaration uses unnamed arguments, this function cannot
be invoked with
passing arguments by name syntax.

Semantics:
----------
in both extern and export, cname is the name of the foreign function
(extern/export),
fname is the SV name for the same function.
If cname not explicitly given, it will be the same as the SV function
fname.
An error will be generated iff the cname has characters that are not
valid in a C function identifier.

This syntax permits several SV functions to be mapped to the same
foreign
function by supplying the same cname for several fnames. Note that all
these SV functions would
have identical argument types (as per rules below)

For any given cname, all declarations, regardless of scope, *must* have
exactly
the same type signature. The type signature includes the return type,
the number,
order, direction and types of each and every arguments. Type includes
dimensions and bounds of
any arrays/array dimensions. Signature also includes the pure/context
qualifiers
that may be associated with an extern definition.

Only one extern declaration or export declaration of a given fname is
permitted in
any given scope. More specifically, for an "extern", the extern must be
the
sole declaration of fname in the given scope. For an "export", the
function
must be declared in the scope where the "export" occurs and there must
be
only one "export" of that fname in that scope.
NOTE: the restriction of a single extern def for a given fname in a
given scope may be relaxed (as per
deferred issue 2) iff the extern declaration is identical (same type
signature and exactly matching
formal names for each and every argument) and exactly matching default
values for all such externs of fname in the same scope.

Argument names and default values are permitted to differ between
"extern"s
declared at different scopes *as long as* the type compatibility
constraints are met.
Extern "DPI" functions are never considered to be a
"constant_function_call" as
described in the SV 3.1 draft 3 LRM, section A.8.2 (page 247).
Specifically, extern function calls
cannot be used in any place requiring that the call be a
constant_function_call.
[therefore extern calls cannot be made during compilation/elaboration]
Exported functions are not affected by this restriction (ie exported
functions can still qualify
as constant functions if they meet the SV criteria for such)

For exported functions, the exported function must be declared in the
same scope
that contains the `export "DPI"` declaration. Only SV functions may be
exported
(specifically, this excludes exporting a class method)

Note that extern "DPI" functions declared this way can be invoked by
hierarchical reference
the same as any normal SV function. Declaring a SV function to be
exported does not change
the semantics or behavior of this function from the SV perspective (ie
no effect in SV usage
other than making this exported function also accessible to C callers)
The qualifier "pure" for an extern function specifies that this function
has absolutely no
side effects and uses no data other than its arguments. The function
output is predicated
only on the values of its input arguments. Side effects include
reading/writing to any files
or stdin/stdout, changing static or global variables, invoking any other
APIs etc. Pure functions
cannot invoke exported SV functions.
NOTE: still have to update above paragraph to use appropriate text from
sv-cc LRM.
An unqualified extern function can have side effects but may not read or
modify any SV signals
other than those provided through its arguments. Unqualified externs are
not permitted to
invoke exported SV functions.
Extern functions with the 'context' qualifier may invoke exported SV
functions, may read or write
to SV signals other than those passed through their arguments, either
through the use of other
interfaces or as a side-effect of invoking exported SV functions.
Context functions are always
implicitly supplied a scope representing the fully qualified instance
name within which the extern
declaration was present. (ie an extern function always runs in the
instance in which the extern
declaration occurred. This is the same semantics as SV functions, which
also run in the scope
they were defined, rather than in the scope of the caller)
Extern context functions are permitted to have side effects and to use
other SV interfaces (including
but not limited to VPI). However note that declaring an extern context
function does not automatically
make any other simulator interface automatically available. For VPI
access (or any other interface access)
to be possible, the appropriate implementation defined mechanism must
still be used to enable these
 interface(s). Note also that DPI calls do not automatically create or
provide any handles
or any special environment that may be needed by those other interfaces.
It is the users responsibility
to create, manage or otherwise manipulate the required
handles/environment(s) needed by the other
interfaces. (the svGetScopeName and related functions exist to provide a
name based linkage from DPI
to other interfaces)
Exported functions can only be invoked if the current context refers to
an instance from which
the named function could be called in SV by an unqualified function call
(ie a call to the function with
no hierarchical path qualifier). In general this implies that an
exported SV function is visible from its
declared scope to any scope lower down in the hierarchy. Note that this
implies that $root functions
are visible to all callers.
Attempting to invoke an exported SV function from a scope in which it is
not directly visible will
result in a runtime error; how such errors are handled is implementation
dependent.
If an extern function needs to invoke an exported function that is not
visible from the current scope,
it needs to change, via svSetScope, the current scope to a scope that
does have visibility to the
exported function. This is conceptually equivalent to making a
hierarchically qualified function call
in SV.
The current SV context will be preserved across a call to an exported
function, even if current context
has been modified by an application. Note that context is not defined
for non-context externs and attempting
to use any functionality depending on context from non-context externs
can lead to unpredictable behavior.

This:
a) uses consistent syntax with other similar SV 3.1 constructs
b) permits straightforward extension later to extern/exported tasks
c) permits all information needed by DPI coder to be put in the scope
   where such usage occurs.
d) by permitting extern/export declarations to be inside module scope,
   this simplifies (permits) use of DPI inside library modules using
just
   normal library resolution mechanisms.
e) allows for later extension of DPI to handle tasks (if such is ever
necessary)
   without syntax conflict with existing usage
f) permits later extension to address other interfaces (eg "extern VPI
function $foobar;")
   without syntax conflict with existing usage
g) use of extern/export is more symmetrical and was recommended by sv-ec
and by
   Friday's all-committees meeting.

NOTES:
1) do not need to put function prototype along with the export because
export has to
   occur in same scope as the function definition being exported.
2) extern/exports can occur anywhere where function declarations can
occur. However
   note that exports must be in same scope as the function being
exported.
3) clarified some of the rules regarding the prohibition of multiple
extern/exports
   in a single scope (prohibition is only with respect to a given fname)
 
The following C side functions will exist in DPI to support contexts:
- svScope svFetchScope()
    returns the current scope. Returns NULL if invoked from a call chain
starting with a
     non-context SV extern function call, otherwise an opaque handle
    to the SV context corresponding to the instance where the extern
definition is present.
- void svPutScope(const svScope)
    sets the current context to the given scope handle
     If this function is supplied an invalid scope handle results may be
unpredictable.
     Note that this affects all following calls to exported SV
functions, as their invocation relies on current scope
     Note also it is not necessary to reset the context prior to
returning from the extern call;
    Note that NULL is not a valid argument to this function. Behavior of
SV calls if NULL passed to this
   function may be unpredictable.
- void* svGetUserData(const svScope)
    gets the current user data associated with the given scope. See
notes for svGetUserData
    Note: always returns NULL if called from a non-context DPI function.
- svSetUserData(const svScope, void*)
    sets the user data (a void*) associated with the current context.
Note that a single (*ONE*) user data pointer
    is associated with each context, regardless of how many extern
functions may be defined in that instance.
    This implies that if two extern functions both set the user data for
the same context, then only the last value
    will be obtained by getContextUserData
- svGetScopeByName(const char*)
    gets a scope handle when given a fully qualified instance name.
Returns NULL if no such name available
    or if "byName" queries not enabled in this simulation run.
- svGetScopeName(const svHandle)
    gets the fully qualified name of a scope handle
- int svGetCallerInfo(char **fileName, int *lineNumber)
  returns the file and line number in the SV code from which the extern
call was made. If this
  information available, returns TRUE and updates fileName and
lineNumber to the appropriate
  values. Behavior is unpredictable if fileName or lineNumber are not
appropriate pointers.
  If this information is not available return FALSE and contents of
fileName and lineNumber not
  modified. Whether this information is available or not is
implementation specific.
  Note that the string provided (if any) is owned by the SV
implementation and is valid only
  until the next call to any SV function. Applications must not modify
this string or free it.

Example usage:
----------------------------------------

------------------- sv code --------------------

// NOTE: distance is SV name, Distance is C name
extern "DPI" pure Distance=function integer distance(input integer a,
input integer b);

module top;
       TB tb;
endmodule

module TB
   // NOTE: MyDistance is SV name, Distance is C name. Both this
function and the function at
   // $root map to the same C function and therefore have to have
identical type signatures
   extern "DPI" pure Distance=function integer MyDistance(input integer
t, input integer v=10)

   DUT dut;

   ...
   $root.distance(10, 20); // invokes the C function Distance(10, 20)
   MyDistance(2,); // invokes the C function Distance(2, 10)

endmodule

module DUT
   ...
   UNIT unit1;
   UNIT unit2;
   ...
endmodule

module UNIT
   extern "DPI" context genPacket = function void genIt();

   export "DPI" drivePacket = function driveIt;
   function void driveIt(input l, m, n)
       ...
   endfunction

   ...
     genPacket; // invokes C function genPacket(), which invokes this
instances driveIt
                                // via the C function drivePacket()'
   ...
endmodule
----------------------- end sv code -----------------

---- c code ----
int Distance(int a, int b)
{
   return (int)(sqrt(a*a + b*b));
}

extern void drivePacket(int a, int b, int c);

/* NOTE: genPacket is context-aware function */
void genPacket()
{
   ...
   drivePacket(x,y,z); // call the drivePacket function in the
instance from which genPacket invoked
   ...
}
---- end c code -----
 
EXAMPLE CLARIFYING THE NOTION OF CONTEXT/SCOPES
This example is specifically to clarify the notion of the context of a
function vs the location where
a function is called.
In Verilog, functions run in the context where they are defined *not*
where they are called from.
Specifically, the only variables a function can "see" without
qualification are the variables that occur in its
context, not those visible in the location where it was called.
 
For example:
 
 
module foo(input clk);
 
   reg a, b; // top level decls
 
   function dummy(input bar);
       a = bar;
   endfunction
 
   always @(posedge clk) begin
      ...
      dummy(b); // call 1
      ...
      begin: myblock
         reg a; // local decls
         ...
         dummy(b); // call 2
      end
      ...
    end
 
endmodule
 
(plz forgive any syntax erros). In the above example, both call 1 and
call 2 cause the same variable, the top-level
a, to be modified, even though in call2's local scope there is a
different version of "a" available.
 
In short: for a SV function, context is always where the function was
declared, not where it was called from.
I hope this explanation clarifies the definition of "function context":
it is the context where the
function was declared (ie where the extern appears, or where the
function definition of an exported function appears)
and is conceptually, just the fully qualified name of that function
(minus the function name part itself).
 SHORT TERM DEFERALL (ie to be completed once extern/export syntax SV
side semantics completed)
- reusable mechanism for user data associated with a scope. Current
suggestion is to modify
  sv(Get|Set)ScopeUserData to take an additional string argument.
Internally tool maintains a
table per instance mapping strings to associated user data. This permits
several independent
applications to manage user data in a consistent way without clashing
with each other (ie permits
interoperable DPI applications requiring context)
 
DEFERED ISSUES (TO SV3.2+) + WORKAROUNDS
1- syntax to export a specific instance of a given SV function
    for example, export only function "foo" from instance "top.here"
    Deferred proposal: export "DPI" [cname=] function path.fname;
    Workaround: At $root,
    export "DPI" c_foo=function globalFoo;
    function global_foo(...)
        top.here.foo(...)
    endfunction
    NOTE that the context of the exported c_foo function is $root and
*not* top.here, which would be the
    case if foo was exported directly in its definition.
2- how to permit multiple IPs to all use the same shared externs
(present in a shared "include" file)
   Deferred proposal: permit multiple externs to coexist in the same
scope as long as all the externs
define exactly the same function. Note that this is a stronger
requirement than that the externs be required
to have the same type signature; this requirement in addition forces
that all the externs use exactly the
same names (if any) for the formals.

Workarounds:
Typically, shared library functions will typically also required that a
set of complex types (structs) also
be shared. Neither C nor SV permit for the multiple definition of types
in a given scope. In C this issue
is addressed by inclusion guards to prevent against the multiple
inclusion of the same header file.
This same approach may also be used with SV, as follows:
`ifndef SV_HEADER_NAME_SV
`define SV_HEADER_NAME_SV
... shared datatype definitions and extern functions etc
`endif
SystemVerilog also permits an additional mechanism to be used, namely
having a shared module contain
all the required types and functions. This approach is commonly used
with existing Verilog IP and would
remain equally valid when DPI is used (in many respects, modules are the
SV equivalent of C++ namespaces)
module MyBusLibrary;
 ... datatype definitions and extern functions etc
endmodule
3- syntax to permit a function definition to be exported from a scope
other than where the function is
   declared.
   Deferred proposal: export "DPI" [cname=] function
DefinitionScope::fname
(note DefinitionScope may itself have DefinitionScope:: qualifiers, for
the case of nested definition scopes, such as nested modules)

Possible workaround: suggestion to investigate the "extends" mechanism
currently under discussion in sv-ac,
which permits for out-of-module code to "extend" the definition of a
module. Using an extend, out-of-module
code could contain the required export and still be considered local to
the module, thus accomplishing
the requirements with no new syntax.

   
Joao
========================================================================
======
Joao Geada, PhD Principal Engineer Verif Tech
Group
Synopsys, Inc TEL: (508)
263-8083
344 Simarano Drive, Suite 300, FAX: (508)
263-8069
Marlboro, MA 01752, USA
========================================================================
======



This archive was generated by hypermail 2b28 : Thu Mar 13 2003 - 15:52:40 PST