Subject: RE: [sv-cc] more about import/export
From: Warmke, Doug (doug_warmke@mentorg.com)
Date: Fri Mar 07 2003 - 16:50:46 PST
Hi Francoise,
Answers in red...
There will be something interessant about the following:
- Calling extern functions at elaboration time
- More details on the VPI context issue
- Legal scopes for extern and export function declarations
Thanks for participating with John and me in this "gnarly thread".
(If you want a French translation of "gnarly", we need to have
a phone call to go over that one - it's complicated!)
Regards,
Doug
-----Original Message-----
From: Francoise Martinolle [mailto:fm@cadence.com]
Sent: Friday, March 07, 2003 8:48 AM
To: Stickley, John; Warmke, Doug
Cc: 'sv-cc@server.eda.org'
Subject: Re: [sv-cc] more about import/export
Comments in blue preceded by "FRANCOISE".
Should we have a phone call to hash this out?
At 08:22 PM 3/6/2003 -0500, Stickley, John wrote:
Doug, Francoise,
My responses embedded.
Warmke, Doug wrote:
Francoise, John, team,
I need to get your opinions on these issues before penning my changes
in the C-side/SV-side LRM. Please see below. Some of these items
are very tricky, and I feel like Andrzej must have felt when he
first embarked on his C-side creation saga.
Thanks and Regards,
Doug
-----Original Message-----
From: Francoise Martinolle [ mailto:fm@cadence.com
<mailto:fm@cadence.com> ]
Sent: Thursday, March 06, 2003 8:57 AM
To: Warmke, Doug; Stickley, John; 'sv-cc@server.eda.org'
Subject: RE: [sv-cc] more about import/export
Doug, John,
some answers embedded.
We need to clarify in the final LRM what does the get_context returns.
Francoise
'
At 10:31 PM 3/5/2003 -0800, Warmke, Doug wrote:
Francoise, John,
Some comments and questions embedded.
Regards,
Doug
>
> Francoise Martinolle wrote:
> > Looking at Andrzej's example which illustrates where and how import
> > declarations to
> > extern function can occur, I have more questions and potential
issues.
> >
> > 1) place of declaration for import/export
> > It looks like the import declaration can appear anywhere a
declaration
> > can appear. right?
> >
> > in SV3.0, the import/export are strictly for interfaces and must be
> > declared in a modport.
> >
> > If we allow the import declaration to appear in any declarative
scope,
> > and the C function is a "context"
> > function, what is the meaning for the context? Is it the current
> > instance? or the current scope?
>
> johnS:
> The context is the place from which the function is called
> not the declaration. On the C side, the callee can obtain
> the SV module context of the call site by calling svGetContext().
> That's how it will know which particular module instance
> is calling it.
DOUG1: Francoise's question brings up a very interesting point.
(Why do you seem to have this habit, Francoise? :^)
Even with John's answer, which makes sense, what exactly is
the context anchored to? I think John is assuming that it
is anchored to the nearest enclosing module instance.
johnS:
Yes, that is what I'm assuming: The instance path to the
innermost module scope surrounding the function call site.
If so, that should be explicitly stated in the LRM.
(Looks like I may have to do such stating when I work
on this part of the SV-side LRM).
What if the function is called from within a program instance
or an interface instance, rather than a module instance?
The context must be anchored to such instances as well.
Are there any other types of instances to which import/extern
functions must be anchored?
FRANCOISE1:
Generate statements may provide some trickery for
implementations, although I don't think we need to
mention that in the LRM.
The function call can be from within a module, interface, program, task
or function,
generate instance.
DOUG2:
The real issue is for us to decide on the answer to Francoise's
original question. What is the anchoring context scope for
extern and export functions?
Here is a partial list of scenarios to consider.
(For extern functions, the scenario is the scope of the call site.)
(For export functions, the scenario is the scope of the definition
site.)
johnS:
I agree with this.
Possible extern function call site scopes
1. module instance
2. program instance
3. interface instance
4. named procedural block
5. unnamed procedural block
6. generate scope
7. task instance
8. function instance
9. class member function instance
Additionally, all kinds of combinations of the above are possible.
Examples:
e1. function call in simple module scope
e2. function call from within a task call inside program scope
e3. function call from an unnamed procedural block inside interface
scope
e4. function call from within generate scope inside unnamed block scope
inside module
e5. class member function call in program scope
etc.
FRANCOISE: you forgot named-fork and unnamed fork for the call site of a
function call.
Function and task calls can appear in a generate
scope inside always, initial
stmts, or to supply the constant value for the
constant expression initializing a genvar
variable, for the loop increment assignment, if
condition or case expression. These
last function calls would be done during
elaboration. Would we allow directC function
to be called during elaboration of the design?
DOUG: Another good question.
External function calls during elaboration would be a useful feature.
The worry is the setup of the context data.
For now I propose we allow external function calls during elaboration,
but only for non-context calls (i.e. "normal" calls and pure calls).
Any contrary opinions?
We need to come up with an intuitive, easy-to-understand set of
rules that determines how "context" will be generated.
(Joao has proposed changing the term "context" to "scope",
at least in the API function names used to work with context functions.
I think this makes sense and I will use that term in the LRM unless
there are strong objections from the team.)
johnS:
The thing I don't like about the term "scope" is scope pertains to
"module scope" whereas context pertains to "module instance".
The two are very different and we want our term to denote the latter.
Let me embellish:
module foo;
module bar;
integer a;
endmodule
endmodule
module top
foo x();
foo y();
endmodule
Scope of integer a:
foo::bar::a
Instances of module a:
top.x.bar.a
top.y.bar.a
In this case integer a has only 1 possible scope but
2 possible contexts. That's why I would prefer to
keep the term "context" since instance path is truely
what we want. If we want to change terms, "instance"
would be more appropriate than "scope" but I would just
as soon keep "context".
FRANCOISE: John, actually there is no difference in Verilog. in VPI a
scope is an instantiated
scope and a scope has a hierarchical name. In VHDL, you are right, there
is the notion of
a declarative scope and sometimes I think about it myself that way.
Look at the definition in Verilog of the $scope system task:
C.10 $scope
Syntax:
$scope ( hierarchical_name ) ;
The $scope system task allows a particular level of hierarchy to be
specified as the scope for identifying objects. This
task accepts a single parameter argument that shall be the complete
hierarchical name of a module, task, function, or
named block. The initial setting of the interactive scope is the first
top-level module.
VPI has also the notion of scope and it is "instantiated scope" not
declarative scope.
The VPI method to traverse the hierarchy is vpiInternalScopes and
vpiScope is the method returning
you the parent instantiated scope.
Look also at section 12.6 Scope rules in Verilog 1364:
In this section however, it looks more that they are describing a
declarative scope and visibility rules
inside that scope.
I would suggest to use the term "instantiated scope" rather than context
which is foreign to the
verilog jargon.
I think one reasonable rule is to explicitly state the
list of 8 scopes above, and require that the scope pointer will be
anchored to the nearest enclosing scope. We may want to make an
exception for unnamed procedural blocks, in which case the nearest
named outer scope would be the anchor point. Opinions?
FRANCOISE: agreed: an unnamed block is not an instantiated scope.
However note that if there is any variables
declared in the unnamed block
and these variables are passed to the function
call, if we are considering
providing the outer most enclosing instantiated
scope, no VPI access will
be possible to the variables in the unnamed block
since you will be
returning with get_context (or
"get_instantiated_scope) the scope surrounding the
unnamed block. that will be odd since these
variables can be passed to the function
call. VPI access is currently not defined for the
SV 3.0 language
so we may not care. However depending of which
scope we return, this may
prevent future VPI access inside directC function
call.
DOUG: As mentioned earlier, I think we should separate VPI context from
DPI context.
DPI context is fetched by svGetContext(). VPI context if fetched by
vpi_xyz().
(Sorry I don't know the proper name of the pertinent VPI function)
This rule might have some unfriendly consequences on "default scope".
For example, consider a module that contains an exported function
defined right in module scope, and an extern function that is called
from within a named procedural block somewhere. In that case, imagine
the extern function wants to turn around and call the exported function.
The default scope would be the named block, not the enclosing module.
This would cause the extern function author to explicitly set the
svScope to the enclosing module's scope. This is pretty cumbersome
and does require knowledge of ASCII hierarchical paths in the SV design.
FRANCOISE: I don't think it is necessary to change the context. In
Verilog,
the export function would be visible to any scope defines inside the
module.
So you should be able to call directly the exported SV function declared
in the
module.
DOUG: Definitely no longer necessary now that we determined external
function context is related to the scope of the extern declaration,
rather
than the extern call site. I was a little slow connecting the dots on
that one.
Here is a different rule to consider:
The scope of an extern function is anchored to the nearest enclosing
module, program, or interface instance. The "unfriendly consequence"
described above would be removed. However, we would now have to
enforce rules about multiple extern declarations in the different
scopes. i.e. totally disallow them, or allow them provided all
default parameter values, names, etc. are identical. This seems
pretty tricky. But it might be good, after we compare and
contrast export function declaration scopes (below).
johnS:
I think it is adequate to say that a function's context instance
is the instance of the nearest enclosing module, program, or
interface as you suggest.
FRANCOISE: the problem with that you will be restricting the VPI access
you can do inside
that "context" function, because you lost the site
of the call.
DOUG: I think I've answered that one above, and that this should no
longer be a problem.
But I would also add, to get around the multiple declarations
problem you mention, that you require the declaration in be
in the nearest enclosing module, program, or interface instance
and no lower. This way, there can only be one extern declaration
per scope.
The general rule of thumb for extern declarations is that
they should be allowable wherever SV function definitions
are allowable and, like function definitions, they should
not be duplicatable.
FRANCOISE: agreed.
****
Now let's consider export function declarations (===definitions).
Here is a list of possible scopes in which a function can be defined.
(Actually the word "declared" seems to be used synonymously with
"defined" in the LRM. This is slightly confusing when compared with
our idea of external function declarations, which are actually more
analogous to function prototypes. Here I mean where the actual body
johnS:
Not quite. If I'm not mistaken, our latest incarnation of
external function declarations is that they're more analogous
to function definitions than function prototypes. That is,
you can only have one and it serves as a "drop in replacement"
that represents where the actual SV function would be placed had
the function been defined in SV rather than C.
items of a function are present and defined.)
1. module instance
2. program instance
3. interface instance
4. class instance
I spent an hour going over draft3 of the SV 3.1 LRM and I can't
find anything that allows functions to be declared inside
block scope, generate scope, function scope, or task scope.
Francoise, I thought that you had mentioned that function
declarations could be nested inside such scopes, did I
misunderstand you?
FRANCOISE: task and functions can be declared in generate scope: see
page 171 ieee 1364
you cannot declare them inside another task or
function or inside blocks. I verified.
DOUG: Thanks. This is real valuable.
I hope so, since now things will be easier.
Here it seems that the rule for export functions should be
that the svScope is anchored to the nearest enclosing module,
program, or interface instance.
or generate scope.
Class instances are a little confusing. First, should we even
allow class member functions to be exported? I propose we
disallow this, since it could be a complex topic that needs
quite a bit of study and debate. (Analogous to pointer-to-
member-functions in C++, which is an advanced and tricky topic)
Please give your opinions about this. If I don't hear anything
to the contrary, I will ban export of class member functions
in the LRM.
FRANCOISE: That could be useful, but I am not sure about the
implications. We may want to
leave it unspecified to allow future extension. I will try to think a
bit more about it.
Finally, let's reconsider the "unfriendly consequence" above.
The extern function's call site sets the default scope.
But in many cases, that scope is totally inapplicable to
export functions. It means that a user would have to manually
set the scope for most export function calls. How ugly.
johnS:
I still think the default scope in this case should be
the nearest enclosing module, program, or interface.
Doesn't that solve it ?
FRANCOISE: make it the current instantiated scope like VPI ( a
instantiated scope can be
a module, program, interface, task/function instance or generate scope
of a named block)
Could we have some kind of internal coercion mechanism?
i.e. if an extern function's call site scope is somewhere
beneath the scope containing the export function, we
automatically find the correct scope for the export
function on the fly? What would that do for performance?
johnS:
Yuck !
OR, should we just go with the simple definition of scope
for extern function call sites, that precisely matches the
3 possible scopes for export function declarations?
FRANCOISE: use the Verilog visibility to find the export.
johnS:
Yes. Yes. Yes. Please !
(i.e. nearest enclosing module, program, or interface scope)
Let's hear some opinions about this.
It is tricky and I can't resolve it by myself.
johnS:
There's an important point to note here.
One of the things we may be struggling with is how to
form a hierarchical name to items in any of these given
contexts.
But, unless I'm missing something, that's not just our problem
to solve. Does not the LRM clearly state what hierarchical
references to these paths should be ? If not, shouldn't it ?
What happens if you have a cross scope reference to some item
in one of these weird nested locations ?
Also, will not VPI have to solve the same problem ?
What should be passed to vpiGetInstanceByName() ?
Instance path names seem to be to be a more general
concept that has to be solved in the language.
And, I think by adopting the simple definition of scope
that you mention above (i.e. 3 possible scopes) by and
large instance pathnaming becomes pretty simple as well.
>
> >
> > SV 3.0 has the ability to declare variables in unnamed
> blocks; this is
> > currently discussed in the bc committee as an issue for
> hierarchical
> > references and VPI name look up.
> > Do we want to allow to have import/export declarations in
> unnamed blocks?
DOUG2: After my "quality time" with the LRM :(, I don't even
see that it's possible to have export declarations in blocks.
What about extern declarations? We would have to add that to
the LRM as an extension, with SV-EC's approval. I don't even
think it's necessary, since the real point about extern functions
is the call-site, not the declaration-site. What do you think
should be the answer to this question, Francoise?
johnS:
You should only allow extern declarations wherever it is
legal to place SV function definitions.
FRANCOISE: Since an extern declaration replaces the SV funciton
definition,
I tend to agree with John.
We have to define where can the export and extern be. It is not defined
in the SV LRM
DOUG: I think we have defined it to the four previously mentioned
scopes:
module, interface, program, and generate scopes. These scopes
precisely
match the allowable scopes for function declarations in SV, right?
And, as you say, context is stipulated by the call site
not the definition site.
Whew ! What a gnarly thread. I'm running out of energy !
-- johnS
DOUG1: Another good question. I think that given John's
answer above, the answer to this question may be a "don't care",
though. Since the context is anchored to the instance
immediately surrounding the call site, not the declaration site.
All instances must be nameable for hierarchical references
to work, thus I don't think this is an issue.
FRANCOISE1:
Yes we should be able to get a hierarchical path name to the function
call,
DOUG1:
Here come a couple questions that may display the limits
of my SV syntax knowledge :-O
1. This reminds me of generate blocks as well.
Is there a firm definition for hierarchically referring
through generated instances? (Maybe already resolved in
Verilog 2001, sorry for my lack of expertise here)
FRANCOISE1:
Yes, look page 192 section Hierarchical names. Each module instance,
generated instance, task, function or named begin-end or fork-join block
defines a new hierarchical level.
Also for generated instances names look page 175 and 176. For for loop
generates,
the value of the genvar variable for the generated instance is appended
between brackets to
the end of the name of the generate block.
DOUG1:
2. In SV 3.1 draft 3, I looked through the BNF for the module
construct and I couldn't find any reference to unnamed blocks.
Here I'm thinking about something parallel to the VHDL "block"
construct, rather than a basic block of sequential code
delimited by begin/end. Is there anything in SV like a
VHDL block? If so, we'll have to watch out for anonymous
blocks.
FRANCOISE1:
In SV3.1, you can have unamed blocks which will contain local variables.
These variables cannot be referenced from outside the unamed block but
are visible to the unnamed block
and any of its nested scopes.
Section 5.5, draft 3.
"Note that in SystemVerilog, data can be declared in unnamed blocks as
well as in named blocks, but in the
unnamed blocks a hierarchical name cannot be used to access it."
DOUG2: Thanks for all this information, Francoise.
You saved me lots of Verilog-2001 and more SV3.1 LRM time :)
After my secondary SV3.1 LRM time, I have determined that there
is no equivalent to a VHDL "block" statement. (i.e. no module-level
declarative item that declares a new scope, like "block" does inside
a VHDL architecture). Verilog/SV blocks are only allowed in
procedural code.
FRANCOISE: correct
> >
> > 2) Context passing for exported SV functions
> > I think the way we have it set up is complex.
> >
> > The export declaration must be in the same declarative scope as the
> > function SV declaration.
> > If there are multiple instantiations of the same function and
> > therefore multiple instantiations of the
> > export declaration, since the export declaration does not have any
> > instance information,
> > how does the C function knows which exported SV function to call?
>
> johnS:
> The C model would typically identify the specific SV module
> instance in which it wants to make the call by geting the SV
> context handle via svGetHandleByName() then passing it to
> svSetContext() prior to making the call. Typically
svGetHandleByName()
> would only be called once at construction time and the handle
> would be stored.
>
> That's one scenario - the case where a C model can call an HDL
> function "out of the blue". This might typically happen if
> the C model is running in it's own kernel that is synchronized
> with the SV simulator. It could also happen if a C function
> being called from SV wants to make a call to an export
> SV function that happens to be in a different module than
> the one it is being called from.
>
> The other scenario is the case when the a C callee function
> called from SV, in turn, makes a call to an exported SV function.
> In that case the "default context" is the context of the
> SV module originally making the call into C. If svSetContext()
> is not called, the context is assumed to be the default context.
>
> Joeo and Andrzej, please let me know if this is the understanding
> we reached this week. I did not see this first scenario in your
> document that you just mailed out Joao.
DOUG1: When I work over the C-side LRM, I will make sure to edit
it to reflect this understanding. The API functions you name
will all be present.
<EOM>
>
> >
> > The answer was that there will be a default context
> which would be
> > inherited from the current context of the C call which is
> calling the SV
> > function.
> > If you don't want to use the current context, there is a
> C library
> > function provided: set_context
> > which would be used to set the context prior to the SV call.
> >
> > I see some problems with that, you would have to
> hardcode in the C
> > function the hierarchical path to
> > the export SV function you want to call if different from
> the current
> > context. The C wrapper code
>
> johnS:
> Not necessarily. The C model may have been initialized at
construction
> time and established the context of the SV model that it wants to
> communinate with by storing the context handle as a local data
member.
>
> Later on, when calls are made back into the SV side, the stored
> context handle can be used with svSetContext(). This way, name
> lookup only needs to be done once.
>
> Additionally, model reuse is supported here. It may be that the C
> model object can be instantiated more than once with the pathname to
> each associated SV module passed to the C model's constructor
> by say a top level testbench module.
>
> > which calls the SV function is now dependent on the
> hierarchical name
> > too, since the SV function arguments can be instance
> specific (width of
> > the ranges can be dependent on a verilog parameter).
> > Note that every C function which calls SV would have to
> be qualified
> > as "context".
> >
> > I think it is simpler to provide the full hierarchical name in the
> > export declaration. The context
> > is contained in the hierarchical path to the function and
> the wrapper
> > code can be generated more
> > easily.
>
> johnS:
> This will not support reuse quite as nicely in my opinion.
> And you still have to somehow identify to the C model which
> particular SV function instance it wants to call.
>
> Unless you require that a different C alias is given for
> each exported instance of an SV function. That really prevents
> reuse !
Some exported functions may not be instance specific.
>
> > Allow the export declaration to be outside of a module
> definition or in
> > $root.
> >
> > The syntax :export cname = hierarchical_path_to_SVfunction...
> > would allow to have different C functions calling different
> instances of
> > the SV function. The C function
> > does not need to know or set the context.
> >
> >
> >
> > Example
> > ========= start of SV code ========
> > module top
> >
> >
> > mod u1#(15)(); //instance of mod parameter size is
> overridden with 15
> > mod u2 (); // instance of mod uses default parameter size value of
7
> >
> > other u3();
> > endmodule
> >
> > module mod
> > parameter size = 7;
> > export SVf;
> > function SVf (reg [size :0] arg1 )
> > ...
> > endfunction
> > endmodule
> >
> > mod other
> > initial
> > begin
> > import extern context B = void foo(int i = 5);
> >
> > foo; // calling B(5), B is calling SVf, which SVf to call?
> > end
> > endmodule
> > ========= end of SV code ========
> >
> > Let's assume in the above example that foo is context sensitive and
> > calls SVf exported function.
> > How do you specify which SVf to call if you have only one export
> > declaration?
> >
> > If you instead use:
> > export C = top.u1.SVf();
> > export D = top.u2.SVf().
> >
> > the C code for function foo can be simple, no need to get
> and set the
> > context
> >
> > function foo (int arg1)
> > {
> > if (arg1 == 5)
> > C(...); // calls C
> > else D( ...); // or calls D
> > }
>
> -- 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 <mailto:John_Stickley@mentor.com> \
/
> Phone: (201)818-2585 \ /
> ---------
>
--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. __ ______ | \ ______________________/ \__ / \ \ 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 <mailto:John_Stickley@mentor.com%A0> \ / Phone: (201)818-2585 \ / ---------
This archive was generated by hypermail 2b28 : Fri Mar 07 2003 - 16:52:27 PST