-
Notifications
You must be signed in to change notification settings - Fork 80
Externs as constructor parameters
We encountered several instances in which the state of an extern needs to be manipulated from the control plane. For example hash functions that compute the hash on a field list specified by the control plane.
The current language specification requires that all the constructor parameters are compile time constants. While we can ask the user to enumerate all the possible field lists that are available as candidates for computing the hash, because lists and tuples are internal compiler data structures, we have no means of identifying the selected list from the control plane. Moreover, the elements should not capture the values at construction time, but rather use the values that are in the fields when the get
method is invoked.
By passing an extern as a constructor parameter to another extern we can:
- use the name of the extern instance or constructor parameter in the control plane to identify a particular encapsulate state, in our case a field list
- since the semantics of the extern is entirely decided by the compiler, we decide what should happen to the state of the argument passed as a constructor parameter. In our example, the extern instance is passed as a reference and values are captured only when we invoke the method that needs them. Think of the same semantics as a match key for a table.
/// Field list extern -- identifies a set of fields
extern FieldList<W> {
FieldList();
};
extern FieldLists<T> {
FieldLists(T fls);
};
/// Declare several filed lists
FieldList fl0 = FieldList({ f1, f2, f3 });
FieldList fl1 = FieldList({ f1, f4, f5, f6 });
/// An extern that requires the control plane to choose which field list is
/// participating in the hash computation
extern DynamicHash<W> {
DynamicHash(HashAlgorithm_t algo, ref FieldLists<_> fls);
/// the control plane needs to select the FieldList.
W get();
W get(in W base, in W max);
/// the data plane may want to set a default
void setDefault(FieldList fl);
}
/// construct a dynamic hash extern
DynamicHash<bit<16>>(CRC_16, FieldLists<_>({fl0, fl1})) hash0;
action a1 () {
f1 = hash0.get(); // correct.
}
What happens if the same instance is passed to multiple externs? We can let the programmers to express what should be the semantics using parameter labels. in
will continue to act as a read-only, copy-in parameter. No direction or ref
can specify a parameter that is acted upon by the control plane and is called by reference.
Trivial -- require removing 4 lines of code that check parameters