Re: [sv-cc] more about import/export


Subject: Re: [sv-cc] more about import/export
From: Francoise Martinolle (fm@cadence.com)
Date: Fri Mar 07 2003 - 08:48:19 PST


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]
>>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?

>>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.

>>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.

>>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.

>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.

>>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

>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 \ /
>> > 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 \ /
>Phone: (201)818-2585 \ /
> ---------



This archive was generated by hypermail 2b28 : Fri Mar 07 2003 - 08:53:15 PST