Packages with external constraints

Hello,
Suppose I have to implement an OVC.
I would like to:

  1. build it as a SystemVerilog package(at least, I won’t worry about my ‘typedef enum {IDLE, BUSY} bus_state’ to conflict with other IDLE’s or BUSY’s, from other OVCs)
  2. use external constraints: the reason I like external constraints it’s the same reason I like declarative languages: when you need something, you just ask for it, you don’t really care how it’s done(SystemVerilog constraints subset looks like a declarative language, in particular)

So, I define

package pkg;
class a;
   rand int b;
   constraint c;
endclass
endpackage

If I add constraint a::c { b == -3; } inside the package(in between package & endpackage, in the OVC core, that is) everything works fine, i.e. no compilation errors. But this is not a viable solution(you don’t want your OVC user to contaminate your OVC sources).
Hence I try(hoping that the scope resolution operator :: will do the trick)

package pkg;
class a;
   rand int b;
   constraint c;
endclass
endpackage
constraint pkg::a::c { b == -3; }

or

package pkg;
class a;
   rand int b;
   constraint c;
endclass
endpackage

module test;
constraint pkg::a::c { b == -3; }
endmodule

or

package pkg;
class a;
   rand int b;
   constraint c;
endclass
endpackage

module test;
import pkg::*;
constraint a::c { b == -3; }
endmodule

Inherently, I get the same error message(s)(regardless the simulator)

Invalid package scope specified for constraint block ‘c’.

or

Class or package ‘a’ not found

(they differ a bit, depending on simulator, but the essence is the same).
My question is: is there a way(allowed by IEEE1800 Std) to use packages with external constraints in the way I described? Or what I get now is merely a temporary limitation of the tools?
I couldn’t find an explicit statement saying that I cannot do this.

P.S.:

  1. I know that what I want can be accomplished by using the Factory(i.e. inheriting class a, set_override()-ing and so on), but, as I said, if I can simply implement tests by doing, for example,
// ahb_only_writes_test.sv
constraint ahb_burst::keep_direction { direction == WRITE; }

or

// usb_back_to_back_transactions_test.sv
constraint usb_transaction::global { itd inside {[1:3]}; }

then I’d rather do it like this.
2. I know that, if an external constraint is left un-defined, a warning or even an compile-time error is thrown. But I can leave with that: I could simply provide my users with a configuration file(that needs to be included after the OVC core is imported) where, initially, all external constraints are empty. e.g.

constraint a::c { }

Daniel,

The LRM is a little vague here. It only says

“Constraint block bodies can be declared outside a class declaration, just like external subroutine bodies.”

There is no such thing as "external subroutine bodies" defined in the LRM. If you read the text as"exactly the same rules as out-of-block method definitions", then you can apply the rule

An out-of-block declaration shall be declared in the same scope as the class declaration and shall follow the class declaration

In your case, that means the completed constraint must be defined inside the package.

The idea behind external methods and constraints is so that you can indeed put the bodies or completed definition in a separate file. In the OVM, you can see *.svh header files that include the *.sv body files.

For example file pkg.svh:

package pkg;
   class a;
        rand int b;
        constraint c;
     endclass
   `include < pkg.sv >
endpackage

Then you can use +incdir+ to set the search path order to pick up the include files from the user’s directory first.

Dave Rich