[rstmgr, top] Streamline rstmgr controls for software resets

Address #3089

Since our reggen tool does not currently support assigning a different
reggen per multireg slot, implement this outside in the module.

Once we work out that feature from reggen, we should return to change this.

Signed-off-by: Timothy Chen <timothytim@google.com>

[rstmgr] Add exclusions

Signed-off-by: Timothy Chen <timothytim@google.com>

[rstmgr] update exclusions once more

Signed-off-by: Timothy Chen <timothytim@google.com>

[rstmgr] update header generation

Signed-off-by: Timothy Chen <timothytim@google.com>
diff --git a/hw/ip/rstmgr/data/rstmgr.hjson.tpl b/hw/ip/rstmgr/data/rstmgr.hjson.tpl
index 15d15a3..bc18fd6 100644
--- a/hw/ip/rstmgr/data/rstmgr.hjson.tpl
+++ b/hw/ip/rstmgr/data/rstmgr.hjson.tpl
@@ -204,45 +204,55 @@
     # Templated registers for software control
     ########################
 
-% for rst in sw_rsts:
-    { name: "${rst['name'].upper()}_REGEN",
-      desc: '''
-            Register write enable for ${rst['name']} reset.
-            ''',
-      swaccess: "rw1c",
-      hwaccess: "none",
-      fields: [
-        {
-            bits:   "0",
-            desc: ''' When 1, rst_${rst['name']}_n is software programmable.
-            '''
-            resval: 1,
-        },
-      ]
-      tags: [// Don't reset other IPs as it will affect CSR access on these IPs
-             "excl:CsrAllTests:CsrExclWrite"]
-    },
+    { multireg: {
+        cname: "RSTMGR_SW_RST",
+        name:  "SW_RST_REGEN",
+        desc:  '''
+          Register write enable for software controllabe resets.
+          When a particular bit value is 0, the corresponding value in !SW_RST_CTRL can no longer be changed.
+          When a particular bit value is 1, the corresponding value in !SW_RST_CTRL can be changed.
+        ''',
+        count: ${len(sw_rsts)},
+        swaccess: "rw0c",
+        hwaccess: "hro",
+        fields: [
+          {
+            bits: "0",
+            name: "EN",
+            desc: "Register write enable for software controllable resets",
+            resval: "1",
+            tags: [// Don't reset other IPs as it will affect CSR access on these IPs
+              "excl:CsrAllTests:CsrExclCheck"]
+          },
+        ],
+      }
+    }
 
-    { name: "RST_${rst['name'].upper()}_N",
-      regwen:  "${rst['name'].upper()}_REGEN",
-      desc: '''
-            Software reset control for ${rst['name']}
-            ''',
-      swaccess: "rw",
-      hwaccess: "hro",
-      fields: [
-        {
-            bits:   "0",
-            desc: ''' When set to 0, ${rst['name']} is held in reset.  This bit can only be
-            programmed when ${rst['name']}_regen is 1.
-            '''
-            resval: 1,
-        },
-      ]
-      tags: [// Don't reset other IPs as it will affect CSR access on these IPs
-             "excl:CsrAllTests:CsrExclWrite"]
-    },
-% endfor
+    { multireg: {
+        cname: "RSTMGR_SW_RST",
+        name:  "SW_RST_CTRL_N",
+        desc:  '''
+          Software controllabe resets.
+          When a particular bit value is 0, the corresponding module is held in reset.
+          When a particular bit value is 1, the corresponding module is not held in reset.
+        ''',
+        count: ${len(sw_rsts)},
+        swaccess: "rw",
+        hwaccess: "hro",
+        hwext: "true",
+        hwqe: "true",
+        fields: [
+          {
+            bits: "0",
+            name: "VAL",
+            desc: "Software reset value",
+            resval: "1",
+            tags: [// Don't reset other IPs as it will affect CSR access on these IPs
+              "excl:CsrAllTests:CsrExclCheck"]
+          },
+        ],
+      }
+    }
   ]
 
 
diff --git a/hw/ip/rstmgr/data/rstmgr.sv.tpl b/hw/ip/rstmgr/data/rstmgr.sv.tpl
index 620020c..43b0dd9 100644
--- a/hw/ip/rstmgr/data/rstmgr.sv.tpl
+++ b/hw/ip/rstmgr/data/rstmgr.sv.tpl
@@ -146,6 +146,30 @@
   assign pwr_o.rst_lc_src_n = rst_lc_src_n;
   assign pwr_o.rst_sys_src_n = rst_sys_src_n;
 
