[topgen/tlgen] Multi-tiered Xbar

The script is to support multi-tiered crossbars on top_earlgrey.

Now any crossbar can have connections to other crossbars. It is allowed
only one connection between two crossbars at this time.

If `xbar: "true"` is defined in the node, the tool does below:

- Recognize it as a crossbar connection
- Gather downstream addresses and calculate the common address range (*)
- If device is a port to another crossbar, the address steering compares
  list of address range not a single `address_from`, `address_to`

Signed-off-by: Eunchan Kim <eunchan@opentitan.org>
diff --git a/hw/top_earlgrey/data/top_earlgrey.sv.tpl b/hw/top_earlgrey/data/top_earlgrey.sv.tpl
index c0f3207..f41c7a1 100644
--- a/hw/top_earlgrey/data/top_earlgrey.sv.tpl
+++ b/hw/top_earlgrey/data/top_earlgrey.sv.tpl
@@ -102,6 +102,22 @@
   tl_d2h_t tl_${m["name"]}_d_d2h;
 % endfor
 
+## Xbar connection
+% for xbar in top["xbar"]:
+<%
+  xbar_devices = [x for x in xbar["nodes"] if x["type"] == "device" and x["xbar"]]
+%>\
+  % for node in xbar_devices:
+  tl_h2d_t tl_${xbar["name"]}_h_h2d;
+  tl_d2h_t tl_${xbar["name"]}_h_d2h;
+  tl_h2d_t tl_${node["name"]}_d_h2d;
+  tl_d2h_t tl_${node["name"]}_d_d2h;
+
+  assign tl_${xbar["name"]}_h_h2d = tl_${node["name"]}_d_h2d;
+  assign tl_${node["name"]}_d_d2h = tl_${xbar["name"]}_h_d2h;
+  % endfor
+% endfor
+
   //reset wires declaration
 % for reset in top['resets']:
   logic ${reset['name']}_rst_n;
@@ -622,8 +638,8 @@
   % endfor
 
     .scanmode_i
-% endfor
   );
+% endfor
 
 % if "pinmux" in top:
   // Pinmux connections