Consequences of "local name for a hierarchical reference" in modports

A typical use case, where SystemVerilog interfaces could help to get an efficiently described model is the following:

There is a CPU connected to a memory via a SystemVerilog interface. The CPU and the memory are composed to a sub-system that contains the same interface as interface port to connect additional peripherals from outside.

interface sys_intf();
   logic [31:0] addr, data_to_cpu, data_from_cpu;
   
   modport m_sub (input data_to_cpu, output data_from_cpu, addr);
   modport m_cpu (input data_to_cpu, output data_from_cpu, addr);
   modport m_mem (input addr, data_from_cpu, output data_to_cpu);
endinterface

module sub (sys_intf.m_sub intf_sub);
   cpu cpu (.intf_cpu (intf_sub));
   mem mem (.intf_mem (intf_sub));
endmodule

module cpu (sys_intf.m_cpu intf_cpu);
endmodule

module mem (sys_intf.m_mem intf_mem);
endmodule

For my understanding, the code is not correct because intf_sub is already a local name for a hierarchical reference so that
the interface ports inside cpu and mem just see the connected interface from the m_sub point-of-view. Is this correct?
Or is the code incorrect just because of different modport names or just because the directions in m_bub and m_mem are different?

Is there a simple solution in SystemVerilog to model this typical use-case?

Thanks and best regards,
Thomas

In reply to Thomas Kruse:

SystemVerilog interfaces are very poor at handling composition. You cannot say anything kill modport A contains modports B and C. So you either have to use the interface as a whole, or select a particular modport name and stick with it down the hierarchy.

The problem is not just that the directions might not align, but existence of the signals in the modport. For example, suppose I added an extra signal the the m_mem modport that did not exist in any other modport

interface sys_intf();
   logic [31:0] addr, data_to_cpu, data_from_cpu, select;
 
   modport m_sub (input data_to_cpu, output data_from_cpu, addr);
   modport m_cpu (input data_to_cpu, output data_from_cpu, addr);
   modport m_mem (input addr, data_from_cpu, select output data_to_cpu);
endinterface

module sys;
  sys_intf sys_inst();
  sub sub(.intf_sub(sys_inst.m_sub));
endmodule

The problem becomes that select is not in the m_sub modport list of signals and would not be accessible within the sub module, so how could it pass it down to the module mem?

In reply to dave_59:

Thanks, Dave! Understood.

Is there an official way to send found issues or proposals regarding the SV LRM to the language developer team?

Thanks
Thomas

In reply to dave_59:

The problem becomes that select is not in the m_sub modport list of signals and would not be accessible within the sub module, so how could it pass it down to the module mem?

Somewhere I got in my head that the interpretation of a SystemVerilog modport of an Interface was restricting the visibility (and perhaps adding port direction) of the Interface as a whole, depending on context. The entire Interface is still there, however, in certain context only the modport listed items are available. Passing the modport down to a different modport, well, isn’t clean, but works for Thomas’s original example.

In fact, some of my tools allow such. Others don’t. I’m not sure precisely what the standard says here, I think it’s a unclear.

The alternatives:

  1. Dont use modports
  2. Create a new interface within the intermediate level, and pass the appropriate connections through from the modport to the newly created interface. Use this recreated interface to pass down to the next submodule with a different modport

I don’t like 1 as our synthesis tools need hints on port direction - which the modports give. So that leaves 2. For various other reasons, we’ve had to create “interface passthrough” modules which simply pass an interface from one modport to another. This is ugly, but more and more necessary.

I wish this were cleaner in the SystemVerilog standard, and would second Thomas suggestion of adding this to the items to clean up.

In reply to Mark Curry:

This is captured more broadly as issue Mantis 2318. Modports were created to address the needs of synthesis tools so they could replace the interface connection with an actual set of port signal connections. Almost like a cut and paste of the modport definition into the module header’s port list. If you allow the module to pass interface as a whole to lower level modules, then synthesis no longer knows what to do with the top level interface port. Not a problem for simulation only descriptions, but that is rarely the case for interfaces except at the top level.

The best way of getting issues to the the language development team is becoming a part of it. This particular issue is not getting addressed in the next revision of the standard because there was no one who brought it up or wanted to work on resolving it.

The other way is brining it up to your tool vendors and asking that they get it resolved on your behalf.