@@ -3399,21 +3399,49 @@ are instantiated, as long as all conflicting implementations are overridable,
33993399and one of the following is true:
34003400* The implementations can be combined together by calling each one of them, as
34013401 long as that can be done without risking e.g. side-effects being duplicated.
3402+ * The implementations in all but (optionally) one of the involved templates call
3403+ to a "base" method that would serve the same purpose as ` default ` , but whose
3404+ definition may be * overridden* such that the conflicting implementations can
3405+ be resolved by overriding these base methods and leveraging template-qualified
3406+ method implementation calls in order to define the chain of how each
3407+ implementation gets called.
3408+
3409+ This requires that the names of the base methods are unique to each template
3410+ involved, and also some thought as to how the implementations in the chain
3411+ should be ordered.
3412+
3413+ If the implementations in some templates call ` default ` instead of an
3414+ overridable base method, consider modifying those templates (if possible) to
3415+ each use a base method instead &mdash ; a template-qualified
3416+ method implementation call can be used as the default implementation of each
3417+ base method in order to make it act like ` default ` in the typical case where
3418+ no conflicting templates are in play.
34023419* The implementations can be combined by choosing one particular template's
34033420 implementation to invoke (typically the one most complex), and then adding
34043421 code around that implementation call in order to replicate the behaviour of
34053422 the implementations of the other templates. Ideally, the other templates would
34063423 provide methods that may be leveraged so that their behaviour may be
34073424 replicated without the need for excessive boilerplate.
34083425
3426+ These cases are ordered by difficulty to resolve in ascending order. In
3427+ practice, most conflicts between unrelated templates can be resolved by
3428+ modifying the templates such that the second case may apply.
3429+
3430+ > [ !NOTE]
3431+ > The examples given below apply regardless of whether the method
3432+ > implementations in the original templates are ` shared ` or not. However, the
3433+ > implementations in the template defined to resolve the conflicts may need to
3434+ > be non-` shared ` if some of the implementations involved are not ` shared ` ;
3435+ > see the final paragraph of this subsection.
3436+
34093437The following is an example of the first case:
34103438```
34113439template alter_write is write {
34123440 method write(uint64 written) {
34133441 default(alter_write(written));
34143442 }
34153443
3416- method alter_write(uint64 curr, uint64 written) -> (uint64);
3444+ shared method alter_write(uint64 curr, uint64 written) -> (uint64);
34173445}
34183446
34193447template gated_write is alter_write {
@@ -3447,6 +3475,57 @@ in each (gated_write, write_1_clears) { is gated_write_1_clears; }
34473475
34483476The following is an example of the second case:
34493477```
3478+ template gated_write is write {
3479+ method write_allowed() -> (bool) default {
3480+ return true;
3481+ }
3482+
3483+ method write(uint64 val) default {
3484+ if (write_allowed()) {
3485+ base_write_of_gated_write(val); // instead of calling default()
3486+ }
3487+ }
3488+
3489+ method base_write_of_gated_write(uint64 val) default {
3490+ // If no conflicting template is in play such as to override this
3491+ // base method, then its behavior is as though the write implementation
3492+ // called default() instead
3493+ this.templates.write.write(val);
3494+ }
3495+ }
3496+
3497+ template write_1_clears is (write, get) {
3498+ method write(uint64 val) default {
3499+ default(get() & ~val);
3500+ }
3501+ }
3502+
3503+ template gated_write_1_clears is (gated_write, write_1_clears) {
3504+ method write(uint64 val) default {
3505+ // This makes gated_write the first link in the call chain...
3506+ this.templates.gated_write.write(val);
3507+ }
3508+
3509+ // And by overriding gated_write's base method, we make write_1_clears
3510+ // the second (and final) link in the chain
3511+ //
3512+ // If even more conflicting templates could be in play, then one could
3513+ // consider converting write_1_clears to also leverage a base method
3514+ // instead of calling default and extend the call chain; on the other
3515+ // hand, the way write_1_clears manipulates the written value may violate
3516+ // the expectations of implementations later on in the chain, so it might
3517+ // make most sense to always place write_1_clears as the final link, and
3518+ // have all other templates leverage base methods instead.
3519+ method base_write_of_gated_write(uint64 val) default {
3520+ this.templates.write_1_clears.write(val);
3521+ }
3522+ }
3523+
3524+ in each (gated_write, write_1_clears) { is gated_write_1_clears; }
3525+ ```
3526+
3527+ The following is an example of the third case:
3528+ ```
34503529template very_complex_register is register {
34513530 method write_register(uint64 written, uint64 enabled_bytes,
34523531 void *aux) default {
0 commit comments