[pinmux/tap] Rework DFT TAP hooks

The current DFT TAP hooks expose the JTAG signals as a struct type,
and the pinmux_jtag_buf module is instantiated not only for the DFT
TAP but also for the other TAPs that are connected in RTL.

While this is all correct from a syntax and design perspective, the
struct type seems to confuse certain automatic DFT insertion tools.
Further having multiple pinmux_jtag_buf modules instantiated exposed a
uniquification bug in Tessent.

To solve this issue, this patch adds a breakout module called
pinmux_jtag_breakout for the DFT tap on the top-level that exposes the
DFT signal hooks as simple logic ports.

Signed-off-by: Michael Schaffner <msf@opentitan.org>
diff --git a/hw/ip/pinmux/pinmux_component.core b/hw/ip/pinmux/pinmux_component.core
index d7e0283..8789541 100644
--- a/hw/ip/pinmux/pinmux_component.core
+++ b/hw/ip/pinmux/pinmux_component.core
@@ -24,6 +24,7 @@
       - rtl/pinmux_pkg.sv
       - rtl/pinmux_wkup.sv
       - rtl/pinmux_jtag_buf.sv
+      - rtl/pinmux_jtag_breakout.sv
       - rtl/pinmux_strap_sampling.sv
       - rtl/pinmux.sv
     file_type: systemVerilogSource
diff --git a/hw/ip/pinmux/rtl/pinmux_jtag_breakout.sv b/hw/ip/pinmux/rtl/pinmux_jtag_breakout.sv
new file mode 100644
index 0000000..2feb510
--- /dev/null
+++ b/hw/ip/pinmux/rtl/pinmux_jtag_breakout.sv
@@ -0,0 +1,24 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+module pinmux_jtag_breakout (
+  input  jtag_pkg::jtag_req_t req_i,
+  output jtag_pkg::jtag_rsp_t rsp_o,
+
+  output logic tck_o,
+  output logic trst_no,
+  output logic tms_o,
+  output logic tdi_o,
+  input        tdo_i,
+  input        tdo_oe_i
+);
+
+  assign tck_o        = req_i.tck;
+  assign trst_no      = req_i.trst_n;
+  assign tms_o        = req_i.tms;
+  assign tdi_o        = req_i.tdi;
+  assign rsp_o.tdo    = tdo_i;
+  assign rsp_o.tdo_oe = tdo_oe_i;
+
+endmodule : pinmux_jtag_breakout
diff --git a/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson b/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson
index 3cf9218..834aaca 100644
--- a/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson
+++ b/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson
@@ -2942,6 +2942,8 @@
           act: req
           width: 1
           inst_name: pinmux_aon
+          default: ""
+          top_signame: pinmux_aon_dft_jtag
           index: -1
         }
         {
@@ -6265,6 +6267,7 @@
       main.tl_cored
       main.tl_dm_sba
       main.tl_debug_mem
+      pinmux_aon.dft_jtag
     ]
     external:
     {
@@ -13282,6 +13285,8 @@
         act: req
         width: 1
         inst_name: pinmux_aon
+        default: ""
+        top_signame: pinmux_aon_dft_jtag
         index: -1
       }
       {
@@ -18286,6 +18291,24 @@
         end_idx: -1
         default: ""
       }
+      {
+        package: jtag_pkg
+        struct: jtag_req
+        signame: pinmux_aon_dft_jtag_req
+        width: 1
+        type: req_rsp
+        end_idx: -1
+        default: ""
+      }
+      {
+        package: jtag_pkg
+        struct: jtag_rsp
+        signame: pinmux_aon_dft_jtag_rsp
+        width: 1
+        type: req_rsp
+        end_idx: -1
+        default: ""
+      }
     ]
   }
 }
\ No newline at end of file
diff --git a/hw/top_earlgrey/data/top_earlgrey.hjson b/hw/top_earlgrey/data/top_earlgrey.hjson
index 86077dd..0841037 100644
--- a/hw/top_earlgrey/data/top_earlgrey.hjson
+++ b/hw/top_earlgrey/data/top_earlgrey.hjson
@@ -912,9 +912,6 @@
       'clkmgr_aon.idle'         : [],
 
       // Pinmux JTAG signals
