@@ -37,6 +37,42 @@ class SimpleInterface extends PairInterface {
3737 SimpleInterface clone () => SimpleInterface ();
3838}
3939
40+ class SubInterface extends PairInterface {
41+ Logic get subReq => port ('sub_req' );
42+ Logic get subRsp => port ('sub_rsp' );
43+
44+ SubInterface ()
45+ : super (
46+ portsFromConsumer: [Logic .port ('sub_rsp' , 8 )],
47+ portsFromProvider: [Logic .port ('sub_req' , 8 )],
48+ );
49+
50+ @override
51+ SubInterface clone () => SubInterface ();
52+ }
53+
54+ class HierarchicalInterface extends PairInterface {
55+ Logic get mainReq => port ('main_req' );
56+ Logic get mainRsp => port ('main_rsp' );
57+ SubInterface get sub1 => subInterfaces['sub1' ]! as SubInterface ;
58+ SubInterface get sub2 => subInterfaces['sub2' ]! as SubInterface ;
59+
60+ HierarchicalInterface ({bool excludeSubInterfaces = false })
61+ : super (
62+ portsFromProvider: [Logic .port ('main_req' , 8 )],
63+ portsFromConsumer: [Logic .port ('main_rsp' , 8 )],
64+ ) {
65+ if (! excludeSubInterfaces) {
66+ addSubInterface ('sub1' , SubInterface (), uniquify: (orig) => 'sub1_$orig ' );
67+ addSubInterface ('sub2' , SubInterface (),
68+ uniquify: (orig) => 'sub2_$orig ' , reverse: true );
69+ }
70+ }
71+
72+ @override
73+ HierarchicalInterface clone () => HierarchicalInterface ();
74+ }
75+
4076class SimpleProvider extends Module {
4177 late final SimpleInterface _intf;
4278 SimpleProvider (SimpleInterface intf) {
@@ -118,6 +154,34 @@ class PassthroughPairIntfModule extends Module {
118154 }
119155}
120156
157+ class SubInterfaceTestModule extends Module {
158+ SubInterfaceTestModule (
159+ HierarchicalInterface intf1, HierarchicalInterface intf2,
160+ {required bool useConditional}) {
161+ intf1 = addPairInterfacePorts (
162+ intf1,
163+ PairRole .consumer,
164+ uniquify: (original) => 'intf1_$original ' ,
165+ );
166+ intf2 = addPairInterfacePorts (
167+ intf2,
168+ PairRole .provider,
169+ uniquify: (original) => 'intf2_$original ' ,
170+ );
171+
172+ if (useConditional) {
173+ Combinational ([
174+ intf1.conditionalDriveOther (intf2, {PairDirection .fromProvider}),
175+ intf1.conditionalReceiveOther (intf2, {PairDirection .fromConsumer}),
176+ ]);
177+ } else {
178+ intf1
179+ ..driveOther (intf2, {PairDirection .fromProvider})
180+ ..receiveOther (intf2, {PairDirection .fromConsumer});
181+ }
182+ }
183+ }
184+
121185void main () {
122186 tearDown (() async {
123187 await Simulator .reset ();
@@ -187,4 +251,62 @@ void main() {
187251 }
188252 }
189253 });
254+
255+ group ('sub-interface drive and receive other' , () {
256+ for (final useConditional in [false , true ]) {
257+ test ('with useConditional: $useConditional ' , () async {
258+ final mod = SubInterfaceTestModule (
259+ HierarchicalInterface (),
260+ HierarchicalInterface (),
261+ useConditional: useConditional,
262+ );
263+ await mod.build ();
264+
265+ final vectors = [
266+ Vector ({
267+ 'intf1_main_req' : 0x01 ,
268+ 'intf2_main_rsp' : 0x12 ,
269+ 'intf1_sub1_sub_req' : 0x23 ,
270+ 'intf2_sub1_sub_rsp' : 0x34 ,
271+ 'intf1_sub2_sub_rsp' : 0x45 ,
272+ 'intf2_sub2_sub_req' : 0x56
273+ }, {
274+ 'intf2_main_req' : 0x01 ,
275+ 'intf1_main_rsp' : 0x12 ,
276+ 'intf2_sub1_sub_req' : 0x23 ,
277+ 'intf1_sub1_sub_rsp' : 0x34 ,
278+ 'intf2_sub2_sub_rsp' : 0x45 ,
279+ 'intf1_sub2_sub_req' : 0x56
280+ }),
281+ ];
282+
283+ await SimCompare .checkFunctionalVector (mod, vectors);
284+ SimCompare .checkIverilogVector (mod, vectors);
285+ });
286+ }
287+ });
288+
289+ test ('hierarchical interface creation and access' , () {
290+ final intf = HierarchicalInterface ();
291+
292+ // Test that sub-interfaces were created properly
293+ expect (intf.subInterfaces.containsKey ('sub1' ), isTrue);
294+ expect (intf.subInterfaces.containsKey ('sub2' ), isTrue);
295+ expect (intf.subInterfaces.length, equals (2 ));
296+
297+ // Test access to sub-interface ports
298+ expect (intf.sub1.subReq.width, equals (8 ));
299+ expect (intf.sub1.subRsp.width, equals (8 ));
300+ expect (intf.sub2.subReq.width, equals (8 ));
301+ expect (intf.sub2.subRsp.width, equals (8 ));
302+ });
303+
304+ test ('sub-interface missing error handling' , () {
305+ expect (
306+ () => HierarchicalInterface ().driveOther (
307+ HierarchicalInterface (excludeSubInterfaces: true ),
308+ {PairDirection .fromProvider}),
309+ throwsA (isA <InterfaceTypeException >()),
310+ );
311+ });
190312}
0 commit comments