[sv-bc] Stand-alone modports - more detail

From: Peter Flake <flake@elda.demon.co.uk>
Date: Fri Jan 28 2011 - 13:03:20 PST

For a data type such as a class, the type definition and actual parameter
values are sufficient to determine the types of all components. For a design
unit this is not the case, because defparam statements may be used to alter
parameters. Furthermore, a design unit does not exist independently of its
instances, whereas a class exists before any instances (objects) are
created. Configurations can replace design units but not classes. The
generate construct means that elaboration depends very much upon parameters
to design units.

 

Virtual interfaces present a unique problem in that they have a data type
that refers to a design unit. A virtual interface may be assigned to
various interface instances in turn, and consequently the data types of the
interface components accessed can only be determined at run time. Run time
type determination creates an unacceptable overhead, so one of the interface
instances, with the same actual parameter values, is usually selected for
elaboration time type determination.

 

A better method would be for a virtual interface to have an "interface to an
interface" that has component data types which are determined at elaboration
time like those in a class. A modport is already a kind of "interface to an
interface". However it does not exist outside its interface and it does not
include data types. Jonathan Bromley has proposed stand-alone modports with
parameters and data typed ports:

 

"The new stand-alone declaration syntax closely follows the existing syntax
for declaring a

modport within an interface, except that each modport item must have its
data type specified.

Note how this differs from modports in Std.1800-2005 interfaces; the modport
items in such

modports are invariably references to things of known data type that already
exist within the

interface. In an abstract (stand-alone) modport declaration the modport
items cannot refer to an

existing thing, and therefore they must be explicitly typed.

A modport declaration may optionally have type parameters and value
parameters. These

parameters act in much the same way as parameters associated with a class
declaration, in the

sense that they may be overridden to create a specialisation of the modport.
Parameters of the

modport may be used in the modport_typed_items, for example to specify bit
widths, item data

types, or the argument types of subprograms.

There shall be at least one modport_typed_item in a modport declaration. A
modport_typed_item

can be a list of port connections, import/export subprogram prototypes, or
clocking blocks."

 

"package P_3_2;

// Modport suitable for connection to an RS-232 serial link

modport rs_232 (

input logic RXD, DSR, CTS, DCD,

output logic TXD, RTS, DTR );

// Modport representing a general-purpose test point of any type

modport testpoint #(parameter type T = logic) (output T TP);

endpackage : P_3_2"

 

"A modport that has been declared stand-alone can be used to create a
modport connector in an

interface, exposing items in the interface through the connector. When the
interface is instanced,

such a modport connector can then be used to meet the obligation represented
by a modport

receptacle in an instance of some other module.

Every item in the modport connector must be associated with an expression of
equivalent type in

the enclosing interface. Each modport item merely provides visibility of a
data object in the

enclosing interface. The connector does not create any new data objects for
its modport items.

Items of the modport connector are associated with expressions using the
same syntax as port

connection lists on a module instance. The connection shorthand .name is
acceptable as an

abbreviation for the association .name(name), and the connection shorthand
.* is acceptable

for wildcard association of all items not otherwise associated.

Items can be explicitly specified to have no association by using the empty
association syntax

.name().

interface I_4_4();

import P_4_3::*; // makes declaration of mp_4_3 visible

logic R, W, Lire, Ecrire; // data objects in the interface

mp_4_3 rw_conn1( .W(Ecrire), .R ); // .R(R) is implied

mp_4_3 rw_conn2( .*, .R(Lire) ); // .W(W) is implied

endinterface : I_4_4"

 

"An import task or function in a modport provides access, through a modport
port in a

client module, to a subprogram declared in the module or interface enclosing
the modport

connector.

Standalone modport declarations (i.e. those in a package) must fully specify
the prototype of any

imported subprogram item:

package P_6_2;

modport MP_6_2 ( import function int MP_F ( input byte B ) );

endpackage : P_6_2

When such a modport is used to create a connector, the enclosing interface
must provide a

suitable subprogram. It is not necessary for the actual subprogram to have
the same name as

the corresponding modport item, because the name can be mapped through the
extended form

of modport expression:

interface I_6_2;

import P_6_2::*;

function int f ( input byte B );

...

endfunction : f

MP_6_2 f_conn ( .MP_F(f) ); // expose function f() to modport

endinterface : I_6_2"

 

 

Such modports could be considered to be like data types and allowed in
packages, but they are not real data types and are not allowed with new.
Modport instances in interfaces could be used with hierarchical names in
expressions. This would require the user to create local names and data
types in modports for such expressions, and the types would be checked at
interface instance elaboration. The local names would have to be used
instead of hierarchical names in code to access interface components.

 

A clocking block in a modport can be considered to be in a hierarchical
modport. Since a stand-alone modport in a package would not have access to
a clocking block, another modport should be used to provide the names, data
types and directions. This should then be linked to a clocking block in the
interface instance to which it is connected.

 

package P_6;

modport CP_6 (input bit[3:0] I .);

modport MP_6 ( modport CP_6 mp_cb );

endpackage : P_6

 

interface I_6_1 ( input bit clk );

import P_6::*;

clocking intf_cb @(posedge clk);

input bit[3:0] I ...

endclocking : intf_cb

MP_6 mp ( .mp_cb(intf_cb) );

endinterface : I_6_1;

 

 

Another example (modified from DVCon 09 paper)

 

 

package pkg;

modport Abstract ( output logic [3:0] L );

endpackage

 

interface AI;

import pkg::*;

logic [7:0] Vec;

Abstract a_mp(.L(Vec[5:2]));

endinterface

 

module CE3 import pkg::*;

(Abstract P);

initial P.L = 4'b0;

endmodule

 

Syntax changes:

 

 

package_item ::=

package_or_generate_item_declaration

| anonymous_program

| package_export_declaration

| timeunits_declaration

| package_modport_declaration

 

package_modport_declaration ::=

      {attribute_instance} modport [parameter_port_list]

( package_modport_item { , package modport_item } ) ;

 

package_modport_item ::=

      modport_identifier ( package_modport_ports_declaration

{ , package_modport_ports_declaration } )

 

package_modport_ports_declaration ::=

        {attribute_instance} list_of_port_declarations

      | {attribute_instance} import_export method_prototype

{ , method_prototype }

      | {attribute_instance} modport modport_identifier port_identifier
{ unpacked_dimension }

 

interface_or_generate_item ::=

  { attribute_instance } module_common_item

| { attribute_instance } modport_declaration

| { attribute_instance } extern_tf_declaration

      | { attribute_instance } modport_instantiation

 

modport_instantiation ::=

      modport_identifier [ parameter_value_assignment ] modport_instance {
, modport_instance } ;

 

modport_instance ::=

      name_of_instance ( list_of_modport_connections )

 

list_of_modport_connections ::=

      ordered_modport_connection { , ordered_modport_connection }

      named_modport_connection { , named_modport_connection }

 

ordered_modport_connection ::=

      { attribute_instance } [ net_lvalue ]

      | {attribute_instance } tf_identifier

      | {attribute_instance } clocking_identifier

      | {attribute_instance } name_of_instance

 

named_modport_connection ::=

      { attribute_instance } . port_identifier [ ( [ net_lvalue ] ) ]

      | {attribute_instance } . port_identifier [ ( [ tf_identifier ])]

      | .*

 

 

-- 
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.
Received on Fri Jan 28 13:04:00 2011

This archive was generated by hypermail 2.1.8 : Fri Jan 28 2011 - 13:04:17 PST