-      // Note that the DFT TAP will be connected
-      // automatically by the DFT insertion tool,
-      // hence it does not have to be connected here.
       'pinmux_aon.lc_jtag' : ['lc_ctrl.jtag'],
       'pinmux_aon.rv_jtag' : ['rv_dm.jtag'],
 
@@ -971,7 +968,11 @@
         'pwrmgr_aon.fetch_en',
 
         // Xbars
-        'main.tl_corei', 'main.tl_cored', 'main.tl_dm_sba', 'main.tl_debug_mem'
+        'main.tl_corei', 'main.tl_cored', 'main.tl_dm_sba', 'main.tl_debug_mem',
+
+        // Pinmux JTAG signals for the tool-inserted DFT TAP
+        'pinmux_aon.dft_jtag'
+
     ],
 
     // ext is to create port in the top.
diff --git a/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv b/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv
index 0a430f3..de4714e 100644
--- a/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv
+++ b/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv
@@ -643,6 +643,8 @@
   tlul_pkg::tl_d2h_t       main_tl_dm_sba_rsp;
   tlul_pkg::tl_h2d_t       main_tl_debug_mem_req;
   tlul_pkg::tl_d2h_t       main_tl_debug_mem_rsp;
+  jtag_pkg::jtag_req_t       pinmux_aon_dft_jtag_req;
+  jtag_pkg::jtag_rsp_t       pinmux_aon_dft_jtag_rsp;
 
   // define mixed connection to port
   assign edn0_edn_req[2] = ast_edn_req_i;
@@ -805,6 +807,18 @@
   assign rstmgr_aon_cpu.ndmreset_req = ndmreset_req;
   assign rstmgr_aon_cpu.rst_cpu_n = rstmgr_aon_resets.rst_sys_n[rstmgr_pkg::Domain0Sel];
 
+  // Struct breakout module tool-inserted DFT TAP signals
+  pinmux_jtag_breakout u_dft_tap_breakout (
+    .req_i    (pinmux_aon_dft_jtag_req),
+    .rsp_o    (pinmux_aon_dft_jtag_rsp),
+    .tck_o    (),
+    .trst_no  (),
+    .tms_o    (),
+    .tdi_o    (),
+    .tdo_i    (1'b0),
+    .tdo_oe_i (1'b0)
+  );
+
   // sram device
   logic        ram_main_req;
   logic        ram_main_gnt;
@@ -1796,8 +1810,8 @@
       .lc_jtag_i(pinmux_aon_lc_jtag_rsp),
       .rv_jtag_o(pinmux_aon_rv_jtag_req),
       .rv_jtag_i(pinmux_aon_rv_jtag_rsp),
-      .dft_jtag_o(),
-      .dft_jtag_i(jtag_pkg::JTAG_RSP_DEFAULT),
+      .dft_jtag_o(pinmux_aon_dft_jtag_req),
+      .dft_jtag_i(pinmux_aon_dft_jtag_rsp),
       .dft_strap_test_o(dft_strap_test_o),
       .dft_hold_tap_sel_i(dft_hold_tap_sel_i),
       .sleep_en_i(pwrmgr_aon_low_power),
diff --git a/util/topgen/templates/toplevel.sv.tpl b/util/topgen/templates/toplevel.sv.tpl
index f0248b3..c7470ff 100644
--- a/util/topgen/templates/toplevel.sv.tpl
+++ b/util/topgen/templates/toplevel.sv.tpl
@@ -347,6 +347,18 @@
   assign rstmgr_aon_cpu.ndmreset_req = ndmreset_req;
   assign rstmgr_aon_cpu.rst_cpu_n = ${top["reset_paths"]["sys"]}[rstmgr_pkg::Domain0Sel];
 
+  // Struct breakout module tool-inserted DFT TAP signals
+  pinmux_jtag_breakout u_dft_tap_breakout (
+    .req_i    (pinmux_aon_dft_jtag_req),
+    .rsp_o    (pinmux_aon_dft_jtag_rsp),
+    .tck_o    (),
+    .trst_no  (),
+    .tms_o    (),
+    .tdi_o    (),
+    .tdo_i    (1'b0),
+    .tdo_oe_i (1'b0)
+  );
+
 ## Memory Instantiation
 % for m in top["memory"]:
 <%