Subject: [sv-cc] SV Layer Feedback
From: Stickley, John (john_stickley@mentorg.com)
Date: Wed Feb 26 2003 - 15:30:34 PST
Joao and Andrezj,
I just got done reviewing your SV layer document as received from
Joe's LRM drafts.
All in all a very good document and pretty much in accordance with
what we had previously talked about. However there were a few issues
and some feedback that I have.
I will list it here item by item - referring to the section and
page numbers as per the .pdf's that Joe sent out earlier this week
- particularly the one entitled "SV_layer.pdf".
Here's my feedback:
-------------------------------------------
page 1 section 1.1.1 2nd statement of 2nd paragraph
"In particular, the external functions shall be non-blocking ..."
I'm uncomfortable with the term "non-blocking" although I agree
with the point you're trying to convey here. All function calls
are in one sense "blocking" and in another sense "non-blocking".
You can think of function calls as "blocking" if you observe
that when a function call is made, the statement following
the call site is not executed until the function itself has
completely executed and returned.
But in the sense you're trying to convey, inside the function call,
you cannot block for example on a thread to allow time to pass.
I understand what you're saying but, using "non-blocking" can
be confused with the other meaning I described above.
So, to avoid all ambiguity, I would prefer you remove the
term completely and instead just say "0-time" to always
imply that function calls execute instantaneously (which
you already correctly state here).
-------------------------------------------
page 3 section 1.3.1
As described above, I would like to request that we take
non-blocking out completely. Please re-title this section
as "0-time functions"
Your explanatory text in this section is satisfactory except
that I would like to see you remove "non-blocking".
-------------------------------------------
top of page 4 section 1.3.3 last paragraphs describing context
Although everything you've said about context is fine,
you've left out the single most important aspect of
why "context" is important: it adds context sensitivity to
the function call. It provides a way for C code or models
to know from what specific HDL instance the function is
being called.
This is such an important concept - in fact, I'll venture
to say that in the future it will be the most heavily used
mode of C calls (but that's only my opinion !) - that I think
it deserves its own paragraph.
I have some suggested wording for it if you would like.
I also have some issues with how context gets passed into
the function call that may require some adjustments to the C
layer.
We had some discussion about this a couple of months back but
it fell by the wayside. The discussion was whether we want
context handling to be strictly through VPI or whether we
should have standalone svAPI calls that support context.
Remember, the only three calls we need for both the SV-to-C
and C-to-SV directions are basically:
svHandle *svGetHandleByName( const char *instance_path_name )
void svSetUserContext( svHandle *handle, void *userContext );
void *svGetUserContext( svHandle *handle );
With these three calls we completely support context sensitivity
C model to SV module bindings.
These calls can be layered over VPI or a vendor can implement
them standalone (along with all the C layer calls for data
type access in Andrezj's C-layer spec).
Now - here's a slight change that may be needed to the C layer:
1. Any external C function declared with "context" should, when
called on the C side, be passed an svHandle as it's first
argument. From that handle, you can get associated user
context by calling svGetUserContext(). The remaining arguments
are the user defined arguments.
Example:
SV Side:
// Declare an external, callable, aliased, context sensitive C function
extern MyCFunc context function integer MapID( input integer portID ;
C Side:
// Define the function and model class on the C++ side:
class MyCModel {
private:
int locallyMapped( int portID );
public:
// Constructor
MyCModel( const char *svInstancePath ){
svHandle svInstance = svGetHandleByName( svInstancePath );
// Associate “this” with SV instance
svSetUserContext( svInstance, this );
}
friend int MyCFunc( svHandle hdlContext, int portID );
};
int MyCFunc( svHandle hdlContext, int portID ){
// Retrieve local context.
MyCModel *me = (MyCModel *)svGetUserContext( hdlContext );
return me->locallyMapped( portID );
}
This will nicely support calling C functions in object oriented
C or C++ modeling environments.
2. When C code calls an exported SV function, it should pass
an svHandle as the first argument to identify which instance
of the SV function is being called. The remaining arguments
are the user defined arguments.
If the exported function is declared in root scope we can
either say this handle should be NULL or not passed - I don't
care which.
I would like to request that we make these adjustments to the
C layer. I thought we had reached agreement on this previously
but it is still missing from the specs.
-------------------------------------------
page 4 section 1.4 6th paragraph
You specify the syntax "$root.xf"
to override locally visible identifiers that conflict in name.
How about $root::xf for more symmetry with module scope
specification in export declarations ?
-------------------------------------------
page 4 section 1.4
What about cname aliasing ? I think this is important
in the SV-to-C direction as well as C-to-SV. Your spec
shows it in one direction but not the other. My understanding
is that we all agreed support aliasing in either direction.
You should mention this in its own paragraph, in the BNF
syntax for external function decls, and in the examples at
the top of page 5. I show some examples with aliasing below.
Perhaps your dedicated paragraph can be worded as
follows:
"The cname is an optional alias for the external C
function. If present, the external C function would
actually have this name but all SystemVerilog code that
calls the function would refer to it as the function_identifier
given in the named_function_proto (see section 10.3).
If the cname is absent, the C function name must match exactly
with the function_identifier. In this case the function_identifier
would be restricted to legal C identifier syntax."
-------------------------------------------
page 5 section 1.4.3
Can we allow packed arrays up to 64 bits as return types rather
than 32 bits ? Since all modern language compilers support 64 bit
scalar types (for ANSI C it is "long long") let's make the most use
of today's machine architectures. 32 bits is rather limiting.
Even if code is running on 32 bit machines, all the compilers
still support the long long type so let's just make it 64.
And for 64 bit machines it's a big win.
-------------------------------------------
page 7 section 1.4.7
You've not included the BNF syntax yet but let me
suggest that we use the "named_function_proto" as per
SV LRM 3.1 draft 3 section 10.3, Syntax 10-2.
So, using that, may I suggest this be our external
function syntax:
external_function_declaration ::= // from Annex ???
extern [cname] [property] named_function_proto ;
property ::=
pure | context;
Note that this definition also provides for C aliasing.
So, to revise the some of the examples in your spec:
extern function void myInit();
// An impure, context free, unaliased C function
extern myCInit function void myInit();
// An impure, context free aliased C function
extern pure function real sin(real);
// A pure, context free, unaliased C function
...
extern context function void processTransaction(
handle elem, output logic [64:1] arr [0:63]);
// A context sensitive unaliased C function
extern sendPacket context function void receivePacket(
output [7:0] payload [0:1499] );
// A context sensitive aliased C function
-------------------------------------------
page 9 section 1.6.3.2 1st statement of 1st paragraph
I don't like your wording "Some PLI and VPI functions require the context ..."
We're really talking about C models or C functions that may use
PLI and VPI but also may have no idea what these API's are yet
still require context sensitivity. Our API should not assume they
use PLI/VPI.
Please reword as,
"Some C function calls require that the context of their call is known.
For example those calls may be associated with instances of
C models that have a one-to-one correspondence of instances
of SV modules that are making the call. It may take special
instrumentation of their call to provide such context ..."
The discussion in this section should not be so oriented
to PLI/VPI but more generic to instance based model couplings.
It does not hurt to mention PLI/VPI as examples of how
one might couple with the HDL but it should still be possible
to use context couplings without use of PLI/VPI. This is
characteristic of today's emerging transaction APIs that
connect HVL testbench model instances with HDL DUT module
instances. Let's allow for this use model. In fact,
let's encourage it ! After all, it is good object oriented
programming practice.
-------------------------------------------
page 9 section 1.7 last sentence on page
Please give more detail about C name aliasing.
My suggested wording the I gave above for extern
declarations would be appriate here too (except
in the reverse sense of call direction).
I also have more wording for context sensitive exported
SV functions if you would like me to send it on.
-------------------------------------------
page 10 section 1.7 examples at the very end
I have a big problem with these examples. I don't ever remember
coming to agreement in this committee that we can export instances
of functions. All we agreed to was to be able to export
functions in specific module scopes.
What you're suggesting here may be highly problematic
for implementations and is probably not very useful
anyway.
What you really want to be able to do is export function
"foo" of module "bar" for *all* instances of "bar".
You would do it this way:
export bar::foo;
If module foo is nested inside module "phi" (I seem to remember
that SV allows module nesting) then you would revise the
declaration as follows:
export phi::bar::foo;
For functions at root scope we can use:
export $root::foo;
or simply,
export foo;
Absent a module scope specifier at root scope
the assumption should be that it is root scope.
Actually this should be true for any module.
That is, absent a module specifier, the scope
is assumed the be the scope of the declaration.
If the export declaration itself resides inside
module bar as follows:
module phi;
...
module bar;
...
export foo;
endmodule
endmodule
This is equivalent to having this declaration at root
scope:
export phi::bar::foo;
module phi;
...
module bar;
...
// No local export decl.
endmodule
endmodule
That was my last understanding of how we left scoping rules.
Please let me know if I'm missing something.
-- johnS
__
______ | \
______________________/ \__ / \
\ H Dome ___/ |
John Stickley E | a __ ___/ / \____
Principal Engineer l | l | \ /
Verification Solutions Group | f | \/ ____
Mentor Graphics Corp. - MED C \ -- / /
17 E. Cedar Place a \ __/ / /
Ramsey, NJ 07446 p | / ___/
| / /
mailto:John_Stickley@mentor.com \ /
Phone: (201)818-2585 \ /
---------
This archive was generated by hypermail 2b28 : Wed Feb 26 2003 - 15:37:19 PST