+
+  ////////////////////////////////////////////////////
+  // Software reset controls external reg           //
+  ////////////////////////////////////////////////////
+  logic [${len(sw_rsts)}-1:0] sw_rst_ctrl_n;
+
+  for (genvar i=0; i < ${len(sw_rsts)}; i++) begin : gen_sw_rst_ext_regs
+    prim_subreg #(
+      .DW(1),
+      .SWACCESS("RW"),
+      .RESVAL(1)
+    ) u_rst_sw_ctrl_reg (
+      .clk_i,
+      .rst_ni(local_rst_n),
+      .we(reg2hw.sw_rst_ctrl_n[i].qe & reg2hw.sw_rst_regen[i]),
+      .wd(reg2hw.sw_rst_ctrl_n[i].q),
+      .de('0),
+      .d('0),
+      .qe(),
+      .q(sw_rst_ctrl_n[i]),
+      .qs(hw2reg.sw_rst_ctrl_n[i].d)
+    );
+  end
+
   ////////////////////////////////////////////////////
   // leaf reset in the system                       //
   // These should all be generated                  //
@@ -165,7 +189,7 @@
     .rst_ni(rst_${rst['parent']}_n),
   % endif
   % if "sw" in rst:
-    .d_i(reg2hw.rst_${rst['name']}_n.q),
+    .d_i(sw_rst_ctrl_n[${rst['name'].upper()}]),
   % else:
     .d_i(1'b1),
   % endif
diff --git a/hw/ip/rstmgr/data/rstmgr_pkg.sv.tpl b/hw/ip/rstmgr/data/rstmgr_pkg.sv.tpl
index b40fafa..538c5a1 100644
--- a/hw/ip/rstmgr/data/rstmgr_pkg.sv.tpl
+++ b/hw/ip/rstmgr/data/rstmgr_pkg.sv.tpl
@@ -18,8 +18,10 @@
   // calculated domains
   parameter int OffDomains = PowerDomains-1;
 
-  // low power exit + ndm_reset_req + external reasons
-  //parameter int ResetReasons = 1 + 1 + HwResetReqs;
+  // positions of software controllable reset bits
+% for rst in sw_rsts:
+  parameter int ${rst['name'].upper()} = ${loop.index};
+% endfor
 
   // ast interface
   typedef struct packed {
diff --git a/hw/top_earlgrey/data/top_earlgrey.h.tpl b/hw/top_earlgrey/data/top_earlgrey.h.tpl
index 1343122..3d94a52 100644
--- a/hw/top_earlgrey/data/top_earlgrey.h.tpl
+++ b/hw/top_earlgrey/data/top_earlgrey.h.tpl
@@ -150,6 +150,11 @@
  */
 ${helper.pwrmgr_wakeups.render()}
 
+/**
+ * Reset Manager Software Controlled Resets
+ */
+${helper.rstmgr_sw_rsts.render()}
+
 // Header Extern Guard
 #ifdef __cplusplus
 }  // extern "C"
diff --git a/util/topgen/c.py b/util/topgen/c.py
index 77ec472..d98e16d 100644
--- a/util/topgen/c.py
+++ b/util/topgen/c.py
@@ -139,6 +139,7 @@
         self._init_alert_mapping()
         self._init_pinmux_mapping()
         self._init_pwrmgr_wakeups()
+        self._init_rstmgr_sw_rsts()
 
     def modules(self):
         return [(m["name"],
@@ -368,3 +369,17 @@
         enum.add_last_constant("Last valid pwrmgr wakeup signal")
 
         self.pwrmgr_wakeups = enum
+
+    # Enumerates the positions of all software controllable resets
+    def _init_rstmgr_sw_rsts(self):
+        sw_rsts = [rst for rst in self.top["resets"]["nodes"] if 'sw' in rst
+                   and rst['sw'] == 1]
+
+        enum = CEnum(self._top_name + Name(["reset", "manager", "sw", "resets"]))
+
+        for rst in sw_rsts:
+            enum.add_constant(Name.from_snake_case(rst["name"]))
+
+        enum.add_last_constant("Last valid rstmgr software reset request")
+
+        self.rstmgr_sw_rsts = enum