[sw] Add spi_host_tx_rx_test

Add a basic spi host tx rx test.
This test uses the spi_agent's native "loopback" behavior.
The spi agent, when in device mode, by default just plays
back whatever data is sent to it by the host.

The test prepares a random payload, sends it to the device agent,
and just reads back to make sure the data is matched.

This test DOES NOT do any kind of flash protocol checking.

- Add a device value for high speed peripehral clock
- Add a minor fix for dif_spi_host clock divider setting

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

[sw] test updates

- update spi_host_tx_rx_test
- minor fix for spi_host clock divider

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

[dv] Add test sequence

- updates to testplan
- add if_mode setup into chip_base_test

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

[top/dv] Minor updates

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

[top/dv] spi_host configuration fix

spi host does not support outputting at 1:1 frequencies.

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

[top/dv] Various updates for spi_host testing

- integrate with latest chip_if
- add support for multiple spi_device agents
- add enum to access pad pull-up attributes

Signed-off-by: Timothy Chen <timothytim@google.com>
diff --git a/util/topgen/c.py b/util/topgen/c.py
index 1c6adae..78d955a 100644
--- a/util/topgen/c.py
+++ b/util/topgen/c.py
@@ -115,6 +115,7 @@
         self._init_plic_mapping()
         self._init_alert_mapping()
         self._init_pinmux_mapping()
+        self._init_pad_mapping()
         self._init_pwrmgr_wakeups()
         self._init_rstmgr_sw_rsts()
         self._init_pwrmgr_reset_requests()
@@ -389,6 +390,45 @@
         self.pinmux_mio_out = mio_out
         self.pinmux_outsel = outsel
 
+    def _init_pad_mapping(self):
+        """Generate C enums for order of MIO and DIO pads.
+
+        These are needed to configure pad specific configurations such as
+        slew rate and other flags.
+        """
+        direct_enum = CEnum(self._top_name +
+                               Name(["direct", "pads"]))
+
+        muxed_enum = CEnum(self._top_name +
+                               Name(["muxed", "pads"]))
+
+        pads_info = self.top['pinout']['pads']
+        muxed = [pad['name'] for pad in pads_info if pad['connection'] == 'muxed']
+
+        # The logic here follows the sequence done in toplevel_pkg.sv.tpl.
+        # The direct pads do not enumerate directly from the pinout like the muxed
+        # ios.  Instead it follows a direction from the pinmux perspective.
+        pads_info = self.top['pinmux']['ios']
+        direct = [pad for pad in pads_info if pad['connection'] != 'muxed']
+
+        for pad in (direct):
+            name = f"{pad['name']}"
+            if pad['width'] > 1:
+                name = f"{name}{pad['idx']}"
+
+            direct_enum.add_constant(
+                Name.from_snake_case(name))
+        direct_enum.add_last_constant("Last valid direct pad")
+
+        for pad in (muxed):
+            muxed_enum.add_constant(
+                Name.from_snake_case(pad))
+        muxed_enum.add_last_constant("Last valid muxed pad")
+
+        self.direct_pads = direct_enum
+        self.muxed_pads = muxed_enum
+
+
     def _init_pwrmgr_wakeups(self):
         enum = CEnum(self._top_name +
                      Name(["power", "manager", "wake", "ups"]))