From 2f368f1b8a4776512560be3c900090f17ac4033a Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Thu, 3 Aug 2023 11:40:32 -0700 Subject: [PATCH 01/88] [hw,mbx,rtl] RTL skeleton for DOE Mailbox Signed-off-by: Robert Schilling --- hw/Makefile | 1 + hw/ip/README.md | 2 + hw/ip/mbx/README.md | 13 ++ hw/ip/mbx/data/BUILD | 12 ++ hw/ip/mbx/data/mbx.hjson | 41 ++++ hw/ip/mbx/lint/mbx.vlt | 7 + hw/ip/mbx/lint/mbx.waiver | 5 + hw/ip/mbx/mbx.core | 76 ++++++++ hw/ip/mbx/rtl/mbx.sv | 24 +++ hw/ip/mbx/rtl/mbx_host_reg_top.sv | 298 ++++++++++++++++++++++++++++++ hw/ip/mbx/rtl/mbx_reg_pkg.sv | 70 +++++++ hw/ip/mbx/rtl/mbx_sys_reg_top.sv | 42 +++++ 12 files changed, 591 insertions(+) create mode 100644 hw/ip/mbx/README.md create mode 100644 hw/ip/mbx/data/BUILD create mode 100644 hw/ip/mbx/data/mbx.hjson create mode 100644 hw/ip/mbx/lint/mbx.vlt create mode 100644 hw/ip/mbx/lint/mbx.waiver create mode 100644 hw/ip/mbx/mbx.core create mode 100644 hw/ip/mbx/rtl/mbx.sv create mode 100644 hw/ip/mbx/rtl/mbx_host_reg_top.sv create mode 100644 hw/ip/mbx/rtl/mbx_reg_pkg.sv create mode 100644 hw/ip/mbx/rtl/mbx_sys_reg_top.sv diff --git a/hw/Makefile b/hw/Makefile index c5a87f9316a23..238e348a7a005 100644 --- a/hw/Makefile +++ b/hw/Makefile @@ -28,6 +28,7 @@ IPS ?= aes \ keymgr_dpe \ kmac \ lc_ctrl \ + mbx \ otbn \ otp_ctrl \ pattgen \ diff --git a/hw/ip/README.md b/hw/ip/README.md index c0d3400b15822..9cc0e2cd20abb 100644 --- a/hw/ip/README.md +++ b/hw/ip/README.md @@ -19,6 +19,7 @@ | [`keymgr_dpe`] | Manage multiple DICE sessions in a DPE-compatible way | | [`kmac`] | Accelerator for Keccak-based keyed hash message authentication code and SHA-3 hash functions; with SCA and FI countermeasures | | [`lc_ctrl`] | Manages device life cycle states and transitions, and controls key manager, flash, OTP, and debug access | +| [`mbx`] | DOE mailbox for use as an integrated OpenTitan communication channel. | | [`otbn`] | Programmable coprocessor for asymmetric cryptography with SCA and FI countermeasures | | [`otp_ctrl`] | Interfaces integrated one-time programmable memory, supports scrambling, integrity and secure wipe | | [`pattgen`] | Transmission of short time-dependent data patterns on two clock-parallel output channels | @@ -53,6 +54,7 @@ [`keymgr_dpe`]: ./keymgr_dpe/README.md [`kmac`]: ./kmac/README.md [`lc_ctrl`]: ./lc_ctrl/README.md +[`mbx`]: ./mbx/README.md [`otbn`]: ./otbn/README.md [`otp_ctrl`]: ./otp_ctrl/README.md [`pattgen`]: ./pattgen/README.md diff --git a/hw/ip/mbx/README.md b/hw/ip/mbx/README.md new file mode 100644 index 0000000000000..e729bd1d835c0 --- /dev/null +++ b/hw/ip/mbx/README.md @@ -0,0 +1,13 @@ +# DOE MBX HWIP Technical Specification + +{{#block-dashboard mbx}} + +# Overview + +## Features + +## Description + +### Security + +## Compatibility diff --git a/hw/ip/mbx/data/BUILD b/hw/ip/mbx/data/BUILD new file mode 100644 index 0000000000000..730e284d2d896 --- /dev/null +++ b/hw/ip/mbx/data/BUILD @@ -0,0 +1,12 @@ +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +package(default_visibility = ["//visibility:public"]) + +load("//rules:autogen.bzl", "autogen_hjson_header") + +filegroup( + name = "all_files", + srcs = glob(["**"]), +) diff --git a/hw/ip/mbx/data/mbx.hjson b/hw/ip/mbx/data/mbx.hjson new file mode 100644 index 0000000000000..2d728f98e53ed --- /dev/null +++ b/hw/ip/mbx/data/mbx.hjson @@ -0,0 +1,41 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +# DOE register template +{ + name: "mbx" + human_name: "DOE Mailbox" + one_line_desc: "DOE mailbox for use as an integrated OpenTitan communication channel." + one_paragraph_desc: ''' + The SoC Host (or other SoC Execution Engines) may request security services from the OpenTitan RoT. + This means that pre-defined control information must be passed to OpenTitan from the security service requester. + A secure inbound/outbound mailbox can be used to implement a secure channel for these request/response transactions between the Host and the RoT. + ''' + cip_id: "37", + design_spec: "../doc" + dv_doc: "../doc/dv" + version: "0.1.0" + + clocking: [{clock: "clk_i", reset: "rst_ni", primary: true}] + scan: "true" // Enable `scanmode_i` port + scan_reset: "true" // Enable `scan_rst_ni` port + scan_en: "true" // Enable `scan_en_i` port + bus_interfaces: [ + { protocol: "tlul", direction: "device", name: "host" } + { protocol: "tlul", direction: "host", name: "sram" } + { protocol: "tlul", direction: "device", name: "sys" } + ] + interrupt_list: [ + { name: "mbx_ready" + desc: "A new object was received in the inbound mailbox." + } + ] + regwidth: "32" + registers: { + host: [ + ] + sys: [ + ] + } +} diff --git a/hw/ip/mbx/lint/mbx.vlt b/hw/ip/mbx/lint/mbx.vlt new file mode 100644 index 0000000000000..b619d88d5012b --- /dev/null +++ b/hw/ip/mbx/lint/mbx.vlt @@ -0,0 +1,7 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// waiver file for mbx + +`verilator_config diff --git a/hw/ip/mbx/lint/mbx.waiver b/hw/ip/mbx/lint/mbx.waiver new file mode 100644 index 0000000000000..b09dfae2ed0bf --- /dev/null +++ b/hw/ip/mbx/lint/mbx.waiver @@ -0,0 +1,5 @@ +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +# +# waiver file for mbx diff --git a/hw/ip/mbx/mbx.core b/hw/ip/mbx/mbx.core new file mode 100644 index 0000000000000..6aa259cd4def5 --- /dev/null +++ b/hw/ip/mbx/mbx.core @@ -0,0 +1,76 @@ +CAPI=2: +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: "lowrisc:ip:mbx:0.1" +description: "DOE Mailbox" +filesets: + files_rtl: + depend: + - lowrisc:prim:all + - lowrisc:tlul:headers + - lowrisc:ip:tlul + files: + - rtl/mbx.sv + - rtl/mbx_reg_pkg.sv + - rtl/mbx_host_reg_top.sv + - rtl/mbx_sys_reg_top.sv + file_type: systemVerilogSource + + files_verilator_waiver: + depend: + # common waivers + - lowrisc:lint:common + - lowrisc:lint:comportable + files: + - lint/mbx.vlt + file_type: vlt + + files_ascentlint_waiver: + depend: + # common waivers + - lowrisc:lint:common + - lowrisc:lint:comportable + files: + - lint/mbx.waiver + file_type: waiver + + files_veriblelint_waiver: + depend: + # common waivers + - lowrisc:lint:common + - lowrisc:lint:comportable + +parameters: + SYNTHESIS: + datatype: bool + paramtype: vlogdefine + +targets: + default: &default_target + filesets: + - tool_verilator ? (files_verilator_waiver) + - tool_ascentlint ? (files_ascentlint_waiver) + - tool_veriblelint ? (files_veriblelint_waiver) + - files_rtl + toplevel: mbx + + lint: + <<: *default_target + default_tool: verilator + parameters: + - SYNTHESIS=true + tools: + verilator: + mode: lint-only + verilator_options: + - "-Wall" + + syn: + <<: *default_target + # TODO: set default to DC once + # this option is available + # olofk/edalize#89 + default_tool: icarus + parameters: + - SYNTHESIS=true diff --git a/hw/ip/mbx/rtl/mbx.sv b/hw/ip/mbx/rtl/mbx.sv new file mode 100644 index 0000000000000..1c2cfe2a09997 --- /dev/null +++ b/hw/ip/mbx/rtl/mbx.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 + +`include "prim_assert.sv" + +module mbx + import tlul_pkg::*; +( + input logic clk_i, + input logic rst_ni, + output logic irq_o, + // Device port facing OT-host + input tlul_pkg::tl_h2d_t tl_host_i, + output tlul_pkg::tl_d2h_t tl_host_o, + // Device port facing CTN Xbar + input tlul_pkg::tl_h2d_t tl_sys_i, + output tlul_pkg::tl_d2h_t tl_sys_o, + // Host port to access private SRAM + input tlul_pkg::tl_d2h_t tl_sram_i, + output tlul_pkg::tl_h2d_t tl_sram_o +); + +endmodule diff --git a/hw/ip/mbx/rtl/mbx_host_reg_top.sv b/hw/ip/mbx/rtl/mbx_host_reg_top.sv new file mode 100644 index 0000000000000..95177d4badee6 --- /dev/null +++ b/hw/ip/mbx/rtl/mbx_host_reg_top.sv @@ -0,0 +1,298 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Register Top module auto-generated by `reggen` + +`include "prim_assert.sv" + +module mbx_host_reg_top ( + input clk_i, + input rst_ni, + input tlul_pkg::tl_h2d_t tl_i, + output tlul_pkg::tl_d2h_t tl_o, + // To HW + output mbx_reg_pkg::mbx_host_reg2hw_t reg2hw, // Write + input mbx_reg_pkg::mbx_host_hw2reg_t hw2reg, // Read + + // Integrity check errors + output logic intg_err_o +); + + import mbx_reg_pkg::* ; + + localparam int AW = 4; + localparam int DW = 32; + localparam int DBW = DW/8; // Byte Width + + // register signals + logic reg_we; + logic reg_re; + logic [AW-1:0] reg_addr; + logic [DW-1:0] reg_wdata; + logic [DBW-1:0] reg_be; + logic [DW-1:0] reg_rdata; + logic reg_error; + + logic addrmiss, wr_err; + + logic [DW-1:0] reg_rdata_next; + logic reg_busy; + + tlul_pkg::tl_h2d_t tl_reg_h2d; + tlul_pkg::tl_d2h_t tl_reg_d2h; + + + // incoming payload check + logic intg_err; + tlul_cmd_intg_chk u_chk ( + .tl_i(tl_i), + .err_o(intg_err) + ); + + // also check for spurious write enables + logic reg_we_err; + logic [2:0] reg_we_check; + prim_reg_we_check #( + .OneHotWidth(3) + ) u_prim_reg_we_check ( + .clk_i(clk_i), + .rst_ni(rst_ni), + .oh_i (reg_we_check), + .en_i (reg_we && !addrmiss), + .err_o (reg_we_err) + ); + + logic err_q; + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + err_q <= '0; + end else if (intg_err || reg_we_err) begin + err_q <= 1'b1; + end + end + + // integrity error output is permanent and should be used for alert generation + // register errors are transactional + assign intg_err_o = err_q | intg_err | reg_we_err; + + // outgoing integrity generation + tlul_pkg::tl_d2h_t tl_o_pre; + tlul_rsp_intg_gen #( + .EnableRspIntgGen(1), + .EnableDataIntgGen(1) + ) u_rsp_intg_gen ( + .tl_i(tl_o_pre), + .tl_o(tl_o) + ); + + assign tl_reg_h2d = tl_i; + assign tl_o_pre = tl_reg_d2h; + + tlul_adapter_reg #( + .RegAw(AW), + .RegDw(DW), + .EnableDataIntgGen(0) + ) u_reg_if ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + .tl_i (tl_reg_h2d), + .tl_o (tl_reg_d2h), + + .en_ifetch_i(prim_mubi_pkg::MuBi4False), + .intg_error_o(), + + .we_o (reg_we), + .re_o (reg_re), + .addr_o (reg_addr), + .wdata_o (reg_wdata), + .be_o (reg_be), + .busy_i (reg_busy), + .rdata_i (reg_rdata), + .error_i (reg_error) + ); + + // cdc oversampling signals + + assign reg_rdata = reg_rdata_next ; + assign reg_error = addrmiss | wr_err | intg_err; + + // Define SW related signals + // Format: __{wd|we|qs} + // or _{wd|we|qs} if field == 1 or 0 + logic intr_state_we; + logic intr_state_qs; + logic intr_state_wd; + logic intr_enable_we; + logic intr_enable_qs; + logic intr_enable_wd; + logic intr_test_we; + logic intr_test_wd; + + // Register instances + // R[intr_state]: V(False) + prim_subreg #( + .DW (1), + .SwAccess(prim_subreg_pkg::SwAccessW1C), + .RESVAL (1'h0), + .Mubi (1'b0) + ) u_intr_state ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (intr_state_we), + .wd (intr_state_wd), + + // from internal hardware + .de (hw2reg.intr_state.de), + .d (hw2reg.intr_state.d), + + // to internal hardware + .qe (), + .q (reg2hw.intr_state.q), + .ds (), + + // to register interface (read) + .qs (intr_state_qs) + ); + + + // R[intr_enable]: V(False) + prim_subreg #( + .DW (1), + .SwAccess(prim_subreg_pkg::SwAccessRW), + .RESVAL (1'h0), + .Mubi (1'b0) + ) u_intr_enable ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (intr_enable_we), + .wd (intr_enable_wd), + + // from internal hardware + .de (1'b0), + .d ('0), + + // to internal hardware + .qe (), + .q (reg2hw.intr_enable.q), + .ds (), + + // to register interface (read) + .qs (intr_enable_qs) + ); + + + // R[intr_test]: V(True) + logic intr_test_qe; + logic [0:0] intr_test_flds_we; + assign intr_test_qe = &intr_test_flds_we; + prim_subreg_ext #( + .DW (1) + ) u_intr_test ( + .re (1'b0), + .we (intr_test_we), + .wd (intr_test_wd), + .d ('0), + .qre (), + .qe (intr_test_flds_we[0]), + .q (reg2hw.intr_test.q), + .ds (), + .qs () + ); + assign reg2hw.intr_test.qe = intr_test_qe; + + + + logic [2:0] addr_hit; + always_comb begin + addr_hit = '0; + addr_hit[0] = (reg_addr == MBX_INTR_STATE_OFFSET); + addr_hit[1] = (reg_addr == MBX_INTR_ENABLE_OFFSET); + addr_hit[2] = (reg_addr == MBX_INTR_TEST_OFFSET); + end + + assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ; + + // Check sub-word write is permitted + always_comb begin + wr_err = (reg_we & + ((addr_hit[0] & (|(MBX_HOST_PERMIT[0] & ~reg_be))) | + (addr_hit[1] & (|(MBX_HOST_PERMIT[1] & ~reg_be))) | + (addr_hit[2] & (|(MBX_HOST_PERMIT[2] & ~reg_be))))); + end + + // Generate write-enables + assign intr_state_we = addr_hit[0] & reg_we & !reg_error; + + assign intr_state_wd = reg_wdata[0]; + assign intr_enable_we = addr_hit[1] & reg_we & !reg_error; + + assign intr_enable_wd = reg_wdata[0]; + assign intr_test_we = addr_hit[2] & reg_we & !reg_error; + + assign intr_test_wd = reg_wdata[0]; + + // Assign write-enables to checker logic vector. + always_comb begin + reg_we_check = '0; + reg_we_check[0] = intr_state_we; + reg_we_check[1] = intr_enable_we; + reg_we_check[2] = intr_test_we; + end + + // Read data return + always_comb begin + reg_rdata_next = '0; + unique case (1'b1) + addr_hit[0]: begin + reg_rdata_next[0] = intr_state_qs; + end + + addr_hit[1]: begin + reg_rdata_next[0] = intr_enable_qs; + end + + addr_hit[2]: begin + reg_rdata_next[0] = '0; + end + + default: begin + reg_rdata_next = '1; + end + endcase + end + + // shadow busy + logic shadow_busy; + assign shadow_busy = 1'b0; + + // register busy + assign reg_busy = shadow_busy; + + // Unused signal tieoff + + // wdata / byte enable are not always fully used + // add a blanket unused statement to handle lint waivers + logic unused_wdata; + logic unused_be; + assign unused_wdata = ^reg_wdata; + assign unused_be = ^reg_be; + + // Assertions for Register Interface + `ASSERT_PULSE(wePulse, reg_we, clk_i, !rst_ni) + `ASSERT_PULSE(rePulse, reg_re, clk_i, !rst_ni) + + `ASSERT(reAfterRv, $rose(reg_re || reg_we) |=> tl_o_pre.d_valid, clk_i, !rst_ni) + + `ASSERT(en2addrHit, (reg_we || reg_re) |-> $onehot0(addr_hit), clk_i, !rst_ni) + + // this is formulated as an assumption such that the FPV testbenches do disprove this + // property by mistake + //`ASSUME(reqParity, tl_reg_h2d.a_valid |-> tl_reg_h2d.a_user.chk_en == tlul_pkg::CheckDis) + +endmodule diff --git a/hw/ip/mbx/rtl/mbx_reg_pkg.sv b/hw/ip/mbx/rtl/mbx_reg_pkg.sv new file mode 100644 index 0000000000000..c6146f897cfa9 --- /dev/null +++ b/hw/ip/mbx/rtl/mbx_reg_pkg.sv @@ -0,0 +1,70 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Register Package auto-generated by `reggen` containing data structure + +package mbx_reg_pkg; + + // Address widths within the block + parameter int HostAw = 4; + parameter int SysAw = 1; + + /////////////////////////////////////////////// + // Typedefs for registers for host interface // + /////////////////////////////////////////////// + + typedef struct packed { + logic q; + } mbx_reg2hw_intr_state_reg_t; + + typedef struct packed { + logic q; + } mbx_reg2hw_intr_enable_reg_t; + + typedef struct packed { + logic q; + logic qe; + } mbx_reg2hw_intr_test_reg_t; + + typedef struct packed { + logic d; + logic de; + } mbx_hw2reg_intr_state_reg_t; + + // Register -> HW type for host interface + typedef struct packed { + mbx_reg2hw_intr_state_reg_t intr_state; // [3:3] + mbx_reg2hw_intr_enable_reg_t intr_enable; // [2:2] + mbx_reg2hw_intr_test_reg_t intr_test; // [1:0] + } mbx_host_reg2hw_t; + + // HW -> register type for host interface + typedef struct packed { + mbx_hw2reg_intr_state_reg_t intr_state; // [1:0] + } mbx_host_hw2reg_t; + + // Register offsets for host interface + parameter logic [HostAw-1:0] MBX_INTR_STATE_OFFSET = 4'h 0; + parameter logic [HostAw-1:0] MBX_INTR_ENABLE_OFFSET = 4'h 4; + parameter logic [HostAw-1:0] MBX_INTR_TEST_OFFSET = 4'h 8; + + // Reset values for hwext registers and their fields for host interface + parameter logic [0:0] MBX_INTR_TEST_RESVAL = 1'h 0; + parameter logic [0:0] MBX_INTR_TEST_MBX_READY_RESVAL = 1'h 0; + + // Register index for host interface + typedef enum int { + MBX_INTR_STATE, + MBX_INTR_ENABLE, + MBX_INTR_TEST + } mbx_host_id_e; + + // Register width information to check illegal writes for host interface + parameter logic [3:0] MBX_HOST_PERMIT [3] = '{ + 4'b 0001, // index[0] MBX_INTR_STATE + 4'b 0001, // index[1] MBX_INTR_ENABLE + 4'b 0001 // index[2] MBX_INTR_TEST + }; + +endpackage diff --git a/hw/ip/mbx/rtl/mbx_sys_reg_top.sv b/hw/ip/mbx/rtl/mbx_sys_reg_top.sv new file mode 100644 index 0000000000000..639658824c31d --- /dev/null +++ b/hw/ip/mbx/rtl/mbx_sys_reg_top.sv @@ -0,0 +1,42 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Register Top module auto-generated by `reggen` + +`include "prim_assert.sv" + +module mbx_sys_reg_top ( + input clk_i, + input rst_ni, + input tlul_pkg::tl_h2d_t tl_i, + output tlul_pkg::tl_d2h_t tl_o, + // To HW + + // Integrity check errors + output logic intg_err_o +); + + import mbx_reg_pkg::* ; + + + + // Since there are no registers in this block, commands are routed through to windows which + // can report their own integrity errors. + assign intg_err_o = 1'b0; + + // outgoing integrity generation + tlul_pkg::tl_d2h_t tl_o_pre; + tlul_rsp_intg_gen #( + .EnableRspIntgGen(1), + .EnableDataIntgGen(1) + ) u_rsp_intg_gen ( + .tl_i(tl_o_pre), + .tl_o(tl_o) + ); + + assign tl_reg_h2d = tl_i; + assign tl_o_pre = tl_reg_d2h; + + // Unused signal tieoff +endmodule From f214e7b0caca7abe1948aa0ce7f0155e67268b92 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Thu, 17 Aug 2023 13:15:42 -0700 Subject: [PATCH 02/88] [hw,mbx,rtl] Implementation of the host interface Signed-off-by: Robert Schilling --- hw/ip/mbx/data/mbx.hjson | 203 +++++++++- hw/ip/mbx/mbx.core | 4 +- hw/ip/mbx/rtl/mbx.sv | 94 ++++- hw/ip/mbx/rtl/mbx_host_reg_top.sv | 600 +++++++++++++++++++++++++++++- hw/ip/mbx/rtl/mbx_hostif.sv | 149 ++++++++ hw/ip/mbx/rtl/mbx_reg_pkg.sv | 199 +++++++++- 6 files changed, 1210 insertions(+), 39 deletions(-) create mode 100644 hw/ip/mbx/rtl/mbx_hostif.sv diff --git a/hw/ip/mbx/data/mbx.hjson b/hw/ip/mbx/data/mbx.hjson index 2d728f98e53ed..5cdc8f21c2b68 100644 --- a/hw/ip/mbx/data/mbx.hjson +++ b/hw/ip/mbx/data/mbx.hjson @@ -12,15 +12,12 @@ This means that pre-defined control information must be passed to OpenTitan from the security service requester. A secure inbound/outbound mailbox can be used to implement a secure channel for these request/response transactions between the Host and the RoT. ''' - cip_id: "37", + cip_id: "37" design_spec: "../doc" dv_doc: "../doc/dv" version: "0.1.0" clocking: [{clock: "clk_i", reset: "rst_ni", primary: true}] - scan: "true" // Enable `scanmode_i` port - scan_reset: "true" // Enable `scan_rst_ni` port - scan_en: "true" // Enable `scan_en_i` port bus_interfaces: [ { protocol: "tlul", direction: "device", name: "host" } { protocol: "tlul", direction: "host", name: "sram" } @@ -31,9 +28,207 @@ desc: "A new object was received in the inbound mailbox." } ] + alert_list: [ + { name: "fatal_fault" + desc: "This fatal alert is triggered when a fatal TL-UL bus integrity fault is detected." + } + ] + countermeasures: [ + { name: "BUS.INTEGRITY" + desc: "End-to-end bus integrity scheme." + } + ] regwidth: "32" registers: { host: [ + { name: "CONTROL" + desc: "DOE mailbox control register visible to the mailbox host" + fields: [ + { name: "abort" + desc: "Alias of the DoE mailbox abort bit" + bits: "0" + resval: "0x0" + swaccess: "rw" + hwaccess: "hrw" + hwqe: "true" + } + ] + hwext: "true" + } + { name: "STATUS" + desc: "DOE mailbox status register visible to the mailbox host" + fields: [ + { name: "busy" + desc: "Alias of the DoE mailbox busy bit" + bits: "0" + resval: "0x1" + swaccess: "rw" + hwaccess: "hrw" + hwqe: "true" + } + { name: "error" + desc: "Alias of the DoE mailbox error bit" + bits: "2" + resval: "0x0" + swaccess: "rw" + hwaccess: "hrw" + hwqe: "true" + } + { name: "async_msg_status" + desc: ''' + When Set, this bit indicates the DOE instance has one or more asynchronous messages to transfer + The transition of this bit from Clear to Set is an interrupt triggering event + ''' + bits: "3" + resval: "0x0" + swaccess: "rw" + hwaccess: "hrw" + hwqe: "true" + } + { + name: "ready" + desc: "Alias of the DoE mailbox ready bit" + bits: "31" + resval: "0x0" + swaccess: "rw" + hwaccess: "hrw" + hwqe: "true" + } + ] + hwext: "true" + } + { name: "ADDRESS_RANGE_REGWEN" + desc: "Used to lock the inound/outbound base/limit configuration registers." + swaccess: "rw0c" + fields: [ + { name: "regwen" + desc: "Once cleared the mailbox inbound/outbound base/limit registers will be locked until the next reset." + bits: "0" + resval: "1" + } + ] + } + { name: "ADDRESS_RANGE_VALID" + desc: "Used to lock the inound/outbound base/limit configuration registers." + swaccess: "rw" + hwaccess: "hro" + fields: [ + { name: "range_valid" + desc: "Once set the mailbox inbound/outbound base/limit registers are valid." + bits: "0" + resval: "0" + } + ] + } + { name: "INBOUND_BASE_ADDRESS" + desc: '''Base address of SRAM region, which is used to back up the inbound mailbox data. + This address is 4-byte aligned, the lower 2-bits are ignored. + ''' + regwen: "ADDRESS_RANGE_REGWEN" + fields: [ + { name: "base_address" + desc: "Base address of SRAM region, which is used to back up the inbound mailbox data." + bits: "31:2" + resval: "0x0" + swaccess: "rw" + hwqe: "true" + } + ] + } + { + name: "INBOUND_LIMIT_ADDRESS" + desc: '''Limit Address to mark the end of the inbound mailbox memory range in the private SRAM.. + This address is 4-byte aligned, the lower 2-bits are ignored. + ''' + regwen: "ADDRESS_RANGE_REGWEN" + fields: [ + { name: "limit" + desc: "Limit Address to mark the end of the inbound mailbox memory range in the private SRAM." + bits: "31:2" + resval: "0x0" + swaccess: "rw" + hwqe: "true" + } + ] + } + { name: "INBOUND_WRITE_PTR" + desc: '''Write pointer for the next inbound data write. + This pointer is 4-byte aligned, the lower 2-bits are always zero. + ''' + fields: [ + { name: "inbound_read_ptr" + desc: "Write pointer for the next inbound data write." + bits: "31:2" + resval: "0x0" + swaccess: "ro" + hwaccess: "hrw" + hwqe: "true" + } + ] + hwext: "true" + } + { name: "OUTBOUND_BASE_ADDRESS" + desc: '''Base address of SRAM region, which is used to buffer the outbound mailbox data. + This address is 4-byte aligned, the lower 2-bits are ignored. + ''' + regwen: "ADDRESS_RANGE_REGWEN" + fields: [ + { name: "base_address" + desc: "Base address of SRAM region, which is used to buffer the outbound mailbox data." + bits: "31:2" + resval: "0x0" + swaccess: "rw" + hwqe: "true" + } + ] + } + { name: "OUTBOUND_LIMIT_ADDRESS" + desc: '''Limit Address to mark the end of the outbound mailbox memory range in the private SRAM. + This address is 4-byte aligned, the lower 2-bits are ignored. + ''' + regwen: "ADDRESS_RANGE_REGWEN" + fields: [ + { name: "limit" + desc: "Limit Address to mark the end of the outbound mailbox memory range in the private SRAM." + bits: "31:2" + resval: "0x0" + swaccess: "rw" + hwqe: "true" + } + ] + } + { name: "OUTBOUND_READ_PTR" + desc: '''Read pointer for the next outbound data read. + This pointer is 4-byte aligned, the lower 2-bits are always zero. + ''' + fields: [ + { name: "outbound_write_ptr" + desc: "Read pointer for the next outbound data read." + bits: "31:2" + resval: "0x0" + swaccess: "ro" + hwaccess: "hrw" + hwqe: "true" + } + ] + hwext: "true" + } + { name: "OUTBOUND_OBJECT_SIZE" + desc: '''Indicates the size of the data object to be transferred out. + Note that this size specifies the number of 4-byte words (DWORD). + Maximum size supported by any OT DOE instance is 1K DWORDS. + ''' + fields: [ + { name: "cnt" + desc: "Indicates the size of the data object to be transferred out in 4-byte words." + bits: "10:0" + resval: "0x0" + swaccess: "rw" + hwaccess: "hrw" + hwqe: "true" + } + ] + } ] sys: [ ] diff --git a/hw/ip/mbx/mbx.core b/hw/ip/mbx/mbx.core index 6aa259cd4def5..0c710c7a902a2 100644 --- a/hw/ip/mbx/mbx.core +++ b/hw/ip/mbx/mbx.core @@ -11,10 +11,10 @@ filesets: - lowrisc:tlul:headers - lowrisc:ip:tlul files: - - rtl/mbx.sv - rtl/mbx_reg_pkg.sv + - rtl/mbx.sv - rtl/mbx_host_reg_top.sv - - rtl/mbx_sys_reg_top.sv + - rtl/mbx_hostif.sv file_type: systemVerilogSource files_verilator_waiver: diff --git a/hw/ip/mbx/rtl/mbx.sv b/hw/ip/mbx/rtl/mbx.sv index 1c2cfe2a09997..d2c1b6ce77d34 100644 --- a/hw/ip/mbx/rtl/mbx.sv +++ b/hw/ip/mbx/rtl/mbx.sv @@ -6,19 +6,93 @@ module mbx import tlul_pkg::*; -( - input logic clk_i, - input logic rst_ni, - output logic irq_o, + import mbx_reg_pkg::*; +#( + parameter logic [NumAlerts-1:0] AlertAsyncOn = {NumAlerts{1'b1}}, + parameter int unsigned CfgSramAddrWidth = 32, + parameter int unsigned CfgSramDataWidth = 32 +) ( + input logic clk_i, + input logic rst_ni, + output logic intr_mbx_ready_o, + // Alerts + input prim_alert_pkg::alert_rx_t [NumAlerts-1:0] alert_rx_i, + output prim_alert_pkg::alert_tx_t [NumAlerts-1:0] alert_tx_o, // Device port facing OT-host - input tlul_pkg::tl_h2d_t tl_host_i, - output tlul_pkg::tl_d2h_t tl_host_o, + input tlul_pkg::tl_h2d_t tl_host_i, + output tlul_pkg::tl_d2h_t tl_host_o, // Device port facing CTN Xbar - input tlul_pkg::tl_h2d_t tl_sys_i, - output tlul_pkg::tl_d2h_t tl_sys_o, + input tlul_pkg::tl_h2d_t tl_sys_i, + output tlul_pkg::tl_d2h_t tl_sys_o, // Host port to access private SRAM - input tlul_pkg::tl_d2h_t tl_sram_i, - output tlul_pkg::tl_h2d_t tl_sram_o + input tlul_pkg::tl_d2h_t tl_sram_i, + output tlul_pkg::tl_h2d_t tl_sram_o ); + logic [CfgSramAddrWidth-1:0] ib_write_ptr; + logic [CfgSramAddrWidth-1:0] ob_read_ptr; + + // External write signals for control and status register + logic hostif_set_control_abort; + logic hostif_clear_status_busy; + logic hostif_set_status_error, hostif_clear_status_error; + logic hostif_set_status_async_msg_status; + // External read signals for control and status register + logic hostif_status_busy, hostif_status_error; + logic hostif_status_async_msg_status, hostif_status_ready; + + logic [CfgSramAddrWidth-1:0] ibmbx_hostif_sram_write_ptr; + logic [CfgSramDataWidth-1:0] ibmbx_write_data; + logic [CfgSramAddrWidth-1:0] obmbx_hostif_sram_read_ptr; + logic [CfgSramDataWidth-1:0] obmbx_hostif_sram_read_resp; + + logic hostif_address_range_valid; + logic [CfgSramAddrWidth-1:0] hostif_ib_base, hostif_ib_limit; + logic [CfgSramAddrWidth-1:0] hostif_ob_base, hostif_ob_limit; + + logic hostif_write_ob_object_size, hostif_read_ob_object_size; + logic [11:0] hostif_ob_object_size_wdata, hostif_ob_object_size_rdata; + + logic sysif_write_control_abort; + + mbx_hostif #( + .AlertAsyncOn ( AlertAsyncOn ), + .CfgSramAddrWidth( CfgSramAddrWidth ) + ) u_hostif ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + // Device port to the host side + .tl_host_i ( tl_host_i ), + .tl_host_o ( tl_host_o ), + .alert_rx_i ( alert_rx_i ), + .alert_tx_o ( alert_tx_o ), + // Access to the control register + .hostif_set_control_abort_o ( hostif_set_control_abort ), + // Access to the status register + .hostif_clear_status_busy_o ( hostif_clear_status_busy ), + .hostif_set_status_error_o ( hostif_set_status_error ), + .hostif_clear_status_error_o ( hostif_clear_status_error ), + .hostif_set_status_async_msg_status_o( hostif_set_status_async_msg_status ), + .hostif_status_busy_i ( hostif_status_busy ), + .hostif_status_error_i ( hostif_status_error ), + .hostif_status_async_msg_status_i ( hostif_status_async_msg_status ), + .hostif_status_ready_i ( hostif_status_ready ), + // Access to the IB/OB RD/WR Pointers + .hostif_ib_write_ptr_i ( ibmbx_hostif_sram_write_ptr ), + .hostif_ob_read_ptr_i ( obmbx_hostif_sram_read_ptr ), + // Access to the memory region registers + .hostif_address_range_valid_o ( hostif_address_range_valid ), + .hostif_ib_base_o ( hostif_ib_base ), + .hostif_ib_limit_o ( hostif_ib_limit ), + .hostif_ob_base_o ( hostif_ob_base ), + .hostif_ob_limit_o ( hostif_ob_limit ), + // Read/Write access for the OB DW Count register + .hostif_write_ob_object_size_o ( hostif_write_ob_object_size ), + .hostif_ob_object_size_o ( hostif_ob_object_size_wdata ), + .hostif_ob_object_size_i ( hostif_ob_object_size_rdata ), + .hostif_read_ob_object_size_i ( hostif_read_ob_object_size ), + // Control inputs coming from the system registers interface + .sysif_write_control_abort_i ( sysif_write_control_abort ) + ); + endmodule diff --git a/hw/ip/mbx/rtl/mbx_host_reg_top.sv b/hw/ip/mbx/rtl/mbx_host_reg_top.sv index 95177d4badee6..d47b7326d0816 100644 --- a/hw/ip/mbx/rtl/mbx_host_reg_top.sv +++ b/hw/ip/mbx/rtl/mbx_host_reg_top.sv @@ -21,7 +21,7 @@ module mbx_host_reg_top ( import mbx_reg_pkg::* ; - localparam int AW = 4; + localparam int AW = 6; localparam int DW = 32; localparam int DBW = DW/8; // Byte Width @@ -52,9 +52,9 @@ module mbx_host_reg_top ( // also check for spurious write enables logic reg_we_err; - logic [2:0] reg_we_check; + logic [14:0] reg_we_check; prim_reg_we_check #( - .OneHotWidth(3) + .OneHotWidth(15) ) u_prim_reg_we_check ( .clk_i(clk_i), .rst_ni(rst_ni), @@ -129,6 +129,47 @@ module mbx_host_reg_top ( logic intr_enable_wd; logic intr_test_we; logic intr_test_wd; + logic alert_test_we; + logic alert_test_wd; + logic control_re; + logic control_we; + logic control_qs; + logic control_wd; + logic status_re; + logic status_we; + logic status_busy_qs; + logic status_busy_wd; + logic status_error_qs; + logic status_error_wd; + logic status_async_msg_status_qs; + logic status_async_msg_status_wd; + logic status_ready_qs; + logic status_ready_wd; + logic address_range_regwen_we; + logic address_range_regwen_qs; + logic address_range_regwen_wd; + logic address_range_valid_we; + logic address_range_valid_qs; + logic address_range_valid_wd; + logic inbound_base_address_we; + logic [29:0] inbound_base_address_qs; + logic [29:0] inbound_base_address_wd; + logic inbound_limit_address_we; + logic [29:0] inbound_limit_address_qs; + logic [29:0] inbound_limit_address_wd; + logic inbound_write_ptr_re; + logic [29:0] inbound_write_ptr_qs; + logic outbound_base_address_we; + logic [29:0] outbound_base_address_qs; + logic [29:0] outbound_base_address_wd; + logic outbound_limit_address_we; + logic [29:0] outbound_limit_address_qs; + logic [29:0] outbound_limit_address_wd; + logic outbound_read_ptr_re; + logic [29:0] outbound_read_ptr_qs; + logic outbound_object_size_we; + logic [10:0] outbound_object_size_qs; + logic [10:0] outbound_object_size_wd; // Register instances // R[intr_state]: V(False) @@ -207,13 +248,437 @@ module mbx_host_reg_top ( assign reg2hw.intr_test.qe = intr_test_qe; + // R[alert_test]: V(True) + logic alert_test_qe; + logic [0:0] alert_test_flds_we; + assign alert_test_qe = &alert_test_flds_we; + prim_subreg_ext #( + .DW (1) + ) u_alert_test ( + .re (1'b0), + .we (alert_test_we), + .wd (alert_test_wd), + .d ('0), + .qre (), + .qe (alert_test_flds_we[0]), + .q (reg2hw.alert_test.q), + .ds (), + .qs () + ); + assign reg2hw.alert_test.qe = alert_test_qe; + + + // R[control]: V(True) + logic control_qe; + logic [0:0] control_flds_we; + assign control_qe = &control_flds_we; + prim_subreg_ext #( + .DW (1) + ) u_control ( + .re (control_re), + .we (control_we), + .wd (control_wd), + .d (hw2reg.control.d), + .qre (), + .qe (control_flds_we[0]), + .q (reg2hw.control.q), + .ds (), + .qs (control_qs) + ); + assign reg2hw.control.qe = control_qe; + + + // R[status]: V(True) + logic status_qe; + logic [3:0] status_flds_we; + assign status_qe = &status_flds_we; + // F[busy]: 0:0 + prim_subreg_ext #( + .DW (1) + ) u_status_busy ( + .re (status_re), + .we (status_we), + .wd (status_busy_wd), + .d (hw2reg.status.busy.d), + .qre (), + .qe (status_flds_we[0]), + .q (reg2hw.status.busy.q), + .ds (), + .qs (status_busy_qs) + ); + assign reg2hw.status.busy.qe = status_qe; + + // F[error]: 2:2 + prim_subreg_ext #( + .DW (1) + ) u_status_error ( + .re (status_re), + .we (status_we), + .wd (status_error_wd), + .d (hw2reg.status.error.d), + .qre (), + .qe (status_flds_we[1]), + .q (reg2hw.status.error.q), + .ds (), + .qs (status_error_qs) + ); + assign reg2hw.status.error.qe = status_qe; + + // F[async_msg_status]: 3:3 + prim_subreg_ext #( + .DW (1) + ) u_status_async_msg_status ( + .re (status_re), + .we (status_we), + .wd (status_async_msg_status_wd), + .d (hw2reg.status.async_msg_status.d), + .qre (), + .qe (status_flds_we[2]), + .q (reg2hw.status.async_msg_status.q), + .ds (), + .qs (status_async_msg_status_qs) + ); + assign reg2hw.status.async_msg_status.qe = status_qe; + + // F[ready]: 31:31 + prim_subreg_ext #( + .DW (1) + ) u_status_ready ( + .re (status_re), + .we (status_we), + .wd (status_ready_wd), + .d (hw2reg.status.ready.d), + .qre (), + .qe (status_flds_we[3]), + .q (reg2hw.status.ready.q), + .ds (), + .qs (status_ready_qs) + ); + assign reg2hw.status.ready.qe = status_qe; + + + // R[address_range_regwen]: V(False) + prim_subreg #( + .DW (1), + .SwAccess(prim_subreg_pkg::SwAccessW0C), + .RESVAL (1'h1) + ) u_address_range_regwen ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (address_range_regwen_we), + .wd (address_range_regwen_wd), + + // from internal hardware + .de (1'b0), + .d ('0), + + // to internal hardware + .qe (), + .q (reg2hw.address_range_regwen.q), + .ds (), + + // to register interface (read) + .qs (address_range_regwen_qs) + ); + + + // R[address_range_valid]: V(False) + prim_subreg #( + .DW (1), + .SwAccess(prim_subreg_pkg::SwAccessRW), + .RESVAL (1'h0) + ) u_address_range_valid ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (address_range_valid_we), + .wd (address_range_valid_wd), + + // from internal hardware + .de (1'b0), + .d ('0), + + // to internal hardware + .qe (), + .q (reg2hw.address_range_valid.q), + .ds (), + + // to register interface (read) + .qs (address_range_valid_qs) + ); + + + // R[inbound_base_address]: V(False) + logic inbound_base_address_qe; + logic [0:0] inbound_base_address_flds_we; + prim_flop #( + .Width(1), + .ResetValue(0) + ) u_inbound_base_address0_qe ( + .clk_i(clk_i), + .rst_ni(rst_ni), + .d_i(&inbound_base_address_flds_we), + .q_o(inbound_base_address_qe) + ); + // Create REGWEN-gated WE signal + logic inbound_base_address_gated_we; + assign inbound_base_address_gated_we = inbound_base_address_we & address_range_regwen_qs; + prim_subreg #( + .DW (30), + .SwAccess(prim_subreg_pkg::SwAccessRW), + .RESVAL (30'h0) + ) u_inbound_base_address ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (inbound_base_address_gated_we), + .wd (inbound_base_address_wd), + + // from internal hardware + .de (1'b0), + .d ('0), + + // to internal hardware + .qe (inbound_base_address_flds_we[0]), + .q (reg2hw.inbound_base_address.q), + .ds (), + + // to register interface (read) + .qs (inbound_base_address_qs) + ); + assign reg2hw.inbound_base_address.qe = inbound_base_address_qe; + + + // R[inbound_limit_address]: V(False) + logic inbound_limit_address_qe; + logic [0:0] inbound_limit_address_flds_we; + prim_flop #( + .Width(1), + .ResetValue(0) + ) u_inbound_limit_address0_qe ( + .clk_i(clk_i), + .rst_ni(rst_ni), + .d_i(&inbound_limit_address_flds_we), + .q_o(inbound_limit_address_qe) + ); + // Create REGWEN-gated WE signal + logic inbound_limit_address_gated_we; + assign inbound_limit_address_gated_we = inbound_limit_address_we & address_range_regwen_qs; + prim_subreg #( + .DW (30), + .SwAccess(prim_subreg_pkg::SwAccessRW), + .RESVAL (30'h0) + ) u_inbound_limit_address ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (inbound_limit_address_gated_we), + .wd (inbound_limit_address_wd), + + // from internal hardware + .de (1'b0), + .d ('0), + + // to internal hardware + .qe (inbound_limit_address_flds_we[0]), + .q (reg2hw.inbound_limit_address.q), + .ds (), + + // to register interface (read) + .qs (inbound_limit_address_qs) + ); + assign reg2hw.inbound_limit_address.qe = inbound_limit_address_qe; + + + // R[inbound_write_ptr]: V(True) + logic inbound_write_ptr_qe; + logic [0:0] inbound_write_ptr_flds_we; + // In case all fields are read-only the aggregated register QE will be zero as well. + assign inbound_write_ptr_qe = &inbound_write_ptr_flds_we; + prim_subreg_ext #( + .DW (30) + ) u_inbound_write_ptr ( + .re (inbound_write_ptr_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.inbound_write_ptr.d), + .qre (), + .qe (inbound_write_ptr_flds_we[0]), + .q (reg2hw.inbound_write_ptr.q), + .ds (), + .qs (inbound_write_ptr_qs) + ); + assign reg2hw.inbound_write_ptr.qe = inbound_write_ptr_qe; + + + // R[outbound_base_address]: V(False) + logic outbound_base_address_qe; + logic [0:0] outbound_base_address_flds_we; + prim_flop #( + .Width(1), + .ResetValue(0) + ) u_outbound_base_address0_qe ( + .clk_i(clk_i), + .rst_ni(rst_ni), + .d_i(&outbound_base_address_flds_we), + .q_o(outbound_base_address_qe) + ); + // Create REGWEN-gated WE signal + logic outbound_base_address_gated_we; + assign outbound_base_address_gated_we = outbound_base_address_we & address_range_regwen_qs; + prim_subreg #( + .DW (30), + .SwAccess(prim_subreg_pkg::SwAccessRW), + .RESVAL (30'h0) + ) u_outbound_base_address ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (outbound_base_address_gated_we), + .wd (outbound_base_address_wd), + + // from internal hardware + .de (1'b0), + .d ('0), + + // to internal hardware + .qe (outbound_base_address_flds_we[0]), + .q (reg2hw.outbound_base_address.q), + .ds (), + + // to register interface (read) + .qs (outbound_base_address_qs) + ); + assign reg2hw.outbound_base_address.qe = outbound_base_address_qe; + + + // R[outbound_limit_address]: V(False) + logic outbound_limit_address_qe; + logic [0:0] outbound_limit_address_flds_we; + prim_flop #( + .Width(1), + .ResetValue(0) + ) u_outbound_limit_address0_qe ( + .clk_i(clk_i), + .rst_ni(rst_ni), + .d_i(&outbound_limit_address_flds_we), + .q_o(outbound_limit_address_qe) + ); + // Create REGWEN-gated WE signal + logic outbound_limit_address_gated_we; + assign outbound_limit_address_gated_we = outbound_limit_address_we & address_range_regwen_qs; + prim_subreg #( + .DW (30), + .SwAccess(prim_subreg_pkg::SwAccessRW), + .RESVAL (30'h0) + ) u_outbound_limit_address ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (outbound_limit_address_gated_we), + .wd (outbound_limit_address_wd), + + // from internal hardware + .de (1'b0), + .d ('0), + + // to internal hardware + .qe (outbound_limit_address_flds_we[0]), + .q (reg2hw.outbound_limit_address.q), + .ds (), + + // to register interface (read) + .qs (outbound_limit_address_qs) + ); + assign reg2hw.outbound_limit_address.qe = outbound_limit_address_qe; + + + // R[outbound_read_ptr]: V(True) + logic outbound_read_ptr_qe; + logic [0:0] outbound_read_ptr_flds_we; + // In case all fields are read-only the aggregated register QE will be zero as well. + assign outbound_read_ptr_qe = &outbound_read_ptr_flds_we; + prim_subreg_ext #( + .DW (30) + ) u_outbound_read_ptr ( + .re (outbound_read_ptr_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.outbound_read_ptr.d), + .qre (), + .qe (outbound_read_ptr_flds_we[0]), + .q (reg2hw.outbound_read_ptr.q), + .ds (), + .qs (outbound_read_ptr_qs) + ); + assign reg2hw.outbound_read_ptr.qe = outbound_read_ptr_qe; + - logic [2:0] addr_hit; + // R[outbound_object_size]: V(False) + logic outbound_object_size_qe; + logic [0:0] outbound_object_size_flds_we; + prim_flop #( + .Width(1), + .ResetValue(0) + ) u_outbound_object_size0_qe ( + .clk_i(clk_i), + .rst_ni(rst_ni), + .d_i(&outbound_object_size_flds_we), + .q_o(outbound_object_size_qe) + ); + prim_subreg #( + .DW (11), + .SwAccess(prim_subreg_pkg::SwAccessRW), + .RESVAL (11'h0) + ) u_outbound_object_size ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (outbound_object_size_we), + .wd (outbound_object_size_wd), + + // from internal hardware + .de (hw2reg.outbound_object_size.de), + .d (hw2reg.outbound_object_size.d), + + // to internal hardware + .qe (outbound_object_size_flds_we[0]), + .q (reg2hw.outbound_object_size.q), + .ds (), + + // to register interface (read) + .qs (outbound_object_size_qs) + ); + assign reg2hw.outbound_object_size.qe = outbound_object_size_qe; + + + + logic [14:0] addr_hit; always_comb begin addr_hit = '0; - addr_hit[0] = (reg_addr == MBX_INTR_STATE_OFFSET); - addr_hit[1] = (reg_addr == MBX_INTR_ENABLE_OFFSET); - addr_hit[2] = (reg_addr == MBX_INTR_TEST_OFFSET); + addr_hit[ 0] = (reg_addr == MBX_INTR_STATE_OFFSET); + addr_hit[ 1] = (reg_addr == MBX_INTR_ENABLE_OFFSET); + addr_hit[ 2] = (reg_addr == MBX_INTR_TEST_OFFSET); + addr_hit[ 3] = (reg_addr == MBX_ALERT_TEST_OFFSET); + addr_hit[ 4] = (reg_addr == MBX_CONTROL_OFFSET); + addr_hit[ 5] = (reg_addr == MBX_STATUS_OFFSET); + addr_hit[ 6] = (reg_addr == MBX_ADDRESS_RANGE_REGWEN_OFFSET); + addr_hit[ 7] = (reg_addr == MBX_ADDRESS_RANGE_VALID_OFFSET); + addr_hit[ 8] = (reg_addr == MBX_INBOUND_BASE_ADDRESS_OFFSET); + addr_hit[ 9] = (reg_addr == MBX_INBOUND_LIMIT_ADDRESS_OFFSET); + addr_hit[10] = (reg_addr == MBX_INBOUND_WRITE_PTR_OFFSET); + addr_hit[11] = (reg_addr == MBX_OUTBOUND_BASE_ADDRESS_OFFSET); + addr_hit[12] = (reg_addr == MBX_OUTBOUND_LIMIT_ADDRESS_OFFSET); + addr_hit[13] = (reg_addr == MBX_OUTBOUND_READ_PTR_OFFSET); + addr_hit[14] = (reg_addr == MBX_OUTBOUND_OBJECT_SIZE_OFFSET); end assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ; @@ -221,9 +686,21 @@ module mbx_host_reg_top ( // Check sub-word write is permitted always_comb begin wr_err = (reg_we & - ((addr_hit[0] & (|(MBX_HOST_PERMIT[0] & ~reg_be))) | - (addr_hit[1] & (|(MBX_HOST_PERMIT[1] & ~reg_be))) | - (addr_hit[2] & (|(MBX_HOST_PERMIT[2] & ~reg_be))))); + ((addr_hit[ 0] & (|(MBX_HOST_PERMIT[ 0] & ~reg_be))) | + (addr_hit[ 1] & (|(MBX_HOST_PERMIT[ 1] & ~reg_be))) | + (addr_hit[ 2] & (|(MBX_HOST_PERMIT[ 2] & ~reg_be))) | + (addr_hit[ 3] & (|(MBX_HOST_PERMIT[ 3] & ~reg_be))) | + (addr_hit[ 4] & (|(MBX_HOST_PERMIT[ 4] & ~reg_be))) | + (addr_hit[ 5] & (|(MBX_HOST_PERMIT[ 5] & ~reg_be))) | + (addr_hit[ 6] & (|(MBX_HOST_PERMIT[ 6] & ~reg_be))) | + (addr_hit[ 7] & (|(MBX_HOST_PERMIT[ 7] & ~reg_be))) | + (addr_hit[ 8] & (|(MBX_HOST_PERMIT[ 8] & ~reg_be))) | + (addr_hit[ 9] & (|(MBX_HOST_PERMIT[ 9] & ~reg_be))) | + (addr_hit[10] & (|(MBX_HOST_PERMIT[10] & ~reg_be))) | + (addr_hit[11] & (|(MBX_HOST_PERMIT[11] & ~reg_be))) | + (addr_hit[12] & (|(MBX_HOST_PERMIT[12] & ~reg_be))) | + (addr_hit[13] & (|(MBX_HOST_PERMIT[13] & ~reg_be))) | + (addr_hit[14] & (|(MBX_HOST_PERMIT[14] & ~reg_be))))); end // Generate write-enables @@ -236,6 +713,46 @@ module mbx_host_reg_top ( assign intr_test_we = addr_hit[2] & reg_we & !reg_error; assign intr_test_wd = reg_wdata[0]; + assign alert_test_we = addr_hit[3] & reg_we & !reg_error; + + assign alert_test_wd = reg_wdata[0]; + assign control_re = addr_hit[4] & reg_re & !reg_error; + assign control_we = addr_hit[4] & reg_we & !reg_error; + + assign control_wd = reg_wdata[0]; + assign status_re = addr_hit[5] & reg_re & !reg_error; + assign status_we = addr_hit[5] & reg_we & !reg_error; + + assign status_busy_wd = reg_wdata[0]; + + assign status_error_wd = reg_wdata[2]; + + assign status_async_msg_status_wd = reg_wdata[3]; + + assign status_ready_wd = reg_wdata[31]; + assign address_range_regwen_we = addr_hit[6] & reg_we & !reg_error; + + assign address_range_regwen_wd = reg_wdata[0]; + assign address_range_valid_we = addr_hit[7] & reg_we & !reg_error; + + assign address_range_valid_wd = reg_wdata[0]; + assign inbound_base_address_we = addr_hit[8] & reg_we & !reg_error; + + assign inbound_base_address_wd = reg_wdata[31:2]; + assign inbound_limit_address_we = addr_hit[9] & reg_we & !reg_error; + + assign inbound_limit_address_wd = reg_wdata[31:2]; + assign inbound_write_ptr_re = addr_hit[10] & reg_re & !reg_error; + assign outbound_base_address_we = addr_hit[11] & reg_we & !reg_error; + + assign outbound_base_address_wd = reg_wdata[31:2]; + assign outbound_limit_address_we = addr_hit[12] & reg_we & !reg_error; + + assign outbound_limit_address_wd = reg_wdata[31:2]; + assign outbound_read_ptr_re = addr_hit[13] & reg_re & !reg_error; + assign outbound_object_size_we = addr_hit[14] & reg_we & !reg_error; + + assign outbound_object_size_wd = reg_wdata[10:0]; // Assign write-enables to checker logic vector. always_comb begin @@ -243,6 +760,18 @@ module mbx_host_reg_top ( reg_we_check[0] = intr_state_we; reg_we_check[1] = intr_enable_we; reg_we_check[2] = intr_test_we; + reg_we_check[3] = alert_test_we; + reg_we_check[4] = control_we; + reg_we_check[5] = status_we; + reg_we_check[6] = address_range_regwen_we; + reg_we_check[7] = address_range_valid_we; + reg_we_check[8] = inbound_base_address_gated_we; + reg_we_check[9] = inbound_limit_address_gated_we; + reg_we_check[10] = 1'b0; + reg_we_check[11] = outbound_base_address_gated_we; + reg_we_check[12] = outbound_limit_address_gated_we; + reg_we_check[13] = 1'b0; + reg_we_check[14] = outbound_object_size_we; end // Read data return @@ -261,6 +790,57 @@ module mbx_host_reg_top ( reg_rdata_next[0] = '0; end + addr_hit[3]: begin + reg_rdata_next[0] = '0; + end + + addr_hit[4]: begin + reg_rdata_next[0] = control_qs; + end + + addr_hit[5]: begin + reg_rdata_next[0] = status_busy_qs; + reg_rdata_next[2] = status_error_qs; + reg_rdata_next[3] = status_async_msg_status_qs; + reg_rdata_next[31] = status_ready_qs; + end + + addr_hit[6]: begin + reg_rdata_next[0] = address_range_regwen_qs; + end + + addr_hit[7]: begin + reg_rdata_next[0] = address_range_valid_qs; + end + + addr_hit[8]: begin + reg_rdata_next[31:2] = inbound_base_address_qs; + end + + addr_hit[9]: begin + reg_rdata_next[31:2] = inbound_limit_address_qs; + end + + addr_hit[10]: begin + reg_rdata_next[31:2] = inbound_write_ptr_qs; + end + + addr_hit[11]: begin + reg_rdata_next[31:2] = outbound_base_address_qs; + end + + addr_hit[12]: begin + reg_rdata_next[31:2] = outbound_limit_address_qs; + end + + addr_hit[13]: begin + reg_rdata_next[31:2] = outbound_read_ptr_qs; + end + + addr_hit[14]: begin + reg_rdata_next[10:0] = outbound_object_size_qs; + end + default: begin reg_rdata_next = '1; end diff --git a/hw/ip/mbx/rtl/mbx_hostif.sv b/hw/ip/mbx/rtl/mbx_hostif.sv new file mode 100644 index 0000000000000..3078e857db9c9 --- /dev/null +++ b/hw/ip/mbx/rtl/mbx_hostif.sv @@ -0,0 +1,149 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +module mbx_hostif + import mbx_reg_pkg::*; +#( + parameter logic [NumAlerts-1:0] AlertAsyncOn = {NumAlerts{1'b1}}, + parameter int unsigned CfgSramAddrWidth = 32 +) ( + input logic clk_i, + input logic rst_ni, + // Device port to the host side + input tlul_pkg::tl_h2d_t tl_host_i, + output tlul_pkg::tl_d2h_t tl_host_o, + // Alerts + input prim_alert_pkg::alert_rx_t [NumAlerts-1:0] alert_rx_i, + output prim_alert_pkg::alert_tx_t [NumAlerts-1:0] alert_tx_o, + // Access to the control register + output logic hostif_set_control_abort_o, + // Access to the status register + output logic hostif_clear_status_busy_o, + output logic hostif_set_status_error_o, + output logic hostif_clear_status_error_o, + output logic hostif_set_status_async_msg_status_o, + input logic hostif_status_busy_i, + input logic hostif_status_error_i, + input logic hostif_status_async_msg_status_i, + input logic hostif_status_ready_i, + // Access to the IB/OB RD/WR pointers + input logic [CfgSramAddrWidth-1:0] hostif_ib_write_ptr_i, + input logic [CfgSramAddrWidth-1:0] hostif_ob_read_ptr_i, + // Base/Limit for in/outbound mailbox + output logic hostif_address_range_valid_o, + output logic [CfgSramAddrWidth-1:0] hostif_ib_base_o, + output logic [CfgSramAddrWidth-1:0] hostif_ib_limit_o, + output logic [CfgSramAddrWidth-1:0] hostif_ob_base_o, + output logic [CfgSramAddrWidth-1:0] hostif_ob_limit_o, + // Read/Write access for the OB DW Count register + output logic hostif_write_ob_object_size_o, + output logic [11:0] hostif_ob_object_size_o, + input logic [11:0] hostif_ob_object_size_i, + input logic hostif_read_ob_object_size_i, + // Control inputs coming from the system registers interface + input logic sysif_write_control_abort_i +); + mbx_reg_pkg::mbx_host_reg2hw_t reg2hw; + mbx_reg_pkg::mbx_host_hw2reg_t hw2reg; + + // Alerts + logic tlul_intg_err; + logic [NumAlerts-1:0] alert_test, alerts; + assign alert_test = {reg2hw.alert_test.q & reg2hw.alert_test.qe}; + assign alerts[0] = tlul_intg_err; + + for (genvar i = 0; i < NumAlerts; i++) begin : gen_alert_tx + prim_alert_sender #( + .AsyncOn ( AlertAsyncOn[i] ), + .IsFatal ( 1'b1 ) + ) u_prim_alert_sender ( + .clk_i, + .rst_ni, + .alert_test_i ( alert_test[i] ), + .alert_req_i ( alerts[i] ), + .alert_ack_o ( ), + .alert_state_o( ), + .alert_rx_i ( alert_rx_i[i] ), + .alert_tx_o ( alert_tx_o[i] ) + ); + end + + // SEC_CM: BUS.INTEGRITY + mbx_host_reg_top u_regs( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .tl_i ( tl_host_i ), + .tl_o ( tl_host_o ), + .reg2hw ( reg2hw ), + .hw2reg ( hw2reg ), + .intg_err_o ( tlul_intg_err ), + .devmode_i ( 1'b1 ) + ); + + // Control Register + // External read logic + logic abort_d, abort_q; + assign hw2reg.control.d = abort_q; + // External write logic + assign hostif_set_control_abort_o = reg2hw.control.qe & tl_host_i.a_data[0]; + + // Abort computation from system and host interface + always_comb begin + abort_d = abort_q; + + if (sysif_write_control_abort_i) begin + abort_d = 1'b1; + end else if (hostif_set_control_abort_o) begin + abort_d = 1'b0; + end + end + + prim_flop #( + .Width(1) + ) u_abort ( + .clk_i ( clk_i ), + .rst_ni( rst_ni ), + .d_i ( abort_d ), + .q_o ( abort_q ) + ); + + // Status Register + // It is implemented as hwext and implemented in a different hierarchy and only providing an + // alias. Thus manually assigning the external signals + + // External read logic + assign hw2reg.status.busy.d = hostif_status_busy_i; + assign hw2reg.status.error.d = hostif_status_error_i; + assign hw2reg.status.async_msg_status.d = hostif_status_async_msg_status_i; + assign hw2reg.status.ready.d = hostif_status_ready_i; + // External write logic + assign hostif_clear_status_busy_o = reg2hw.status.busy.qe & ~reg2hw.status.busy.q; + assign hostif_set_status_error_o = reg2hw.status.error.qe & reg2hw.status.error.q; + assign hostif_clear_status_error_o = reg2hw.status.error.qe & ~reg2hw.status.error.q; + assign hostif_set_status_async_msg_status_o = + reg2hw.status.async_msg_status.qe & reg2hw.status.async_msg_status.q; + + // Address config valid + assign hostif_address_range_valid_o = reg2hw.address_range_valid.q; + + // Inbound Mailbox Base/Limit Register + assign hostif_ib_base_o = { reg2hw.inbound_base_address.q, {2{1'b0}} }; + assign hostif_ib_limit_o = { reg2hw.inbound_limit_address.q, {2{1'b0}} }; + + // Outbound Mailbox Base/Limit Register + assign hostif_ob_base_o = { reg2hw.outbound_base_address.q, {2{1'b0}} }; + assign hostif_ob_limit_o = { reg2hw.outbound_limit_address.q, {2{1'b0}} }; + + // Read/Write pointers + assign hw2reg.inbound_write_ptr.d = hostif_ib_write_ptr_i[CfgSramAddrWidth-1:2]; + assign hw2reg.outbound_read_ptr.d = hostif_ob_read_ptr_i[CfgSramAddrWidth-1:2]; + + // Outbound object size Register + // External read logic + assign hw2reg.outbound_object_size.d = hostif_ob_object_size_i; + assign hw2reg.outbound_object_size.de = hostif_read_ob_object_size_i; + // External write logic + assign hostif_write_ob_object_size_o = reg2hw.outbound_object_size.qe; + assign hostif_ob_object_size_o = reg2hw.outbound_object_size.q; +endmodule diff --git a/hw/ip/mbx/rtl/mbx_reg_pkg.sv b/hw/ip/mbx/rtl/mbx_reg_pkg.sv index c6146f897cfa9..9b980c1181ead 100644 --- a/hw/ip/mbx/rtl/mbx_reg_pkg.sv +++ b/hw/ip/mbx/rtl/mbx_reg_pkg.sv @@ -6,8 +6,11 @@ package mbx_reg_pkg; + // Param list + parameter int NumAlerts = 1; + // Address widths within the block - parameter int HostAw = 4; + parameter int HostAw = 6; parameter int SysAw = 1; /////////////////////////////////////////////// @@ -27,44 +30,214 @@ package mbx_reg_pkg; logic qe; } mbx_reg2hw_intr_test_reg_t; + typedef struct packed { + logic q; + logic qe; + } mbx_reg2hw_alert_test_reg_t; + + typedef struct packed { + logic q; + logic qe; + } mbx_reg2hw_control_reg_t; + + typedef struct packed { + struct packed { + logic q; + logic qe; + } busy; + struct packed { + logic q; + logic qe; + } error; + struct packed { + logic q; + logic qe; + } async_msg_status; + struct packed { + logic q; + logic qe; + } ready; + } mbx_reg2hw_status_reg_t; + + typedef struct packed { + logic q; + } mbx_reg2hw_address_range_regwen_reg_t; + + typedef struct packed { + logic q; + } mbx_reg2hw_address_range_valid_reg_t; + + typedef struct packed { + logic [29:0] q; + logic qe; + } mbx_reg2hw_inbound_base_address_reg_t; + + typedef struct packed { + logic [29:0] q; + logic qe; + } mbx_reg2hw_inbound_limit_address_reg_t; + + typedef struct packed { + logic [29:0] q; + logic qe; + } mbx_reg2hw_inbound_write_ptr_reg_t; + + typedef struct packed { + logic [29:0] q; + logic qe; + } mbx_reg2hw_outbound_base_address_reg_t; + + typedef struct packed { + logic [29:0] q; + logic qe; + } mbx_reg2hw_outbound_limit_address_reg_t; + + typedef struct packed { + logic [29:0] q; + logic qe; + } mbx_reg2hw_outbound_read_ptr_reg_t; + + typedef struct packed { + logic [10:0] q; + logic qe; + } mbx_reg2hw_outbound_object_size_reg_t; + typedef struct packed { logic d; logic de; } mbx_hw2reg_intr_state_reg_t; + typedef struct packed { + logic d; + } mbx_hw2reg_control_reg_t; + + typedef struct packed { + struct packed { + logic d; + } busy; + struct packed { + logic d; + } error; + struct packed { + logic d; + } async_msg_status; + struct packed { + logic d; + } ready; + } mbx_hw2reg_status_reg_t; + + typedef struct packed { + logic [29:0] d; + } mbx_hw2reg_inbound_write_ptr_reg_t; + + typedef struct packed { + logic [29:0] d; + } mbx_hw2reg_outbound_read_ptr_reg_t; + + typedef struct packed { + logic [10:0] d; + logic de; + } mbx_hw2reg_outbound_object_size_reg_t; + // Register -> HW type for host interface typedef struct packed { - mbx_reg2hw_intr_state_reg_t intr_state; // [3:3] - mbx_reg2hw_intr_enable_reg_t intr_enable; // [2:2] - mbx_reg2hw_intr_test_reg_t intr_test; // [1:0] + mbx_reg2hw_intr_state_reg_t intr_state; // [215:215] + mbx_reg2hw_intr_enable_reg_t intr_enable; // [214:214] + mbx_reg2hw_intr_test_reg_t intr_test; // [213:212] + mbx_reg2hw_alert_test_reg_t alert_test; // [211:210] + mbx_reg2hw_control_reg_t control; // [209:208] + mbx_reg2hw_status_reg_t status; // [207:200] + mbx_reg2hw_address_range_regwen_reg_t address_range_regwen; // [199:199] + mbx_reg2hw_address_range_valid_reg_t address_range_valid; // [198:198] + mbx_reg2hw_inbound_base_address_reg_t inbound_base_address; // [197:167] + mbx_reg2hw_inbound_limit_address_reg_t inbound_limit_address; // [166:136] + mbx_reg2hw_inbound_write_ptr_reg_t inbound_write_ptr; // [135:105] + mbx_reg2hw_outbound_base_address_reg_t outbound_base_address; // [104:74] + mbx_reg2hw_outbound_limit_address_reg_t outbound_limit_address; // [73:43] + mbx_reg2hw_outbound_read_ptr_reg_t outbound_read_ptr; // [42:12] + mbx_reg2hw_outbound_object_size_reg_t outbound_object_size; // [11:0] } mbx_host_reg2hw_t; // HW -> register type for host interface typedef struct packed { - mbx_hw2reg_intr_state_reg_t intr_state; // [1:0] + mbx_hw2reg_intr_state_reg_t intr_state; // [78:77] + mbx_hw2reg_control_reg_t control; // [76:76] + mbx_hw2reg_status_reg_t status; // [75:72] + mbx_hw2reg_inbound_write_ptr_reg_t inbound_write_ptr; // [71:42] + mbx_hw2reg_outbound_read_ptr_reg_t outbound_read_ptr; // [41:12] + mbx_hw2reg_outbound_object_size_reg_t outbound_object_size; // [11:0] } mbx_host_hw2reg_t; // Register offsets for host interface - parameter logic [HostAw-1:0] MBX_INTR_STATE_OFFSET = 4'h 0; - parameter logic [HostAw-1:0] MBX_INTR_ENABLE_OFFSET = 4'h 4; - parameter logic [HostAw-1:0] MBX_INTR_TEST_OFFSET = 4'h 8; + parameter logic [HostAw-1:0] MBX_INTR_STATE_OFFSET = 6'h 0; + parameter logic [HostAw-1:0] MBX_INTR_ENABLE_OFFSET = 6'h 4; + parameter logic [HostAw-1:0] MBX_INTR_TEST_OFFSET = 6'h 8; + parameter logic [HostAw-1:0] MBX_ALERT_TEST_OFFSET = 6'h c; + parameter logic [HostAw-1:0] MBX_CONTROL_OFFSET = 6'h 10; + parameter logic [HostAw-1:0] MBX_STATUS_OFFSET = 6'h 14; + parameter logic [HostAw-1:0] MBX_ADDRESS_RANGE_REGWEN_OFFSET = 6'h 18; + parameter logic [HostAw-1:0] MBX_ADDRESS_RANGE_VALID_OFFSET = 6'h 1c; + parameter logic [HostAw-1:0] MBX_INBOUND_BASE_ADDRESS_OFFSET = 6'h 20; + parameter logic [HostAw-1:0] MBX_INBOUND_LIMIT_ADDRESS_OFFSET = 6'h 24; + parameter logic [HostAw-1:0] MBX_INBOUND_WRITE_PTR_OFFSET = 6'h 28; + parameter logic [HostAw-1:0] MBX_OUTBOUND_BASE_ADDRESS_OFFSET = 6'h 2c; + parameter logic [HostAw-1:0] MBX_OUTBOUND_LIMIT_ADDRESS_OFFSET = 6'h 30; + parameter logic [HostAw-1:0] MBX_OUTBOUND_READ_PTR_OFFSET = 6'h 34; + parameter logic [HostAw-1:0] MBX_OUTBOUND_OBJECT_SIZE_OFFSET = 6'h 38; // Reset values for hwext registers and their fields for host interface parameter logic [0:0] MBX_INTR_TEST_RESVAL = 1'h 0; parameter logic [0:0] MBX_INTR_TEST_MBX_READY_RESVAL = 1'h 0; + parameter logic [0:0] MBX_ALERT_TEST_RESVAL = 1'h 0; + parameter logic [0:0] MBX_ALERT_TEST_FATAL_FAULT_RESVAL = 1'h 0; + parameter logic [0:0] MBX_CONTROL_RESVAL = 1'h 0; + parameter logic [0:0] MBX_CONTROL_ABORT_RESVAL = 1'h 0; + parameter logic [31:0] MBX_STATUS_RESVAL = 32'h 1; + parameter logic [0:0] MBX_STATUS_BUSY_RESVAL = 1'h 1; + parameter logic [0:0] MBX_STATUS_ERROR_RESVAL = 1'h 0; + parameter logic [0:0] MBX_STATUS_ASYNC_MSG_STATUS_RESVAL = 1'h 0; + parameter logic [0:0] MBX_STATUS_READY_RESVAL = 1'h 0; + parameter logic [31:0] MBX_INBOUND_WRITE_PTR_RESVAL = 32'h 0; + parameter logic [29:0] MBX_INBOUND_WRITE_PTR_INBOUND_READ_PTR_RESVAL = 30'h 0; + parameter logic [31:0] MBX_OUTBOUND_READ_PTR_RESVAL = 32'h 0; + parameter logic [29:0] MBX_OUTBOUND_READ_PTR_OUTBOUND_WRITE_PTR_RESVAL = 30'h 0; // Register index for host interface typedef enum int { MBX_INTR_STATE, MBX_INTR_ENABLE, - MBX_INTR_TEST + MBX_INTR_TEST, + MBX_ALERT_TEST, + MBX_CONTROL, + MBX_STATUS, + MBX_ADDRESS_RANGE_REGWEN, + MBX_ADDRESS_RANGE_VALID, + MBX_INBOUND_BASE_ADDRESS, + MBX_INBOUND_LIMIT_ADDRESS, + MBX_INBOUND_WRITE_PTR, + MBX_OUTBOUND_BASE_ADDRESS, + MBX_OUTBOUND_LIMIT_ADDRESS, + MBX_OUTBOUND_READ_PTR, + MBX_OUTBOUND_OBJECT_SIZE } mbx_host_id_e; // Register width information to check illegal writes for host interface - parameter logic [3:0] MBX_HOST_PERMIT [3] = '{ - 4'b 0001, // index[0] MBX_INTR_STATE - 4'b 0001, // index[1] MBX_INTR_ENABLE - 4'b 0001 // index[2] MBX_INTR_TEST + parameter logic [3:0] MBX_HOST_PERMIT [15] = '{ + 4'b 0001, // index[ 0] MBX_INTR_STATE + 4'b 0001, // index[ 1] MBX_INTR_ENABLE + 4'b 0001, // index[ 2] MBX_INTR_TEST + 4'b 0001, // index[ 3] MBX_ALERT_TEST + 4'b 0001, // index[ 4] MBX_CONTROL + 4'b 1111, // index[ 5] MBX_STATUS + 4'b 0001, // index[ 6] MBX_ADDRESS_RANGE_REGWEN + 4'b 0001, // index[ 7] MBX_ADDRESS_RANGE_VALID + 4'b 1111, // index[ 8] MBX_INBOUND_BASE_ADDRESS + 4'b 1111, // index[ 9] MBX_INBOUND_LIMIT_ADDRESS + 4'b 1111, // index[10] MBX_INBOUND_WRITE_PTR + 4'b 1111, // index[11] MBX_OUTBOUND_BASE_ADDRESS + 4'b 1111, // index[12] MBX_OUTBOUND_LIMIT_ADDRESS + 4'b 1111, // index[13] MBX_OUTBOUND_READ_PTR + 4'b 0011 // index[14] MBX_OUTBOUND_OBJECT_SIZE }; endpackage From fd0181965f48580f7b972fd9dffc6ed0f8f84383 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Fri, 18 Aug 2023 05:02:17 -0700 Subject: [PATCH 03/88] [hw,mbx,rtl] Added IRQ primitive Signed-off-by: Robert Schilling --- hw/ip/mbx/rtl/mbx.sv | 6 ++++-- hw/ip/mbx/rtl/mbx_hostif.sv | 21 +++++++++++++++++++-- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/hw/ip/mbx/rtl/mbx.sv b/hw/ip/mbx/rtl/mbx.sv index d2c1b6ce77d34..f7d1ace599149 100644 --- a/hw/ip/mbx/rtl/mbx.sv +++ b/hw/ip/mbx/rtl/mbx.sv @@ -12,7 +12,7 @@ module mbx parameter int unsigned CfgSramAddrWidth = 32, parameter int unsigned CfgSramDataWidth = 32 ) ( - input logic clk_i, + input logic clk_i, input logic rst_ni, output logic intr_mbx_ready_o, // Alerts @@ -52,7 +52,7 @@ module mbx logic hostif_write_ob_object_size, hostif_read_ob_object_size; logic [11:0] hostif_ob_object_size_wdata, hostif_ob_object_size_rdata; - logic sysif_write_control_abort; + logic sysif_write_control_abort, hostif_event_intr; mbx_hostif #( .AlertAsyncOn ( AlertAsyncOn ), @@ -63,6 +63,8 @@ module mbx // Device port to the host side .tl_host_i ( tl_host_i ), .tl_host_o ( tl_host_o ), + .event_intr_i ( hostif_event_intr ), + .irq_o ( irq_o ), .alert_rx_i ( alert_rx_i ), .alert_tx_o ( alert_tx_o ), // Access to the control register diff --git a/hw/ip/mbx/rtl/mbx_hostif.sv b/hw/ip/mbx/rtl/mbx_hostif.sv index 3078e857db9c9..d7db796bb64aa 100644 --- a/hw/ip/mbx/rtl/mbx_hostif.sv +++ b/hw/ip/mbx/rtl/mbx_hostif.sv @@ -13,6 +13,9 @@ module mbx_hostif // Device port to the host side input tlul_pkg::tl_h2d_t tl_host_i, output tlul_pkg::tl_d2h_t tl_host_o, + // Generated interrupt event + input logic event_intr_i, + output logic irq_o, // Alerts input prim_alert_pkg::alert_rx_t [NumAlerts-1:0] alert_rx_i, output prim_alert_pkg::alert_tx_t [NumAlerts-1:0] alert_tx_o, @@ -58,8 +61,8 @@ module mbx_hostif .AsyncOn ( AlertAsyncOn[i] ), .IsFatal ( 1'b1 ) ) u_prim_alert_sender ( - .clk_i, - .rst_ni, + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), .alert_test_i ( alert_test[i] ), .alert_req_i ( alerts[i] ), .alert_ack_o ( ), @@ -81,6 +84,20 @@ module mbx_hostif .devmode_i ( 1'b1 ) ); + // instantiate interrupt hardware primitive + prim_intr_hw #(.Width(1)) u_intr_hw ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .event_intr_i ( event_intr_i ), + .reg2hw_intr_enable_q_i ( reg2hw.intr_enable.q ), + .reg2hw_intr_test_q_i ( reg2hw.intr_test.q ), + .reg2hw_intr_test_qe_i ( reg2hw.intr_test.qe ), + .reg2hw_intr_state_q_i ( reg2hw.intr_state.q ), + .hw2reg_intr_state_de_o ( hw2reg.intr_state.de ), + .hw2reg_intr_state_d_o ( hw2reg.intr_state.d ), + .intr_o ( irq_o ) + ); + // Control Register // External read logic logic abort_d, abort_q; From e55ae11c028d60b601263b237d47aa3224eb4f2d Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Thu, 24 Aug 2023 03:35:23 -0700 Subject: [PATCH 04/88] [hw,mbx,rtl] Rename set/clear signals for better meaning Signed-off-by: Robert Schilling --- hw/ip/mbx/rtl/mbx.sv | 18 +++++++++--------- hw/ip/mbx/rtl/mbx_hostif.sv | 22 +++++++++++----------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/hw/ip/mbx/rtl/mbx.sv b/hw/ip/mbx/rtl/mbx.sv index f7d1ace599149..ad86ff7bf1dd2 100644 --- a/hw/ip/mbx/rtl/mbx.sv +++ b/hw/ip/mbx/rtl/mbx.sv @@ -32,10 +32,10 @@ module mbx logic [CfgSramAddrWidth-1:0] ob_read_ptr; // External write signals for control and status register - logic hostif_set_control_abort; - logic hostif_clear_status_busy; - logic hostif_set_status_error, hostif_clear_status_error; - logic hostif_set_status_async_msg_status; + logic hostif_control_abort_set; + logic hostif_status_busy_clear; + logic hostif_status_error_set, hostif_status_error_clear; + logic hostif_status_async_msg_status_set; // External read signals for control and status register logic hostif_status_busy, hostif_status_error; logic hostif_status_async_msg_status, hostif_status_ready; @@ -68,12 +68,12 @@ module mbx .alert_rx_i ( alert_rx_i ), .alert_tx_o ( alert_tx_o ), // Access to the control register - .hostif_set_control_abort_o ( hostif_set_control_abort ), + .hostif_control_abort_set_o ( hostif_control_abort_set ), // Access to the status register - .hostif_clear_status_busy_o ( hostif_clear_status_busy ), - .hostif_set_status_error_o ( hostif_set_status_error ), - .hostif_clear_status_error_o ( hostif_clear_status_error ), - .hostif_set_status_async_msg_status_o( hostif_set_status_async_msg_status ), + .hostif_status_busy_clear_o ( hostif_status_busy_clear ), + .hostif_status_error_set_o ( hostif_status_error_set ), + .hostif_status_error_clear_o ( hostif_status_error_clear ), + .hostif_status_async_msg_status_set_o( hostif_status_async_msg_status_set ), .hostif_status_busy_i ( hostif_status_busy ), .hostif_status_error_i ( hostif_status_error ), .hostif_status_async_msg_status_i ( hostif_status_async_msg_status ), diff --git a/hw/ip/mbx/rtl/mbx_hostif.sv b/hw/ip/mbx/rtl/mbx_hostif.sv index d7db796bb64aa..728203d4ea464 100644 --- a/hw/ip/mbx/rtl/mbx_hostif.sv +++ b/hw/ip/mbx/rtl/mbx_hostif.sv @@ -20,12 +20,12 @@ module mbx_hostif input prim_alert_pkg::alert_rx_t [NumAlerts-1:0] alert_rx_i, output prim_alert_pkg::alert_tx_t [NumAlerts-1:0] alert_tx_o, // Access to the control register - output logic hostif_set_control_abort_o, + output logic hostif_control_set_abort_o, // Access to the status register - output logic hostif_clear_status_busy_o, - output logic hostif_set_status_error_o, - output logic hostif_clear_status_error_o, - output logic hostif_set_status_async_msg_status_o, + output logic hostif_status_busy_clear_o, + output logic hostif_status_error_set_o, + output logic hostif_status_error_clear_o, + output logic hostif_status_async_msg_status_set_o, input logic hostif_status_busy_i, input logic hostif_status_error_i, input logic hostif_status_async_msg_status_i, @@ -103,7 +103,7 @@ module mbx_hostif logic abort_d, abort_q; assign hw2reg.control.d = abort_q; // External write logic - assign hostif_set_control_abort_o = reg2hw.control.qe & tl_host_i.a_data[0]; + assign hostif_control_set_abort_o = reg2hw.control.qe & tl_host_i.a_data[0]; // Abort computation from system and host interface always_comb begin @@ -111,7 +111,7 @@ module mbx_hostif if (sysif_write_control_abort_i) begin abort_d = 1'b1; - end else if (hostif_set_control_abort_o) begin + end else if (hostif_control_set_abort_o) begin abort_d = 1'b0; end end @@ -135,10 +135,10 @@ module mbx_hostif assign hw2reg.status.async_msg_status.d = hostif_status_async_msg_status_i; assign hw2reg.status.ready.d = hostif_status_ready_i; // External write logic - assign hostif_clear_status_busy_o = reg2hw.status.busy.qe & ~reg2hw.status.busy.q; - assign hostif_set_status_error_o = reg2hw.status.error.qe & reg2hw.status.error.q; - assign hostif_clear_status_error_o = reg2hw.status.error.qe & ~reg2hw.status.error.q; - assign hostif_set_status_async_msg_status_o = + assign hostif_status_busy_clear_o = reg2hw.status.busy.qe & ~reg2hw.status.busy.q; + assign hostif_status_error_set_o = reg2hw.status.error.qe & reg2hw.status.error.q; + assign hostif_status_error_clear_o = reg2hw.status.error.qe & ~reg2hw.status.error.q; + assign hostif_status_async_msg_status_set_o = reg2hw.status.async_msg_status.qe & reg2hw.status.async_msg_status.q; // Address config valid From 296a6acbaea767f680752d2ff01c471652d61d58 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Mon, 21 Aug 2023 01:06:12 -0700 Subject: [PATCH 05/88] [hw,rtl,mbx] System register interface implementation Signed-off-by: Robert Schilling --- hw/ip/mbx/data/mbx.hjson | 157 ++++++++ hw/ip/mbx/mbx.core | 2 + hw/ip/mbx/rtl/mbx.sv | 63 +++- hw/ip/mbx/rtl/mbx_host_reg_top.sv | 21 +- hw/ip/mbx/rtl/mbx_hostif.sv | 4 +- hw/ip/mbx/rtl/mbx_reg_pkg.sv | 191 +++++++++- hw/ip/mbx/rtl/mbx_sys_reg_top.sv | 598 +++++++++++++++++++++++++++++- hw/ip/mbx/rtl/mbx_sysif.sv | 231 ++++++++++++ 8 files changed, 1244 insertions(+), 23 deletions(-) create mode 100644 hw/ip/mbx/rtl/mbx_sysif.sv diff --git a/hw/ip/mbx/data/mbx.hjson b/hw/ip/mbx/data/mbx.hjson index 5cdc8f21c2b68..12cc8850441f0 100644 --- a/hw/ip/mbx/data/mbx.hjson +++ b/hw/ip/mbx/data/mbx.hjson @@ -231,6 +231,163 @@ } ] sys: [ + { name: "extended_cap_header" + desc: "" + swaccess: "ro" + hwaccess: "hrw" + fields: [ + { name: "cap_id" + desc: "" + bits: "15:0" + resval: "0x002E" + } + { name: "cap_version" + desc: "" + bits: "19:16" + resval: "0x2" + + } + { name: "next_capaility_offset" + desc: "" + bits: "31:20" + resval: "0" + } + ] + hwext: "true" + } + { name: "cap_header" + desc: "" + swaccess: "ro" + hwaccess: "hrw" + fields: [ + { name: "doe_intr_support" + desc: "" + bits: "0" + } + { name: "doe_intr_msg_nr" + desc: "" + bits: "11:1" + resval: "0x2" + + } + ] + } + { name: "sys_control" + desc: "DOE mailbox control register." + hwext: "true" + hwaccess: "hrw" + hwqe: "true" + + fields: [ + { name: "abort" + desc: ''' + A write of 1 to this bit causes all data object transfer operations associated with this DOE instance to be aborted. + ''' + bits: "0" + resval: "0x0" + swaccess: "wo" + } + { name: "doe_intr_en" + desc: ''' + If DOE interrupt support is set, when this bit is set and MSI/MSI-X is enabled in MSI capability registers, the DOE instance must issue an MSI/MSI-X interrupt. + ''' + bits: "1" + resval: "0x0" + swaccess: "rw" + } + { name: "async_msg_en" + desc: ''' + If DOE Async Message Support is Set, this bit, when Set, enables the use of the DOE Async Message mechanism. + ''' + bits: "3" + resval: "0x0" + swaccess: "rw" + + } + { name: "go" + desc: ''' + A write of 1 to this bit indicates to the DOE instance that it can start consuming the data object transferred through the DOE Write Data Mailbox register. + ''' + bits: "31" + resval: "0x0" + swaccess: "wo" + } + ] + } + { name: "sys_status" + desc: "DOE mailbox status register" + fields: [ + { name: "busy" + desc: ''' + When Set, this bit indicates the DOE instance is temporarily unable to receive a new data object through the DOE Write Data Mailbox register. + ''' + bits: "0" + resval: "0x1" + swaccess: "ro" + hwaccess: "hrw" + } + { name: "doe_intr_status" + desc: "This bit is set when an interrupt event occurs." + bits: "1" + resval: "0x0" + swaccess: "rw1c" + hwaccess: "hrw" + hwqe: "true" + } + { name: "error" + desc: ''' + When Set, this bit indicates that there has been an internal error associated with data object received, or that a data object has been received for which the DOE instance is unable to provide a response. + The transition of this bit from Clear to Set is an interrupt triggering event. + ''' + bits: "2" + resval: "0x0" + swaccess: "ro" + hwaccess: "hrw" + } + { name: "async_msg_status" + desc: ''' + When Set, this bit indicates the DOE instance has one or more asynchronous messages to transfer. + The transition of this bit from Clear to Set is an interrupt triggering event. + ''' + bits: "3" + resval: "0x0" + swaccess: "ro" + hwaccess: "hrw" + } + { name: "ready" + desc: ''' + When Set, this bit indicates the DOE instance has a data object available to be read by system firmware/software. + The transition of this bit from Clear to Set is an interrupt triggering event. + ''' + bits: "31" + resval: "0x0" + swaccess: "ro" + hwaccess: "hrw" + } + ] + } + { window: { + name: "wdata" + items: "1" + swaccess: "wo" + desc: '''DOE mailbox write data register. + The DOE instance receives data objects via writes to this register. + A successful write adds one DWORD to the data object being assembled in the DOE instance. + A write of 1 to the DOE Go bit in the DOE Control Register marks the completion of the data transfer, i.e, final DWORD for the object has been written. + ''' + } + } + { window: { + name: "rdata" + desc: '''DOE mailbox read data register + If the Data Object Ready bit is Set, a read of this register returns the current DW of the data object. + A write of any value to this register indicates a successful read of the current DWORD. + The next read to this register shall return to the next DW from the data object being read + ''' + items: "1" + swaccess: "rw" + } + } ] } } diff --git a/hw/ip/mbx/mbx.core b/hw/ip/mbx/mbx.core index 0c710c7a902a2..3a4d994998ae5 100644 --- a/hw/ip/mbx/mbx.core +++ b/hw/ip/mbx/mbx.core @@ -14,7 +14,9 @@ filesets: - rtl/mbx_reg_pkg.sv - rtl/mbx.sv - rtl/mbx_host_reg_top.sv + - rtl/mbx_sys_reg_top.sv - rtl/mbx_hostif.sv + - rtl/mbx_sysif.sv file_type: systemVerilogSource files_verilator_waiver: diff --git a/hw/ip/mbx/rtl/mbx.sv b/hw/ip/mbx/rtl/mbx.sv index ad86ff7bf1dd2..62ff59f915248 100644 --- a/hw/ip/mbx/rtl/mbx.sv +++ b/hw/ip/mbx/rtl/mbx.sv @@ -10,7 +10,8 @@ module mbx #( parameter logic [NumAlerts-1:0] AlertAsyncOn = {NumAlerts{1'b1}}, parameter int unsigned CfgSramAddrWidth = 32, - parameter int unsigned CfgSramDataWidth = 32 + parameter int unsigned CfgSramDataWidth = 32, + parameter int unsigned NextExtDoeOffset = 12'h800 ) ( input logic clk_i, input logic rst_ni, @@ -33,7 +34,7 @@ module mbx // External write signals for control and status register logic hostif_control_abort_set; - logic hostif_status_busy_clear; + logic hostif_status_busy_clear, hostif_status_irq_status_set; logic hostif_status_error_set, hostif_status_error_clear; logic hostif_status_async_msg_status_set; // External read signals for control and status register @@ -50,9 +51,11 @@ module mbx logic [CfgSramAddrWidth-1:0] hostif_ob_base, hostif_ob_limit; logic hostif_write_ob_object_size, hostif_read_ob_object_size; - logic [11:0] hostif_ob_object_size_wdata, hostif_ob_object_size_rdata; + logic [10:0] hostif_ob_object_size_wdata, hostif_ob_object_size_rdata; + logic sysif_status_doe_intr_status, sysif_status_doe_intr_status_set; logic sysif_write_control_abort, hostif_event_intr; + logic sysif_intg_err; mbx_hostif #( .AlertAsyncOn ( AlertAsyncOn ), @@ -63,14 +66,16 @@ module mbx // Device port to the host side .tl_host_i ( tl_host_i ), .tl_host_o ( tl_host_o ), + .intg_err_i ( sysif_intg_err ), .event_intr_i ( hostif_event_intr ), - .irq_o ( irq_o ), + .irq_o ( intr_mbx_ready_o ), .alert_rx_i ( alert_rx_i ), .alert_tx_o ( alert_tx_o ), // Access to the control register .hostif_control_abort_set_o ( hostif_control_abort_set ), // Access to the status register .hostif_status_busy_clear_o ( hostif_status_busy_clear ), + .hostif_status_irq_status_set_o ( hostif_status_irq_status_set ), .hostif_status_error_set_o ( hostif_status_error_set ), .hostif_status_error_clear_o ( hostif_status_error_clear ), .hostif_status_async_msg_status_set_o( hostif_status_async_msg_status_set ), @@ -96,5 +101,55 @@ module mbx .sysif_write_control_abort_i ( sysif_write_control_abort ) ); + logic ibmbx_pending, obmbx_pending; + logic ibmbx_status_busy_valid, ibmbx_status_busy; + logic obmbx_status_ready_valid, obmbx_status_ready; + + + logic sysif_control_go_set, sysif_control_abort_set; + logic sysif_control_doe_intr_en, sysif_control_async_msg_en; + + logic sysif_status_intr_support, sysif_status_intr_en; + logic sysif_status_async_msg_status_set, sysif_status_async_msg_status; + + logic sysif_write_data_write_valid; + logic [CfgSramDataWidth-1:0] sysif_write_data, sysif_read_data; + logic sysif_read_data_read_valid, sysif_read_data_write_valid; + + mbx_sysif #( + .CfgSramDataWidth ( CfgSramDataWidth ), + .NextExtDoeOffset ( NextExtDoeOffset ) + ) u_sysif ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .tl_sys_i ( tl_sys_i ), + .tl_sys_o ( tl_sys_o ), + .intg_err_o ( sysif_intg_err ), + // Access to the control register + .sysif_control_abort_set_o ( sysif_control_abort_set ), + .sysif_control_doe_intr_en_o ( sysif_control_doe_intr_en), + .sysif_control_async_msg_en_o ( sysif_control_async_msg_en), + .sysif_control_go_set_o ( sysif_control_go_set ), + // Access to the status register + .sysif_status_busy_valid_i ( ibmbx_status_busy_valid ), + .sysif_status_busy_i ( ibmbx_status_busy ), + .sysif_status_doe_intr_status_set_i ( sysif_status_doe_intr_status_set ), + .sysif_status_doe_intr_status_o ( sysif_status_doe_intr_status ), + .sysif_status_error_set_i ( hostif_status_error_set ), + .sysif_status_error_clear_i ( hostif_status_error_clear ), + .sysif_status_async_msg_status_o ( sysif_status_async_msg_status ), + .sysif_status_async_msg_status_set_i ( sysif_status_async_msg_status_set ), + .sysif_status_ready_valid_i ( obmbx_status_ready_valid ), + .sysif_status_ready_i ( obmbx_status_ready ), + // Control lines for backpressuring the bus + .ibmbx_pending_i ( ibmbx_pending ), + .obmbx_pending_i ( obmbx_pending ), + // Data interface for inbound and outbound mailbox + .write_data_write_valid_o ( sysif_write_data_write_valid ), + .write_data_o ( sysif_write_data ), + .read_data_i ( sysif_read_data ), + .read_data_read_valid_o ( sysif_read_data_read_valid ), + .read_data_write_valid_o ( sysif_read_data_write_valid ) + ); endmodule diff --git a/hw/ip/mbx/rtl/mbx_host_reg_top.sv b/hw/ip/mbx/rtl/mbx_host_reg_top.sv index d47b7326d0816..202160cf24748 100644 --- a/hw/ip/mbx/rtl/mbx_host_reg_top.sv +++ b/hw/ip/mbx/rtl/mbx_host_reg_top.sv @@ -361,7 +361,8 @@ module mbx_host_reg_top ( prim_subreg #( .DW (1), .SwAccess(prim_subreg_pkg::SwAccessW0C), - .RESVAL (1'h1) + .RESVAL (1'h1), + .Mubi (1'b0) ) u_address_range_regwen ( .clk_i (clk_i), .rst_ni (rst_ni), @@ -388,7 +389,8 @@ module mbx_host_reg_top ( prim_subreg #( .DW (1), .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (1'h0) + .RESVAL (1'h0), + .Mubi (1'b0) ) u_address_range_valid ( .clk_i (clk_i), .rst_ni (rst_ni), @@ -429,7 +431,8 @@ module mbx_host_reg_top ( prim_subreg #( .DW (30), .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (30'h0) + .RESVAL (30'h0), + .Mubi (1'b0) ) u_inbound_base_address ( .clk_i (clk_i), .rst_ni (rst_ni), @@ -471,7 +474,8 @@ module mbx_host_reg_top ( prim_subreg #( .DW (30), .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (30'h0) + .RESVAL (30'h0), + .Mubi (1'b0) ) u_inbound_limit_address ( .clk_i (clk_i), .rst_ni (rst_ni), @@ -534,7 +538,8 @@ module mbx_host_reg_top ( prim_subreg #( .DW (30), .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (30'h0) + .RESVAL (30'h0), + .Mubi (1'b0) ) u_outbound_base_address ( .clk_i (clk_i), .rst_ni (rst_ni), @@ -576,7 +581,8 @@ module mbx_host_reg_top ( prim_subreg #( .DW (30), .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (30'h0) + .RESVAL (30'h0), + .Mubi (1'b0) ) u_outbound_limit_address ( .clk_i (clk_i), .rst_ni (rst_ni), @@ -636,7 +642,8 @@ module mbx_host_reg_top ( prim_subreg #( .DW (11), .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (11'h0) + .RESVAL (11'h0), + .Mubi (1'b0) ) u_outbound_object_size ( .clk_i (clk_i), .rst_ni (rst_ni), diff --git a/hw/ip/mbx/rtl/mbx_hostif.sv b/hw/ip/mbx/rtl/mbx_hostif.sv index 728203d4ea464..fff58ef2f4316 100644 --- a/hw/ip/mbx/rtl/mbx_hostif.sv +++ b/hw/ip/mbx/rtl/mbx_hostif.sv @@ -41,8 +41,8 @@ module mbx_hostif output logic [CfgSramAddrWidth-1:0] hostif_ob_limit_o, // Read/Write access for the OB DW Count register output logic hostif_write_ob_object_size_o, - output logic [11:0] hostif_ob_object_size_o, - input logic [11:0] hostif_ob_object_size_i, + output logic [10:0] hostif_ob_object_size_o, + input logic [10:0] hostif_ob_object_size_i, input logic hostif_read_ob_object_size_i, // Control inputs coming from the system registers interface input logic sysif_write_control_abort_i diff --git a/hw/ip/mbx/rtl/mbx_reg_pkg.sv b/hw/ip/mbx/rtl/mbx_reg_pkg.sv index 9b980c1181ead..c148f3a10451c 100644 --- a/hw/ip/mbx/rtl/mbx_reg_pkg.sv +++ b/hw/ip/mbx/rtl/mbx_reg_pkg.sv @@ -11,7 +11,7 @@ package mbx_reg_pkg; // Address widths within the block parameter int HostAw = 6; - parameter int SysAw = 1; + parameter int SysAw = 5; /////////////////////////////////////////////// // Typedefs for registers for host interface // @@ -44,19 +44,19 @@ package mbx_reg_pkg; struct packed { logic q; logic qe; - } busy; + } ready; struct packed { logic q; logic qe; - } error; + } async_msg_status; struct packed { logic q; logic qe; - } async_msg_status; + } error; struct packed { logic q; logic qe; - } ready; + } busy; } mbx_reg2hw_status_reg_t; typedef struct packed { @@ -240,4 +240,185 @@ package mbx_reg_pkg; 4'b 0011 // index[14] MBX_OUTBOUND_OBJECT_SIZE }; + ////////////////////////////////////////////// + // Typedefs for registers for sys interface // + ////////////////////////////////////////////// + + typedef struct packed { + struct packed { + logic [11:0] q; + } next_capaility_offset; + struct packed { + logic [3:0] q; + } cap_version; + struct packed { + logic [15:0] q; + } cap_id; + } mbx_reg2hw_extended_cap_header_reg_t; + + typedef struct packed { + struct packed { + logic [10:0] q; + } doe_intr_msg_nr; + struct packed { + logic q; + } doe_intr_support; + } mbx_reg2hw_cap_header_reg_t; + + typedef struct packed { + struct packed { + logic q; + logic qe; + } go; + struct packed { + logic q; + logic qe; + } async_msg_en; + struct packed { + logic q; + logic qe; + } doe_intr_en; + struct packed { + logic q; + logic qe; + } abort; + } mbx_reg2hw_sys_control_reg_t; + + typedef struct packed { + struct packed { + logic q; + } ready; + struct packed { + logic q; + } async_msg_status; + struct packed { + logic q; + } error; + struct packed { + logic q; + logic qe; + } doe_intr_status; + struct packed { + logic q; + } busy; + } mbx_reg2hw_sys_status_reg_t; + + typedef struct packed { + struct packed { + logic [15:0] d; + } cap_id; + struct packed { + logic [3:0] d; + } cap_version; + struct packed { + logic [11:0] d; + } next_capaility_offset; + } mbx_hw2reg_extended_cap_header_reg_t; + + typedef struct packed { + struct packed { + logic d; + logic de; + } doe_intr_support; + struct packed { + logic [10:0] d; + logic de; + } doe_intr_msg_nr; + } mbx_hw2reg_cap_header_reg_t; + + typedef struct packed { + struct packed { + logic d; + } abort; + struct packed { + logic d; + } doe_intr_en; + struct packed { + logic d; + } async_msg_en; + struct packed { + logic d; + } go; + } mbx_hw2reg_sys_control_reg_t; + + typedef struct packed { + struct packed { + logic d; + logic de; + } busy; + struct packed { + logic d; + logic de; + } doe_intr_status; + struct packed { + logic d; + logic de; + } error; + struct packed { + logic d; + logic de; + } async_msg_status; + struct packed { + logic d; + logic de; + } ready; + } mbx_hw2reg_sys_status_reg_t; + + // Register -> HW type for sys interface + typedef struct packed { + mbx_reg2hw_extended_cap_header_reg_t extended_cap_header; // [57:26] + mbx_reg2hw_cap_header_reg_t cap_header; // [25:14] + mbx_reg2hw_sys_control_reg_t sys_control; // [13:6] + mbx_reg2hw_sys_status_reg_t sys_status; // [5:0] + } mbx_sys_reg2hw_t; + + // HW -> register type for sys interface + typedef struct packed { + mbx_hw2reg_extended_cap_header_reg_t extended_cap_header; // [59:28] + mbx_hw2reg_cap_header_reg_t cap_header; // [27:14] + mbx_hw2reg_sys_control_reg_t sys_control; // [13:10] + mbx_hw2reg_sys_status_reg_t sys_status; // [9:0] + } mbx_sys_hw2reg_t; + + // Register offsets for sys interface + parameter logic [SysAw-1:0] MBX_EXTENDED_CAP_HEADER_OFFSET = 5'h 0; + parameter logic [SysAw-1:0] MBX_CAP_HEADER_OFFSET = 5'h 4; + parameter logic [SysAw-1:0] MBX_SYS_CONTROL_OFFSET = 5'h 8; + parameter logic [SysAw-1:0] MBX_SYS_STATUS_OFFSET = 5'h c; + + // Reset values for hwext registers and their fields for sys interface + parameter logic [31:0] MBX_EXTENDED_CAP_HEADER_RESVAL = 32'h 2002e; + parameter logic [15:0] MBX_EXTENDED_CAP_HEADER_CAP_ID_RESVAL = 16'h 2e; + parameter logic [3:0] MBX_EXTENDED_CAP_HEADER_CAP_VERSION_RESVAL = 4'h 2; + parameter logic [11:0] MBX_EXTENDED_CAP_HEADER_NEXT_CAPAILITY_OFFSET_RESVAL = 12'h 0; + parameter logic [31:0] MBX_SYS_CONTROL_RESVAL = 32'h 0; + parameter logic [0:0] MBX_SYS_CONTROL_ABORT_RESVAL = 1'h 0; + parameter logic [0:0] MBX_SYS_CONTROL_DOE_INTR_EN_RESVAL = 1'h 0; + parameter logic [0:0] MBX_SYS_CONTROL_ASYNC_MSG_EN_RESVAL = 1'h 0; + parameter logic [0:0] MBX_SYS_CONTROL_GO_RESVAL = 1'h 0; + + // Window parameters for sys interface + parameter logic [SysAw-1:0] MBX_WDATA_OFFSET = 5'h 10; + parameter int unsigned MBX_WDATA_SIZE = 'h 4; + parameter int unsigned MBX_WDATA_IDX = 0; + parameter logic [SysAw-1:0] MBX_RDATA_OFFSET = 5'h 14; + parameter int unsigned MBX_RDATA_SIZE = 'h 4; + parameter int unsigned MBX_RDATA_IDX = 1; + + // Register index for sys interface + typedef enum int { + MBX_EXTENDED_CAP_HEADER, + MBX_CAP_HEADER, + MBX_SYS_CONTROL, + MBX_SYS_STATUS + } mbx_sys_id_e; + + // Register width information to check illegal writes for sys interface + parameter logic [3:0] MBX_SYS_PERMIT [4] = '{ + 4'b 1111, // index[0] MBX_EXTENDED_CAP_HEADER + 4'b 0011, // index[1] MBX_CAP_HEADER + 4'b 1111, // index[2] MBX_SYS_CONTROL + 4'b 1111 // index[3] MBX_SYS_STATUS + }; + endpackage diff --git a/hw/ip/mbx/rtl/mbx_sys_reg_top.sv b/hw/ip/mbx/rtl/mbx_sys_reg_top.sv index 639658824c31d..31b23c5c91bec 100644 --- a/hw/ip/mbx/rtl/mbx_sys_reg_top.sv +++ b/hw/ip/mbx/rtl/mbx_sys_reg_top.sv @@ -11,7 +11,14 @@ module mbx_sys_reg_top ( input rst_ni, input tlul_pkg::tl_h2d_t tl_i, output tlul_pkg::tl_d2h_t tl_o, + + // Output port for window + output tlul_pkg::tl_h2d_t tl_win_o [2], + input tlul_pkg::tl_d2h_t tl_win_i [2], + // To HW + output mbx_reg_pkg::mbx_sys_reg2hw_t reg2hw, // Write + input mbx_reg_pkg::mbx_sys_hw2reg_t hw2reg, // Read // Integrity check errors output logic intg_err_o @@ -19,11 +26,60 @@ module mbx_sys_reg_top ( import mbx_reg_pkg::* ; + localparam int AW = 5; + localparam int DW = 32; + localparam int DBW = DW/8; // Byte Width + + // register signals + logic reg_we; + logic reg_re; + logic [AW-1:0] reg_addr; + logic [DW-1:0] reg_wdata; + logic [DBW-1:0] reg_be; + logic [DW-1:0] reg_rdata; + logic reg_error; + + logic addrmiss, wr_err; + + logic [DW-1:0] reg_rdata_next; + logic reg_busy; + + tlul_pkg::tl_h2d_t tl_reg_h2d; + tlul_pkg::tl_d2h_t tl_reg_d2h; + + // incoming payload check + logic intg_err; + tlul_cmd_intg_chk u_chk ( + .tl_i(tl_i), + .err_o(intg_err) + ); + + // also check for spurious write enables + logic reg_we_err; + logic [3:0] reg_we_check; + prim_reg_we_check #( + .OneHotWidth(4) + ) u_prim_reg_we_check ( + .clk_i(clk_i), + .rst_ni(rst_ni), + .oh_i (reg_we_check), + .en_i (reg_we && !addrmiss), + .err_o (reg_we_err) + ); + + logic err_q; + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + err_q <= '0; + end else if (intg_err || reg_we_err) begin + err_q <= 1'b1; + end + end - // Since there are no registers in this block, commands are routed through to windows which - // can report their own integrity errors. - assign intg_err_o = 1'b0; + // integrity error output is permanent and should be used for alert generation + // register errors are transactional + assign intg_err_o = err_q | intg_err | reg_we_err; // outgoing integrity generation tlul_pkg::tl_d2h_t tl_o_pre; @@ -35,8 +91,540 @@ module mbx_sys_reg_top ( .tl_o(tl_o) ); - assign tl_reg_h2d = tl_i; - assign tl_o_pre = tl_reg_d2h; + tlul_pkg::tl_h2d_t tl_socket_h2d [3]; + tlul_pkg::tl_d2h_t tl_socket_d2h [3]; + + logic [1:0] reg_steer; + + // socket_1n connection + assign tl_reg_h2d = tl_socket_h2d[2]; + assign tl_socket_d2h[2] = tl_reg_d2h; + + assign tl_win_o[0] = tl_socket_h2d[0]; + assign tl_socket_d2h[0] = tl_win_i[0]; + assign tl_win_o[1] = tl_socket_h2d[1]; + assign tl_socket_d2h[1] = tl_win_i[1]; + + // Create Socket_1n + tlul_socket_1n #( + .N (3), + .HReqPass (1'b1), + .HRspPass (1'b1), + .DReqPass ({3{1'b1}}), + .DRspPass ({3{1'b1}}), + .HReqDepth (4'h0), + .HRspDepth (4'h0), + .DReqDepth ({3{4'h0}}), + .DRspDepth ({3{4'h0}}), + .ExplicitErrs (1'b0) + ) u_socket ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .tl_h_i (tl_i), + .tl_h_o (tl_o_pre), + .tl_d_o (tl_socket_h2d), + .tl_d_i (tl_socket_d2h), + .dev_select_i (reg_steer) + ); + + // Create steering logic + always_comb begin + reg_steer = + tl_i.a_address[AW-1:0] inside {[16:19]} ? 2'd0 : + tl_i.a_address[AW-1:0] inside {[20:23]} ? 2'd1 : + // Default set to register + 2'd2; + + // Override this in case of an integrity error + if (intg_err) begin + reg_steer = 2'd2; + end + end + + tlul_adapter_reg #( + .RegAw(AW), + .RegDw(DW), + .EnableDataIntgGen(0) + ) u_reg_if ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + .tl_i (tl_reg_h2d), + .tl_o (tl_reg_d2h), + + .en_ifetch_i(prim_mubi_pkg::MuBi4False), + .intg_error_o(), + + .we_o (reg_we), + .re_o (reg_re), + .addr_o (reg_addr), + .wdata_o (reg_wdata), + .be_o (reg_be), + .busy_i (reg_busy), + .rdata_i (reg_rdata), + .error_i (reg_error) + ); + + // cdc oversampling signals + + assign reg_rdata = reg_rdata_next ; + assign reg_error = addrmiss | wr_err | intg_err; + + // Define SW related signals + // Format: __{wd|we|qs} + // or _{wd|we|qs} if field == 1 or 0 + logic extended_cap_header_re; + logic [15:0] extended_cap_header_cap_id_qs; + logic [3:0] extended_cap_header_cap_version_qs; + logic [11:0] extended_cap_header_next_capaility_offset_qs; + logic cap_header_doe_intr_support_qs; + logic [10:0] cap_header_doe_intr_msg_nr_qs; + logic sys_control_re; + logic sys_control_we; + logic sys_control_abort_wd; + logic sys_control_doe_intr_en_qs; + logic sys_control_doe_intr_en_wd; + logic sys_control_async_msg_en_qs; + logic sys_control_async_msg_en_wd; + logic sys_control_go_wd; + logic sys_status_we; + logic sys_status_busy_qs; + logic sys_status_doe_intr_status_qs; + logic sys_status_doe_intr_status_wd; + logic sys_status_error_qs; + logic sys_status_async_msg_status_qs; + logic sys_status_ready_qs; + + // Register instances + // R[extended_cap_header]: V(True) + // F[cap_id]: 15:0 + prim_subreg_ext #( + .DW (16) + ) u_extended_cap_header_cap_id ( + .re (extended_cap_header_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.extended_cap_header.cap_id.d), + .qre (), + .qe (), + .q (reg2hw.extended_cap_header.cap_id.q), + .ds (), + .qs (extended_cap_header_cap_id_qs) + ); + + // F[cap_version]: 19:16 + prim_subreg_ext #( + .DW (4) + ) u_extended_cap_header_cap_version ( + .re (extended_cap_header_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.extended_cap_header.cap_version.d), + .qre (), + .qe (), + .q (reg2hw.extended_cap_header.cap_version.q), + .ds (), + .qs (extended_cap_header_cap_version_qs) + ); + + // F[next_capaility_offset]: 31:20 + prim_subreg_ext #( + .DW (12) + ) u_extended_cap_header_next_capaility_offset ( + .re (extended_cap_header_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.extended_cap_header.next_capaility_offset.d), + .qre (), + .qe (), + .q (reg2hw.extended_cap_header.next_capaility_offset.q), + .ds (), + .qs (extended_cap_header_next_capaility_offset_qs) + ); + + + // R[cap_header]: V(False) + // F[doe_intr_support]: 0:0 + prim_subreg #( + .DW (1), + .SwAccess(prim_subreg_pkg::SwAccessRO), + .RESVAL (1'h0), + .Mubi (1'b0) + ) u_cap_header_doe_intr_support ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (1'b0), + .wd ('0), + + // from internal hardware + .de (hw2reg.cap_header.doe_intr_support.de), + .d (hw2reg.cap_header.doe_intr_support.d), + + // to internal hardware + .qe (), + .q (reg2hw.cap_header.doe_intr_support.q), + .ds (), + + // to register interface (read) + .qs (cap_header_doe_intr_support_qs) + ); + + // F[doe_intr_msg_nr]: 11:1 + prim_subreg #( + .DW (11), + .SwAccess(prim_subreg_pkg::SwAccessRO), + .RESVAL (11'h2), + .Mubi (1'b0) + ) u_cap_header_doe_intr_msg_nr ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (1'b0), + .wd ('0), + + // from internal hardware + .de (hw2reg.cap_header.doe_intr_msg_nr.de), + .d (hw2reg.cap_header.doe_intr_msg_nr.d), + + // to internal hardware + .qe (), + .q (reg2hw.cap_header.doe_intr_msg_nr.q), + .ds (), + + // to register interface (read) + .qs (cap_header_doe_intr_msg_nr_qs) + ); + + + // R[sys_control]: V(True) + logic sys_control_qe; + logic [3:0] sys_control_flds_we; + assign sys_control_qe = &sys_control_flds_we; + // F[abort]: 0:0 + prim_subreg_ext #( + .DW (1) + ) u_sys_control_abort ( + .re (1'b0), + .we (sys_control_we), + .wd (sys_control_abort_wd), + .d (hw2reg.sys_control.abort.d), + .qre (), + .qe (sys_control_flds_we[0]), + .q (reg2hw.sys_control.abort.q), + .ds (), + .qs () + ); + assign reg2hw.sys_control.abort.qe = sys_control_qe; + + // F[doe_intr_en]: 1:1 + prim_subreg_ext #( + .DW (1) + ) u_sys_control_doe_intr_en ( + .re (sys_control_re), + .we (sys_control_we), + .wd (sys_control_doe_intr_en_wd), + .d (hw2reg.sys_control.doe_intr_en.d), + .qre (), + .qe (sys_control_flds_we[1]), + .q (reg2hw.sys_control.doe_intr_en.q), + .ds (), + .qs (sys_control_doe_intr_en_qs) + ); + assign reg2hw.sys_control.doe_intr_en.qe = sys_control_qe; + + // F[async_msg_en]: 3:3 + prim_subreg_ext #( + .DW (1) + ) u_sys_control_async_msg_en ( + .re (sys_control_re), + .we (sys_control_we), + .wd (sys_control_async_msg_en_wd), + .d (hw2reg.sys_control.async_msg_en.d), + .qre (), + .qe (sys_control_flds_we[2]), + .q (reg2hw.sys_control.async_msg_en.q), + .ds (), + .qs (sys_control_async_msg_en_qs) + ); + assign reg2hw.sys_control.async_msg_en.qe = sys_control_qe; + + // F[go]: 31:31 + prim_subreg_ext #( + .DW (1) + ) u_sys_control_go ( + .re (1'b0), + .we (sys_control_we), + .wd (sys_control_go_wd), + .d (hw2reg.sys_control.go.d), + .qre (), + .qe (sys_control_flds_we[3]), + .q (reg2hw.sys_control.go.q), + .ds (), + .qs () + ); + assign reg2hw.sys_control.go.qe = sys_control_qe; + + + // R[sys_status]: V(False) + logic sys_status_qe; + logic [4:0] sys_status_flds_we; + prim_flop #( + .Width(1), + .ResetValue(0) + ) u_sys_status0_qe ( + .clk_i(clk_i), + .rst_ni(rst_ni), + .d_i(&(sys_status_flds_we | 5'h1d)), + .q_o(sys_status_qe) + ); + // F[busy]: 0:0 + prim_subreg #( + .DW (1), + .SwAccess(prim_subreg_pkg::SwAccessRO), + .RESVAL (1'h1), + .Mubi (1'b0) + ) u_sys_status_busy ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (1'b0), + .wd ('0), + + // from internal hardware + .de (hw2reg.sys_status.busy.de), + .d (hw2reg.sys_status.busy.d), + + // to internal hardware + .qe (sys_status_flds_we[0]), + .q (reg2hw.sys_status.busy.q), + .ds (), + + // to register interface (read) + .qs (sys_status_busy_qs) + ); + + // F[doe_intr_status]: 1:1 + prim_subreg #( + .DW (1), + .SwAccess(prim_subreg_pkg::SwAccessW1C), + .RESVAL (1'h0), + .Mubi (1'b0) + ) u_sys_status_doe_intr_status ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (sys_status_we), + .wd (sys_status_doe_intr_status_wd), + + // from internal hardware + .de (hw2reg.sys_status.doe_intr_status.de), + .d (hw2reg.sys_status.doe_intr_status.d), + + // to internal hardware + .qe (sys_status_flds_we[1]), + .q (reg2hw.sys_status.doe_intr_status.q), + .ds (), + + // to register interface (read) + .qs (sys_status_doe_intr_status_qs) + ); + assign reg2hw.sys_status.doe_intr_status.qe = sys_status_qe; + + // F[error]: 2:2 + prim_subreg #( + .DW (1), + .SwAccess(prim_subreg_pkg::SwAccessRO), + .RESVAL (1'h0), + .Mubi (1'b0) + ) u_sys_status_error ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (1'b0), + .wd ('0), + + // from internal hardware + .de (hw2reg.sys_status.error.de), + .d (hw2reg.sys_status.error.d), + + // to internal hardware + .qe (sys_status_flds_we[2]), + .q (reg2hw.sys_status.error.q), + .ds (), + + // to register interface (read) + .qs (sys_status_error_qs) + ); + + // F[async_msg_status]: 3:3 + prim_subreg #( + .DW (1), + .SwAccess(prim_subreg_pkg::SwAccessRO), + .RESVAL (1'h0), + .Mubi (1'b0) + ) u_sys_status_async_msg_status ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (1'b0), + .wd ('0), + + // from internal hardware + .de (hw2reg.sys_status.async_msg_status.de), + .d (hw2reg.sys_status.async_msg_status.d), + + // to internal hardware + .qe (sys_status_flds_we[3]), + .q (reg2hw.sys_status.async_msg_status.q), + .ds (), + + // to register interface (read) + .qs (sys_status_async_msg_status_qs) + ); + + // F[ready]: 31:31 + prim_subreg #( + .DW (1), + .SwAccess(prim_subreg_pkg::SwAccessRO), + .RESVAL (1'h0), + .Mubi (1'b0) + ) u_sys_status_ready ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (1'b0), + .wd ('0), + + // from internal hardware + .de (hw2reg.sys_status.ready.de), + .d (hw2reg.sys_status.ready.d), + + // to internal hardware + .qe (sys_status_flds_we[4]), + .q (reg2hw.sys_status.ready.q), + .ds (), + + // to register interface (read) + .qs (sys_status_ready_qs) + ); + + + + logic [3:0] addr_hit; + always_comb begin + addr_hit = '0; + addr_hit[0] = (reg_addr == MBX_EXTENDED_CAP_HEADER_OFFSET); + addr_hit[1] = (reg_addr == MBX_CAP_HEADER_OFFSET); + addr_hit[2] = (reg_addr == MBX_SYS_CONTROL_OFFSET); + addr_hit[3] = (reg_addr == MBX_SYS_STATUS_OFFSET); + end + + assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ; + + // Check sub-word write is permitted + always_comb begin + wr_err = (reg_we & + ((addr_hit[0] & (|(MBX_SYS_PERMIT[0] & ~reg_be))) | + (addr_hit[1] & (|(MBX_SYS_PERMIT[1] & ~reg_be))) | + (addr_hit[2] & (|(MBX_SYS_PERMIT[2] & ~reg_be))) | + (addr_hit[3] & (|(MBX_SYS_PERMIT[3] & ~reg_be))))); + end + + // Generate write-enables + assign extended_cap_header_re = addr_hit[0] & reg_re & !reg_error; + assign sys_control_re = addr_hit[2] & reg_re & !reg_error; + assign sys_control_we = addr_hit[2] & reg_we & !reg_error; + + assign sys_control_abort_wd = reg_wdata[0]; + + assign sys_control_doe_intr_en_wd = reg_wdata[1]; + + assign sys_control_async_msg_en_wd = reg_wdata[3]; + + assign sys_control_go_wd = reg_wdata[31]; + assign sys_status_we = addr_hit[3] & reg_we & !reg_error; + + assign sys_status_doe_intr_status_wd = reg_wdata[1]; + + // Assign write-enables to checker logic vector. + always_comb begin + reg_we_check = '0; + reg_we_check[0] = 1'b0; + reg_we_check[1] = 1'b0; + reg_we_check[2] = sys_control_we; + reg_we_check[3] = sys_status_we; + end + + // Read data return + always_comb begin + reg_rdata_next = '0; + unique case (1'b1) + addr_hit[0]: begin + reg_rdata_next[15:0] = extended_cap_header_cap_id_qs; + reg_rdata_next[19:16] = extended_cap_header_cap_version_qs; + reg_rdata_next[31:20] = extended_cap_header_next_capaility_offset_qs; + end + + addr_hit[1]: begin + reg_rdata_next[0] = cap_header_doe_intr_support_qs; + reg_rdata_next[11:1] = cap_header_doe_intr_msg_nr_qs; + end + + addr_hit[2]: begin + reg_rdata_next[0] = '0; + reg_rdata_next[1] = sys_control_doe_intr_en_qs; + reg_rdata_next[3] = sys_control_async_msg_en_qs; + reg_rdata_next[31] = '0; + end + + addr_hit[3]: begin + reg_rdata_next[0] = sys_status_busy_qs; + reg_rdata_next[1] = sys_status_doe_intr_status_qs; + reg_rdata_next[2] = sys_status_error_qs; + reg_rdata_next[3] = sys_status_async_msg_status_qs; + reg_rdata_next[31] = sys_status_ready_qs; + end + + default: begin + reg_rdata_next = '1; + end + endcase + end + + // shadow busy + logic shadow_busy; + assign shadow_busy = 1'b0; + + // register busy + assign reg_busy = shadow_busy; // Unused signal tieoff + + // wdata / byte enable are not always fully used + // add a blanket unused statement to handle lint waivers + logic unused_wdata; + logic unused_be; + assign unused_wdata = ^reg_wdata; + assign unused_be = ^reg_be; + + // Assertions for Register Interface + `ASSERT_PULSE(wePulse, reg_we, clk_i, !rst_ni) + `ASSERT_PULSE(rePulse, reg_re, clk_i, !rst_ni) + + `ASSERT(reAfterRv, $rose(reg_re || reg_we) |=> tl_o_pre.d_valid, clk_i, !rst_ni) + + `ASSERT(en2addrHit, (reg_we || reg_re) |-> $onehot0(addr_hit), clk_i, !rst_ni) + + // this is formulated as an assumption such that the FPV testbenches do disprove this + // property by mistake + //`ASSUME(reqParity, tl_reg_h2d.a_valid |-> tl_reg_h2d.a_user.chk_en == tlul_pkg::CheckDis) + endmodule diff --git a/hw/ip/mbx/rtl/mbx_sysif.sv b/hw/ip/mbx/rtl/mbx_sysif.sv new file mode 100644 index 0000000000000..24196251d1068 --- /dev/null +++ b/hw/ip/mbx/rtl/mbx_sysif.sv @@ -0,0 +1,231 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +module mbx_sysif + import tlul_pkg::*; +#( + parameter int unsigned CfgSramDataWidth = 32, + parameter int unsigned NextExtDoeOffset = 12'h800 +) ( + input logic clk_i, + input logic rst_ni, + // Device port to the system fabric + input tlul_pkg::tl_h2d_t tl_sys_i, + output tlul_pkg::tl_d2h_t tl_sys_o, + output logic intg_err_o, + // Access to the control register + output logic sysif_control_abort_set_o, + output logic sysif_control_doe_intr_en_o, + output logic sysif_control_async_msg_en_o, + output logic sysif_control_go_set_o, + // Access to the status register + input logic sysif_status_busy_valid_i, + input logic sysif_status_busy_i, + input logic sysif_status_doe_intr_status_set_i, + output logic sysif_status_doe_intr_status_o, + input logic sysif_status_error_set_i, + input logic sysif_status_error_clear_i, + output logic sysif_status_async_msg_status_o, + input logic sysif_status_async_msg_status_set_i, + input logic sysif_status_ready_valid_i, + input logic sysif_status_ready_i, + // Control lines for backpressuring the bus + input logic ibmbx_pending_i, + input logic obmbx_pending_i, + // Data interface for inbound and outbound mailbox + output logic write_data_write_valid_o, + output logic [CfgSramDataWidth-1:0] write_data_o, + input logic [CfgSramDataWidth-1:0] read_data_i, + output logic read_data_read_valid_o, + output logic read_data_write_valid_o +); + import mbx_reg_pkg::*; + + mbx_sys_reg2hw_t reg2hw; + mbx_sys_hw2reg_t hw2reg; + + // Interface for the custom register interface with bus blocking support + tlul_pkg::tl_h2d_t tl_win_h2d[2]; + tlul_pkg::tl_d2h_t tl_win_d2h[2]; + + // SEC_CM: BUS.INTEGRITY + mbx_sys_reg_top u_sys_regs ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .tl_i ( tl_sys_i ), + .tl_o ( tl_sys_o ), + .tl_win_o ( tl_win_h2d ), + .tl_win_i ( tl_win_d2h ), + .intg_err_o ( intg_err_o ), + .devmode_i ( 1'b1 ) + ); + + // Extended capability register + assign hw2reg.extended_cap_header.cap_id = 16'h002E; + assign hw2reg.extended_cap_header.cap_version = 4'h2; + assign hw2reg.extended_cap_header.next_capaility_offset = NextExtDoeOffset; + + // Capability header register + assign hw2reg.cap_header.doe_intr_support = 1'b1; + assign hw2reg.cap_header.doe_intr_msg_nr = '0; + + // Control register + assign sysif_control_abort_set_o = reg2hw.sys_control.abort.qe & reg2hw.sys_control.abort.q; + assign hw2reg.sys_control.go.de = 1'b1; + assign hw2reg.sys_control.go.d = 1'b0; + + assign sysif_control_go_set_o = reg2hw.sys_control.go.qe & reg2hw.sys_control.go.q; + assign hw2reg.sys_control.go.de = 1'b1; + assign hw2reg.sys_control.go.d = 1'b0; + + assign sysif_control_doe_intr_en_o = reg2hw.sys_control.doe_intr_en.q; + assign sysif_control_async_msg_en_o = reg2hw.sys_control.async_msg_en.q; + + // F[async_msg_en]: 3:3 + prim_subreg #( + .DW (1), + .SwAccess(prim_subreg_pkg::SwAccessRW), + .RESVAL (1'h0) + ) u_sys_control_async_msg_en ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (sys_control_we), + .wd (sys_control_async_msg_en_wd), + + // from internal hardware + .de (1'b0), + .d ('0), + + // to internal hardware + .qe (sys_control_flds_we[2]), + .q (reg2hw.sys_control.async_msg_en.q), + .ds (), + + // to register interface (read) + .qs (sys_control_async_msg_en_qs) + ); + + + + // Fiddle out status register bits for external write logic + assign sysif_status_async_msg_status_o = reg2hw.sys_status.async_msg_status.q; + assign sysif_status_doe_intr_status_o = reg2hw.sys_status.doe_intr_status.q; + + // External read logic + assign hw2reg.sys_status.busy.de = sysif_status_busy_valid_i; + assign hw2reg.sys_status.busy.d = sysif_status_busy_i; + + // Set by the Host firmware (w1s) + // Cleared by the Sys firmware (w1c) + assign hw2reg.sys_status.doe_intr_status.de = sysif_status_doe_intr_status_set_i; + assign hw2reg.sys_status.doe_intr_status.d = sysif_status_doe_intr_status_set_i; + + assign hw2reg.sys_status.error.de = sysif_status_error_set_i | sysif_status_error_clear_i; + assign hw2reg.sys_status.error.d = sysif_status_error_set_i; + + // Set by the Host firmware (w1s) + // Cleared by the Sys firmware (w1c) + assign hw2reg.sys_status.async_msg_status.de = sysif_status_async_msg_status_set_i; + assign hw2reg.sys_status.async_msg_status.d = sysif_status_async_msg_status_set_i; + assign hw2reg.sys_status.ready.de = sysif_status_ready_valid_i; + assign hw2reg.sys_status.ready.d = sysif_status_ready_i; + + // Dedicated TLUL adapter for implementing the write data mailbox register via a register window. + // We use the register window to access the internal bus signals, allowing the mailbox to halt + // the bus if there are too many outstanding requests. + logic reg_wdata_we; + logic [top_pkg::TL_DW-1:0] reg_wdata_wdata, reg_wdata_rdata; + tlul_adapter_reg #( + .RegAw ( SysAw ), + .RegDw ( top_pkg::TL_DW ), + .EnableDataIntgGen ( 0 ) + ) u_wdata_reg_if ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .tl_i ( tl_win_h2d[MBX_WDATA_IDX] ), + .tl_o ( tl_win_d2h[MBX_WDATA_IDX] ), + .en_ifetch_i ( prim_mubi_pkg::MuBi4False ), + .intg_error_o ( ), + .we_o ( reg_wdata_we ), + // No Reading of the write register. Always reads zero + .re_o ( ), + .addr_o ( ), + .wdata_o ( reg_wdata_wdata ), + .be_o ( ), + .busy_i ( obmbx_pending_i ), + .rdata_i ( '0 ), + .error_i ( 1'b0 ) + ); + + // Dedicated TLUL adapter for implementing the read data mailbox register via a register window. + // We use the register window to access the internal bus signals, allowing the mailbox to halt + // the bus if there are too many outstanding requests. The register is immplemented as hwext + // outside of this hierarchy + tlul_adapter_reg #( + .RegAw ( SysAw ), + .RegDw ( top_pkg::TL_DW ), + .EnableDataIntgGen ( 0 ) + ) u_rdata_reg_if ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .tl_i ( tl_win_h2d[MBX_RDATA_IDX] ), + .tl_o ( tl_win_d2h[MBX_RDATA_IDX] ), + .en_ifetch_i ( prim_mubi_pkg::MuBi4False ), + .intg_error_o ( ), + // No writing to the read register + .we_o ( read_data_write_valid_o ), + .re_o ( read_data_read_valid_o ), + .addr_o ( ), + // Write values are ignored. A Write simply means the read has occured. + .wdata_o ( ), + .be_o ( ), + .busy_i ( ibmbx_pending_i ), + .rdata_i ( read_data_i ), + .error_i ( 1'b0 ) + ); + + // Manual implementation of the write read mailbox register. + // The manual implementation of the register via a register window is needed to expose the + // internal register interface of the TLUL bus to halt the bus if there too many outstanding + // requests. + logic mbx_wrdata_flds_we; + prim_flop #( + .Width(1), + .ResetValue(0) + ) u_mbxwrdat0_qe ( + .clk_i(clk_i), + .rst_ni(rst_ni), + .d_i(mbx_wrdata_flds_we), + .q_o(write_data_write_valid_o) + ); + prim_subreg #( + .DW (CfgSramDataWidth), + .SwAccess(prim_subreg_pkg::SwAccessWO), + .RESVAL (32'h0) + ) u_reg_wrdata ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (reg_wdata_we), + .wd (reg_wdata_wdata), + + // from internal hardware + .de (1'b0), + .d ('0), + + // to internal hardware + .qe (mbx_wrdata_flds_we), + .q (write_data_o), + .ds (), + + // to register interface (read) + .qs () + ); + + // Assertions + `ASSERT(DataWidthCheck_A, CfgSramDataWidth == top_pkg::TL_DW) +endmodule From 8b28952579c5397042390c23327a464919b0af7f Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Mon, 28 Aug 2023 09:20:22 -0700 Subject: [PATCH 06/88] [hw,mbx,rtl] External control register Signed-off-by: Robert Schilling --- hw/ip/mbx/data/mbx.hjson | 4 ++- hw/ip/mbx/rtl/mbx_sysif.sv | 55 +++++++++++++++++++++++--------------- 2 files changed, 37 insertions(+), 22 deletions(-) diff --git a/hw/ip/mbx/data/mbx.hjson b/hw/ip/mbx/data/mbx.hjson index 12cc8850441f0..3963cde2d5783 100644 --- a/hw/ip/mbx/data/mbx.hjson +++ b/hw/ip/mbx/data/mbx.hjson @@ -274,9 +274,10 @@ } { name: "sys_control" desc: "DOE mailbox control register." - hwext: "true" + hwext: "false" hwaccess: "hrw" hwqe: "true" + hwext: "true" fields: [ { name: "abort" @@ -303,6 +304,7 @@ resval: "0x0" swaccess: "rw" + } { name: "go" desc: ''' diff --git a/hw/ip/mbx/rtl/mbx_sysif.sv b/hw/ip/mbx/rtl/mbx_sysif.sv index 24196251d1068..e7f1ed4384ebe 100644 --- a/hw/ip/mbx/rtl/mbx_sysif.sv +++ b/hw/ip/mbx/rtl/mbx_sysif.sv @@ -72,17 +72,37 @@ module mbx_sysif // Control register assign sysif_control_abort_set_o = reg2hw.sys_control.abort.qe & reg2hw.sys_control.abort.q; - assign hw2reg.sys_control.go.de = 1'b1; - assign hw2reg.sys_control.go.d = 1'b0; + assign hw2reg.sys_control.abort.d = 1'b0; assign sysif_control_go_set_o = reg2hw.sys_control.go.qe & reg2hw.sys_control.go.q; - assign hw2reg.sys_control.go.de = 1'b1; assign hw2reg.sys_control.go.d = 1'b0; - assign sysif_control_doe_intr_en_o = reg2hw.sys_control.doe_intr_en.q; - assign sysif_control_async_msg_en_o = reg2hw.sys_control.async_msg_en.q; + // Manual implementation of the doe_intr_en bit + // SWAccess: RW + // HWAccess: RO + prim_subreg #( + .DW (1), + .SwAccess(prim_subreg_pkg::SwAccessRW), + .RESVAL (1'h0) + ) u_sys_control_doe_intr_en ( + .clk_i (clk_i), + .rst_ni (rst_ni), + // from register interface + .we (reg2hw.sys_control.doe_intr_en.qe), + .wd (reg2hw.sys_control.doe_intr_en.q), + // HWAccess: hro + .de (1'b0), + .d (1'b0), + // to internal hardware + .qe (), + .q (doe_intr_en_o), + .ds (hw2reg.sys_control.doe_intr_en.d), + .qs () + ); - // F[async_msg_en]: 3:3 + // Manual implementation of the async_msg_en bit + // SWAccess: RW + // HWAccess: RO prim_subreg #( .DW (1), .SwAccess(prim_subreg_pkg::SwAccessRW), @@ -90,26 +110,19 @@ module mbx_sysif ) u_sys_control_async_msg_en ( .clk_i (clk_i), .rst_ni (rst_ni), - // from register interface - .we (sys_control_we), - .wd (sys_control_async_msg_en_wd), - - // from internal hardware + .we (reg2hw.sys_control.async_msg_en.qe), + .wd (reg2hw.sys_control.async_msg_en.q), + // HWAccess: hro .de (1'b0), - .d ('0), - + .d (1'b0), // to internal hardware - .qe (sys_control_flds_we[2]), - .q (reg2hw.sys_control.async_msg_en.q), - .ds (), - - // to register interface (read) - .qs (sys_control_async_msg_en_qs) + .qe (), + .q (sysif_control_async_msg_en_o), + .ds (hw2reg.sys_control.async_msg_en.d), + .qs () ); - - // Fiddle out status register bits for external write logic assign sysif_status_async_msg_status_o = reg2hw.sys_status.async_msg_status.q; assign sysif_status_doe_intr_status_o = reg2hw.sys_status.doe_intr_status.q; From d7b3d4c4f8bb1281a27d5250fe3eaaf82dc91079 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Mon, 28 Aug 2023 12:53:58 -0700 Subject: [PATCH 07/88] [hw,mbx,rtl] Implement DOE IRQ support Signed-off-by: Robert Schilling --- hw/ip/mbx/data/mbx.hjson | 41 ++++++++++++++++- hw/ip/mbx/rtl/mbx.sv | 26 +++++++---- hw/ip/mbx/rtl/mbx_host_reg_top.sv | 73 ++++++++++++++++++++++++------- hw/ip/mbx/rtl/mbx_hostif.sv | 17 ++++--- hw/ip/mbx/rtl/mbx_reg_pkg.sv | 46 +++++++++++++------ hw/ip/mbx/rtl/mbx_sysif.sv | 12 ++++- 6 files changed, 170 insertions(+), 45 deletions(-) diff --git a/hw/ip/mbx/data/mbx.hjson b/hw/ip/mbx/data/mbx.hjson index 3963cde2d5783..3b8e6dc79a37d 100644 --- a/hw/ip/mbx/data/mbx.hjson +++ b/hw/ip/mbx/data/mbx.hjson @@ -23,6 +23,29 @@ { protocol: "tlul", direction: "host", name: "sram" } { protocol: "tlul", direction: "device", name: "sys" } ] + inter_signal_list: [ + { struct: "logic", + type: "uni", + name: "doe_intr_support", + act: "req", + package: "", + default: "1'b0" + } + { struct: "logic", + type: "uni", + name: "doe_intr_en", + act: "req", + package: "", + default: "1'b0" + } + { struct: "logic", + type: "uni", + name: "doe_intr", + act: "req", + package: "", + default: "1'b0" + } + ] interrupt_list: [ { name: "mbx_ready" desc: "A new object was received in the inbound mailbox." @@ -52,6 +75,14 @@ hwaccess: "hrw" hwqe: "true" } + { name: "doe_intr_en" + desc: "Alias of the DoE mailbox interrupt enable bit" + bits: "1" + resval: "0x0" + swaccess: "rw" + hwaccess: "hrw" + hwqe: "true" + } ] hwext: "true" } @@ -66,6 +97,14 @@ hwaccess: "hrw" hwqe: "true" } + { name: "doe_intr_status" + desc: "Alias of the DoE mailbox interrupt status bit" + bits: "1" + resval: "0x0" + swaccess: "rw" + hwaccess: "hrw" + hwqe: "true" + } { name: "error" desc: "Alias of the DoE mailbox error bit" bits: "2" @@ -303,8 +342,6 @@ bits: "3" resval: "0x0" swaccess: "rw" - - } { name: "go" desc: ''' diff --git a/hw/ip/mbx/rtl/mbx.sv b/hw/ip/mbx/rtl/mbx.sv index 62ff59f915248..45c0f6b68190a 100644 --- a/hw/ip/mbx/rtl/mbx.sv +++ b/hw/ip/mbx/rtl/mbx.sv @@ -11,11 +11,18 @@ module mbx parameter logic [NumAlerts-1:0] AlertAsyncOn = {NumAlerts{1'b1}}, parameter int unsigned CfgSramAddrWidth = 32, parameter int unsigned CfgSramDataWidth = 32, - parameter int unsigned NextExtDoeOffset = 12'h800 + parameter int unsigned NextExtDoeOffset = 12'h800, + // PCIe capabilities + parameter bit DoeIrqSupport = 1'b1 ) ( input logic clk_i, input logic rst_ni, + // Comportable interrupt to the OT output logic intr_mbx_ready_o, + // Custom interrupt to the system requester + output logic doe_intr_support_o, + output logic doe_intr_en_o, + output logic doe_intr_o, // Alerts input prim_alert_pkg::alert_rx_t [NumAlerts-1:0] alert_rx_i, output prim_alert_pkg::alert_tx_t [NumAlerts-1:0] alert_tx_o, @@ -34,7 +41,7 @@ module mbx // External write signals for control and status register logic hostif_control_abort_set; - logic hostif_status_busy_clear, hostif_status_irq_status_set; + logic hostif_status_busy_clear; logic hostif_status_error_set, hostif_status_error_clear; logic hostif_status_async_msg_status_set; // External read signals for control and status register @@ -75,11 +82,12 @@ module mbx .hostif_control_abort_set_o ( hostif_control_abort_set ), // Access to the status register .hostif_status_busy_clear_o ( hostif_status_busy_clear ), - .hostif_status_irq_status_set_o ( hostif_status_irq_status_set ), + .hostif_status_doe_intr_status_set_o ( sysif_status_doe_intr_status_set ), .hostif_status_error_set_o ( hostif_status_error_set ), .hostif_status_error_clear_o ( hostif_status_error_clear ), .hostif_status_async_msg_status_set_o( hostif_status_async_msg_status_set ), .hostif_status_busy_i ( hostif_status_busy ), + .hostif_status_doe_intr_status_i ( sysif_status_doe_intr_status ), .hostif_status_error_i ( hostif_status_error ), .hostif_status_async_msg_status_i ( hostif_status_async_msg_status ), .hostif_status_ready_i ( hostif_status_ready ), @@ -105,9 +113,7 @@ module mbx logic ibmbx_status_busy_valid, ibmbx_status_busy; logic obmbx_status_ready_valid, obmbx_status_ready; - - logic sysif_control_go_set, sysif_control_abort_set; - logic sysif_control_doe_intr_en, sysif_control_async_msg_en; + logic sysif_control_go_set, sysif_control_abort_set, sysif_control_async_msg_en; logic sysif_status_intr_support, sysif_status_intr_en; logic sysif_status_async_msg_status_set, sysif_status_async_msg_status; @@ -118,16 +124,20 @@ module mbx mbx_sysif #( .CfgSramDataWidth ( CfgSramDataWidth ), - .NextExtDoeOffset ( NextExtDoeOffset ) + .NextExtDoeOffset ( NextExtDoeOffset ), + .DoeIrqSupport ( DoeIrqSupport ) ) u_sysif ( .clk_i ( clk_i ), .rst_ni ( rst_ni ), .tl_sys_i ( tl_sys_i ), .tl_sys_o ( tl_sys_o ), .intg_err_o ( sysif_intg_err ), + // System interrupt support + .doe_intr_support_o ( doe_intr_support_o ), + .doe_intr_en_o ( doe_intr_en_o ), + .doe_intr_o ( doe_intr_o ), // Access to the control register .sysif_control_abort_set_o ( sysif_control_abort_set ), - .sysif_control_doe_intr_en_o ( sysif_control_doe_intr_en), .sysif_control_async_msg_en_o ( sysif_control_async_msg_en), .sysif_control_go_set_o ( sysif_control_go_set ), // Access to the status register diff --git a/hw/ip/mbx/rtl/mbx_host_reg_top.sv b/hw/ip/mbx/rtl/mbx_host_reg_top.sv index 202160cf24748..d669b29e1cb0b 100644 --- a/hw/ip/mbx/rtl/mbx_host_reg_top.sv +++ b/hw/ip/mbx/rtl/mbx_host_reg_top.sv @@ -133,12 +133,16 @@ module mbx_host_reg_top ( logic alert_test_wd; logic control_re; logic control_we; - logic control_qs; - logic control_wd; + logic control_abort_qs; + logic control_abort_wd; + logic control_doe_intr_en_qs; + logic control_doe_intr_en_wd; logic status_re; logic status_we; logic status_busy_qs; logic status_busy_wd; + logic status_doe_intr_status_qs; + logic status_doe_intr_status_wd; logic status_error_qs; logic status_error_wd; logic status_async_msg_status_qs; @@ -270,27 +274,44 @@ module mbx_host_reg_top ( // R[control]: V(True) logic control_qe; - logic [0:0] control_flds_we; + logic [1:0] control_flds_we; assign control_qe = &control_flds_we; + // F[abort]: 0:0 prim_subreg_ext #( .DW (1) - ) u_control ( + ) u_control_abort ( .re (control_re), .we (control_we), - .wd (control_wd), - .d (hw2reg.control.d), + .wd (control_abort_wd), + .d (hw2reg.control.abort.d), .qre (), .qe (control_flds_we[0]), - .q (reg2hw.control.q), + .q (reg2hw.control.abort.q), .ds (), - .qs (control_qs) + .qs (control_abort_qs) ); - assign reg2hw.control.qe = control_qe; + assign reg2hw.control.abort.qe = control_qe; + + // F[doe_intr_en]: 1:1 + prim_subreg_ext #( + .DW (1) + ) u_control_doe_intr_en ( + .re (control_re), + .we (control_we), + .wd (control_doe_intr_en_wd), + .d (hw2reg.control.doe_intr_en.d), + .qre (), + .qe (control_flds_we[1]), + .q (reg2hw.control.doe_intr_en.q), + .ds (), + .qs (control_doe_intr_en_qs) + ); + assign reg2hw.control.doe_intr_en.qe = control_qe; // R[status]: V(True) logic status_qe; - logic [3:0] status_flds_we; + logic [4:0] status_flds_we; assign status_qe = &status_flds_we; // F[busy]: 0:0 prim_subreg_ext #( @@ -308,6 +329,22 @@ module mbx_host_reg_top ( ); assign reg2hw.status.busy.qe = status_qe; + // F[doe_intr_status]: 1:1 + prim_subreg_ext #( + .DW (1) + ) u_status_doe_intr_status ( + .re (status_re), + .we (status_we), + .wd (status_doe_intr_status_wd), + .d (hw2reg.status.doe_intr_status.d), + .qre (), + .qe (status_flds_we[1]), + .q (reg2hw.status.doe_intr_status.q), + .ds (), + .qs (status_doe_intr_status_qs) + ); + assign reg2hw.status.doe_intr_status.qe = status_qe; + // F[error]: 2:2 prim_subreg_ext #( .DW (1) @@ -317,7 +354,7 @@ module mbx_host_reg_top ( .wd (status_error_wd), .d (hw2reg.status.error.d), .qre (), - .qe (status_flds_we[1]), + .qe (status_flds_we[2]), .q (reg2hw.status.error.q), .ds (), .qs (status_error_qs) @@ -333,7 +370,7 @@ module mbx_host_reg_top ( .wd (status_async_msg_status_wd), .d (hw2reg.status.async_msg_status.d), .qre (), - .qe (status_flds_we[2]), + .qe (status_flds_we[3]), .q (reg2hw.status.async_msg_status.q), .ds (), .qs (status_async_msg_status_qs) @@ -349,7 +386,7 @@ module mbx_host_reg_top ( .wd (status_ready_wd), .d (hw2reg.status.ready.d), .qre (), - .qe (status_flds_we[3]), + .qe (status_flds_we[4]), .q (reg2hw.status.ready.q), .ds (), .qs (status_ready_qs) @@ -726,12 +763,16 @@ module mbx_host_reg_top ( assign control_re = addr_hit[4] & reg_re & !reg_error; assign control_we = addr_hit[4] & reg_we & !reg_error; - assign control_wd = reg_wdata[0]; + assign control_abort_wd = reg_wdata[0]; + + assign control_doe_intr_en_wd = reg_wdata[1]; assign status_re = addr_hit[5] & reg_re & !reg_error; assign status_we = addr_hit[5] & reg_we & !reg_error; assign status_busy_wd = reg_wdata[0]; + assign status_doe_intr_status_wd = reg_wdata[1]; + assign status_error_wd = reg_wdata[2]; assign status_async_msg_status_wd = reg_wdata[3]; @@ -802,11 +843,13 @@ module mbx_host_reg_top ( end addr_hit[4]: begin - reg_rdata_next[0] = control_qs; + reg_rdata_next[0] = control_abort_qs; + reg_rdata_next[1] = control_doe_intr_en_qs; end addr_hit[5]: begin reg_rdata_next[0] = status_busy_qs; + reg_rdata_next[1] = status_doe_intr_status_qs; reg_rdata_next[2] = status_error_qs; reg_rdata_next[3] = status_async_msg_status_qs; reg_rdata_next[31] = status_ready_qs; diff --git a/hw/ip/mbx/rtl/mbx_hostif.sv b/hw/ip/mbx/rtl/mbx_hostif.sv index fff58ef2f4316..6ef66ef7e755f 100644 --- a/hw/ip/mbx/rtl/mbx_hostif.sv +++ b/hw/ip/mbx/rtl/mbx_hostif.sv @@ -16,17 +16,21 @@ module mbx_hostif // Generated interrupt event input logic event_intr_i, output logic irq_o, + // External errors + input logic intg_err_i, // Alerts input prim_alert_pkg::alert_rx_t [NumAlerts-1:0] alert_rx_i, output prim_alert_pkg::alert_tx_t [NumAlerts-1:0] alert_tx_o, // Access to the control register - output logic hostif_control_set_abort_o, + output logic hostif_control_abort_set_o, // Access to the status register output logic hostif_status_busy_clear_o, + output logic hostif_status_doe_intr_status_set_o, output logic hostif_status_error_set_o, output logic hostif_status_error_clear_o, output logic hostif_status_async_msg_status_set_o, input logic hostif_status_busy_i, + input logic hostif_status_doe_intr_status_i, input logic hostif_status_error_i, input logic hostif_status_async_msg_status_i, input logic hostif_status_ready_i, @@ -54,7 +58,7 @@ module mbx_hostif logic tlul_intg_err; logic [NumAlerts-1:0] alert_test, alerts; assign alert_test = {reg2hw.alert_test.q & reg2hw.alert_test.qe}; - assign alerts[0] = tlul_intg_err; + assign alerts[0] = tlul_intg_err | intg_err_i; for (genvar i = 0; i < NumAlerts; i++) begin : gen_alert_tx prim_alert_sender #( @@ -101,9 +105,9 @@ module mbx_hostif // Control Register // External read logic logic abort_d, abort_q; - assign hw2reg.control.d = abort_q; + assign hw2reg.control.abort.d = abort_q; // External write logic - assign hostif_control_set_abort_o = reg2hw.control.qe & tl_host_i.a_data[0]; + assign hostif_control_abort_set_o = reg2hw.control.abort.qe & reg2hw.control.abort.q; // Abort computation from system and host interface always_comb begin @@ -111,7 +115,7 @@ module mbx_hostif if (sysif_write_control_abort_i) begin abort_d = 1'b1; - end else if (hostif_control_set_abort_o) begin + end else if (hostif_control_abort_set_o) begin abort_d = 1'b0; end end @@ -131,11 +135,14 @@ module mbx_hostif // External read logic assign hw2reg.status.busy.d = hostif_status_busy_i; + assign hw2reg.status.doe_intr_status.d = hostif_status_doe_intr_status_i; assign hw2reg.status.error.d = hostif_status_error_i; assign hw2reg.status.async_msg_status.d = hostif_status_async_msg_status_i; assign hw2reg.status.ready.d = hostif_status_ready_i; // External write logic assign hostif_status_busy_clear_o = reg2hw.status.busy.qe & ~reg2hw.status.busy.q; + assign hostif_status_doe_intr_status_set_o = reg2hw.status.doe_intr_status.qe & + reg2hw.status.doe_intr_status.q; assign hostif_status_error_set_o = reg2hw.status.error.qe & reg2hw.status.error.q; assign hostif_status_error_clear_o = reg2hw.status.error.qe & ~reg2hw.status.error.q; assign hostif_status_async_msg_status_set_o = diff --git a/hw/ip/mbx/rtl/mbx_reg_pkg.sv b/hw/ip/mbx/rtl/mbx_reg_pkg.sv index c148f3a10451c..413fc1bf8dbab 100644 --- a/hw/ip/mbx/rtl/mbx_reg_pkg.sv +++ b/hw/ip/mbx/rtl/mbx_reg_pkg.sv @@ -36,8 +36,14 @@ package mbx_reg_pkg; } mbx_reg2hw_alert_test_reg_t; typedef struct packed { - logic q; - logic qe; + struct packed { + logic q; + logic qe; + } doe_intr_en; + struct packed { + logic q; + logic qe; + } abort; } mbx_reg2hw_control_reg_t; typedef struct packed { @@ -53,6 +59,10 @@ package mbx_reg_pkg; logic q; logic qe; } error; + struct packed { + logic q; + logic qe; + } doe_intr_status; struct packed { logic q; logic qe; @@ -108,13 +118,21 @@ package mbx_reg_pkg; } mbx_hw2reg_intr_state_reg_t; typedef struct packed { - logic d; + struct packed { + logic d; + } abort; + struct packed { + logic d; + } doe_intr_en; } mbx_hw2reg_control_reg_t; typedef struct packed { struct packed { logic d; } busy; + struct packed { + logic d; + } doe_intr_status; struct packed { logic d; } error; @@ -141,12 +159,12 @@ package mbx_reg_pkg; // Register -> HW type for host interface typedef struct packed { - mbx_reg2hw_intr_state_reg_t intr_state; // [215:215] - mbx_reg2hw_intr_enable_reg_t intr_enable; // [214:214] - mbx_reg2hw_intr_test_reg_t intr_test; // [213:212] - mbx_reg2hw_alert_test_reg_t alert_test; // [211:210] - mbx_reg2hw_control_reg_t control; // [209:208] - mbx_reg2hw_status_reg_t status; // [207:200] + mbx_reg2hw_intr_state_reg_t intr_state; // [219:219] + mbx_reg2hw_intr_enable_reg_t intr_enable; // [218:218] + mbx_reg2hw_intr_test_reg_t intr_test; // [217:216] + mbx_reg2hw_alert_test_reg_t alert_test; // [215:214] + mbx_reg2hw_control_reg_t control; // [213:210] + mbx_reg2hw_status_reg_t status; // [209:200] mbx_reg2hw_address_range_regwen_reg_t address_range_regwen; // [199:199] mbx_reg2hw_address_range_valid_reg_t address_range_valid; // [198:198] mbx_reg2hw_inbound_base_address_reg_t inbound_base_address; // [197:167] @@ -160,9 +178,9 @@ package mbx_reg_pkg; // HW -> register type for host interface typedef struct packed { - mbx_hw2reg_intr_state_reg_t intr_state; // [78:77] - mbx_hw2reg_control_reg_t control; // [76:76] - mbx_hw2reg_status_reg_t status; // [75:72] + mbx_hw2reg_intr_state_reg_t intr_state; // [80:79] + mbx_hw2reg_control_reg_t control; // [78:77] + mbx_hw2reg_status_reg_t status; // [76:72] mbx_hw2reg_inbound_write_ptr_reg_t inbound_write_ptr; // [71:42] mbx_hw2reg_outbound_read_ptr_reg_t outbound_read_ptr; // [41:12] mbx_hw2reg_outbound_object_size_reg_t outbound_object_size; // [11:0] @@ -190,10 +208,12 @@ package mbx_reg_pkg; parameter logic [0:0] MBX_INTR_TEST_MBX_READY_RESVAL = 1'h 0; parameter logic [0:0] MBX_ALERT_TEST_RESVAL = 1'h 0; parameter logic [0:0] MBX_ALERT_TEST_FATAL_FAULT_RESVAL = 1'h 0; - parameter logic [0:0] MBX_CONTROL_RESVAL = 1'h 0; + parameter logic [1:0] MBX_CONTROL_RESVAL = 2'h 0; parameter logic [0:0] MBX_CONTROL_ABORT_RESVAL = 1'h 0; + parameter logic [0:0] MBX_CONTROL_DOE_INTR_EN_RESVAL = 1'h 0; parameter logic [31:0] MBX_STATUS_RESVAL = 32'h 1; parameter logic [0:0] MBX_STATUS_BUSY_RESVAL = 1'h 1; + parameter logic [0:0] MBX_STATUS_DOE_INTR_STATUS_RESVAL = 1'h 0; parameter logic [0:0] MBX_STATUS_ERROR_RESVAL = 1'h 0; parameter logic [0:0] MBX_STATUS_ASYNC_MSG_STATUS_RESVAL = 1'h 0; parameter logic [0:0] MBX_STATUS_READY_RESVAL = 1'h 0; diff --git a/hw/ip/mbx/rtl/mbx_sysif.sv b/hw/ip/mbx/rtl/mbx_sysif.sv index e7f1ed4384ebe..0b4a4fb94e6ac 100644 --- a/hw/ip/mbx/rtl/mbx_sysif.sv +++ b/hw/ip/mbx/rtl/mbx_sysif.sv @@ -6,7 +6,8 @@ module mbx_sysif import tlul_pkg::*; #( parameter int unsigned CfgSramDataWidth = 32, - parameter int unsigned NextExtDoeOffset = 12'h800 + parameter int unsigned NextExtDoeOffset = 12'h800, + parameter bit DoeIrqSupport = 1'b1 ) ( input logic clk_i, input logic rst_ni, @@ -14,9 +15,12 @@ module mbx_sysif input tlul_pkg::tl_h2d_t tl_sys_i, output tlul_pkg::tl_d2h_t tl_sys_o, output logic intg_err_o, + // Custom interrupt to the system requester + output logic doe_intr_support_o, + output logic doe_intr_en_o, + output logic doe_intr_o, // Access to the control register output logic sysif_control_abort_set_o, - output logic sysif_control_doe_intr_en_o, output logic sysif_control_async_msg_en_o, output logic sysif_control_go_set_o, // Access to the status register @@ -61,6 +65,10 @@ module mbx_sysif .devmode_i ( 1'b1 ) ); + // Interrupt support + assign doe_intr_support_o = DoeIrqSupport; + assign doe_intr_o = reg2hw.sys_status.doe_intr_status.q; + // Extended capability register assign hw2reg.extended_cap_header.cap_id = 16'h002E; assign hw2reg.extended_cap_header.cap_version = 4'h2; From b531818fa44c2687aee0c03d74951d6936d5acb1 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Mon, 28 Aug 2023 15:03:02 -0700 Subject: [PATCH 08/88] [hw,mbx,rtl] FW2FW IRQ registers Signed-off-by: Robert Schilling --- hw/ip/mbx/data/mbx.hjson | 59 +++++------- hw/ip/mbx/rtl/mbx.sv | 5 +- hw/ip/mbx/rtl/mbx_reg_pkg.sv | 68 +++----------- hw/ip/mbx/rtl/mbx_sys_reg_top.sv | 153 +++++++++++++------------------ hw/ip/mbx/rtl/mbx_sysif.sv | 16 +--- 5 files changed, 109 insertions(+), 192 deletions(-) diff --git a/hw/ip/mbx/data/mbx.hjson b/hw/ip/mbx/data/mbx.hjson index 3b8e6dc79a37d..dfa93d73485bc 100644 --- a/hw/ip/mbx/data/mbx.hjson +++ b/hw/ip/mbx/data/mbx.hjson @@ -270,48 +270,39 @@ } ] sys: [ - { name: "extended_cap_header" - desc: "" - swaccess: "ro" - hwaccess: "hrw" + { name: "DOE_INTR_MSG_ADDR" + desc: ''' + Utilized by the mailbox responder to send an interrupt message to the requester via a write to the configured address. + Defined only for FW-to-FW mailboxes. + ''' fields: [ - { name: "cap_id" - desc: "" - bits: "15:0" - resval: "0x002E" - } - { name: "cap_version" - desc: "" - bits: "19:16" - resval: "0x2" - - } - { name: "next_capaility_offset" - desc: "" - bits: "31:20" - resval: "0" + { name: "doe_intr_msg_addr" + desc: "Utilized by the mailbox responder to send an interrupt message to the requester via a write to the configured address." + bits: "31:0" + resval: "0x0" + swaccess: "rw" + hwaccess: "hro" + hwqe: "true" } ] - hwext: "true" } - { name: "cap_header" - desc: "" - swaccess: "ro" - hwaccess: "hrw" + { name: "DOE_INTR_MSG_DATA" + desc: ''' + Interrupt message data to be sent to the address configured in the DOE_INTR_MSG_ADDR register. + Defined only for FW-to-FW mailboxes. + ''' fields: [ - { name: "doe_intr_support" - desc: "" - bits: "0" - } - { name: "doe_intr_msg_nr" - desc: "" - bits: "11:1" - resval: "0x2" - + { name: "doe_intr_msg_data" + desc: "Interrupt message data to be sent to the address configured in the DOE_INTR_MSG_ADDR register." + bits: "31:0" + resval: "0x0" + swaccess: "rw" + hwaccess: "hro" + hwqe: "true" } ] } - { name: "sys_control" + { name: "SYS_CONTROL" desc: "DOE mailbox control register." hwext: "false" hwaccess: "hrw" diff --git a/hw/ip/mbx/rtl/mbx.sv b/hw/ip/mbx/rtl/mbx.sv index 45c0f6b68190a..50033770dd934 100644 --- a/hw/ip/mbx/rtl/mbx.sv +++ b/hw/ip/mbx/rtl/mbx.sv @@ -11,9 +11,7 @@ module mbx parameter logic [NumAlerts-1:0] AlertAsyncOn = {NumAlerts{1'b1}}, parameter int unsigned CfgSramAddrWidth = 32, parameter int unsigned CfgSramDataWidth = 32, - parameter int unsigned NextExtDoeOffset = 12'h800, - // PCIe capabilities - parameter bit DoeIrqSupport = 1'b1 + parameter bit DoeIrqSupport = 1'b1 ) ( input logic clk_i, input logic rst_ni, @@ -124,7 +122,6 @@ module mbx mbx_sysif #( .CfgSramDataWidth ( CfgSramDataWidth ), - .NextExtDoeOffset ( NextExtDoeOffset ), .DoeIrqSupport ( DoeIrqSupport ) ) u_sysif ( .clk_i ( clk_i ), diff --git a/hw/ip/mbx/rtl/mbx_reg_pkg.sv b/hw/ip/mbx/rtl/mbx_reg_pkg.sv index 413fc1bf8dbab..c9199471e5cdd 100644 --- a/hw/ip/mbx/rtl/mbx_reg_pkg.sv +++ b/hw/ip/mbx/rtl/mbx_reg_pkg.sv @@ -265,25 +265,14 @@ package mbx_reg_pkg; ////////////////////////////////////////////// typedef struct packed { - struct packed { - logic [11:0] q; - } next_capaility_offset; - struct packed { - logic [3:0] q; - } cap_version; - struct packed { - logic [15:0] q; - } cap_id; - } mbx_reg2hw_extended_cap_header_reg_t; + logic [31:0] q; + logic qe; + } mbx_reg2hw_doe_intr_msg_addr_reg_t; typedef struct packed { - struct packed { - logic [10:0] q; - } doe_intr_msg_nr; - struct packed { - logic q; - } doe_intr_support; - } mbx_reg2hw_cap_header_reg_t; + logic [31:0] q; + logic qe; + } mbx_reg2hw_doe_intr_msg_data_reg_t; typedef struct packed { struct packed { @@ -323,29 +312,6 @@ package mbx_reg_pkg; } busy; } mbx_reg2hw_sys_status_reg_t; - typedef struct packed { - struct packed { - logic [15:0] d; - } cap_id; - struct packed { - logic [3:0] d; - } cap_version; - struct packed { - logic [11:0] d; - } next_capaility_offset; - } mbx_hw2reg_extended_cap_header_reg_t; - - typedef struct packed { - struct packed { - logic d; - logic de; - } doe_intr_support; - struct packed { - logic [10:0] d; - logic de; - } doe_intr_msg_nr; - } mbx_hw2reg_cap_header_reg_t; - typedef struct packed { struct packed { logic d; @@ -386,31 +352,25 @@ package mbx_reg_pkg; // Register -> HW type for sys interface typedef struct packed { - mbx_reg2hw_extended_cap_header_reg_t extended_cap_header; // [57:26] - mbx_reg2hw_cap_header_reg_t cap_header; // [25:14] + mbx_reg2hw_doe_intr_msg_addr_reg_t doe_intr_msg_addr; // [79:47] + mbx_reg2hw_doe_intr_msg_data_reg_t doe_intr_msg_data; // [46:14] mbx_reg2hw_sys_control_reg_t sys_control; // [13:6] mbx_reg2hw_sys_status_reg_t sys_status; // [5:0] } mbx_sys_reg2hw_t; // HW -> register type for sys interface typedef struct packed { - mbx_hw2reg_extended_cap_header_reg_t extended_cap_header; // [59:28] - mbx_hw2reg_cap_header_reg_t cap_header; // [27:14] mbx_hw2reg_sys_control_reg_t sys_control; // [13:10] mbx_hw2reg_sys_status_reg_t sys_status; // [9:0] } mbx_sys_hw2reg_t; // Register offsets for sys interface - parameter logic [SysAw-1:0] MBX_EXTENDED_CAP_HEADER_OFFSET = 5'h 0; - parameter logic [SysAw-1:0] MBX_CAP_HEADER_OFFSET = 5'h 4; + parameter logic [SysAw-1:0] MBX_DOE_INTR_MSG_ADDR_OFFSET = 5'h 0; + parameter logic [SysAw-1:0] MBX_DOE_INTR_MSG_DATA_OFFSET = 5'h 4; parameter logic [SysAw-1:0] MBX_SYS_CONTROL_OFFSET = 5'h 8; parameter logic [SysAw-1:0] MBX_SYS_STATUS_OFFSET = 5'h c; // Reset values for hwext registers and their fields for sys interface - parameter logic [31:0] MBX_EXTENDED_CAP_HEADER_RESVAL = 32'h 2002e; - parameter logic [15:0] MBX_EXTENDED_CAP_HEADER_CAP_ID_RESVAL = 16'h 2e; - parameter logic [3:0] MBX_EXTENDED_CAP_HEADER_CAP_VERSION_RESVAL = 4'h 2; - parameter logic [11:0] MBX_EXTENDED_CAP_HEADER_NEXT_CAPAILITY_OFFSET_RESVAL = 12'h 0; parameter logic [31:0] MBX_SYS_CONTROL_RESVAL = 32'h 0; parameter logic [0:0] MBX_SYS_CONTROL_ABORT_RESVAL = 1'h 0; parameter logic [0:0] MBX_SYS_CONTROL_DOE_INTR_EN_RESVAL = 1'h 0; @@ -427,16 +387,16 @@ package mbx_reg_pkg; // Register index for sys interface typedef enum int { - MBX_EXTENDED_CAP_HEADER, - MBX_CAP_HEADER, + MBX_DOE_INTR_MSG_ADDR, + MBX_DOE_INTR_MSG_DATA, MBX_SYS_CONTROL, MBX_SYS_STATUS } mbx_sys_id_e; // Register width information to check illegal writes for sys interface parameter logic [3:0] MBX_SYS_PERMIT [4] = '{ - 4'b 1111, // index[0] MBX_EXTENDED_CAP_HEADER - 4'b 0011, // index[1] MBX_CAP_HEADER + 4'b 1111, // index[0] MBX_DOE_INTR_MSG_ADDR + 4'b 1111, // index[1] MBX_DOE_INTR_MSG_DATA 4'b 1111, // index[2] MBX_SYS_CONTROL 4'b 1111 // index[3] MBX_SYS_STATUS }; diff --git a/hw/ip/mbx/rtl/mbx_sys_reg_top.sv b/hw/ip/mbx/rtl/mbx_sys_reg_top.sv index 31b23c5c91bec..ad3c13d59fdd7 100644 --- a/hw/ip/mbx/rtl/mbx_sys_reg_top.sv +++ b/hw/ip/mbx/rtl/mbx_sys_reg_top.sv @@ -173,12 +173,12 @@ module mbx_sys_reg_top ( // Define SW related signals // Format: __{wd|we|qs} // or _{wd|we|qs} if field == 1 or 0 - logic extended_cap_header_re; - logic [15:0] extended_cap_header_cap_id_qs; - logic [3:0] extended_cap_header_cap_version_qs; - logic [11:0] extended_cap_header_next_capaility_offset_qs; - logic cap_header_doe_intr_support_qs; - logic [10:0] cap_header_doe_intr_msg_nr_qs; + logic doe_intr_msg_addr_we; + logic [31:0] doe_intr_msg_addr_qs; + logic [31:0] doe_intr_msg_addr_wd; + logic doe_intr_msg_data_we; + logic [31:0] doe_intr_msg_data_qs; + logic [31:0] doe_intr_msg_data_wd; logic sys_control_re; logic sys_control_we; logic sys_control_abort_wd; @@ -196,107 +196,84 @@ module mbx_sys_reg_top ( logic sys_status_ready_qs; // Register instances - // R[extended_cap_header]: V(True) - // F[cap_id]: 15:0 - prim_subreg_ext #( - .DW (16) - ) u_extended_cap_header_cap_id ( - .re (extended_cap_header_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.extended_cap_header.cap_id.d), - .qre (), - .qe (), - .q (reg2hw.extended_cap_header.cap_id.q), - .ds (), - .qs (extended_cap_header_cap_id_qs) - ); - - // F[cap_version]: 19:16 - prim_subreg_ext #( - .DW (4) - ) u_extended_cap_header_cap_version ( - .re (extended_cap_header_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.extended_cap_header.cap_version.d), - .qre (), - .qe (), - .q (reg2hw.extended_cap_header.cap_version.q), - .ds (), - .qs (extended_cap_header_cap_version_qs) - ); - - // F[next_capaility_offset]: 31:20 - prim_subreg_ext #( - .DW (12) - ) u_extended_cap_header_next_capaility_offset ( - .re (extended_cap_header_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.extended_cap_header.next_capaility_offset.d), - .qre (), - .qe (), - .q (reg2hw.extended_cap_header.next_capaility_offset.q), - .ds (), - .qs (extended_cap_header_next_capaility_offset_qs) + // R[doe_intr_msg_addr]: V(False) + logic doe_intr_msg_addr_qe; + logic [0:0] doe_intr_msg_addr_flds_we; + prim_flop #( + .Width(1), + .ResetValue(0) + ) u_doe_intr_msg_addr0_qe ( + .clk_i(clk_i), + .rst_ni(rst_ni), + .d_i(&doe_intr_msg_addr_flds_we), + .q_o(doe_intr_msg_addr_qe) ); - - - // R[cap_header]: V(False) - // F[doe_intr_support]: 0:0 prim_subreg #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessRO), - .RESVAL (1'h0), + .DW (32), + .SwAccess(prim_subreg_pkg::SwAccessRW), + .RESVAL (32'h0), .Mubi (1'b0) - ) u_cap_header_doe_intr_support ( + ) u_doe_intr_msg_addr ( .clk_i (clk_i), .rst_ni (rst_ni), // from register interface - .we (1'b0), - .wd ('0), + .we (doe_intr_msg_addr_we), + .wd (doe_intr_msg_addr_wd), // from internal hardware - .de (hw2reg.cap_header.doe_intr_support.de), - .d (hw2reg.cap_header.doe_intr_support.d), + .de (1'b0), + .d ('0), // to internal hardware - .qe (), - .q (reg2hw.cap_header.doe_intr_support.q), + .qe (doe_intr_msg_addr_flds_we[0]), + .q (reg2hw.doe_intr_msg_addr.q), .ds (), // to register interface (read) - .qs (cap_header_doe_intr_support_qs) + .qs (doe_intr_msg_addr_qs) ); + assign reg2hw.doe_intr_msg_addr.qe = doe_intr_msg_addr_qe; - // F[doe_intr_msg_nr]: 11:1 + + // R[doe_intr_msg_data]: V(False) + logic doe_intr_msg_data_qe; + logic [0:0] doe_intr_msg_data_flds_we; + prim_flop #( + .Width(1), + .ResetValue(0) + ) u_doe_intr_msg_data0_qe ( + .clk_i(clk_i), + .rst_ni(rst_ni), + .d_i(&doe_intr_msg_data_flds_we), + .q_o(doe_intr_msg_data_qe) + ); prim_subreg #( - .DW (11), - .SwAccess(prim_subreg_pkg::SwAccessRO), - .RESVAL (11'h2), + .DW (32), + .SwAccess(prim_subreg_pkg::SwAccessRW), + .RESVAL (32'h0), .Mubi (1'b0) - ) u_cap_header_doe_intr_msg_nr ( + ) u_doe_intr_msg_data ( .clk_i (clk_i), .rst_ni (rst_ni), // from register interface - .we (1'b0), - .wd ('0), + .we (doe_intr_msg_data_we), + .wd (doe_intr_msg_data_wd), // from internal hardware - .de (hw2reg.cap_header.doe_intr_msg_nr.de), - .d (hw2reg.cap_header.doe_intr_msg_nr.d), + .de (1'b0), + .d ('0), // to internal hardware - .qe (), - .q (reg2hw.cap_header.doe_intr_msg_nr.q), + .qe (doe_intr_msg_data_flds_we[0]), + .q (reg2hw.doe_intr_msg_data.q), .ds (), // to register interface (read) - .qs (cap_header_doe_intr_msg_nr_qs) + .qs (doe_intr_msg_data_qs) ); + assign reg2hw.doe_intr_msg_data.qe = doe_intr_msg_data_qe; // R[sys_control]: V(True) @@ -521,8 +498,8 @@ module mbx_sys_reg_top ( logic [3:0] addr_hit; always_comb begin addr_hit = '0; - addr_hit[0] = (reg_addr == MBX_EXTENDED_CAP_HEADER_OFFSET); - addr_hit[1] = (reg_addr == MBX_CAP_HEADER_OFFSET); + addr_hit[0] = (reg_addr == MBX_DOE_INTR_MSG_ADDR_OFFSET); + addr_hit[1] = (reg_addr == MBX_DOE_INTR_MSG_DATA_OFFSET); addr_hit[2] = (reg_addr == MBX_SYS_CONTROL_OFFSET); addr_hit[3] = (reg_addr == MBX_SYS_STATUS_OFFSET); end @@ -539,7 +516,12 @@ module mbx_sys_reg_top ( end // Generate write-enables - assign extended_cap_header_re = addr_hit[0] & reg_re & !reg_error; + assign doe_intr_msg_addr_we = addr_hit[0] & reg_we & !reg_error; + + assign doe_intr_msg_addr_wd = reg_wdata[31:0]; + assign doe_intr_msg_data_we = addr_hit[1] & reg_we & !reg_error; + + assign doe_intr_msg_data_wd = reg_wdata[31:0]; assign sys_control_re = addr_hit[2] & reg_re & !reg_error; assign sys_control_we = addr_hit[2] & reg_we & !reg_error; @@ -557,8 +539,8 @@ module mbx_sys_reg_top ( // Assign write-enables to checker logic vector. always_comb begin reg_we_check = '0; - reg_we_check[0] = 1'b0; - reg_we_check[1] = 1'b0; + reg_we_check[0] = doe_intr_msg_addr_we; + reg_we_check[1] = doe_intr_msg_data_we; reg_we_check[2] = sys_control_we; reg_we_check[3] = sys_status_we; end @@ -568,14 +550,11 @@ module mbx_sys_reg_top ( reg_rdata_next = '0; unique case (1'b1) addr_hit[0]: begin - reg_rdata_next[15:0] = extended_cap_header_cap_id_qs; - reg_rdata_next[19:16] = extended_cap_header_cap_version_qs; - reg_rdata_next[31:20] = extended_cap_header_next_capaility_offset_qs; + reg_rdata_next[31:0] = doe_intr_msg_addr_qs; end addr_hit[1]: begin - reg_rdata_next[0] = cap_header_doe_intr_support_qs; - reg_rdata_next[11:1] = cap_header_doe_intr_msg_nr_qs; + reg_rdata_next[31:0] = doe_intr_msg_data_qs; end addr_hit[2]: begin diff --git a/hw/ip/mbx/rtl/mbx_sysif.sv b/hw/ip/mbx/rtl/mbx_sysif.sv index 0b4a4fb94e6ac..99e940544ba91 100644 --- a/hw/ip/mbx/rtl/mbx_sysif.sv +++ b/hw/ip/mbx/rtl/mbx_sysif.sv @@ -5,9 +5,9 @@ module mbx_sysif import tlul_pkg::*; #( - parameter int unsigned CfgSramDataWidth = 32, - parameter int unsigned NextExtDoeOffset = 12'h800, - parameter bit DoeIrqSupport = 1'b1 + parameter int unsigned CfgSramDataWidth = 32, + // PCIe capabilities + parameter bit DoeIrqSupport = 1'b1 ) ( input logic clk_i, input logic rst_ni, @@ -65,19 +65,9 @@ module mbx_sysif .devmode_i ( 1'b1 ) ); - // Interrupt support assign doe_intr_support_o = DoeIrqSupport; assign doe_intr_o = reg2hw.sys_status.doe_intr_status.q; - // Extended capability register - assign hw2reg.extended_cap_header.cap_id = 16'h002E; - assign hw2reg.extended_cap_header.cap_version = 4'h2; - assign hw2reg.extended_cap_header.next_capaility_offset = NextExtDoeOffset; - - // Capability header register - assign hw2reg.cap_header.doe_intr_support = 1'b1; - assign hw2reg.cap_header.doe_intr_msg_nr = '0; - // Control register assign sysif_control_abort_set_o = reg2hw.sys_control.abort.qe & reg2hw.sys_control.abort.q; assign hw2reg.sys_control.abort.d = 1'b0; From c15926c85112638451e26a29c70116e05b3fe917 Mon Sep 17 00:00:00 2001 From: Neeraj Upasani Date: Fri, 28 Jul 2023 15:36:11 +0100 Subject: [PATCH 09/88] [mbx,doc] Initial ingestion of mailbox spec Signed-off-by: Neeraj Upasani --- hw/ip/mbx/README.md | 563 ++++++++++- hw/ip/mbx/data/mbx.hjson | 4 +- hw/ip/mbx/doc/DOE.md | 1090 ++++++++++++++++++++++ hw/ip/mbx/doc/carved_shared_memory.svg | 509 ++++++++++ hw/ip/mbx/doc/dedicated_memory.svg | 367 ++++++++ hw/ip/mbx/doc/local_shared_memory.svg | 406 ++++++++ hw/ip/mbx/doc/mbx_interface.svg | 1 + hw/ip/mbx/doc/separate_shared_memory.svg | 539 +++++++++++ 8 files changed, 3470 insertions(+), 9 deletions(-) create mode 100644 hw/ip/mbx/doc/DOE.md create mode 100644 hw/ip/mbx/doc/carved_shared_memory.svg create mode 100644 hw/ip/mbx/doc/dedicated_memory.svg create mode 100644 hw/ip/mbx/doc/local_shared_memory.svg create mode 100644 hw/ip/mbx/doc/mbx_interface.svg create mode 100644 hw/ip/mbx/doc/separate_shared_memory.svg diff --git a/hw/ip/mbx/README.md b/hw/ip/mbx/README.md index e729bd1d835c0..f80f81fea59b8 100644 --- a/hw/ip/mbx/README.md +++ b/hw/ip/mbx/README.md @@ -1,13 +1,562 @@ -# DOE MBX HWIP Technical Specification +# OpenTitan Secure Mailbox Interface (secure_mailbox_spec) -{{#block-dashboard mbx}} +## Scope -# Overview +Document a proposal for the secure mailbox communication channel for the Integrated OpenTitan project. -## Features +## Glossary -## Description +| Term | Description | +|-------|---------------------------------------------------------| +| PCIe | PCI Express | +| DOE | Data Object Exchange | +| CXL | Compute Express Link | +| MCTP | Management Component Transport Protocol | +| SPDM | Security Protocol and Data Model | +| CMA | Component Measurement and Attestation | +| DMTF | formerly known as the Distributed Management Task Force | +| OT | OpenTitan | +| RoT | Root Of Trust | +| CTN | ConTrol Network | +| SoC | System On Chip | +| SCS | System Control Subsystem | +| IOMMU | Input Output Memory Management Unit | +| ECR | Engineering Change Request | +| ECN | Engineering Change Notification | -### Security +## Overview -## Compatibility +The integrated version of OpenTitan Root-Of-Trust may provide security services to the SoC such as: + +- Encryption or decryption of data blobs. +- Cryptographic hashing of data blobs. +- Key derivation. +- Random seed generation service. +- Public Key ( PK ) signing. +- PK verification. +- Root of Trust for Measurement, Reporting and Storage. +- Secure Firmware update. +- Access to secure storage. +- Mutual authentication / attestation services. +- SoC security monitoring / book-keeping services. +- Debug authentication / unlock service. + +The SoC Host (or other SoC Execution Engines) may request these services from OpenTitan. +This means that pre-defined control information must be passed to OpenTitan from the security service requester. + +A secure inbound/outbound mailbox is defined to enable the exchange of such control information between the root-of-trust and the security service requester. +This proposal adopts the [PCIe specification defined Data-Object-Exchange](https://members.pcisig.com/wg/PCI-SIG/document/18363) mailbox protocol as the OpenTitan Integrated mailbox communication channel. + +As an example, a DMA controller may be used in conjunction with the newly defined OpenTitan mailbox interface. +The mailbox interface is used to pass pointers to data blobs external to the OT RoT and request operations via pre-defined command objects. + +## Secure Mailbox Interface + +![](doc/mbx_interface.svg) + +### Mailbox Terminology + +- **Requester**\ +*Typically System Host or an SoC firmware agent that would request a security service via predefined DOE objects.* + +- **Responder**\ +*Entity that processes the DOE request object and generates a DOE response in case one is expected for the original request.*\ +OpenTitan would generally have the responder role; however there may be use cases where OpenTitan is a DOE requester. + +- **OT Mailbox registers (Inbox/Outbox regs)**\ +*PCIe DOE specification defined registers used for reading and writing to the mailbox.*\ +These registers may be mapped into the PCIe Config space for the System Host to access the mailbox via the PCIe defined mechanism. +Accesses from other SoC firmware based agents may not be mapped into the config address space. +The access mechanism and relevant address space for such agents is defined by the SoC integrator. +*(See the PCI Express Base Specification 6.0 section 7.9.24 for further details.)* + +- **OT Inbox Memory**\ +*Memory within the OpenTitan RoT secure perimeter that is allocated to the mailbox mechanism to store data objects passed from System/SoC mailbox writer.*\ +System/SoC mailbox writer can write this memory via mailbox interface registers only. +OpenTitan Ibex core may have direct read/write access to this memory. +Please refer to the section below for inbox memory implementation options. + +- **OT Outbox Memory**\ +*Memory within the OpenTitan RoT secure perimeter that is allocated to the mailbox mechanism to store data objects passed from OT to System/SoC mailbox reader.*\ +System/SoC mailbox reader can read this memory via mailbox interface registers only. +OpenTitan Ibex core may have direct read/write access to this memory. +Please refer to the section below for outbox memory implementation options. + +- **DOE mailbox instance**\ +*A collection of the mailbox registers, inbound mailbox memory and outbound mailbox memory that can be used to exchange objects between OT and an SoC agent.*\ +A separate mailbox instance is required for each uncoordinated SoC agent that communicates with Integrated OpenTitan via the mailbox mechanism. +OpenTitan may arbitrate between (read or write) objects from each DOE mailbox instance in a simple round robin fashion. +Note that this is firmware controlled based on pending mailbox interrupts. + +- **Inbox / Outbox Handler**\ +*Hardware widget to move mailbox data back and forth between mailbox registers and corresponding memories.* + +### Mailbox Memory Topology Options + +The following options for memory topologies should be considered for a mailbox implementation: + +#### **Dedicated Memory within mailbox instance** + +![](doc/dedicated_memory.svg) + +✅ Pros + +- Each mailbox instance has access to its own inbox memory space. +- No memory arbitration required when mailbox is written. +- Easy to prevent IBEX instruction fetch port from accessing mailbox memory (prevent address decode) + +❌ Cons + +- Difficult to implement memory protection mechanisms such as scrambling. + +#### **Shared Mailbox Memory within mailbox wrapper** + +![](doc/local_shared_memory.svg) + +- local write port, read access by memory +- (separate instance than RoT private memory) + +✅ Pros + +- Easier to implement memory protection schemes such as scrambling, if desired. +- Mailboxes not an initiator on TL-UL fabric; additional access control not required. +- Easy to prevent IBEX instruction fetch port from accessing mailbox memory (prevent address decode). + +❌ Cons + +- Memory controller may need dedicated arbitration logic. + +#### **Shared Mailbox Memory On RoT Fabric** + +![](doc/separate_shared_memory.svg) + +- (separate instance than RoT private memory) + +✅ Pros + +- Memory access arbitration handled by fabric. +- Easier to implement memory protection schemes such as scrambling, if desired. +- Easy to prevent IBEX instruction fetch port from accessing mailbox memory (prevent address decode). + +❌ Cons + +- Mailbox port is an initiator port on the fabric; requires additional security access control mechanisms such as IOPMP (access range protection registers etc). + +#### **Shared Mailbox Memory (carved out of existing RoT memory)** + +![](doc/carved_shared_memory.svg) + +- *Note that this option is not preferred* + +✅ Pros + +- Easier to manage memory size requirements (flexible range setup). + +❌ Cons + +- Hard address decode based prevention of IBEX instruction fetch from this memory not possible (mixed with IBEX code memory) + +### Mailbox Basics + +- PCIe specification section 6.30 defines the (optional) Data Object Exchange mechanism.\ +It is accessed using a PCIe extended capability defined in section 7.9.24 that provides a Mailbox for data exchange. +- All inbound and outbound mailbox communication takes place via a set of mailbox registers + - [DOE Control Register](#doe-control-register) + - [DOE Status Register](#doe-status-register) + - [DOE Write Data Mailbox Register](#doe-write-data-mailbox-register) + - [DOE Read Data Mailbox Register](#doe-read-data-mailbox-register) +- [DOE Control Register](#doe-control-register) and [DOE Status Register](#doe-status-register) are used by the requester and the responder to perform a valid handshake protocol while transferring objects back and forth. +- An entity that supports the DOE mechanism is permitted to specify its own vendor defined data objects. +- DOE Inbox is used by a ‘requester’ to query the supported data object formats + - A mailbox instance is not required to support all DOE object formats. + - PCIe Vendor ID and an object format index number together uniquely identify the supported object format. + - Mailbox requester FW/SW knows how to interpret the data object format(s) of interest. + - DOE specification defined query mechanism enables Mailbox requester to check if the DOE instance supports the data object format of interest. +- DOE Inbox is used by a ‘requester’ to write supported data objects into the DOE mailbox. + - DOE mailbox drops the object in case it is an unsupported format or does not match the expected format. + - Each mailbox write is a non-posted transaction and expects a response back. + - [DOE Write Data Mailbox Register](#doe-write-data-mailbox-register) is used to write the inbox, one DWORD (32 bit) at a time. +- DOE Outbox is used by the responder to populate a response, in case one is expected +- DOE instances have the ability to send an interrupt to notify that an object response is ready. Note that a PCIe compatible DOE mailbox instance shall have the ability to send an MSI interrupt. +- Various error handling scenarios are described later in this document. + +Following is a basic mailbox read / write sequence: + +1. System host consults the DOE Busy bit in the [DOE Status Register](#doe-status-register) to check if the DOE instance is free..\ +Busy being Clear indicates that the mailbox instance is not being actively used and is ready to accept new requests.\ +2. System host writes the entire data object one DWORD at a time via the [DOE Write Data Mailbox Register](#doe-write-data-mailbox-register). + - The inbox handler places each DWORD into the appropriate location of the OT inbox memory to assemble the object being transferred. +3. System host sets the DOE Go bit in [DOE Control Register](#doe-control-register) + - The inbox handler generates an interrupt to notify the responder (e.g. OpenTitan Ibex core) to start parsing the transferred object. + - The parser consumes the DOE request from the DOE mailbox. +4. After successful processing, the responder (OT Ibex core) generates a response, in case one is expected. + - OT host places the response in the outbox memory. + - OT host sets the Data Object Ready bit. + - DOE outbox handler generates a notification interrupt, if supported and enabled. +5. System host waits for an interrupt if applicable.\ +Upon receiving an interrupt, it checks the [DOE Status Register](#doe-status-register).*ready* bit to see if the object is ready.\ +Alternatively, if an interrupt is not supported, it polls the [DOE Status Register](#doe-status-register).*ready* bit.\ +Note that SoC level power management schemes and related interrupt delivery mechanism are outside the scope of this document.\ +Any logic required to support SoC wake from deeper power management states for interrupt delivery shall be implemented at the SoC level at the time of integration. +6. If the ready bit is Set: + - System host reads data from the [DOE Read Data Mailbox Register](#doe-read-data-mailbox-register) one DWORD at a time. + - For each DWORD, it writes the [DOE Read Data Mailbox Register](#doe-read-data-mailbox-register) to indicate a successful read. + - The process is repeated until the entire object is read. + +**Note**: Sequence above assumes System Host as the requester of the mailbox object write. +In this case a PCIe compatible DOE mailbox instance is implemented. +Similar mechanism and sequence would apply for communication with other SoC firmware controllers. +For such a DOE mailbox instance, a fully PCIe compatible implementation is not required. +See [below](#system-level-use-cases) for more details. + +**Note**: Please refer to the [PCIe Specification](https://members.pcisig.com/wg/PCI-SIG/document/18363) for more detailed and up to date information on the PCIe compatible DOE Mailbox operation basics. + +### Integrated OpenTitan Usage Of DOE Mailbox Mechanism + +Integrated OpenTitan shall: + +- Adopt the basic mechanisms as defined in the PCIe specification. +- Support one or more DOE mailbox instances. +- Support design options to allow configuration of number of mailbox instances depending upon the needs of the integrating SoC. +- Support the following Interrupt mechanisms: + - A firmware based mechanism to generate an interrupt.\ +Such a mechanism may require a method to ‘write’ to a predefined address in the appropriate address space (System, CTN or other) via the corresponding port of a DMA controller.\ +Example: Write to a location within system address space via the [SYS port of the Integrated OT DMA controller](../dma/README.md) to generate an MSI-interrupt for PCIe compatible DOE instance(s). + - Wired interrupt output(s) for each DOE instance.\ +Such a mechanism may be applied for DOE instances assigned to agents that support wired interrupt mechanism. + - Depending upon the application & PCIe compatibility requirement for the instance, SoC may decide to use the wired interrupt or firmware based MSI interrupt mechanism at the time of SoC integration.\ +Alternatively, for PCIe compatible DOE mailbox instance, an SoC may also decide to convert the wired interrupt into an MSI via dedicated hardware support at the SoC level. +- Not required to support a dedicated mutex mechanism for more than one agent to access the same DOE instance. +- Object Definition; Vendor ID + +The integrating SoC shall: + +- For the DOE instance dedicated to System Host: + - Provide the plumbing to map into PCIe Config address space. + - Provide the plumbing necessary to route the MSI interrupt to the appropriate location in the SoC’s system address space. +- For mailboxes dedicated to other SoC FW agents: + - Provide an access controlled path for the SoC FW Agent to access the DOE registers. + - Provide the plumbing necessary to route the MSI interrupt to the appropriate location in the SoC’s relevant address space (System, CTN or otherwise). +- For Access Control: + - Provide proper protection to make sure that no requester other than the one to which the mailbox is assigned, is able to access the mailbox registers. + - May be static or dynamic based on SoC level access mechanisms. +- Regarding assignment of more than one coordinated requesters / agents to the same DOE instance + - If the SoC chooses to do so, it will be the responsibility of the cooperating agents to get ownership of the DOE mailbox in a SoC defined synchronization mechanism.\ +For example, consider the case where there is more than one physical instance of SoC firmware based controllers implementing a common function like power management.\ +In such a case, the two power management controllers may acquire a software mutex or a hardware mutex, as defined and implemented by SoC. + +### Mailbox Use Cases + +#### Interprocessor Communication + +A basic usage of the DOE mailbox mechanism is to achieve Interprocessor communication (IPC) between the OpenTitan based SoC root of trust and other SoC firmware based controllers. +An example scenario is as follows: + +Such an IPC mechanism may be deployed during a system secure boot up operation. +Here OT RoT has the responsibility to fetch firmware images from external flash, verify / measure & them and place in appropriate memory locations on the SoC that are protected via access control mechanisms to prevent further modification of firmware images. +Other firmware based controllers may be configured to boot from such a memory location. +Proper reset sequencing, voltage, clock and other configuration of the SoC region / subsystem under consideration may be needed prior to this operation. +An SoC power management controller (PMC) may be responsible for these activities. +OT RoT and the PMC may need to work together to complete the operation to bootstrap the firmware based controller of a subsystem under consideration. +OT RoT and the PMC may exchange messages via DOE based mailbox mechanism through predefined message data objects to achieve this coordination. +More coordination may be required during runtime as well and may continue to use the mailboxes for further communication beyond boot time operation. + +In another example, more than one OT RoT instance may exist within an SoC - for example an RoT on each chiplet in an SoC compiled of multiple chiplets. +Such RoTs may have a primary - secondary relationship, and may require communication to perform different operations. +A dedicated DOE mailbox channel and predefined DOE objects may be assigned for such communication. + +#### System level use cases + +DOE mailbox is used to perform various security protocols like SPDM based component measurement and authentication. + +#### PCIe component measurement + +A PCIe device, either discrete or integrated within a system, may need to establish a security trust level with the appropriate software running on the System Host for various security based applications like: + +- Allowing a datacenter operator to query the state of the platform via remote mechanisms before deploying any workloads to the platform.\ +Such mechanisms may involve cryptographic measurements of the hardware components including any unique device bindings and firmware running on that platform, and attestation to a local (e.g sideband management controller) or a remote (e.g. datacenter operator) agent.\ +An OpenTitan-based root of trust integrated within a PCIe device may participate in such an authentication protocol, with the responsibility to create such measurements and present them to the system software upon request via a standard PCIe based DOE mailbox communication channel. +- Similar authentication scheme may be used for PCIe device hot plug support (adding new cards during system runtime) where the system software may decide to include the hot plugged device within its operation only upon successfully attesting to a local agent or a remote agent. + +#### Setup of Trusted Execution Environments + +An SoC may participate in providing Trusted Execution environments. +An integrated root of trust would have the responsibility to bring up, perform secure boot, measure, establish the proper chain of trust in order to bootstrap the trusted execution environment. +Trusted Software would use the DOE mailbox communication channel to establish secure protocols with the additional components (e.g. a new PCIe virtual function) before allowing them into the trusted execution boundary. + +#### Generic security services + +An integrated OpenTitan RoT may provide generic security services to the SoC or system as a whole, such as secure storage, secure firmware update, PK crypto based certificate signing, encryption/decryption. +Such operations require exchange of information (commands as well as data) back and forth between the requesters of these security services and OT. +DOE mailbox mechanism with properly defined DOE objects supporting such information exchange is envisioned to be the method to expose these security services to other components. + +## Data Object Definition + +### PCIe defined + +Following are the PCIe specification defined object types that shall be supported by the OT DOE implementation: +Vendor ID 0x0001, Data Object Types 0x00, 0x01, 0x02, 0x03, 0x04 and 0x05. + +### OT defined + +An example DOE mapping for integrated OpenTitan can be found [here](./doc/DOE.md) + +## External DOE Registers + +Note: The DOE mailbox is accessible in two different forms: + +1. PCIe compatible DOE mailbox - exposed as part of the PCIe configuration space.\ +The [DOE Extended Capability Header](#doe-extended-capability-header) and the [DOE Capability Header](#doe-capability-header) registers are supported for such a DOE mailbox instance only. +2. Firmware to Firmware communication mailboxes - uses the same underlying mechanism to transferring data objects between a firmware requester and a firmware responder.\ +However such mailboxes do not require the DOE capability registers.\ +For such mailbox instances, these address offsets are utilized to specify / configure the address of the register where a doorbell interrupt shall be sent as well as the corresponding data to be sent. + +### DOE Extended Capability Header + +| | | +|----------|--------------------------------| +| Register | DOE Extended Capability Header | +| Width | 32 bits | +| Offset | 0x00 | +| Access | RO | + +| Bit Pos | Bit Definition | Notes | +|---------|------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 15:0 | Capability ID | PCIe defined Capability ID. Should read value of 0x002E for DOE capability | +| 19:16 | Capability Version | Second version; Value of 2 | +| 31:20 | Next Capability Offset | Offset to the next capability structure. Equal to zero if no other items exist. Can be tool generated to link to other extended capabilities that may be supported. | + + +### DOE Capability Header + +| | | +|----------|-----------------------| +| Register | DOE Capability Header | +| Width | 32 bits | +| Offset | 0x04 | +| Access | RO | + +| Bit Pos | Bit Definition | Notes | +|---------|------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 0 | DOE Interrupt Support | One when interrupts are supported. In the PCIe world, this means MSI/MSI-x support. | +| 11:1 | DOE Interrupt Message number | When value is 0: Responder only support MSI (not MSI-X); and same message data for all interrupts including the DOE interrupt. MSI address/data pairs are configured in the MSI or MSI-X capability of the PCIe function hosting the mailbox. When MSI-X is implemented, this message number indexes into the table of address/data pairs to determine the one to use. **Note:** Non-PCIe DOE mailboxes (e.g. Firmware - Firmware communication mailbox) may use the wired interrupt capability. [Please see above for interrupt support.](#integrated-opentitan-usage-of-doe-mailbox-mechanism) | +| 31:12 | Reserved | | + +### DOE Interrupt Message Address Register + +| | | +|----------|----------------------------------------| +| Register | DOE Interrupt Message Address Register | +| Width | 32 bits | +| Offset | 0xFIXME | +| Access | RW | + +| Bit Pos | Bit Definition | Notes | +|---------|----------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 31:0 | Interrupt Register Address | Defined only in case of a firmware to firmware mailbox communication. Utilized by the mailbox responder to send an interrupt message to the requester via a write to the configured address. Note that such FW 2 FW mailboxes may primarily be accessible in the CTN address space. As such the configured address is part of the SoC CTN address space. | + +### DOE Interrupt Message Data Register + +| | | +|----------|----------------------------------------| +| Register | DOE Interrupt Message Address Register | +| Width | 32 bits | +| Offset | 0xFIXME | +| Access | RW | + +| Bit Pos | Bit Definition | Notes | +|---------|-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 31:0 | Interrupt Register Data | Interrupt message data to be sent to the address configured in the [DOE Interrupt Message Address Register](#DOE-Interrupt-Message-Address-Register) | + +### DOE Control Register + +| | | +|----------|----------------------| +| Register | DOE Control Register | +| Width | 32 bits | +| Offset | 0xFIXME | +| Access | RW | + +Please refer to Table 7-315 of the PCIe specification for detailed information on this register. + +| Bit Pos | Bit Definition | Notes | +|---------|--------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 0 | DOE Abort | Abort all data object transfer operations once a value of 1’b1 is written to this field. Reads for this field always return 0. | +| 1 | DOE Interrupt Enable | When set, DOE instance is enabled to send an interrupt. Also see the [interrupt support mechanisms here](#Integrated-OpenTitan-Usage-Of-DOE-Mailbox-Mechanism). | +| 2 | | TBD | +| 3 | DOE Async Message Enable | Adds capability for the responder to send asynchronous messages to the requester. (N.B. This capability is part of a PCIe ECR that is not in the released specification yet) | +| 4:30 | Reserved | | +| 31 | DOE Go | Indicates that the DOE object transferred via the [DOE Write Data Mailbox Register](#DOE-Write-Data-Mailbox-Register) is ready for consumption. Behavior is undefined if Go bit is set prior to transferring the entire object. Behavior is undefined if Go bit is set while DOE busy bit is asserted. Read of this bit always returns a zero. | + +### DOE Status Register + +| | | +|----------|---------------------| +| Register | DOE Status Register | +| Width | 32 bits | +| Offset | 0xFIXME | +| Access | RW | + +Please refer to Table 7-316 from the PCIe specification for details on this register. + +| Bit Pos | Bit Definition | Notes | +|---------|--------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 0 | DOE Busy | This bit is set by the DOE instance when it is busy processing a received data object. When set, indicates that the DOE Instance is busy and cannot accept a new data object via the [DOE Write Data Mailbox Register](#DOE-Write-Data-Mailbox-Register). This bit must be set by the DOE instance while processing an abort command. Cleared when abort handling is complete. | +| 1 | DOE Interrupt Status | An interrupt, if enabled, is generated to indicate that a data object (response) is ready for the requester to be consumed or DOE error is set, or DOE busy bit is cleared (i.e. ready to accept new objects). This bit is set when such an interrupt is asserted. Bit is a write-1-to-clear bit i.e. writing a value of 1 to this bit clears the status bit. | +| 2 | DOE Error | Set by the DOE instance if an internal error occurs with processing of a received data object or an unsupported data object. Bit is cleared by writing a 1’b1 to the DOE abort bit in the [DOE Control Register](#doe-control-register). DOE Abort is the only mechanism to clear this status bit. | +| 3 | DOE Async Message Status | Set by the responder when there are one or more asynchronous messages ready to be transferred to the requester. Note that this capability is part of a PCIe ECR that is not in the released specification yet. | +| 4 | | TBD | +| 5:30 | Reserved | | +| 31 | DOE Object Ready | Indicates that the DOE object (response) is ready to be ready by the System Host via the [DOE Read Data Mailbox Register](#DOE-Read-Data-Mailbox-Register). DOE instance shall clear this bit once the entire data object is ready by system software and no further objects are ready for transfer. DOE instance shall clear this bit in response to a DOE Abort handling, if not already clear. Read of this bit always returns a zero. Default value is 1’b0. | + +### DOE Write Data Mailbox Register + +| | | +|----------|---------------------| +| Register | DOE Status Register | +| Width | 32 bits | +| Offset | 0xFIXME | +| Access | RW | + +Please refer to Table 7-317 in the PCIe specification for details on this register. + +| Bit Pos | Bit Definition | Notes | +|---------|----------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 0:31 | DOE Write Data DWORD | A DOE object is transferred to a DOE instance by writing to this register 1 DWORD at a time. A successful write adds one DWORD to the data object being assembled in the DOE instance. A write of 1’b1 to the DOE Go bit in the DOE Control Register marks the completion of the data transfer i.e final DWORD for the object has been written. | + +### DOE Read Data Mailbox Register + +| | | +|----------|---------------------| +| Register | DOE Status Register | +| Width | 32 bits | +| Offset | 0xFIXME | +| Access | RW | + +Please refer to Table 7-317 in the PCIe specification for details on this register. + +| Bit Pos | Bit Definition | Notes | +|---------|---------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 0:31 | DOE Read Data DWORD | A DOE object is read by system software from a DOE instance by reading this register 1 DWORD at a time, once the DOE Object Ready bit is set by the DOE instance in the DOE status register. A write of any value to this register indicates a successful read of the current DWORD. The following read from this register shall return to the next DWORD from the data object being read. Back to back data objects can be transferred while the DOE Object ready bit is set. If Data Object Ready bit is clear, writes of any value to this register must have no effect and a read from this register must return zeros. | + +## OpenTitan Internal DOE Registers + +The following registers are visible in the OT internal private address +space only. As such, these registers are accessible to the firmware +running on IBEX core only + +### Inbox Write Pointer Register + +| | | +|----------|------------------------------| +| Register | Inbox Write Pointer Register | +| Width | 32 bits | +| Offset | 0xFIXME | +| Access | RW | + +| Bit Pos | Bit Definition | Notes | +|---------|----------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 0:31 | Wr Pointer | Pointer to a location within the Inbox memory where the next DWORD will be written. Pointer is initialized to the Inbox memory base address before the start of a transfer. Inbox handler maintains the updated pointer as data DWORDS are received by the DOE inbox. | + +### Outbox Read Pointer Register + +| | | +|----------|------------------------------| +| Register | Outbox Read Pointer Register | +| Width | 32 bits | +| Offset | 0xFIXME | +| Access | RW | + +| Bit Pos | Bit Definition | Notes | +|---------|----------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 0:31 | Rd Pointer | Pointer to a location within the Outbox memory from where the next DWORD will be read. Pointer is initialized to the Outbox memory base address before the start of a outgoing object transfer. Outbox handler maintains the updated pointer as data DWORDS are read from the DOE instance by the requester. | + +### DOE Inbox Memory Range Base Register + +| | | +|----------|--------------------------------------| +| Register | DOE Inbox Memory Range Base Register | +| Width | 32 bits | +| Offset | 0xFIXME | +| Access | RW | + +| Bit Pos | Bit Definition | Notes | +|---------|------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------| +| 0:31 | Memory Range Base Addr | Base Address to mark the start of the enabled memory range within the OT internal memory space. Note that this address must be DWORD aligned. | + +### DOE Inbox Memory Range Limit Register + +| | | +|----------|---------------------------------------| +| Register | DOE Inbox Memory Range Limit Register | +| Width | 32 bits | +| Offset | 0xFIXME | +| Access | RW | + +| Bit Pos | Bit Definition | Notes | +|---------|-------------------------|----------------------------------------------------------------------------------------------------------------------------------------| +| 0:31 | Memory Range Limit Addr | Limit to mark the end of the DOE Inbox memory range within the OT internal memory space. Note that this address must be DWORD aligned. | + +### DOE Outbox Memory Range Base Register + +| | | +|----------|---------------------------------------| +| Register | DOE Outbox Memory Range Base Register | +| Width | 32 bits | +| Offset | 0xFIXME | +| Access | RW | + +| Bit Pos | Bit Definition | Notes | +|---------|------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------| +| 0:31 | Memory Range Base Addr | Base Address to mark the start of the DOE outbox memory range within the OT internal memory space. Note that this address must be DWORD aligned. | + +### DOE Outbox Memory Range Limit Register + +| | | +|----------|----------------------------------------| +| Register | DOE Outbox Memory Range Limit Register | +| Width | 32 bits | +| Offset | 0xFIXME | +| Access | RW | + +| Bit Pos | Bit Definition | Notes | +|---------|-------------------------|-----------------------------------------------------------------------------------------------------------------------------------------| +| 0:31 | Memory Range Limit Addr | Limit to mark the end of the DOE Outbox memory range within the OT internal memory space. Note that this address must be DWORD aligned. | + +### DOE Memory Range Register LockEnable + +| | | +|----------|--------------------------------------| +| Register | DOE Memory Range Register LockEnable | +| Width | 32 bits | +| Offset | 0xFIXME | +| Access | RW | + +| Bit Pos | Bit Definition | Notes | +|---------|----------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 0 | Lock | Global Lock bit. Once Set, the inbox and outbox memory range registers shall not be further modifiable. The lock bit, once set, can be cleared only upon next reset assertion | +| 1 | Enable | Global Enable bit. Once Set, the inbox and outbox memory range registers (base and limit) shall be active. | +| 2:31 | Reserved | | + +### DOE Outbox Object Size Register + +| | | +|----------|---------------------------------| +| Register | DOE Outbox Object Size Register | +| Width | 32 bits | +| Offset | 0xFIXME | +| Access | RW | + +| Bit Pos | Bit Definition | Notes | +|---------|----------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 0:9 | Size | Indicates the size of the data object to be transferred out. Written by the Responder firmware. Used by Outbox handler to track the size of the message to be read. Note that this size specifies the number of DWORDs to be read. Maximum size supported by any OT DOE instance is 1K DWORDS. (Note that maximum permitted size is 256K DWORDS) | +| 10:31 | Reserved | | + +## Appendix + +A few important constraints from the PCIe specification for correct mailbox operation and error handling. +Please refer to the PCIe specification section 6.30 for detailed information, specifically the sections titled: + +- Response time +- Abort function +- Error handling diff --git a/hw/ip/mbx/data/mbx.hjson b/hw/ip/mbx/data/mbx.hjson index dfa93d73485bc..61cb6f013a837 100644 --- a/hw/ip/mbx/data/mbx.hjson +++ b/hw/ip/mbx/data/mbx.hjson @@ -8,9 +8,9 @@ human_name: "DOE Mailbox" one_line_desc: "DOE mailbox for use as an integrated OpenTitan communication channel." one_paragraph_desc: ''' - The SoC Host (or other SoC Execution Engines) may request security services from the OpenTitan RoT. + The SoC (i.e., the SoC Host CPU or other SoC Execution Engines) may request security services from OpenTitan. This means that pre-defined control information must be passed to OpenTitan from the security service requester. - A secure inbound/outbound mailbox can be used to implement a secure channel for these request/response transactions between the Host and the RoT. + A secure inbound/outbound mailbox can be used to implement a secure channel for these request/response transactions between the SoC and OpenTitan. ''' cip_id: "37" design_spec: "../doc" diff --git a/hw/ip/mbx/doc/DOE.md b/hw/ip/mbx/doc/DOE.md new file mode 100644 index 0000000000000..fbefc785f7a2b --- /dev/null +++ b/hw/ip/mbx/doc/DOE.md @@ -0,0 +1,1090 @@ +# OpenTitan-defined DOE objects + +Please refer to the following pages for additional details on the DMA controller. +- [OpenTitan DMA Controller specification](../../dma/README.md) + +## Simple DMA transfer request + +Requester specifies Source address, Destination address, source space ID and Destination space ID as required by the DMA transfer operation. +Integrated OpenTitan Host firmware parses the object, checks the request and configures the OT DMA controller if it deems the transfer to be OK. + +Response Object: [Response DOE object expected](#simple-dma-completion-response-object) + +Interrupt: Can be configured to generate interrupt to Requester, if enabled, once DMA transfer complete. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
3130292827262524232221201918171615141312111009080706050403020100Byte Offset
ReservedObject Data Type=0x0Vendor ID=<OT TBD>0x0
ReservedLength = 0x8 DWORDS0x4
ReservedOpcode = <SimpleDMA> + +Reserved\[15:10\], + +Dest Addr Space ID\[9:8\] + + + +Reserved\[7:2\], + +Source Addr Space ID\[1:0\] + +0x8
Total Data size  (in bytes)0xC
Source Address Low0x10
+ +Source Address High (Used only if targeting 64 bit +address space; else all zero) + +0x14
Destination Address Low0x18
+ +Destination Address High (Used only if targeting 64 +bit address space; else all zero) + +0x1C
+ +## Simple DMA completion response object + +DMA transfer completion response to the requester. +Response object conveys the status of the operation. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
3130292827262524232221201918171615141312111009080706050403020100Byte Offset
ReservedObject Data Type= 0x0Vendor ID=<OT TBD>0x0
ReservedLength = 0x3 DWORDS0x4
+ +DMA Completion Status {Error Code, Error/Success, +Done}; \[exact format TBD\] + +0x8
+ +## Firmware Update request + +Used by System Host software to initiate a firmware update request. +System software places the firmware update blob in the system memory. +Requester specifies Source address pointer to memory. The source address space ID is fixed toSystem). +Destination address shall be ignored by the responder. +Destination address space ID is fixed to 0x03 (FLASH). +Note that the assumption here is that OT RoT firmware is in control and aware of the Flash map. + +Integrated OpenTitan Host firmware parses the object, checks the request and configures the OT DMA controller if it deems the transfer to be OK to write the update binary into an appropriate location of the OT flash, cryptographically verifies the update candidate blob , then initiates and completes the final flash update operation upon successful verification. + +Response Object: [Response DOE object expected](#simple-dma-completion-response-object) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
3130292827262524232221201918171615141312111009080706050403020100Byte Offset
ReservedObject Data Type= 0x1Vendor ID=<OT TBD>0x0
ReservedLength = 0x8 DWORDS0x4
+ +Interrupt to Requester  = <Yes/No> + + + +Opcode = <FirmwareUpdate> + +Reserved\[15:08\],Reserved\[7:0\],0x8
Total Data size (in bytes)0xC
Source Address Low0x10
+ +Source Address High (Used only if targeting 64 bit +address space; else all zero) + +0x14
Reserved0x18
Reserved0x1C
+ +## Firmware Update Ready for Reset Notification + +Notify Requester, to system HOST that it is ready for system reset to complete the update operation. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
3130292827262524232221201918171615141312111009080706050403020100Byte Offset
ReservedObject Data Type=0x1Vendor ID=<OT TBD>0x0
ReservedLength = 0x3 DWORDS0x4
+ +Ready for Reset / Error \[exact format TBD\] + +0x8
+ +## Secure Storage Read Proxy + +Used by Requester (System Host or SoC firmware elements) to request the OT RoT to provide proxy access to the flash storage owned by the OT RoT. +Requester initiates a read request via the DOE object. +Responder performs the corresponding flash operation and sends the contents of the flash back to the requester via a DMA operation. + +Requester sets the following parameters in the request object: + +Source address: Pointer to the flash storage address from where data is read +Source address ID: = 0x3 (FLASH) +Destination address: memory location where NV storage read data shall be placed +Destination address ID: System memory or CTN memory, based on requester requirements +Total Size: size of the data block (in bytes) requested + +OT shall initiate the read access if it’s security policy allows the section of flash to be read by the requester + +Response Object: [Response DOE object expected](#secure-storage-read-completion-response) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
3130292827262524232221201918171615141312111009080706050403020100Byte Offset
ReservedObject Data Type=0x2Vendor ID=<OT TBD>0x0
ReservedLength = 0x8 DWORDS0x4
+ +Interrupt Requester  = <Yes/No> + + + +Opcode = <NVStorageRead> + + + +Reserved\[15:08\], + +Dest Addr Space ID\[1:0\] + +Reserved\[7:0\],0x8
Total Data size (in bytes)0xC
Source Address Low0x10
+ +Source Address High (Used only if targeting 64 bit +address space; else all zero) + +0x14
Destination Address Low0x18
+ +Destination Address High (Used only if targeting 64 +bit address space; else all zero) + +0x1C
+ +## Secure Storage Read Completion response + +Proxy Read completion response to the requester. +Response object conveys the status of the operation. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
3130292827262524232221201918171615141312111009080706050403020100Byte Offset
ReservedObject Data Type=0x2Vendor ID=<OT TBD>0x0
ReservedLength = 0x3 DWORDS0x4
+ +Secure Storage Read Completion Status {Error Code, +Error/Success, Done}; \[exact format TBD\] + +0x8
+ +## Secure Storage Write Proxy + +Used by Requester (System Host or SoC firmware elements) to request the OT RoT to provide proxy access to the flash storage owned by the OT RoT. +The contents to be written to the flash are placed by the requester in a SoC memory location & passes the write request along with memory pointers via the DOE object. +Responder performs the security checks, initiates a DMA transfer of the contents to be written to flash and completes the flash write operation. + +Requester sets the following parameters in the request object: + +Destination address: Pointer to the flash storage address from where data is read +Destination address ID: = 0x3 (FLASH) +Source address: memory location where NV storage read data shall be placed +Source address ID: System memory or CTN memory, based on requester requirements +Total Size: size of the data block to be written + +OT shall initiate the write access if it’s policy allows the section of flash to be written + +Response Object: [Response DOE object expected](#secure-storage-write-completion-response) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
3130292827262524232221201918171615141312111009080706050403020100Byte Offset
ReservedObject Data Type=0x3Vendor ID=<OT TBD>0x0
ReservedLength = 0x8 DWORDS0x4
+ +Interrupt Requester  = <Yes/No> + + + +Opcode = <NVStorageWrite> + + + +Reserved\[15:08\], + +Dest Addr Space ID\[1:0\] + +Reserved\[7:0\],0x8
Total Data size0xC
Source Address Low0x10
+ +Source Address High (Used only if targeting 64 bit +address space; else all zero) + +0x14
Destination Address Low0x18
+ +Destination Address High (Used only if targeting 64 +bit address space; else all zero) + +0x1C
+ +## Secure Storage Write Completion response + +Proxy Read completion response to the requester. +Response object conveys the status of the operation. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
3130292827262524232221201918171615141312111009080706050403020100Byte Offset
ReservedObject Data Type=0x3Vendor ID=<OT TBD>0x0
ReservedLength = 0x3 DWORDS0x4
+ +Secure Storage Write Completion Status {Error Code, +Error/Success, Done}; \[exact format TBD\] + +0x8
+ +## Secure Authenticated Debug Unlock Request + +Used by Requester (System Host, SoC firmware agents or JTAG proxy) to initiate debug authentication & unlock request. +OT shall initiate the crypto challenge-response protocol with the authorizing agent; System Host software or an alternate agent (implementation specific) may provide network access to the remote authorizing agent. +OT shall send a signed challenge token to the remote agent. +The remote agent shall send a signed response. +OT verifies the response & sets the corresponding feature unlock command to other SoC components using the [OT debug unlock bus]() + +Requester sets the following parameters in the request object: + +Destination Address: Pointer to the memory location where signed challenge is placed in response to this Req +Unlock Category: +- Requester sets the desired unlock category +- Provides up to 16 different debug categories; Each category may define its own Debug feature unlock privileges +- Unlocking / enabling specific debug / DFT features in a category is SoC defined + +Response Object: +- Signed Challenge Token; DOE response is generated only if DOE Rsp is set to YES +- Debug authentication via JTAG proxy channel may use the DOE response object scheme. +- System Host based authentication may benefit from DMA transfer to system memory. +- If DOE response is set to NO, then signed challenge is placed in the destination point using the OT DMA operation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
3130292827262524232221201918171615141312111009080706050403020100Byte Offset
ReservedObject Data Type=0x4Vendor ID=<OT TBD>0x0
ReservedLength = 0x8 DWORDS0x4
+ +DOE Rsp = <Yes/No> + + + +Send INT = <Yes/No> + + + +Opcode = <AuthDebugUnlockReq> + + + +Reserved\[15:08\], + +Dest Addr Space ID\[1:0\] + +ReservedUnlock Category0x8
Destination Buffer Size0xC
Reserved0x10
Reserved0x14
Destination Address Low0x18
+ +Destination Address High (Used only if targeting 64 +bit address space; else all zero) + +0x1C
+ +## DOE Response - Debug Unlock Challenge + +OT sends this DOE response message in response to the [Secure Authenticated Debug Unlock Request](#secure-authenticated-debug-unlock-request) (if DOE Rsp is set to YES) to initiate the crypto challenge-response protocol with the authorizing agent. +Requester (JTAG proxy or system software) shall read the token via DOE outbox and relay to the remote agent. +The remote agent shall send a signed unlock token in response. +OT verifies the response & sets the corresponding feature unlock command to other SoC components using the [OT debug unlock bus](). + +Responder (OT RoT) sets the following parameters in the request object: + +Nonce: OT generates a NONCE; Size TBD; Embeds within the object. +Unlock Category: +- Sets the desired unlock category based on the original request. +- Provides up to 16 different debug categories; Each category may define its own Debug feature unlock privileges +- Unlocking / enabling specific debug / DFT features in a category is SoC defined +Signature: Size TBD; Algorithm TBD. + +OT generates a digital signature using a private key over the header, NONCE & the Requested unlock category. +Embeds the digital signature within the Response object. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
3130292827262524232221201918171615141312111009080706050403020100Byte Offset
ReservedObject Data Type=0x5Vendor ID=<OT TBD>0x0
Reserved + +Length = <TBD>  DWORDS + +0x4
+ +<TBD> <Signed Debug Unlock Challenge Token +format> + +0x8
0xC
0x10
0x14
0x18
0x1C
+ +## DOE Request Object - Debug Unlock Response + +System Software receives a response to the Debug Unlock Challenge from the remote server. +System software sends this Unlock response to the OT RoT through this “DOE Request Object - Debug Unlock Response”. +The signed response contains the Unlock Category that the RoT is allowed to set (same as the original request of a lower category, as determined by the remote authentication agent). +Upon successful verification of the response token, the RoT sets the corresponding unlock category via the [OT debug unlock bus](). + +The Object Contains the following format: + +- DOE Header (2 DWORDS) +- Debug Unlock Response Token: Size and Format TBD. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
3130292827262524232221201918171615141312111009080706050403020100Byte Offset
ReservedObject Data Type=0x5Vendor ID=<OT TBD>0x0
Reserved + +Length = <TBD>  DWORDS + +0x4
+ +<TBD> <Signed Debug Unlock Response Token +format> + +0x8
0xC
0x10
0x14
0x18
0x1C
+ +## DOE TPM-like Service objects + +Placeholder for defining DOE objects to provide TPM like services. + +One or more just object definitions may be needed for TPM interface. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
3130292827262524232221201918171615141312111009080706050403020100Byte Offset
ReservedObject Data Type=0x5Vendor ID=<OT TBD>0x0
Reserved + +Length = <TBD>  DWORDS + +0x4
+ +<TBD> <Signed Debug Unlock Challenge Token +format> + +0x8
0xC
0x10
0x14
0x18
0x1C
diff --git a/hw/ip/mbx/doc/carved_shared_memory.svg b/hw/ip/mbx/doc/carved_shared_memory.svg new file mode 100644 index 0000000000000..a85c3dba7e386 --- /dev/null +++ b/hw/ip/mbx/doc/carved_shared_memory.svg @@ -0,0 +1,509 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hw/ip/mbx/doc/dedicated_memory.svg b/hw/ip/mbx/doc/dedicated_memory.svg new file mode 100644 index 0000000000000..ae74d08478c52 --- /dev/null +++ b/hw/ip/mbx/doc/dedicated_memory.svg @@ -0,0 +1,367 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hw/ip/mbx/doc/local_shared_memory.svg b/hw/ip/mbx/doc/local_shared_memory.svg new file mode 100644 index 0000000000000..9a432b1f07ea3 --- /dev/null +++ b/hw/ip/mbx/doc/local_shared_memory.svg @@ -0,0 +1,406 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hw/ip/mbx/doc/mbx_interface.svg b/hw/ip/mbx/doc/mbx_interface.svg new file mode 100644 index 0000000000000..049a020b85e7d --- /dev/null +++ b/hw/ip/mbx/doc/mbx_interface.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/hw/ip/mbx/doc/separate_shared_memory.svg b/hw/ip/mbx/doc/separate_shared_memory.svg new file mode 100644 index 0000000000000..d8b530e2af877 --- /dev/null +++ b/hw/ip/mbx/doc/separate_shared_memory.svg @@ -0,0 +1,539 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From fc073d10d364c87ec86c4e81691bd2d05f1da60e Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Wed, 30 Aug 2023 00:16:01 -0700 Subject: [PATCH 10/88] [hw,mbx,rtl] Add countermeasure testplan Signed-off-by: Robert Schilling --- hw/ip/mbx/data/mbx_sec_cm_testplan.hjson | 33 ++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 hw/ip/mbx/data/mbx_sec_cm_testplan.hjson diff --git a/hw/ip/mbx/data/mbx_sec_cm_testplan.hjson b/hw/ip/mbx/data/mbx_sec_cm_testplan.hjson new file mode 100644 index 0000000000000..fdd1361e1e4bd --- /dev/null +++ b/hw/ip/mbx/data/mbx_sec_cm_testplan.hjson @@ -0,0 +1,33 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// Security countermeasures testplan extracted from the IP Hjson using reggen. +// +// This testplan is auto-generated only the first time it is created. This is +// because this testplan needs to be hand-editable. It is possible that these +// testpoints can go out of date if the spec is updated with new +// countermeasures. When `reggen` is invoked when this testplan already exists, +// It checks if the list of testpoints is up-to-date and enforces the user to +// make further manual updates. +// +// These countermeasures and their descriptions can be found here: +// .../mbx/data/mbx.hjson +// +// It is possible that the testing of some of these countermeasures may already +// be covered as a testpoint in a different testplan. This duplication is ok - +// the test would have likely already been developed. We simply map those tests +// to the testpoints below using the `tests` key. +// +// Please ensure that this testplan is imported in: +// .../mbx/data/mbx_testplan.hjson +{ + testpoints: [ + { + name: sec_cm_bus_integrity + desc: "Verify the countermeasure(s) BUS.INTEGRITY." + stage: V2S + tests: [] + } + ] +} From 33b8e23346a08fad87ea77e3c9ef9b3f63db5946 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Tue, 22 Aug 2023 00:44:47 -0700 Subject: [PATCH 11/88] [hw,mbx,rtl] Implement SRAM arbiter Signed-off-by: Robert Schilling --- hw/ip/mbx/mbx.core | 1 + hw/ip/mbx/rtl/mbx.sv | 34 +++++++++- hw/ip/mbx/rtl/mbx_sramrwarb.sv | 120 +++++++++++++++++++++++++++++++++ 3 files changed, 153 insertions(+), 2 deletions(-) create mode 100644 hw/ip/mbx/rtl/mbx_sramrwarb.sv diff --git a/hw/ip/mbx/mbx.core b/hw/ip/mbx/mbx.core index 3a4d994998ae5..37319ac7a6a13 100644 --- a/hw/ip/mbx/mbx.core +++ b/hw/ip/mbx/mbx.core @@ -17,6 +17,7 @@ filesets: - rtl/mbx_sys_reg_top.sv - rtl/mbx_hostif.sv - rtl/mbx_sysif.sv + - rtl/mbx_sramrwarb.sv file_type: systemVerilogSource files_verilator_waiver: diff --git a/hw/ip/mbx/rtl/mbx.sv b/hw/ip/mbx/rtl/mbx.sv index 50033770dd934..88f03a66bdcef 100644 --- a/hw/ip/mbx/rtl/mbx.sv +++ b/hw/ip/mbx/rtl/mbx.sv @@ -60,7 +60,7 @@ module mbx logic sysif_status_doe_intr_status, sysif_status_doe_intr_status_set; logic sysif_write_control_abort, hostif_event_intr; - logic sysif_intg_err; + logic sysif_intg_er, tl_sram_intg_err; mbx_hostif #( .AlertAsyncOn ( AlertAsyncOn ), @@ -71,7 +71,7 @@ module mbx // Device port to the host side .tl_host_i ( tl_host_i ), .tl_host_o ( tl_host_o ), - .intg_err_i ( sysif_intg_err ), + .intg_err_i ( sysif_intg_err | tl_sram_intg_err ), .event_intr_i ( hostif_event_intr ), .irq_o ( intr_mbx_ready_o ), .alert_rx_i ( alert_rx_i ), @@ -159,4 +159,34 @@ module mbx .read_data_write_valid_o ( sysif_read_data_write_valid ) ); + logic ibmbx_hostif_sram_write_req, ibmbx_hostif_sram_write_gnt; + logic ibmbx_hostif_sram_write_resp_vld; + logic obmbx_hostif_sram_read_req, obmbx_hostif_sram_read_gnt; + logic obmbx_hostif_sram_read_resp_vld; + + // Host port conecction to access the private SRAM. + // Arbitrates between inbound and outbound mailbox + mbx_sramrwarb #( + .CfgSramAddrWidth(CfgSramAddrWidth), + .CfgSramDataWidth(CfgSramDataWidth) + ) u_sramrwarb ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .tl_host_o ( tl_sram_o ), + .tl_host_i ( tl_sram_i ), + .intg_err_o ( tl_sram_intg_err ), + // Interface to the inbound mailbox + .ibmbx_hostif_sram_write_req_i ( ibmbx_hostif_sram_write_req ), + .ibmbx_hostif_sram_write_gnt_o ( ibmbx_hostif_sram_write_gnt ), + .ibmbx_hostif_sram_write_ptr_i ( ibmbx_hostif_sram_write_ptr ), + .ibmbx_hostif_sram_write_resp_vld_o( ibmbx_hostif_sram_write_resp_vld ), + .ibmbx_write_data_i ( sysif_write_data ), + // Interface to the outbound mailbox + .obmbx_hostif_sram_read_req_i ( obmbx_hostif_sram_read_req ), + .obmbx_hostif_sram_read_gnt_o ( obmbx_hostif_sram_read_gnt ), + .obmbx_hostif_sram_read_ptr_i ( obmbx_hostif_sram_read_ptr ), + .obmbx_hostif_sram_read_resp_vld_o ( obmbx_hostif_sram_read_resp_vld ), + .obmbx_hostif_sram_read_resp_o ( obmbx_hostif_sram_read_resp ) + ); + endmodule diff --git a/hw/ip/mbx/rtl/mbx_sramrwarb.sv b/hw/ip/mbx/rtl/mbx_sramrwarb.sv new file mode 100644 index 0000000000000..0083974f7d016 --- /dev/null +++ b/hw/ip/mbx/rtl/mbx_sramrwarb.sv @@ -0,0 +1,120 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +module mbx_sramrwarb + import tlul_pkg::*; +#( + parameter int unsigned CfgSramAddrWidth = 32, + parameter int unsigned CfgSramDataWidth = 32 +) ( + input logic clk_i, + input logic rst_ni, + // Host port for memory accesses to the OT private memory + output tlul_pkg::tl_h2d_t tl_host_o, + input tlul_pkg::tl_d2h_t tl_host_i, + output logic intg_err_o, + + // Interface to the inbound mailbox + input logic ibmbx_hostif_sram_write_req_i, + output logic ibmbx_hostif_sram_write_gnt_o, + input logic [CfgSramAddrWidth-1:0] ibmbx_hostif_sram_write_ptr_i, + output logic ibmbx_hostif_sram_write_resp_vld_o, + input logic [CfgSramDataWidth-1:0] ibmbx_write_data_i, + // Interface to the outpbound mailbox + input logic obmbx_hostif_sram_read_req_i, + output logic obmbx_hostif_sram_read_gnt_o, + input logic [CfgSramAddrWidth-1:0] obmbx_hostif_sram_read_ptr_i, + output logic obmbx_hostif_sram_read_resp_vld_o, + output logic [CfgSramDataWidth-1:0] obmbx_hostif_sram_read_resp_o +); + import prim_mubi_pkg::*; + // Maximum number of outstanding requests + localparam int unsigned LCFG_MAX_REQS = 4; + localparam int unsigned LCFG_MAX_REQS_LOG2 = $clog2(LCFG_MAX_REQS) + 1; + + // We prioritze the read request. + // Winner has an outstanding read request. + logic arb_read_winner; + assign arb_read_winner = obmbx_hostif_sram_read_req_i; + + // Winnder has an outstanding write request but there is no read request + logic arb_write_winner; + assign arb_write_winner = ibmbx_hostif_sram_write_req_i & ~arb_read_winner; + + // Granting logic. Mux it to the request + logic sram_gnt, sram_valid, max_outstanding_reqs_reached; + assign obmbx_hostif_sram_read_gnt_o = arb_read_winner & + (~max_outstanding_reqs_reached & sram_gnt); + assign ibmbx_hostif_sram_write_gnt_o = arb_write_winner & + (~max_outstanding_reqs_reached & sram_gnt); + + // Mux the arbitration winner address + logic [CfgSramAddrWidth-1:0] sram_address; + assign sram_address = arb_read_winner? obmbx_hostif_sram_read_ptr_i : + ibmbx_hostif_sram_write_ptr_i; + + // make sure the request FIFO is ready (ie not empty) + logic sram_req; + assign sram_req = (obmbx_hostif_sram_read_req_i | ibmbx_hostif_sram_write_req_i); + + // FIFO Counting logic for maximum outstanding requests + logic [LCFG_MAX_REQS_LOG2-1:0] outstanding_req_count_d, outstanding_req_count_q; + logic inc_cnt, dec_cnt; + assign inc_cnt = sram_req & ~max_outstanding_reqs_reached & sram_gnt; + assign dec_cnt = sram_valid; + assign outstanding_req_count_d = outstanding_req_count_q + inc_cnt - dec_cnt; + + prim_generic_flop_en #( + .Width(LCFG_MAX_REQS_LOG2) + ) u_outstanding_req_cnt ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .en_i ( inc_cnt | dec_cnt ), + .d_i ( outstanding_req_count_d ), + .q_o ( outstanding_req_count_q ) + ); + // Block SRAM requests if we reached the maximum outstanding number + assign max_outstanding_reqs_reached = (outstanding_req_count_q == LCFG_MAX_REQS); + + tlul_adapter_host #( + .MAX_REQS (LCFG_MAX_REQS), + .EnableDataIntgGen (1), + .EnableRspDataIntgCheck (1) + ) u_sram_host_adapter ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + // Request channel + .req_i ( sram_req & ~max_outstanding_reqs_reached ), + .gnt_o ( sram_gnt ), + .addr_i ( sram_address ), + .we_i ( arb_write_winner ), + .wdata_i ( ibmbx_write_data_i ), + .wdata_intg_i ( TL_A_USER_DEFAULT.data_intg ), + .be_i ( {{top_pkg::TL_DBW}{1'b1}} ), + .instr_type_i ( prim_mubi_pkg::MuBi4False ), + .user_rsvd_i ( '0 ), + // Response channel + .valid_o ( sram_valid ), + .rdata_o ( obmbx_hostif_sram_read_resp_o ), + .rdata_intg_o ( ), + .err_o ( ), + .intg_err_o ( intg_err_o ), + // Bus interface + .tl_o ( tl_host_o ), + .tl_i ( tl_host_i ) + ); + + // Mux out response valid signal + // We cannot differentiate on directly on the response signal of the TLUL adapter. We need + // to look if the response was a response with data or not. It it's with data, it was a read + // request and we serve obmbx_hostif_sram_read_resp_vld_o. If it was a response without data + // it was a write request, so we serve ibmbx_hostif_sram_write_resp_vld_o + assign obmbx_hostif_sram_read_resp_vld_o = sram_valid & + (tl_host_i.d_opcode == tlul_pkg::AccessAckData); + assign ibmbx_hostif_sram_write_resp_vld_o = sram_valid & + (tl_host_i.d_opcode == tlul_pkg::AccessAck); + + // Functional Coverage + `COVER(MaxOutstandingRequetsReached_C, sram_req & max_outstanding_reqs_reached) +endmodule From fa895d7ca1267698d56f1960e4e2891989acc61d Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Tue, 22 Aug 2023 06:24:06 -0700 Subject: [PATCH 12/88] [hw,mbx,rtl] Inbound mailbox implementation Signed-off-by: Robert Schilling --- hw/ip/mbx/mbx.core | 3 + hw/ip/mbx/rtl/mbx.sv | 44 ++++++- hw/ip/mbx/rtl/mbx_fsm.sv | 140 +++++++++++++++++++++ hw/ip/mbx/rtl/mbx_ibmbx.sv | 193 +++++++++++++++++++++++++++++ hw/ip/mbx/rtl/mbx_wrsrm_req_ack.sv | 64 ++++++++++ 5 files changed, 440 insertions(+), 4 deletions(-) create mode 100644 hw/ip/mbx/rtl/mbx_fsm.sv create mode 100644 hw/ip/mbx/rtl/mbx_ibmbx.sv create mode 100644 hw/ip/mbx/rtl/mbx_wrsrm_req_ack.sv diff --git a/hw/ip/mbx/mbx.core b/hw/ip/mbx/mbx.core index 37319ac7a6a13..e5845641434c7 100644 --- a/hw/ip/mbx/mbx.core +++ b/hw/ip/mbx/mbx.core @@ -18,6 +18,9 @@ filesets: - rtl/mbx_hostif.sv - rtl/mbx_sysif.sv - rtl/mbx_sramrwarb.sv + - rtl/mbx_fsm.sv + - rtl/mbx_wrsrm_req_ack.sv + - rtl/mbx_ibmbx.sv file_type: systemVerilogSource files_verilator_waiver: diff --git a/hw/ip/mbx/rtl/mbx.sv b/hw/ip/mbx/rtl/mbx.sv index 88f03a66bdcef..1545c831bb436 100644 --- a/hw/ip/mbx/rtl/mbx.sv +++ b/hw/ip/mbx/rtl/mbx.sv @@ -47,7 +47,6 @@ module mbx logic hostif_status_async_msg_status, hostif_status_ready; logic [CfgSramAddrWidth-1:0] ibmbx_hostif_sram_write_ptr; - logic [CfgSramDataWidth-1:0] ibmbx_write_data; logic [CfgSramAddrWidth-1:0] obmbx_hostif_sram_read_ptr; logic [CfgSramDataWidth-1:0] obmbx_hostif_sram_read_resp; @@ -60,7 +59,10 @@ module mbx logic sysif_status_doe_intr_status, sysif_status_doe_intr_status_set; logic sysif_write_control_abort, hostif_event_intr; - logic sysif_intg_er, tl_sram_intg_err; + logic sysif_intg_err, tl_sram_intg_err, ibmbx_state_error, alert_signal; + + // Collect all error sources + assign alert_signal = sysif_intg_err | tl_sram_intg_err | ibmbx_state_error; mbx_hostif #( .AlertAsyncOn ( AlertAsyncOn ), @@ -71,7 +73,7 @@ module mbx // Device port to the host side .tl_host_i ( tl_host_i ), .tl_host_o ( tl_host_o ), - .intg_err_i ( sysif_intg_err | tl_sram_intg_err ), + .intg_err_i ( alert_signal ), .event_intr_i ( hostif_event_intr ), .irq_o ( intr_mbx_ready_o ), .alert_rx_i ( alert_rx_i ), @@ -159,12 +161,46 @@ module mbx .read_data_write_valid_o ( sysif_read_data_write_valid ) ); + // Interface signals for SRAM host access logic ibmbx_hostif_sram_write_req, ibmbx_hostif_sram_write_gnt; logic ibmbx_hostif_sram_write_resp_vld; logic obmbx_hostif_sram_read_req, obmbx_hostif_sram_read_gnt; logic obmbx_hostif_sram_read_resp_vld; - // Host port conecction to access the private SRAM. + + mbx_ibmbx #( + .CfgSramAddrWidth( CfgSramAddrWidth ), + .CfgSramDataWidth( CfgSramDataWidth ) + ) u_ibmbx ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + // Interface to the host port + .ibmbx_state_error_o ( ibmbx_state_error ), + .ibmbx_pending_o ( ibmbx_pending ), + .ibmbx_irq_host_o ( hostif_event_intr ), + .ibmbx_status_busy_update_o ( ibmbx_status_busy_valid ), + .ibmbx_status_busy_o ( ibmbx_status_busy ), + + .hostif_control_abort_set_i ( hostif_set_control_abort ), + .hostif_status_busy_clear_i ( hostif_clear_status_busy ), + .hostif_status_error_set_i ( hostif_status_error ), + + .hostif_base_valid_i ( hostif_ib_base_valid ), + .hostif_base_i ( hostif_ib_base ), + .hostif_limit_valid_i ( hostif_ib_limit_valid ), + .hostif_limit_i ( hostif_ib_limit ), + // Interface to the system port + .sysif_status_busy_i ( sysif_status_busy ), + .sysif_control_go_set_i ( sysif_set_control_go ), + .sysif_control_abort_set_i ( sysif_set_control_abort ), + .sysif_data_write_valid_i ( sysif_write_data_write_valid ), + // Host interface to access private SRAM + .hostif_sram_write_req_o ( ibmbx_hostif_sram_write_req ), + .hostif_sram_write_gnt_i ( ibmbx_hostif_sram_write_gnt ), + .hostif_sram_write_ptr_o ( ibmbx_hostif_sram_write_ptr ) + ); + + // Host port connection to access the private SRAM. // Arbitrates between inbound and outbound mailbox mbx_sramrwarb #( .CfgSramAddrWidth(CfgSramAddrWidth), diff --git a/hw/ip/mbx/rtl/mbx_fsm.sv b/hw/ip/mbx/rtl/mbx_fsm.sv new file mode 100644 index 0000000000000..c2fccfe0cf49b --- /dev/null +++ b/hw/ip/mbx/rtl/mbx_fsm.sv @@ -0,0 +1,140 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +`include "prim_assert.sv" + +module mbx_fsm #( + parameter bit CfgObMbx = 1'b1 // 1'b1: Obmbx, 1'b0: Ibmbx +) ( + input logic clk_i, + input logic rst_ni, + // Control input signals + input logic mbx_base_valid_i, + input logic mbx_limit_valid_i, + input logic hostif_abort_ack_i, + input logic hostif_status_error_set_i, + input logic hostif_status_busy_clear_i, + input logic sysif_control_abort_set_i, + input logic sys_read_all_i, + input logic writer_write_valid_i, + input logic writer_close_mbx_i, + // Status signals + output logic mbx_empty_o, + output logic mbx_write_o, + output logic mbx_read_o, + output logic mbx_sys_abort_o, + output logic mbx_ob_ready_update_o, + output logic mbx_ob_ready_o, + output logic mbx_state_error_o +); + typedef enum logic [1:0] { + MbxIdle = 2'b00, + MbxWrite = 2'b01, + MbxRead = 2'b10, + MbxSysAbortHost = 2'b11 + } mbx_ctrl_state_e; + + mbx_ctrl_state_e ctrl_state_q, ctrl_state_d; + + // Following cast is needed to avoid conversion errors between mbx_ctrl_state_e <-> logic + logic [$bits(mbx_ctrl_state_e)-1:0] ctrl_state_logic; + assign ctrl_state_q = mbx_ctrl_state_e'(ctrl_state_logic); + + prim_flop #( + .Width($bits(mbx_ctrl_state_e)), + .ResetValue(MbxIdle) + ) aff_ctrl_state_q ( + .clk_i ( clk_i ), + .rst_ni( rst_ni ), + .d_i ( ctrl_state_d ), + .q_o ( ctrl_state_logic ) + ); + + // Control signals for external usage + logic mbx_idle; + assign mbx_idle = (ctrl_state_q == MbxIdle); + assign mbx_empty_o = mbx_idle & mbx_base_valid_i & mbx_limit_valid_i; + assign mbx_write_o = (ctrl_state_q == MbxWrite); + assign mbx_read_o = (ctrl_state_q == MbxRead); + assign mbx_sys_abort_o = (ctrl_state_q == MbxSysAbortHost); + + logic ob_set_ready, ob_clear_ready; + // Outbound mailbox is ready + assign ob_set_ready = CfgObMbx + & mbx_idle + & mbx_base_valid_i & mbx_limit_valid_i & writer_close_mbx_i + & ~sysif_control_abort_set_i; + + // MbxRead is a common state for imbx and ombx + // Exit of MbxRead is used to clear imbx.Busy and ombx.Ready + assign ob_clear_ready = CfgObMbx & (hostif_status_error_set_i | + sysif_control_abort_set_i | + mbx_read_o & sys_read_all_i); + + assign mbx_ob_ready_update_o = CfgObMbx & (ob_set_ready | ob_clear_ready); // MUTEX(set,clr) + assign mbx_ob_ready_o = ob_set_ready; + + always_comb begin + ctrl_state_d = ctrl_state_q; + mbx_state_error_o = 1'b0; + + unique case (ctrl_state_q) + MbxIdle: begin + if (CfgObMbx) begin + if (mbx_base_valid_i & mbx_limit_valid_i & writer_close_mbx_i) begin + ctrl_state_d = MbxWrite; + end + end else begin + if (mbx_base_valid_i & mbx_limit_valid_i & writer_write_valid_i) begin + ctrl_state_d = MbxRead; + end + end + + // If system wants to abort, it has the highest priority + if (sysif_control_abort_set_i) begin + ctrl_state_d = MbxSysAbortHost; + end + end + + // Inbound mailbox being written by the system = writer + // Outbound mailbox: not applicable + MbxWrite: begin + if (hostif_status_error_set_i) begin // Host asserts an error + ctrl_state_d = MbxIdle; + end else if (sysif_control_abort_set_i) begin // System wants to abort + ctrl_state_d = MbxSysAbortHost; + end else if (writer_close_mbx_i) begin // Writer decided to close the mailbox + ctrl_state_d = MbxRead; + end + end + + // Inbound mailbox being read by the reader = host + // Outbound mailbox being read by the reader = system + MbxRead: begin + if (hostif_status_error_set_i) begin // Host asserts an error + ctrl_state_d = MbxIdle; + end else if (sysif_control_abort_set_i) begin // System wants to abort + ctrl_state_d = MbxSysAbortHost; + end else if (sys_read_all_i | hostif_status_busy_clear_i) begin + // Inbound mailbox: Host (FW) finishes the read + // Outbound mailbox: Object reader (HW) finishes the read + ctrl_state_d = MbxIdle; + end + end + + MbxSysAbortHost: begin + // Wait for the host to acknowledge the abort + if (hostif_abort_ack_i) begin + ctrl_state_d = MbxIdle; + end + end + + default: begin + // Should not reach this + ctrl_state_d = MbxIdle; + mbx_state_error_o = 1'b1; + end + endcase + end +endmodule diff --git a/hw/ip/mbx/rtl/mbx_ibmbx.sv b/hw/ip/mbx/rtl/mbx_ibmbx.sv new file mode 100644 index 0000000000000..4b3d1b468fd25 --- /dev/null +++ b/hw/ip/mbx/rtl/mbx_ibmbx.sv @@ -0,0 +1,193 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +`include "prim_assert.sv" + +module mbx_ibmbx #( + parameter int unsigned CfgSramAddrWidth = 32, + parameter int unsigned CfgSramDataWidth = 32 +) ( + input logic clk_i, + input logic rst_ni, + output logic ibmbx_state_error_o, + output logic ibmbx_pending_o, + output logic ibmbx_irq_host_o, + output logic ibmbx_status_busy_update_o, + output logic ibmbx_status_busy_o, + + // Device interface from the host side + input logic hostif_control_abort_set_i, + input logic hostif_status_busy_clear_i, + input logic hostif_status_error_set_i, + + input logic hostif_base_valid_i, + input logic [CfgSramAddrWidth-1:0] hostif_base_i, + input logic hostif_limit_valid_i, + input logic [CfgSramAddrWidth-1:0] hostif_limit_i, + // Device interface from the system side + input logic sysif_status_busy_i, + input logic sysif_control_go_set_i, + input logic sysif_control_abort_set_i, + input logic sysif_data_write_valid_i, + // Host interface to the private SRAM + output logic hostif_sram_write_req_o, + input logic hostif_sram_write_gnt_i, + output logic [CfgSramAddrWidth-1:0] hostif_sram_write_ptr_o +); + localparam int unsigned LCFG_SRM_ADDRINC = CfgSramDataWidth / 8; + localparam int unsigned LCFG_SRM_ADDRINC_LOG2 = $clog2(LCFG_SRM_ADDRINC); + + logic [CfgSramAddrWidth-1:0] sram_write_ptr_d, sram_write_ptr_q; + + logic req_ack_state_error, fsm_state_error; + assign ibmbx_state_error_o = req_ack_state_error | fsm_state_error; + + // Status signals from the FSM + logic mbx_empty, mbx_write, mbx_read, mbx_sys_abort; + + // hostif_sram_write_req_o is actually sticky because the sys-side TLUL_adapter_reg is + // NOT ack'ed until the command is grated by the host-side TLUL_adapter_host + // RW2A = sticky from DEC/RW-stage to (srm command) ACK + logic write_req; + assign write_req = (mbx_empty & sysif_data_write_valid_i) | + (mbx_write & sysif_data_write_valid_i & (sram_write_ptr_q < hostif_limit_i)); + + // Create TLUL write request + mbxwrsrm_req_ack u_mbxwrsrm_req_ack( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .req_i ( write_req ), + .gnt_i ( hostif_sram_write_gnt_i ), + .tlul_req_o ( hostif_sram_write_req_o ), + .state_error_o( req_ack_state_error ) + ); + + logic sys_abort; + logic load_write_ptr, advance_write_ptr; + + assign sys_abort = hostif_control_abort_set_i & mbx_sys_abort; + + // Rewind the write pointer to the base + assign load_write_ptr = mbx_empty | sys_abort | + (mbx_read & hostif_status_busy_clear_i); + + // Advance the write pointer when the valid write command is granted by the tlul_adaptor_host + assign advance_write_ptr = hostif_sram_write_req_o & hostif_sram_write_gnt_i; + + always_comb begin + sram_write_ptr_d = sram_write_ptr_q; + + if (load_write_ptr) begin + sram_write_ptr_d = hostif_base_i; + end else if (advance_write_ptr) begin + sram_write_ptr_d = sram_write_ptr_q + (1'b1 << LCFG_SRM_ADDRINC_LOG2); + end + end + + prim_generic_flop_en #( + .Width(CfgSramAddrWidth) + ) u_sram_write_ptr ( + .clk_i ( clk_i ), + .rst_ni( rst_ni ), + .en_i ( load_write_ptr | advance_write_ptr ), + .d_i ( sram_write_ptr_d ), + .q_o ( sram_write_ptr_q ) + ); + assign hostif_sram_write_ptr_o = sram_write_ptr_q; + + // Backpressure the next write data until the current write data is granted by the TLUL adapter + logic set_pending, clear_pending; + + // Block the request from TLUL until the SRAM write is complete + assign set_pending = mbx_write & sysif_data_write_valid_i & (sram_write_ptr_q < hostif_limit_i); + assign clear_pending = hostif_sram_write_gnt_i; + + prim_flop #( + .Width(1) + ) u_pending ( + .clk_i ( clk_i ), + .rst_ni( rst_ni ), + .d_i ( ~clear_pending & (set_pending | ibmbx_pending_o) ), + .q_o ( ibmbx_pending_o ) + ); + + // Busy logic + logic ibmbx_set_busy, ibmbx_clear_busy; + assign ibmbx_set_busy = (mbx_write & + sysif_control_go_set_i & + ~hostif_status_error_set_i & + ~sysif_control_abort_set_i) | + sysif_control_abort_set_i; + + // Exit of mailbox read is used to clear ibmbx.busy and ibmbx.ready + // Not yet qualified with mbx_read + assign ibmbx_clear_busy = hostif_status_error_set_i | + sysif_control_abort_set_i | + hostif_status_busy_clear_i; + + // External busy update interface + assign ibmbx_status_busy_update_o = ibmbx_set_busy | ibmbx_clear_busy; + assign ibmbx_status_busy_o = ibmbx_set_busy; + + // Generate host interrupt + // on sys_write go, when host enters state to process the received objects + // on abort + assign ibmbx_irq_host_o = mbx_read | sys_abort; + + mbx_fsm #( + .CfgObMbx ( 0 ) + ) u_mbxfsm( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .mbx_base_valid_i ( hostif_base_valid_i ), + .mbx_limit_valid_i ( hostif_limit_valid_i ), + .hostif_abort_ack_i ( hostif_control_abort_set_i ), + .hostif_status_error_set_i ( hostif_status_error_set_i ), + .hostif_status_busy_clear_i( hostif_status_busy_clear_i ), + .sysif_control_abort_set_i ( sysif_control_abort_set_i ), + .sys_read_all_i ( 1'b0 ), + .writer_close_mbx_i ( sysif_control_go_set_i ), + .writer_write_valid_i ( sysif_data_write_valid_i ), + // Status signals + .mbx_empty_o ( mbx_empty ), + .mbx_write_o ( mbx_write ), + .mbx_read_o ( mbx_read ), + .mbx_sys_abort_o ( mbx_sys_abort ), + .obmbx_ready_update_o ( ), + .obmbx_ready_o ( ), + .mbx_state_error_o ( fsm_state_error ) + ); + + // Assertions + + // Don't write the mailbox if it is full + `ASSERT(NeverWriteMbxIfFull_A, ibmbx_is_full & hostif_sram_write_req_o); + +`ifdef INC_ASSERT + logic[CfgSramAddrWidth-1:0] sram_write_ptr_assert_q; + prim_flop #( + .Width(CfgSramAddrWidth) + ) u_sram_write_ptr_assert ( + .clk_i ( clk_i ), + .rst_ni( rst_ni ), + .d_i ( sram_write_ptr_d ), + .q_o ( sram_write_ptr_assert_q ) + ); + // A granted write by the host adapter must advance the write pointer + `ASSERT_IF(GntMustAdvanceWritePtr_A, sram_write_ptr_assert_q == sram_write_ptr_q, + hostif_sram_write_gnt_i) +`endif + + // The write pointer should not be advanced if there is not yet acked request + `ASSERT_IF(WrPtrShouldNotAdvanceIfNoAck_A, ~ibmbx_pending_o, advance_write_ptr & ibmbx_pending_o) + // Clear busy/abort does not clear the IRQ + `ASSERT_IF(ClearBusyAbortDoesNotClearIrq_A, sysif_status_busy_i == ibmbx_irq_host_o, + sysif_status_busy_i & ibmbx_irq_host_o) + // Busy and host IRQ are not set together + `ASSERT_IF(BusyIrqNotSetTogether_A, sysif_status_busy_i & ibmbx_irq_host_o, + sysif_control_go_set_i | sysif_control_abort_set_i) + // When writing to the mailbox, DOE status busy must be low + `ASSERT_NEVER(WriteToMbxBusyMustBeLow_A, hostif_sram_write_req_o & sysif_status_busy_i) + +endmodule diff --git a/hw/ip/mbx/rtl/mbx_wrsrm_req_ack.sv b/hw/ip/mbx/rtl/mbx_wrsrm_req_ack.sv new file mode 100644 index 0000000000000..64e3f5aabeddb --- /dev/null +++ b/hw/ip/mbx/rtl/mbx_wrsrm_req_ack.sv @@ -0,0 +1,64 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +module mbxwrsrm_req_ack ( + input logic clk_i, + input logic rst_ni, + input logic req_i, + input logic gnt_i, + output logic tlul_req_o, + output logic state_error_o +); + typedef enum logic { + Idle = 1'b0, + WaitForGnt = 1'b1 + } req_state_e; + + req_state_e req_state_d, req_state_q; + + // Following cast is needed to avoid conversion errors between req_state_e <-> logic + logic [$bits(req_state_e)-1:0] req_state_logic; + assign req_state_q = req_state_e'(req_state_logic); + + prim_flop #( + .Width($bits(req_state_e)), + .ResetValue(Idle) + ) u_req_state ( + .clk_i ( clk_i ), + .rst_ni( rst_ni ), + .d_i ( req_state_d ), + .q_o ( req_state_logic ) + ); + + logic wait_for_gnt; + assign wait_for_gnt = req_state_q == WaitForGnt; + + // Request is leveled and de-asserted when granted + assign tlul_req_o = (req_i & ~wait_for_gnt) | wait_for_gnt; + + always_comb begin + req_state_d = req_state_q; + state_error_o = 1'b0; + + unique case (req_state_q) + Idle: begin + if (req_i & ~gnt_i) begin + req_state_d = WaitForGnt; + end + end + + WaitForGnt: begin + if (gnt_i) begin + req_state_d = Idle; + end + end + + default: begin + // Should not reach this + req_state_d = Idle; + state_error_o = 1'b1; + end + endcase + end +endmodule From d0d82857e62f8295bf14f5a4e18dd73e16a3747d Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Thu, 31 Aug 2023 05:58:15 -0700 Subject: [PATCH 13/88] [hw,mbx,rtl] Simplify and fix signal assignments Signed-off-by: Robert Schilling --- hw/ip/mbx/mbx.core | 1 - hw/ip/mbx/rtl/mbx.sv | 85 ++++++++++++++++++++---------- hw/ip/mbx/rtl/mbx_fsm.sv | 11 ++-- hw/ip/mbx/rtl/mbx_ibmbx.sv | 38 ++++++------- hw/ip/mbx/rtl/mbx_sysif.sv | 6 +-- hw/ip/mbx/rtl/mbx_wrsrm_req_ack.sv | 64 ---------------------- 6 files changed, 85 insertions(+), 120 deletions(-) delete mode 100644 hw/ip/mbx/rtl/mbx_wrsrm_req_ack.sv diff --git a/hw/ip/mbx/mbx.core b/hw/ip/mbx/mbx.core index e5845641434c7..0cfbb683883bc 100644 --- a/hw/ip/mbx/mbx.core +++ b/hw/ip/mbx/mbx.core @@ -19,7 +19,6 @@ filesets: - rtl/mbx_sysif.sv - rtl/mbx_sramrwarb.sv - rtl/mbx_fsm.sv - - rtl/mbx_wrsrm_req_ack.sv - rtl/mbx_ibmbx.sv file_type: systemVerilogSource diff --git a/hw/ip/mbx/rtl/mbx.sv b/hw/ip/mbx/rtl/mbx.sv index 1545c831bb436..bbc1e71b4db29 100644 --- a/hw/ip/mbx/rtl/mbx.sv +++ b/hw/ip/mbx/rtl/mbx.sv @@ -37,33 +37,53 @@ module mbx logic [CfgSramAddrWidth-1:0] ib_write_ptr; logic [CfgSramAddrWidth-1:0] ob_read_ptr; + ////////////////////////////////////////////////////////////////////////////// + // General signals for the mailbox + ////////////////////////////////////////////////////////////////////////////// + + // Collect all error sources + logic sysif_intg_err, tl_sram_intg_err, ibmbx_state_error, alert_signal; + assign alert_signal = sysif_intg_err | + tl_sram_intg_err | + ibmbx_state_error; + + ////////////////////////////////////////////////////////////////////////////// + // Control and Status signals of the host interface + ////////////////////////////////////////////////////////////////////////////// + // External write signals for control and status register logic hostif_control_abort_set; logic hostif_status_busy_clear; logic hostif_status_error_set, hostif_status_error_clear; logic hostif_status_async_msg_status_set; + // External read signals for control and status register logic hostif_status_busy, hostif_status_error; logic hostif_status_async_msg_status, hostif_status_ready; - logic [CfgSramAddrWidth-1:0] ibmbx_hostif_sram_write_ptr; - logic [CfgSramAddrWidth-1:0] obmbx_hostif_sram_read_ptr; - logic [CfgSramDataWidth-1:0] obmbx_hostif_sram_read_resp; - + logic hostif_event_intr; logic hostif_address_range_valid; + + logic sysif_status_doe_intr_status, sysif_status_doe_intr_status_set; + logic sysif_write_control_abort, ; + + ////////////////////////////////////////////////////////////////////////////// + // Signals for the Inbox + ////////////////////////////////////////////////////////////////////////////// + logic [CfgSramAddrWidth-1:0] hostif_ib_base, hostif_ib_limit; + logic [CfgSramAddrWidth-1:0] ibmbx_hostif_sram_write_ptr; + + ////////////////////////////////////////////////////////////////////////////// + // Signals for the Outbox + ////////////////////////////////////////////////////////////////////////////// + logic [CfgSramAddrWidth-1:0] hostif_ob_base, hostif_ob_limit; + logic [CfgSramAddrWidth-1:0] obmbx_hostif_sram_read_ptr; logic hostif_write_ob_object_size, hostif_read_ob_object_size; logic [10:0] hostif_ob_object_size_wdata, hostif_ob_object_size_rdata; - logic sysif_status_doe_intr_status, sysif_status_doe_intr_status_set; - logic sysif_write_control_abort, hostif_event_intr; - logic sysif_intg_err, tl_sram_intg_err, ibmbx_state_error, alert_signal; - - // Collect all error sources - assign alert_signal = sysif_intg_err | tl_sram_intg_err | ibmbx_state_error; - mbx_hostif #( .AlertAsyncOn ( AlertAsyncOn ), .CfgSramAddrWidth( CfgSramAddrWidth ) @@ -109,17 +129,35 @@ module mbx .sysif_write_control_abort_i ( sysif_write_control_abort ) ); - logic ibmbx_pending, obmbx_pending; - logic ibmbx_status_busy_valid, ibmbx_status_busy; - logic obmbx_status_ready_valid, obmbx_status_ready; - + ////////////////////////////////////////////////////////////////////////////// + // Control and Status signals of the system interface + ////////////////////////////////////////////////////////////////////////////// logic sysif_control_go_set, sysif_control_abort_set, sysif_control_async_msg_en; logic sysif_status_intr_support, sysif_status_intr_en; logic sysif_status_async_msg_status_set, sysif_status_async_msg_status; - logic sysif_write_data_write_valid; - logic [CfgSramDataWidth-1:0] sysif_write_data, sysif_read_data; + ////////////////////////////////////////////////////////////////////////////// + // Signals for the Inbox + ////////////////////////////////////////////////////////////////////////////// + logic ibmbx_pending; + logic ibmbx_status_busy_valid, ibmbx_status_busy; + + // Interface signals for SRAM host access to write the incoming data to memory + logic ibmbx_hostif_sram_write_req, ibmbx_hostif_sram_write_gnt; + logic ibmbx_hostif_sram_write_resp_vld; + logic [CfgSramDataWidth-1:0] sysif_write_data, + + ////////////////////////////////////////////////////////////////////////////// + // Signals for the Outbox + ////////////////////////////////////////////////////////////////////////////// + logic obmbx_pending; + logic obmbx_status_ready_valid, obmbx_status_ready; + + // Interface signals for SRAM host access to read the memory and serve it to the outbox + logic obmbx_hostif_sram_read_req, obmbx_hostif_sram_read_gnt; + logic obmbx_hostif_sram_read_resp_vld; + logic [CfgSramDataWidth-1:0] sysif_read_data; logic sysif_read_data_read_valid, sysif_read_data_write_valid; mbx_sysif #( @@ -161,13 +199,7 @@ module mbx .read_data_write_valid_o ( sysif_read_data_write_valid ) ); - // Interface signals for SRAM host access - logic ibmbx_hostif_sram_write_req, ibmbx_hostif_sram_write_gnt; - logic ibmbx_hostif_sram_write_resp_vld; - logic obmbx_hostif_sram_read_req, obmbx_hostif_sram_read_gnt; - logic obmbx_hostif_sram_read_resp_vld; - - + mbx_ibmbx #( .CfgSramAddrWidth( CfgSramAddrWidth ), .CfgSramDataWidth( CfgSramDataWidth ) @@ -185,9 +217,8 @@ module mbx .hostif_status_busy_clear_i ( hostif_clear_status_busy ), .hostif_status_error_set_i ( hostif_status_error ), - .hostif_base_valid_i ( hostif_ib_base_valid ), + .hostif_range_valid_i ( hostif_address_range_valid ), .hostif_base_i ( hostif_ib_base ), - .hostif_limit_valid_i ( hostif_ib_limit_valid ), .hostif_limit_i ( hostif_ib_limit ), // Interface to the system port .sysif_status_busy_i ( sysif_status_busy ), @@ -222,7 +253,7 @@ module mbx .obmbx_hostif_sram_read_gnt_o ( obmbx_hostif_sram_read_gnt ), .obmbx_hostif_sram_read_ptr_i ( obmbx_hostif_sram_read_ptr ), .obmbx_hostif_sram_read_resp_vld_o ( obmbx_hostif_sram_read_resp_vld ), - .obmbx_hostif_sram_read_resp_o ( obmbx_hostif_sram_read_resp ) + .obmbx_hostif_sram_read_resp_o ( sysif_read_data ) ); endmodule diff --git a/hw/ip/mbx/rtl/mbx_fsm.sv b/hw/ip/mbx/rtl/mbx_fsm.sv index c2fccfe0cf49b..536002898d7b9 100644 --- a/hw/ip/mbx/rtl/mbx_fsm.sv +++ b/hw/ip/mbx/rtl/mbx_fsm.sv @@ -10,8 +10,7 @@ module mbx_fsm #( input logic clk_i, input logic rst_ni, // Control input signals - input logic mbx_base_valid_i, - input logic mbx_limit_valid_i, + input logic mbx_range_valid_i, input logic hostif_abort_ack_i, input logic hostif_status_error_set_i, input logic hostif_status_busy_clear_i, @@ -54,7 +53,7 @@ module mbx_fsm #( // Control signals for external usage logic mbx_idle; assign mbx_idle = (ctrl_state_q == MbxIdle); - assign mbx_empty_o = mbx_idle & mbx_base_valid_i & mbx_limit_valid_i; + assign mbx_empty_o = mbx_idle & mbx_range_valid_i; assign mbx_write_o = (ctrl_state_q == MbxWrite); assign mbx_read_o = (ctrl_state_q == MbxRead); assign mbx_sys_abort_o = (ctrl_state_q == MbxSysAbortHost); @@ -63,7 +62,7 @@ module mbx_fsm #( // Outbound mailbox is ready assign ob_set_ready = CfgObMbx & mbx_idle - & mbx_base_valid_i & mbx_limit_valid_i & writer_close_mbx_i + & mbx_range_valid_i & writer_close_mbx_i & ~sysif_control_abort_set_i; // MbxRead is a common state for imbx and ombx @@ -82,11 +81,11 @@ module mbx_fsm #( unique case (ctrl_state_q) MbxIdle: begin if (CfgObMbx) begin - if (mbx_base_valid_i & mbx_limit_valid_i & writer_close_mbx_i) begin + if (mbx_range_valid_i & writer_close_mbx_i) begin ctrl_state_d = MbxWrite; end end else begin - if (mbx_base_valid_i & mbx_limit_valid_i & writer_write_valid_i) begin + if (mbx_range_valid_i & writer_write_valid_i) begin ctrl_state_d = MbxRead; end end diff --git a/hw/ip/mbx/rtl/mbx_ibmbx.sv b/hw/ip/mbx/rtl/mbx_ibmbx.sv index 4b3d1b468fd25..7e86eec2c200c 100644 --- a/hw/ip/mbx/rtl/mbx_ibmbx.sv +++ b/hw/ip/mbx/rtl/mbx_ibmbx.sv @@ -21,9 +21,8 @@ module mbx_ibmbx #( input logic hostif_status_busy_clear_i, input logic hostif_status_error_set_i, - input logic hostif_base_valid_i, + input logic hostif_range_valid_i, input logic [CfgSramAddrWidth-1:0] hostif_base_i, - input logic hostif_limit_valid_i, input logic [CfgSramAddrWidth-1:0] hostif_limit_i, // Device interface from the system side input logic sysif_status_busy_i, @@ -40,29 +39,31 @@ module mbx_ibmbx #( logic [CfgSramAddrWidth-1:0] sram_write_ptr_d, sram_write_ptr_q; - logic req_ack_state_error, fsm_state_error; - assign ibmbx_state_error_o = req_ack_state_error | fsm_state_error; - // Status signals from the FSM logic mbx_empty, mbx_write, mbx_read, mbx_sys_abort; // hostif_sram_write_req_o is actually sticky because the sys-side TLUL_adapter_reg is - // NOT ack'ed until the command is grated by the host-side TLUL_adapter_host + // NOT ack'ed until the command is granted by the host-side TLUL_adapter_host // RW2A = sticky from DEC/RW-stage to (srm command) ACK logic write_req; assign write_req = (mbx_empty & sysif_data_write_valid_i) | (mbx_write & sysif_data_write_valid_i & (sram_write_ptr_q < hostif_limit_i)); - // Create TLUL write request - mbxwrsrm_req_ack u_mbxwrsrm_req_ack( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .req_i ( write_req ), - .gnt_i ( hostif_sram_write_gnt_i ), - .tlul_req_o ( hostif_sram_write_req_o ), - .state_error_o( req_ack_state_error ) + // Create a sticky TLUL write request until its granted + logic req_q; + assign hostif_sram_write_req_o = write_req | req_q; + + prim_flop #( + .Width(1) + ) u_req_state ( + .clk_i ( clk_i ), + .rst_ni( rst_ni ), + .d_i ( hostif_sram_write_req_o & ~hostif_sram_write_req_o ), + .q_o ( req_q ) ); + + logic sys_abort; logic load_write_ptr, advance_write_ptr; @@ -140,8 +141,7 @@ module mbx_ibmbx #( ) u_mbxfsm( .clk_i ( clk_i ), .rst_ni ( rst_ni ), - .mbx_base_valid_i ( hostif_base_valid_i ), - .mbx_limit_valid_i ( hostif_limit_valid_i ), + .mbx_range_valid_i ( hostif_range_valid_i ), .hostif_abort_ack_i ( hostif_control_abort_set_i ), .hostif_status_error_set_i ( hostif_status_error_set_i ), .hostif_status_busy_clear_i( hostif_status_busy_clear_i ), @@ -154,9 +154,9 @@ module mbx_ibmbx #( .mbx_write_o ( mbx_write ), .mbx_read_o ( mbx_read ), .mbx_sys_abort_o ( mbx_sys_abort ), - .obmbx_ready_update_o ( ), - .obmbx_ready_o ( ), - .mbx_state_error_o ( fsm_state_error ) + .mbx_ob_ready_update_o ( ), + .mbx_ob_ready_o ( ), + .mbx_state_error_o ( ibmbx_state_error_o ) ); // Assertions diff --git a/hw/ip/mbx/rtl/mbx_sysif.sv b/hw/ip/mbx/rtl/mbx_sysif.sv index 99e940544ba91..4e90617c250a5 100644 --- a/hw/ip/mbx/rtl/mbx_sysif.sv +++ b/hw/ip/mbx/rtl/mbx_sysif.sv @@ -166,14 +166,14 @@ module mbx_sysif .addr_o ( ), .wdata_o ( reg_wdata_wdata ), .be_o ( ), - .busy_i ( obmbx_pending_i ), + .busy_i ( ibmbx_pending_i ), .rdata_i ( '0 ), .error_i ( 1'b0 ) ); // Dedicated TLUL adapter for implementing the read data mailbox register via a register window. // We use the register window to access the internal bus signals, allowing the mailbox to halt - // the bus if there are too many outstanding requests. The register is immplemented as hwext + // the bus if there are too many outstanding requests. The register is implemented as hwext // outside of this hierarchy tlul_adapter_reg #( .RegAw ( SysAw ), @@ -193,7 +193,7 @@ module mbx_sysif // Write values are ignored. A Write simply means the read has occured. .wdata_o ( ), .be_o ( ), - .busy_i ( ibmbx_pending_i ), + .busy_i ( obmbx_pending_i ), .rdata_i ( read_data_i ), .error_i ( 1'b0 ) ); diff --git a/hw/ip/mbx/rtl/mbx_wrsrm_req_ack.sv b/hw/ip/mbx/rtl/mbx_wrsrm_req_ack.sv deleted file mode 100644 index 64e3f5aabeddb..0000000000000 --- a/hw/ip/mbx/rtl/mbx_wrsrm_req_ack.sv +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright lowRISC contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 - -module mbxwrsrm_req_ack ( - input logic clk_i, - input logic rst_ni, - input logic req_i, - input logic gnt_i, - output logic tlul_req_o, - output logic state_error_o -); - typedef enum logic { - Idle = 1'b0, - WaitForGnt = 1'b1 - } req_state_e; - - req_state_e req_state_d, req_state_q; - - // Following cast is needed to avoid conversion errors between req_state_e <-> logic - logic [$bits(req_state_e)-1:0] req_state_logic; - assign req_state_q = req_state_e'(req_state_logic); - - prim_flop #( - .Width($bits(req_state_e)), - .ResetValue(Idle) - ) u_req_state ( - .clk_i ( clk_i ), - .rst_ni( rst_ni ), - .d_i ( req_state_d ), - .q_o ( req_state_logic ) - ); - - logic wait_for_gnt; - assign wait_for_gnt = req_state_q == WaitForGnt; - - // Request is leveled and de-asserted when granted - assign tlul_req_o = (req_i & ~wait_for_gnt) | wait_for_gnt; - - always_comb begin - req_state_d = req_state_q; - state_error_o = 1'b0; - - unique case (req_state_q) - Idle: begin - if (req_i & ~gnt_i) begin - req_state_d = WaitForGnt; - end - end - - WaitForGnt: begin - if (gnt_i) begin - req_state_d = Idle; - end - end - - default: begin - // Should not reach this - req_state_d = Idle; - state_error_o = 1'b1; - end - endcase - end -endmodule From 741e44a78f15dce082e0c5296cd3fbf48ae08d31 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Thu, 31 Aug 2023 07:29:03 -0700 Subject: [PATCH 14/88] [hw,mbx,rtl] Refactor top-level signalling and naming Signed-off-by: Robert Schilling --- hw/ip/mbx/mbx.core | 2 +- hw/ip/mbx/rtl/mbx.sv | 232 ++++++++++---------- hw/ip/mbx/rtl/mbx_hostif.sv | 44 ++-- hw/ip/mbx/rtl/{mbx_ibmbx.sv => mbx_imbx.sv} | 56 ++--- hw/ip/mbx/rtl/mbx_sramrwarb.sv | 56 +++-- hw/ip/mbx/rtl/mbx_sysif.sv | 26 ++- 6 files changed, 209 insertions(+), 207 deletions(-) rename hw/ip/mbx/rtl/{mbx_ibmbx.sv => mbx_imbx.sv} (79%) diff --git a/hw/ip/mbx/mbx.core b/hw/ip/mbx/mbx.core index 0cfbb683883bc..122b020b61f7e 100644 --- a/hw/ip/mbx/mbx.core +++ b/hw/ip/mbx/mbx.core @@ -19,7 +19,7 @@ filesets: - rtl/mbx_sysif.sv - rtl/mbx_sramrwarb.sv - rtl/mbx_fsm.sv - - rtl/mbx_ibmbx.sv + - rtl/mbx_imbx.sv file_type: systemVerilogSource files_verilator_waiver: diff --git a/hw/ip/mbx/rtl/mbx.sv b/hw/ip/mbx/rtl/mbx.sv index bbc1e71b4db29..989ee495350bb 100644 --- a/hw/ip/mbx/rtl/mbx.sv +++ b/hw/ip/mbx/rtl/mbx.sv @@ -34,55 +34,49 @@ module mbx input tlul_pkg::tl_d2h_t tl_sram_i, output tlul_pkg::tl_h2d_t tl_sram_o ); - logic [CfgSramAddrWidth-1:0] ib_write_ptr; - logic [CfgSramAddrWidth-1:0] ob_read_ptr; - - ////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////// // General signals for the mailbox ////////////////////////////////////////////////////////////////////////////// // Collect all error sources - logic sysif_intg_err, tl_sram_intg_err, ibmbx_state_error, alert_signal; - assign alert_signal = sysif_intg_err | - tl_sram_intg_err | - ibmbx_state_error; + logic sysif_intg_err, tl_sram_intg_err, imbx_state_error, alert_signal; + assign alert_signal = sysif_intg_err | + tl_sram_intg_err | + imbx_state_error; - ////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////// // Control and Status signals of the host interface ////////////////////////////////////////////////////////////////////////////// - // External write signals for control and status register - logic hostif_control_abort_set; - logic hostif_status_busy_clear; - logic hostif_status_error_set, hostif_status_error_clear; - logic hostif_status_async_msg_status_set; - - // External read signals for control and status register - logic hostif_status_busy, hostif_status_error; - logic hostif_status_async_msg_status, hostif_status_ready; - logic hostif_event_intr; logic hostif_address_range_valid; + logic sysif_control_abort_write; + + // Status signal inputs from the sysif to the hostif + logic sysif_status_busy, sysif_status_doe_intr_status, sysif_status_async_msg_status, + sysif_status_error, sysif_status_ready; - logic sysif_status_doe_intr_status, sysif_status_doe_intr_status_set; - logic sysif_write_control_abort, ; + // Setter signals from the hostif to the sysif + logic hostif_status_doe_intr_status_set, hostif_status_async_msg_status_set, + hostif_control_abort_set, hostif_status_busy_clear, + hostif_status_error_set, hostif_status_error_clear; - ////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////// // Signals for the Inbox ////////////////////////////////////////////////////////////////////////////// - logic [CfgSramAddrWidth-1:0] hostif_ib_base, hostif_ib_limit; - logic [CfgSramAddrWidth-1:0] ibmbx_hostif_sram_write_ptr; + logic [CfgSramAddrWidth-1:0] hostif_imbx_base, hostif_imbx_limit; + logic [CfgSramAddrWidth-1:0] imbx_sram_write_ptr; - ////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////// // Signals for the Outbox ////////////////////////////////////////////////////////////////////////////// - logic [CfgSramAddrWidth-1:0] hostif_ob_base, hostif_ob_limit; - logic [CfgSramAddrWidth-1:0] obmbx_hostif_sram_read_ptr; + logic [CfgSramAddrWidth-1:0] hostif_ombx_base, hostif_ombx_limit; + logic [CfgSramAddrWidth-1:0] ombx_sram_read_ptr; - logic hostif_write_ob_object_size, hostif_read_ob_object_size; - logic [10:0] hostif_ob_object_size_wdata, hostif_ob_object_size_rdata; + logic hostif_ombx_object_size_write, hostif_ombx_object_size_read; + logic [10:0] hostif_ombx_object_size_wdata, hostif_ombx_object_size_rdata; mbx_hostif #( .AlertAsyncOn ( AlertAsyncOn ), @@ -102,61 +96,59 @@ module mbx .hostif_control_abort_set_o ( hostif_control_abort_set ), // Access to the status register .hostif_status_busy_clear_o ( hostif_status_busy_clear ), - .hostif_status_doe_intr_status_set_o ( sysif_status_doe_intr_status_set ), + .hostif_status_busy_i ( sysif_status_busy ), + .hostif_status_doe_intr_status_set_o ( hostif_status_doe_intr_status_set ), + .hostif_status_doe_intr_status_i ( sysif_status_doe_intr_status ), + .hostif_status_async_msg_status_set_o( hostif_status_async_msg_status_set ), + .hostif_status_async_msg_status_i ( sysif_status_async_msg_status ), .hostif_status_error_set_o ( hostif_status_error_set ), .hostif_status_error_clear_o ( hostif_status_error_clear ), - .hostif_status_async_msg_status_set_o( hostif_status_async_msg_status_set ), - .hostif_status_busy_i ( hostif_status_busy ), - .hostif_status_doe_intr_status_i ( sysif_status_doe_intr_status ), - .hostif_status_error_i ( hostif_status_error ), - .hostif_status_async_msg_status_i ( hostif_status_async_msg_status ), - .hostif_status_ready_i ( hostif_status_ready ), + .hostif_status_error_i ( sysif_status_error ), + .hostif_status_ready_i ( sysif_status_ready ), // Access to the IB/OB RD/WR Pointers - .hostif_ib_write_ptr_i ( ibmbx_hostif_sram_write_ptr ), - .hostif_ob_read_ptr_i ( obmbx_hostif_sram_read_ptr ), + .hostif_imbx_write_ptr_i ( imbx_sram_write_ptr ), + .hostif_ombx_read_ptr_i ( ombx_sram_read_ptr ), // Access to the memory region registers .hostif_address_range_valid_o ( hostif_address_range_valid ), - .hostif_ib_base_o ( hostif_ib_base ), - .hostif_ib_limit_o ( hostif_ib_limit ), - .hostif_ob_base_o ( hostif_ob_base ), - .hostif_ob_limit_o ( hostif_ob_limit ), + .hostif_imbx_base_o ( hostif_imbx_base ), + .hostif_imbx_limit_o ( hostif_imbx_limit ), + .hostif_ombx_base_o ( hostif_ombx_base ), + .hostif_ombx_limit_o ( hostif_ombx_limit ), // Read/Write access for the OB DW Count register - .hostif_write_ob_object_size_o ( hostif_write_ob_object_size ), - .hostif_ob_object_size_o ( hostif_ob_object_size_wdata ), - .hostif_ob_object_size_i ( hostif_ob_object_size_rdata ), - .hostif_read_ob_object_size_i ( hostif_read_ob_object_size ), + .hostif_ombx_object_size_write_o ( hostif_ombx_object_size_write ), + .hostif_ombx_object_size_o ( hostif_ombx_object_size_wdata ), + .hostif_ombx_object_size_read_i ( hostif_ombx_object_size_read ), + .hostif_ombx_object_size_i ( hostif_ombx_object_size_rdata ), // Control inputs coming from the system registers interface - .sysif_write_control_abort_i ( sysif_write_control_abort ) + .sysif_control_abort_write_i ( sysif_control_abort_write ) ); - ////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////// // Control and Status signals of the system interface ////////////////////////////////////////////////////////////////////////////// logic sysif_control_go_set, sysif_control_abort_set, sysif_control_async_msg_en; - logic sysif_status_intr_support, sysif_status_intr_en; - logic sysif_status_async_msg_status_set, sysif_status_async_msg_status; - - ////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////// // Signals for the Inbox - ////////////////////////////////////////////////////////////////////////////// - logic ibmbx_pending; - logic ibmbx_status_busy_valid, ibmbx_status_busy; - + ////////////////////////////////////////////////////////////////////////////// + logic imbx_pending; + logic imbx_status_busy_valid, imbx_status_busy; + // Interface signals for SRAM host access to write the incoming data to memory - logic ibmbx_hostif_sram_write_req, ibmbx_hostif_sram_write_gnt; - logic ibmbx_hostif_sram_write_resp_vld; - logic [CfgSramDataWidth-1:0] sysif_write_data, + logic imbx_sram_write_req, imbx_sram_write_gnt; + logic imbx_sram_write_resp_vld; + logic [CfgSramDataWidth-1:0] sysif_write_data; + logic sysif_write_data_write_valid; - ////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////// // Signals for the Outbox - ////////////////////////////////////////////////////////////////////////////// - logic obmbx_pending; - logic obmbx_status_ready_valid, obmbx_status_ready; + ////////////////////////////////////////////////////////////////////////////// + logic ombx_pending; + logic ombx_status_ready_valid, ombx_status_ready; // Interface signals for SRAM host access to read the memory and serve it to the outbox - logic obmbx_hostif_sram_read_req, obmbx_hostif_sram_read_gnt; - logic obmbx_hostif_sram_read_resp_vld; + logic ombx_sram_read_req, ombx_sram_read_gnt; + logic ombx_sram_read_resp_vld; logic [CfgSramDataWidth-1:0] sysif_read_data; logic sysif_read_data_read_valid, sysif_read_data_write_valid; @@ -175,85 +167,93 @@ module mbx .doe_intr_o ( doe_intr_o ), // Access to the control register .sysif_control_abort_set_o ( sysif_control_abort_set ), - .sysif_control_async_msg_en_o ( sysif_control_async_msg_en), + .sysif_control_async_msg_en_o ( sysif_control_async_msg_en ), .sysif_control_go_set_o ( sysif_control_go_set ), // Access to the status register - .sysif_status_busy_valid_i ( ibmbx_status_busy_valid ), - .sysif_status_busy_i ( ibmbx_status_busy ), - .sysif_status_doe_intr_status_set_i ( sysif_status_doe_intr_status_set ), + .sysif_status_busy_valid_i ( imbx_status_busy_valid ), + .sysif_status_busy_i ( imbx_status_busy ), + .sysif_status_busy_o ( sysif_status_busy ), + + + .sysif_status_doe_intr_status_set_i ( hostif_status_doe_intr_status_set ), .sysif_status_doe_intr_status_o ( sysif_status_doe_intr_status ), + .sysif_status_error_set_i ( hostif_status_error_set ), .sysif_status_error_clear_i ( hostif_status_error_clear ), + .sysif_status_error_o ( sysif_status_error ), + + .sysif_status_async_msg_status_set_i ( hostif_status_async_msg_status_set ), .sysif_status_async_msg_status_o ( sysif_status_async_msg_status ), - .sysif_status_async_msg_status_set_i ( sysif_status_async_msg_status_set ), - .sysif_status_ready_valid_i ( obmbx_status_ready_valid ), - .sysif_status_ready_i ( obmbx_status_ready ), + + .sysif_status_ready_valid_i ( ombx_status_ready_valid ), + .sysif_status_ready_i ( ombx_status_ready ), + .sysif_status_ready_o ( sysif_status_ready ), // Control lines for backpressuring the bus - .ibmbx_pending_i ( ibmbx_pending ), - .obmbx_pending_i ( obmbx_pending ), + .imbx_pending_i ( imbx_pending ), + .ombx_pending_i ( ombx_pending ), // Data interface for inbound and outbound mailbox .write_data_write_valid_o ( sysif_write_data_write_valid ), .write_data_o ( sysif_write_data ), - .read_data_i ( sysif_read_data ), .read_data_read_valid_o ( sysif_read_data_read_valid ), - .read_data_write_valid_o ( sysif_read_data_write_valid ) + .read_data_write_valid_o ( sysif_read_data_write_valid ), + .read_data_i ( sysif_read_data ) ); - - mbx_ibmbx #( + + mbx_imbx #( .CfgSramAddrWidth( CfgSramAddrWidth ), .CfgSramDataWidth( CfgSramDataWidth ) - ) u_ibmbx ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), + ) u_imbx ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), // Interface to the host port - .ibmbx_state_error_o ( ibmbx_state_error ), - .ibmbx_pending_o ( ibmbx_pending ), - .ibmbx_irq_host_o ( hostif_event_intr ), - .ibmbx_status_busy_update_o ( ibmbx_status_busy_valid ), - .ibmbx_status_busy_o ( ibmbx_status_busy ), + .imbx_state_error_o ( imbx_state_error ), + .imbx_pending_o ( imbx_pending ), + .imbx_irq_host_o ( hostif_event_intr ), + .imbx_status_busy_update_o ( imbx_status_busy_valid ), + .imbx_status_busy_o ( imbx_status_busy ), - .hostif_control_abort_set_i ( hostif_set_control_abort ), - .hostif_status_busy_clear_i ( hostif_clear_status_busy ), - .hostif_status_error_set_i ( hostif_status_error ), + .hostif_control_abort_set_i ( hostif_control_abort_set ), + .hostif_status_busy_clear_i ( hostif_status_busy_clear ), + .hostif_status_error_set_i ( hostif_status_error_set ), - .hostif_range_valid_i ( hostif_address_range_valid ), - .hostif_base_i ( hostif_ib_base ), - .hostif_limit_i ( hostif_ib_limit ), + .hostif_range_valid_i ( hostif_address_range_valid ), + .hostif_base_i ( hostif_imbx_base ), + .hostif_limit_i ( hostif_imbx_limit ), // Interface to the system port - .sysif_status_busy_i ( sysif_status_busy ), - .sysif_control_go_set_i ( sysif_set_control_go ), - .sysif_control_abort_set_i ( sysif_set_control_abort ), - .sysif_data_write_valid_i ( sysif_write_data_write_valid ), + .sysif_status_busy_i ( sysif_status_busy ), + .sysif_control_go_set_i ( sysif_control_go_set ), + .sysif_control_abort_set_i ( sysif_control_abort_set ), + .sysif_data_write_valid_i ( sysif_write_data_write_valid ), // Host interface to access private SRAM - .hostif_sram_write_req_o ( ibmbx_hostif_sram_write_req ), - .hostif_sram_write_gnt_i ( ibmbx_hostif_sram_write_gnt ), - .hostif_sram_write_ptr_o ( ibmbx_hostif_sram_write_ptr ) + .hostif_sram_write_req_o ( imbx_sram_write_req ), + .hostif_sram_write_gnt_i ( imbx_sram_write_gnt ), + .hostif_sram_write_ptr_o ( imbx_sram_write_ptr ) ); // Host port connection to access the private SRAM. // Arbitrates between inbound and outbound mailbox mbx_sramrwarb #( - .CfgSramAddrWidth(CfgSramAddrWidth), - .CfgSramDataWidth(CfgSramDataWidth) + .CfgSramAddrWidth( CfgSramAddrWidth ), + .CfgSramDataWidth( CfgSramDataWidth ) ) u_sramrwarb ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .tl_host_o ( tl_sram_o ), - .tl_host_i ( tl_sram_i ), - .intg_err_o ( tl_sram_intg_err ), + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .tl_host_o ( tl_sram_o ), + .tl_host_i ( tl_sram_i ), + .intg_err_o ( tl_sram_intg_err ), // Interface to the inbound mailbox - .ibmbx_hostif_sram_write_req_i ( ibmbx_hostif_sram_write_req ), - .ibmbx_hostif_sram_write_gnt_o ( ibmbx_hostif_sram_write_gnt ), - .ibmbx_hostif_sram_write_ptr_i ( ibmbx_hostif_sram_write_ptr ), - .ibmbx_hostif_sram_write_resp_vld_o( ibmbx_hostif_sram_write_resp_vld ), - .ibmbx_write_data_i ( sysif_write_data ), + .imbx_sram_write_req_i ( imbx_sram_write_req ), + .imbx_sram_write_gnt_o ( imbx_sram_write_gnt ), + .imbx_sram_write_ptr_i ( imbx_sram_write_ptr ), + .imbx_sram_write_resp_vld_o( imbx_sram_write_resp_vld ), + .imbx_write_data_i ( sysif_write_data ), // Interface to the outbound mailbox - .obmbx_hostif_sram_read_req_i ( obmbx_hostif_sram_read_req ), - .obmbx_hostif_sram_read_gnt_o ( obmbx_hostif_sram_read_gnt ), - .obmbx_hostif_sram_read_ptr_i ( obmbx_hostif_sram_read_ptr ), - .obmbx_hostif_sram_read_resp_vld_o ( obmbx_hostif_sram_read_resp_vld ), - .obmbx_hostif_sram_read_resp_o ( sysif_read_data ) + .ombx_sram_read_req_i ( ombx_sram_read_req ), + .ombx_sram_read_gnt_o ( ombx_sram_read_gnt ), + .ombx_sram_read_ptr_i ( ombx_sram_read_ptr ), + .ombx_sram_read_resp_vld_o ( ombx_sram_read_resp_vld ), + .ombx_sram_read_resp_o ( sysif_read_data ) ); endmodule diff --git a/hw/ip/mbx/rtl/mbx_hostif.sv b/hw/ip/mbx/rtl/mbx_hostif.sv index 6ef66ef7e755f..7b986605b6881 100644 --- a/hw/ip/mbx/rtl/mbx_hostif.sv +++ b/hw/ip/mbx/rtl/mbx_hostif.sv @@ -35,21 +35,21 @@ module mbx_hostif input logic hostif_status_async_msg_status_i, input logic hostif_status_ready_i, // Access to the IB/OB RD/WR pointers - input logic [CfgSramAddrWidth-1:0] hostif_ib_write_ptr_i, - input logic [CfgSramAddrWidth-1:0] hostif_ob_read_ptr_i, + input logic [CfgSramAddrWidth-1:0] hostif_imbx_write_ptr_i, + input logic [CfgSramAddrWidth-1:0] hostif_ombx_read_ptr_i, // Base/Limit for in/outbound mailbox output logic hostif_address_range_valid_o, - output logic [CfgSramAddrWidth-1:0] hostif_ib_base_o, - output logic [CfgSramAddrWidth-1:0] hostif_ib_limit_o, - output logic [CfgSramAddrWidth-1:0] hostif_ob_base_o, - output logic [CfgSramAddrWidth-1:0] hostif_ob_limit_o, + output logic [CfgSramAddrWidth-1:0] hostif_imbx_base_o, + output logic [CfgSramAddrWidth-1:0] hostif_imbx_limit_o, + output logic [CfgSramAddrWidth-1:0] hostif_ombx_base_o, + output logic [CfgSramAddrWidth-1:0] hostif_ombx_limit_o, // Read/Write access for the OB DW Count register - output logic hostif_write_ob_object_size_o, - output logic [10:0] hostif_ob_object_size_o, - input logic [10:0] hostif_ob_object_size_i, - input logic hostif_read_ob_object_size_i, + output logic hostif_ombx_object_size_write_o, + output logic [10:0] hostif_ombx_object_size_o, + input logic hostif_ombx_object_size_read_i, + input logic [10:0] hostif_ombx_object_size_i, // Control inputs coming from the system registers interface - input logic sysif_write_control_abort_i + input logic sysif_control_abort_write_i ); mbx_reg_pkg::mbx_host_reg2hw_t reg2hw; mbx_reg_pkg::mbx_host_hw2reg_t hw2reg; @@ -113,7 +113,7 @@ module mbx_hostif always_comb begin abort_d = abort_q; - if (sysif_write_control_abort_i) begin + if (sysif_control_abort_write_i) begin abort_d = 1'b1; end else if (hostif_control_abort_set_o) begin abort_d = 1'b0; @@ -152,22 +152,22 @@ module mbx_hostif assign hostif_address_range_valid_o = reg2hw.address_range_valid.q; // Inbound Mailbox Base/Limit Register - assign hostif_ib_base_o = { reg2hw.inbound_base_address.q, {2{1'b0}} }; - assign hostif_ib_limit_o = { reg2hw.inbound_limit_address.q, {2{1'b0}} }; + assign hostif_imbx_base_o = { reg2hw.inbound_base_address.q, {2{1'b0}} }; + assign hostif_imbx_limit_o = { reg2hw.inbound_limit_address.q, {2{1'b0}} }; // Outbound Mailbox Base/Limit Register - assign hostif_ob_base_o = { reg2hw.outbound_base_address.q, {2{1'b0}} }; - assign hostif_ob_limit_o = { reg2hw.outbound_limit_address.q, {2{1'b0}} }; + assign hostif_ombx_base_o = { reg2hw.outbound_base_address.q, {2{1'b0}} }; + assign hostif_ombx_limit_o = { reg2hw.outbound_limit_address.q, {2{1'b0}} }; // Read/Write pointers - assign hw2reg.inbound_write_ptr.d = hostif_ib_write_ptr_i[CfgSramAddrWidth-1:2]; - assign hw2reg.outbound_read_ptr.d = hostif_ob_read_ptr_i[CfgSramAddrWidth-1:2]; + assign hw2reg.inbound_write_ptr.d = hostif_imbx_write_ptr_i[CfgSramAddrWidth-1:2]; + assign hw2reg.outbound_read_ptr.d = hostif_ombx_read_ptr_i[CfgSramAddrWidth-1:2]; // Outbound object size Register // External read logic - assign hw2reg.outbound_object_size.d = hostif_ob_object_size_i; - assign hw2reg.outbound_object_size.de = hostif_read_ob_object_size_i; + assign hw2reg.outbound_object_size.d = hostif_ombx_object_size_i; + assign hw2reg.outbound_object_size.de = hostif_ombx_object_size_read_i; // External write logic - assign hostif_write_ob_object_size_o = reg2hw.outbound_object_size.qe; - assign hostif_ob_object_size_o = reg2hw.outbound_object_size.q; + assign hostif_ombx_object_size_write_o = reg2hw.outbound_object_size.qe; + assign hostif_ombx_object_size_o = reg2hw.outbound_object_size.q; endmodule diff --git a/hw/ip/mbx/rtl/mbx_ibmbx.sv b/hw/ip/mbx/rtl/mbx_imbx.sv similarity index 79% rename from hw/ip/mbx/rtl/mbx_ibmbx.sv rename to hw/ip/mbx/rtl/mbx_imbx.sv index 7e86eec2c200c..8873779cc34c0 100644 --- a/hw/ip/mbx/rtl/mbx_ibmbx.sv +++ b/hw/ip/mbx/rtl/mbx_imbx.sv @@ -4,17 +4,17 @@ `include "prim_assert.sv" -module mbx_ibmbx #( +module mbx_imbx #( parameter int unsigned CfgSramAddrWidth = 32, parameter int unsigned CfgSramDataWidth = 32 ) ( input logic clk_i, input logic rst_ni, - output logic ibmbx_state_error_o, - output logic ibmbx_pending_o, - output logic ibmbx_irq_host_o, - output logic ibmbx_status_busy_update_o, - output logic ibmbx_status_busy_o, + output logic imbx_state_error_o, + output logic imbx_pending_o, + output logic imbx_irq_host_o, + output logic imbx_status_busy_update_o, + output logic imbx_status_busy_o, // Device interface from the host side input logic hostif_control_abort_set_i, @@ -62,8 +62,6 @@ module mbx_ibmbx #( .q_o ( req_q ) ); - - logic sys_abort; logic load_write_ptr, advance_write_ptr; @@ -107,34 +105,34 @@ module mbx_ibmbx #( prim_flop #( .Width(1) ) u_pending ( - .clk_i ( clk_i ), - .rst_ni( rst_ni ), - .d_i ( ~clear_pending & (set_pending | ibmbx_pending_o) ), - .q_o ( ibmbx_pending_o ) + .clk_i ( clk_i ), + .rst_ni( rst_ni ), + .d_i ( ~clear_pending & (set_pending | imbx_pending_o) ), + .q_o ( imbx_pending_o ) ); // Busy logic - logic ibmbx_set_busy, ibmbx_clear_busy; - assign ibmbx_set_busy = (mbx_write & - sysif_control_go_set_i & - ~hostif_status_error_set_i & - ~sysif_control_abort_set_i) | + logic imbx_set_busy, imbx_clear_busy; + assign imbx_set_busy = (mbx_write & + sysif_control_go_set_i & + ~hostif_status_error_set_i & + ~sysif_control_abort_set_i) | sysif_control_abort_set_i; - // Exit of mailbox read is used to clear ibmbx.busy and ibmbx.ready + // Exit of mailbox read is used to clear imbx.busy and imbx.ready // Not yet qualified with mbx_read - assign ibmbx_clear_busy = hostif_status_error_set_i | + assign imbx_clear_busy = hostif_status_error_set_i | sysif_control_abort_set_i | hostif_status_busy_clear_i; // External busy update interface - assign ibmbx_status_busy_update_o = ibmbx_set_busy | ibmbx_clear_busy; - assign ibmbx_status_busy_o = ibmbx_set_busy; + assign imbx_status_busy_update_o = imbx_set_busy | imbx_clear_busy; + assign imbx_status_busy_o = imbx_set_busy; // Generate host interrupt // on sys_write go, when host enters state to process the received objects // on abort - assign ibmbx_irq_host_o = mbx_read | sys_abort; + assign imbx_irq_host_o = mbx_read | sys_abort; mbx_fsm #( .CfgObMbx ( 0 ) @@ -156,13 +154,15 @@ module mbx_ibmbx #( .mbx_sys_abort_o ( mbx_sys_abort ), .mbx_ob_ready_update_o ( ), .mbx_ob_ready_o ( ), - .mbx_state_error_o ( ibmbx_state_error_o ) + .mbx_state_error_o ( imbx_state_error_o ) ); + ////////////////////////////////////////////////////////////////////////////// // Assertions + ////////////////////////////////////////////////////////////////////////////// // Don't write the mailbox if it is full - `ASSERT(NeverWriteMbxIfFull_A, ibmbx_is_full & hostif_sram_write_req_o); + `ASSERT(NeverWriteMbxIfFull_A, imbx_is_full & hostif_sram_write_req_o) `ifdef INC_ASSERT logic[CfgSramAddrWidth-1:0] sram_write_ptr_assert_q; @@ -180,12 +180,12 @@ module mbx_ibmbx #( `endif // The write pointer should not be advanced if there is not yet acked request - `ASSERT_IF(WrPtrShouldNotAdvanceIfNoAck_A, ~ibmbx_pending_o, advance_write_ptr & ibmbx_pending_o) + `ASSERT_IF(WrPtrShouldNotAdvanceIfNoAck_A, ~imbx_pending_o, advance_write_ptr & imbx_pending_o) // Clear busy/abort does not clear the IRQ - `ASSERT_IF(ClearBusyAbortDoesNotClearIrq_A, sysif_status_busy_i == ibmbx_irq_host_o, - sysif_status_busy_i & ibmbx_irq_host_o) + `ASSERT_IF(ClearBusyAbortDoesNotClearIrq_A, sysif_status_busy_i == imbx_irq_host_o, + sysif_status_busy_i & imbx_irq_host_o) // Busy and host IRQ are not set together - `ASSERT_IF(BusyIrqNotSetTogether_A, sysif_status_busy_i & ibmbx_irq_host_o, + `ASSERT_IF(BusyIrqNotSetTogether_A, sysif_status_busy_i & imbx_irq_host_o, sysif_control_go_set_i | sysif_control_abort_set_i) // When writing to the mailbox, DOE status busy must be low `ASSERT_NEVER(WriteToMbxBusyMustBeLow_A, hostif_sram_write_req_o & sysif_status_busy_i) diff --git a/hw/ip/mbx/rtl/mbx_sramrwarb.sv b/hw/ip/mbx/rtl/mbx_sramrwarb.sv index 0083974f7d016..eb8774ffc44ee 100644 --- a/hw/ip/mbx/rtl/mbx_sramrwarb.sv +++ b/hw/ip/mbx/rtl/mbx_sramrwarb.sv @@ -16,17 +16,17 @@ module mbx_sramrwarb output logic intg_err_o, // Interface to the inbound mailbox - input logic ibmbx_hostif_sram_write_req_i, - output logic ibmbx_hostif_sram_write_gnt_o, - input logic [CfgSramAddrWidth-1:0] ibmbx_hostif_sram_write_ptr_i, - output logic ibmbx_hostif_sram_write_resp_vld_o, - input logic [CfgSramDataWidth-1:0] ibmbx_write_data_i, + input logic imbx_sram_write_req_i, + output logic imbx_sram_write_gnt_o, + input logic [CfgSramAddrWidth-1:0] imbx_sram_write_ptr_i, + output logic imbx_sram_write_resp_vld_o, + input logic [CfgSramDataWidth-1:0] imbx_write_data_i, // Interface to the outpbound mailbox - input logic obmbx_hostif_sram_read_req_i, - output logic obmbx_hostif_sram_read_gnt_o, - input logic [CfgSramAddrWidth-1:0] obmbx_hostif_sram_read_ptr_i, - output logic obmbx_hostif_sram_read_resp_vld_o, - output logic [CfgSramDataWidth-1:0] obmbx_hostif_sram_read_resp_o + input logic ombx_sram_read_req_i, + output logic ombx_sram_read_gnt_o, + input logic [CfgSramAddrWidth-1:0] ombx_sram_read_ptr_i, + output logic ombx_sram_read_resp_vld_o, + output logic [CfgSramDataWidth-1:0] ombx_sram_read_resp_o ); import prim_mubi_pkg::*; // Maximum number of outstanding requests @@ -36,27 +36,25 @@ module mbx_sramrwarb // We prioritze the read request. // Winner has an outstanding read request. logic arb_read_winner; - assign arb_read_winner = obmbx_hostif_sram_read_req_i; + assign arb_read_winner = ombx_sram_read_req_i; // Winnder has an outstanding write request but there is no read request logic arb_write_winner; - assign arb_write_winner = ibmbx_hostif_sram_write_req_i & ~arb_read_winner; + assign arb_write_winner = imbx_sram_write_req_i & ~arb_read_winner; // Granting logic. Mux it to the request logic sram_gnt, sram_valid, max_outstanding_reqs_reached; - assign obmbx_hostif_sram_read_gnt_o = arb_read_winner & - (~max_outstanding_reqs_reached & sram_gnt); - assign ibmbx_hostif_sram_write_gnt_o = arb_write_winner & - (~max_outstanding_reqs_reached & sram_gnt); + assign ombx_sram_read_gnt_o = arb_read_winner & (~max_outstanding_reqs_reached & sram_gnt); + assign imbx_sram_write_gnt_o = arb_write_winner & (~max_outstanding_reqs_reached & sram_gnt); // Mux the arbitration winner address logic [CfgSramAddrWidth-1:0] sram_address; - assign sram_address = arb_read_winner? obmbx_hostif_sram_read_ptr_i : - ibmbx_hostif_sram_write_ptr_i; + assign sram_address = arb_read_winner? ombx_sram_read_ptr_i : + imbx_sram_write_ptr_i; // make sure the request FIFO is ready (ie not empty) logic sram_req; - assign sram_req = (obmbx_hostif_sram_read_req_i | ibmbx_hostif_sram_write_req_i); + assign sram_req = (ombx_sram_read_req_i | imbx_sram_write_req_i); // FIFO Counting logic for maximum outstanding requests logic [LCFG_MAX_REQS_LOG2-1:0] outstanding_req_count_d, outstanding_req_count_q; @@ -78,9 +76,9 @@ module mbx_sramrwarb assign max_outstanding_reqs_reached = (outstanding_req_count_q == LCFG_MAX_REQS); tlul_adapter_host #( - .MAX_REQS (LCFG_MAX_REQS), - .EnableDataIntgGen (1), - .EnableRspDataIntgCheck (1) + .MAX_REQS ( LCFG_MAX_REQS ), + .EnableDataIntgGen ( 1 ), + .EnableRspDataIntgCheck( 1 ) ) u_sram_host_adapter ( .clk_i ( clk_i ), .rst_ni ( rst_ni ), @@ -89,14 +87,14 @@ module mbx_sramrwarb .gnt_o ( sram_gnt ), .addr_i ( sram_address ), .we_i ( arb_write_winner ), - .wdata_i ( ibmbx_write_data_i ), + .wdata_i ( imbx_write_data_i ), .wdata_intg_i ( TL_A_USER_DEFAULT.data_intg ), .be_i ( {{top_pkg::TL_DBW}{1'b1}} ), .instr_type_i ( prim_mubi_pkg::MuBi4False ), .user_rsvd_i ( '0 ), // Response channel .valid_o ( sram_valid ), - .rdata_o ( obmbx_hostif_sram_read_resp_o ), + .rdata_o ( ombx_sram_read_resp_o ), .rdata_intg_o ( ), .err_o ( ), .intg_err_o ( intg_err_o ), @@ -108,12 +106,10 @@ module mbx_sramrwarb // Mux out response valid signal // We cannot differentiate on directly on the response signal of the TLUL adapter. We need // to look if the response was a response with data or not. It it's with data, it was a read - // request and we serve obmbx_hostif_sram_read_resp_vld_o. If it was a response without data - // it was a write request, so we serve ibmbx_hostif_sram_write_resp_vld_o - assign obmbx_hostif_sram_read_resp_vld_o = sram_valid & - (tl_host_i.d_opcode == tlul_pkg::AccessAckData); - assign ibmbx_hostif_sram_write_resp_vld_o = sram_valid & - (tl_host_i.d_opcode == tlul_pkg::AccessAck); + // request and we serve ombx_sram_read_resp_vld_o. If it was a response without data + // it was a write request, so we serve imbx_sram_write_resp_vld_o + assign ombx_sram_read_resp_vld_o = sram_valid & (tl_host_i.d_opcode == tlul_pkg::AccessAckData); + assign imbx_sram_write_resp_vld_o = sram_valid & (tl_host_i.d_opcode == tlul_pkg::AccessAck); // Functional Coverage `COVER(MaxOutstandingRequetsReached_C, sram_req & max_outstanding_reqs_reached) diff --git a/hw/ip/mbx/rtl/mbx_sysif.sv b/hw/ip/mbx/rtl/mbx_sysif.sv index 4e90617c250a5..7cb416539bd9d 100644 --- a/hw/ip/mbx/rtl/mbx_sysif.sv +++ b/hw/ip/mbx/rtl/mbx_sysif.sv @@ -26,23 +26,26 @@ module mbx_sysif // Access to the status register input logic sysif_status_busy_valid_i, input logic sysif_status_busy_i, + output logic sysif_status_busy_o, input logic sysif_status_doe_intr_status_set_i, output logic sysif_status_doe_intr_status_o, input logic sysif_status_error_set_i, input logic sysif_status_error_clear_i, - output logic sysif_status_async_msg_status_o, + output logic sysif_status_error_o, input logic sysif_status_async_msg_status_set_i, + output logic sysif_status_async_msg_status_o, input logic sysif_status_ready_valid_i, input logic sysif_status_ready_i, + output logic sysif_status_ready_o, // Control lines for backpressuring the bus - input logic ibmbx_pending_i, - input logic obmbx_pending_i, + input logic imbx_pending_i, + input logic ombx_pending_i, // Data interface for inbound and outbound mailbox output logic write_data_write_valid_o, output logic [CfgSramDataWidth-1:0] write_data_o, - input logic [CfgSramDataWidth-1:0] read_data_i, output logic read_data_read_valid_o, - output logic read_data_write_valid_o + output logic read_data_write_valid_o, + input logic [CfgSramDataWidth-1:0] read_data_i ); import mbx_reg_pkg::*; @@ -70,10 +73,10 @@ module mbx_sysif // Control register assign sysif_control_abort_set_o = reg2hw.sys_control.abort.qe & reg2hw.sys_control.abort.q; - assign hw2reg.sys_control.abort.d = 1'b0; + assign hw2reg.sys_control.abort.d = 1'b0; - assign sysif_control_go_set_o = reg2hw.sys_control.go.qe & reg2hw.sys_control.go.q; - assign hw2reg.sys_control.go.d = 1'b0; + assign sysif_control_go_set_o = reg2hw.sys_control.go.qe & reg2hw.sys_control.go.q; + assign hw2reg.sys_control.go.d = 1'b0; // Manual implementation of the doe_intr_en bit // SWAccess: RW @@ -124,6 +127,9 @@ module mbx_sysif // Fiddle out status register bits for external write logic assign sysif_status_async_msg_status_o = reg2hw.sys_status.async_msg_status.q; assign sysif_status_doe_intr_status_o = reg2hw.sys_status.doe_intr_status.q; + assign sysif_status_busy_o = reg2hw.sys_status.busy.q; + assign sysif_status_ready_o = reg2hw.sys_status.ready.q; + assign sysif_status_error_o = reg2hw.sys_status.error.q; // External read logic assign hw2reg.sys_status.busy.de = sysif_status_busy_valid_i; @@ -166,7 +172,7 @@ module mbx_sysif .addr_o ( ), .wdata_o ( reg_wdata_wdata ), .be_o ( ), - .busy_i ( ibmbx_pending_i ), + .busy_i ( imbx_pending_i ), .rdata_i ( '0 ), .error_i ( 1'b0 ) ); @@ -193,7 +199,7 @@ module mbx_sysif // Write values are ignored. A Write simply means the read has occured. .wdata_o ( ), .be_o ( ), - .busy_i ( obmbx_pending_i ), + .busy_i ( ombx_pending_i ), .rdata_i ( read_data_i ), .error_i ( 1'b0 ) ); From befec22e7b1ad93bbb9bf87a7e49927c80f559ba Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Tue, 5 Sep 2023 01:01:29 -0700 Subject: [PATCH 15/88] [hw,mbx,rtl] Adaptions to the signaling Signed-off-by: Robert Schilling --- hw/ip/mbx/data/mbx.hjson | 4 ++-- hw/ip/mbx/rtl/mbx_fsm.sv | 4 ++-- hw/ip/mbx/rtl/mbx_imbx.sv | 28 +++++++++++++--------------- hw/ip/mbx/rtl/mbx_sramrwarb.sv | 4 ++-- 4 files changed, 19 insertions(+), 21 deletions(-) diff --git a/hw/ip/mbx/data/mbx.hjson b/hw/ip/mbx/data/mbx.hjson index 61cb6f013a837..37404532944a4 100644 --- a/hw/ip/mbx/data/mbx.hjson +++ b/hw/ip/mbx/data/mbx.hjson @@ -137,7 +137,7 @@ hwext: "true" } { name: "ADDRESS_RANGE_REGWEN" - desc: "Used to lock the inound/outbound base/limit configuration registers." + desc: "Used to lock the inbound/outbound base/limit configuration registers." swaccess: "rw0c" fields: [ { name: "regwen" @@ -148,7 +148,7 @@ ] } { name: "ADDRESS_RANGE_VALID" - desc: "Used to lock the inound/outbound base/limit configuration registers." + desc: "Used to mark the inbound/outbound base/limit configuration registers to have a valid configuration." swaccess: "rw" hwaccess: "hro" fields: [ diff --git a/hw/ip/mbx/rtl/mbx_fsm.sv b/hw/ip/mbx/rtl/mbx_fsm.sv index 536002898d7b9..9bc23f1519ed9 100644 --- a/hw/ip/mbx/rtl/mbx_fsm.sv +++ b/hw/ip/mbx/rtl/mbx_fsm.sv @@ -82,11 +82,11 @@ module mbx_fsm #( MbxIdle: begin if (CfgObMbx) begin if (mbx_range_valid_i & writer_close_mbx_i) begin - ctrl_state_d = MbxWrite; + ctrl_state_d = MbxRead; end end else begin if (mbx_range_valid_i & writer_write_valid_i) begin - ctrl_state_d = MbxRead; + ctrl_state_d = MbxWrite; end end diff --git a/hw/ip/mbx/rtl/mbx_imbx.sv b/hw/ip/mbx/rtl/mbx_imbx.sv index 8873779cc34c0..eec5aa817d96f 100644 --- a/hw/ip/mbx/rtl/mbx_imbx.sv +++ b/hw/ip/mbx/rtl/mbx_imbx.sv @@ -15,12 +15,11 @@ module mbx_imbx #( output logic imbx_irq_host_o, output logic imbx_status_busy_update_o, output logic imbx_status_busy_o, - - // Device interface from the host side + // Access to the control and status registers of host interface input logic hostif_control_abort_set_i, input logic hostif_status_busy_clear_i, input logic hostif_status_error_set_i, - + // Range configuration for the private SRAM input logic hostif_range_valid_i, input logic [CfgSramAddrWidth-1:0] hostif_base_i, input logic [CfgSramAddrWidth-1:0] hostif_limit_i, @@ -34,8 +33,7 @@ module mbx_imbx #( input logic hostif_sram_write_gnt_i, output logic [CfgSramAddrWidth-1:0] hostif_sram_write_ptr_o ); - localparam int unsigned LCFG_SRM_ADDRINC = CfgSramDataWidth / 8; - localparam int unsigned LCFG_SRM_ADDRINC_LOG2 = $clog2(LCFG_SRM_ADDRINC); + localparam int unsigned LCFG_SRM_ADDRINC = CfgSramDataWidth / 8; logic [CfgSramAddrWidth-1:0] sram_write_ptr_d, sram_write_ptr_q; @@ -47,7 +45,7 @@ module mbx_imbx #( // RW2A = sticky from DEC/RW-stage to (srm command) ACK logic write_req; assign write_req = (mbx_empty & sysif_data_write_valid_i) | - (mbx_write & sysif_data_write_valid_i & (sram_write_ptr_q < hostif_limit_i)); + (mbx_write & sysif_data_write_valid_i & (sram_write_ptr_q <= hostif_limit_i)); // Create a sticky TLUL write request until its granted logic req_q; @@ -58,17 +56,17 @@ module mbx_imbx #( ) u_req_state ( .clk_i ( clk_i ), .rst_ni( rst_ni ), - .d_i ( hostif_sram_write_req_o & ~hostif_sram_write_req_o ), + .d_i ( hostif_sram_write_req_o & ~hostif_sram_write_gnt_i ), .q_o ( req_q ) ); - logic sys_abort; + logic sys_clear_abort; logic load_write_ptr, advance_write_ptr; - assign sys_abort = hostif_control_abort_set_i & mbx_sys_abort; + assign sys_clear_abort = hostif_control_abort_set_i & mbx_sys_abort; // Rewind the write pointer to the base - assign load_write_ptr = mbx_empty | sys_abort | + assign load_write_ptr = mbx_empty | sys_clear_abort | (mbx_read & hostif_status_busy_clear_i); // Advance the write pointer when the valid write command is granted by the tlul_adaptor_host @@ -80,7 +78,7 @@ module mbx_imbx #( if (load_write_ptr) begin sram_write_ptr_d = hostif_base_i; end else if (advance_write_ptr) begin - sram_write_ptr_d = sram_write_ptr_q + (1'b1 << LCFG_SRM_ADDRINC_LOG2); + sram_write_ptr_d = sram_write_ptr_q + LCFG_SRM_ADDRINC; end end @@ -99,7 +97,7 @@ module mbx_imbx #( logic set_pending, clear_pending; // Block the request from TLUL until the SRAM write is complete - assign set_pending = mbx_write & sysif_data_write_valid_i & (sram_write_ptr_q < hostif_limit_i); + assign set_pending = write_req; assign clear_pending = hostif_sram_write_gnt_i; prim_flop #( @@ -122,8 +120,8 @@ module mbx_imbx #( // Exit of mailbox read is used to clear imbx.busy and imbx.ready // Not yet qualified with mbx_read assign imbx_clear_busy = hostif_status_error_set_i | - sysif_control_abort_set_i | - hostif_status_busy_clear_i; + sysif_control_abort_set_i | + hostif_status_busy_clear_i; // External busy update interface assign imbx_status_busy_update_o = imbx_set_busy | imbx_clear_busy; @@ -132,7 +130,7 @@ module mbx_imbx #( // Generate host interrupt // on sys_write go, when host enters state to process the received objects // on abort - assign imbx_irq_host_o = mbx_read | sys_abort; + assign imbx_irq_host_o = mbx_read | mbx_sys_abort; mbx_fsm #( .CfgObMbx ( 0 ) diff --git a/hw/ip/mbx/rtl/mbx_sramrwarb.sv b/hw/ip/mbx/rtl/mbx_sramrwarb.sv index eb8774ffc44ee..7768870d1d6f0 100644 --- a/hw/ip/mbx/rtl/mbx_sramrwarb.sv +++ b/hw/ip/mbx/rtl/mbx_sramrwarb.sv @@ -33,12 +33,12 @@ module mbx_sramrwarb localparam int unsigned LCFG_MAX_REQS = 4; localparam int unsigned LCFG_MAX_REQS_LOG2 = $clog2(LCFG_MAX_REQS) + 1; - // We prioritze the read request. + // We prioritize the read request. // Winner has an outstanding read request. logic arb_read_winner; assign arb_read_winner = ombx_sram_read_req_i; - // Winnder has an outstanding write request but there is no read request + // Winner has an outstanding write request but there is no read request logic arb_write_winner; assign arb_write_winner = imbx_sram_write_req_i & ~arb_read_winner; From f72132288f9b029f5c725f495d7cdad06e485d1a Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Wed, 6 Sep 2023 01:10:12 -0700 Subject: [PATCH 16/88] [hw,mbx,rtl] Use Mubi-regwen for range config Signed-off-by: Robert Schilling --- hw/ip/mbx/data/mbx.hjson | 14 ++++++++--- hw/ip/mbx/data/mbx_sec_cm_testplan.hjson | 6 +++++ hw/ip/mbx/rtl/mbx_host_reg_top.sv | 30 +++++++++++++++--------- hw/ip/mbx/rtl/mbx_hostif.sv | 1 + hw/ip/mbx/rtl/mbx_reg_pkg.sv | 16 ++++++------- 5 files changed, 45 insertions(+), 22 deletions(-) diff --git a/hw/ip/mbx/data/mbx.hjson b/hw/ip/mbx/data/mbx.hjson index 37404532944a4..fc07f79852cef 100644 --- a/hw/ip/mbx/data/mbx.hjson +++ b/hw/ip/mbx/data/mbx.hjson @@ -60,6 +60,9 @@ { name: "BUS.INTEGRITY" desc: "End-to-end bus integrity scheme." } + { name: "ADDRESS_RANGE.CONFIG.REGWEN_MUBI", + desc: "Private SRAM memory range is software multibit lockable." + } ] regwidth: "32" registers: { @@ -141,9 +144,14 @@ swaccess: "rw0c" fields: [ { name: "regwen" - desc: "Once cleared the mailbox inbound/outbound base/limit registers will be locked until the next reset." - bits: "0" - resval: "1" + desc: ''' + Once cleared the mailbox inbound/outbound base/limit registers will be locked until the next reset. + + Default Value = kMultiBitBool4True -> Unlocked at reset. + ''' + bits: "3:0" + mubi: "true" + resval: true } ] } diff --git a/hw/ip/mbx/data/mbx_sec_cm_testplan.hjson b/hw/ip/mbx/data/mbx_sec_cm_testplan.hjson index fdd1361e1e4bd..aa6a330b11526 100644 --- a/hw/ip/mbx/data/mbx_sec_cm_testplan.hjson +++ b/hw/ip/mbx/data/mbx_sec_cm_testplan.hjson @@ -29,5 +29,11 @@ stage: V2S tests: [] } + { + name: sec_cm_address_range_config_regwen_mubi + desc: "Verify the countermeasure(s) ADDRESS_RANGE.CONFIG.REGWEN_MUBI." + stage: V2S + tests: [] + } ] } diff --git a/hw/ip/mbx/rtl/mbx_host_reg_top.sv b/hw/ip/mbx/rtl/mbx_host_reg_top.sv index d669b29e1cb0b..eca6f583d4a8c 100644 --- a/hw/ip/mbx/rtl/mbx_host_reg_top.sv +++ b/hw/ip/mbx/rtl/mbx_host_reg_top.sv @@ -150,8 +150,8 @@ module mbx_host_reg_top ( logic status_ready_qs; logic status_ready_wd; logic address_range_regwen_we; - logic address_range_regwen_qs; - logic address_range_regwen_wd; + logic [3:0] address_range_regwen_qs; + logic [3:0] address_range_regwen_wd; logic address_range_valid_we; logic address_range_valid_qs; logic address_range_valid_wd; @@ -396,10 +396,10 @@ module mbx_host_reg_top ( // R[address_range_regwen]: V(False) prim_subreg #( - .DW (1), + .DW (4), .SwAccess(prim_subreg_pkg::SwAccessW0C), - .RESVAL (1'h1), - .Mubi (1'b0) + .RESVAL (4'h6), + .Mubi (1'b1) ) u_address_range_regwen ( .clk_i (clk_i), .rst_ni (rst_ni), @@ -464,7 +464,9 @@ module mbx_host_reg_top ( ); // Create REGWEN-gated WE signal logic inbound_base_address_gated_we; - assign inbound_base_address_gated_we = inbound_base_address_we & address_range_regwen_qs; + assign inbound_base_address_gated_we = + inbound_base_address_we & + prim_mubi_pkg::mubi4_test_true_strict(prim_mubi_pkg::mubi4_t'(address_range_regwen_qs)); prim_subreg #( .DW (30), .SwAccess(prim_subreg_pkg::SwAccessRW), @@ -507,7 +509,9 @@ module mbx_host_reg_top ( ); // Create REGWEN-gated WE signal logic inbound_limit_address_gated_we; - assign inbound_limit_address_gated_we = inbound_limit_address_we & address_range_regwen_qs; + assign inbound_limit_address_gated_we = + inbound_limit_address_we & + prim_mubi_pkg::mubi4_test_true_strict(prim_mubi_pkg::mubi4_t'(address_range_regwen_qs)); prim_subreg #( .DW (30), .SwAccess(prim_subreg_pkg::SwAccessRW), @@ -571,7 +575,9 @@ module mbx_host_reg_top ( ); // Create REGWEN-gated WE signal logic outbound_base_address_gated_we; - assign outbound_base_address_gated_we = outbound_base_address_we & address_range_regwen_qs; + assign outbound_base_address_gated_we = + outbound_base_address_we & + prim_mubi_pkg::mubi4_test_true_strict(prim_mubi_pkg::mubi4_t'(address_range_regwen_qs)); prim_subreg #( .DW (30), .SwAccess(prim_subreg_pkg::SwAccessRW), @@ -614,7 +620,9 @@ module mbx_host_reg_top ( ); // Create REGWEN-gated WE signal logic outbound_limit_address_gated_we; - assign outbound_limit_address_gated_we = outbound_limit_address_we & address_range_regwen_qs; + assign outbound_limit_address_gated_we = + outbound_limit_address_we & + prim_mubi_pkg::mubi4_test_true_strict(prim_mubi_pkg::mubi4_t'(address_range_regwen_qs)); prim_subreg #( .DW (30), .SwAccess(prim_subreg_pkg::SwAccessRW), @@ -780,7 +788,7 @@ module mbx_host_reg_top ( assign status_ready_wd = reg_wdata[31]; assign address_range_regwen_we = addr_hit[6] & reg_we & !reg_error; - assign address_range_regwen_wd = reg_wdata[0]; + assign address_range_regwen_wd = reg_wdata[3:0]; assign address_range_valid_we = addr_hit[7] & reg_we & !reg_error; assign address_range_valid_wd = reg_wdata[0]; @@ -856,7 +864,7 @@ module mbx_host_reg_top ( end addr_hit[6]: begin - reg_rdata_next[0] = address_range_regwen_qs; + reg_rdata_next[3:0] = address_range_regwen_qs; end addr_hit[7]: begin diff --git a/hw/ip/mbx/rtl/mbx_hostif.sv b/hw/ip/mbx/rtl/mbx_hostif.sv index 7b986605b6881..43166fe80eecb 100644 --- a/hw/ip/mbx/rtl/mbx_hostif.sv +++ b/hw/ip/mbx/rtl/mbx_hostif.sv @@ -77,6 +77,7 @@ module mbx_hostif end // SEC_CM: BUS.INTEGRITY + // SEC_CM: ADDRESS_RANGE.CONFIG.REGWEN_MUBI mbx_host_reg_top u_regs( .clk_i ( clk_i ), .rst_ni ( rst_ni ), diff --git a/hw/ip/mbx/rtl/mbx_reg_pkg.sv b/hw/ip/mbx/rtl/mbx_reg_pkg.sv index c9199471e5cdd..c98dbd260b049 100644 --- a/hw/ip/mbx/rtl/mbx_reg_pkg.sv +++ b/hw/ip/mbx/rtl/mbx_reg_pkg.sv @@ -70,7 +70,7 @@ package mbx_reg_pkg; } mbx_reg2hw_status_reg_t; typedef struct packed { - logic q; + logic [3:0] q; } mbx_reg2hw_address_range_regwen_reg_t; typedef struct packed { @@ -159,13 +159,13 @@ package mbx_reg_pkg; // Register -> HW type for host interface typedef struct packed { - mbx_reg2hw_intr_state_reg_t intr_state; // [219:219] - mbx_reg2hw_intr_enable_reg_t intr_enable; // [218:218] - mbx_reg2hw_intr_test_reg_t intr_test; // [217:216] - mbx_reg2hw_alert_test_reg_t alert_test; // [215:214] - mbx_reg2hw_control_reg_t control; // [213:210] - mbx_reg2hw_status_reg_t status; // [209:200] - mbx_reg2hw_address_range_regwen_reg_t address_range_regwen; // [199:199] + mbx_reg2hw_intr_state_reg_t intr_state; // [222:222] + mbx_reg2hw_intr_enable_reg_t intr_enable; // [221:221] + mbx_reg2hw_intr_test_reg_t intr_test; // [220:219] + mbx_reg2hw_alert_test_reg_t alert_test; // [218:217] + mbx_reg2hw_control_reg_t control; // [216:213] + mbx_reg2hw_status_reg_t status; // [212:203] + mbx_reg2hw_address_range_regwen_reg_t address_range_regwen; // [202:199] mbx_reg2hw_address_range_valid_reg_t address_range_valid; // [198:198] mbx_reg2hw_inbound_base_address_reg_t inbound_base_address; // [197:167] mbx_reg2hw_inbound_limit_address_reg_t inbound_limit_address; // [166:136] From e8b300e5f38479815e4e8ae11b0e21c56eadb26f Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Fri, 8 Sep 2023 09:21:26 -0700 Subject: [PATCH 17/88] [hw,mbx,rtl] No IRQ muxing between ready and abort Signed-off-by: Robert Schilling --- hw/ip/mbx/data/mbx.hjson | 3 + hw/ip/mbx/rtl/mbx.sv | 12 ++- hw/ip/mbx/rtl/mbx_host_reg_top.sv | 137 ++++++++++++++++++++++++------ hw/ip/mbx/rtl/mbx_hostif.sv | 43 +++++++--- hw/ip/mbx/rtl/mbx_imbx.sv | 6 +- hw/ip/mbx/rtl/mbx_reg_pkg.sv | 45 +++++++--- 6 files changed, 190 insertions(+), 56 deletions(-) diff --git a/hw/ip/mbx/data/mbx.hjson b/hw/ip/mbx/data/mbx.hjson index fc07f79852cef..1efdd5bdda39f 100644 --- a/hw/ip/mbx/data/mbx.hjson +++ b/hw/ip/mbx/data/mbx.hjson @@ -50,6 +50,9 @@ { name: "mbx_ready" desc: "A new object was received in the inbound mailbox." } + { name: "mbx_abort" + desc: "An abort request was received from the requester." + } ] alert_list: [ { name: "fatal_fault" diff --git a/hw/ip/mbx/rtl/mbx.sv b/hw/ip/mbx/rtl/mbx.sv index 989ee495350bb..b9e6fb9b3f449 100644 --- a/hw/ip/mbx/rtl/mbx.sv +++ b/hw/ip/mbx/rtl/mbx.sv @@ -17,6 +17,7 @@ module mbx input logic rst_ni, // Comportable interrupt to the OT output logic intr_mbx_ready_o, + output logic intr_mbx_abort_o, // Custom interrupt to the system requester output logic doe_intr_support_o, output logic doe_intr_en_o, @@ -48,7 +49,7 @@ module mbx // Control and Status signals of the host interface ////////////////////////////////////////////////////////////////////////////// - logic hostif_event_intr; + logic hostif_event_intr_ready, hostif_event_intr_abort; logic hostif_address_range_valid; logic sysif_control_abort_write; @@ -88,8 +89,10 @@ module mbx .tl_host_i ( tl_host_i ), .tl_host_o ( tl_host_o ), .intg_err_i ( alert_signal ), - .event_intr_i ( hostif_event_intr ), - .irq_o ( intr_mbx_ready_o ), + .event_intr_ready_i ( hostif_event_intr_ready ), + .event_intr_abort_i ( hostif_event_intr_abort ), + .intr_ready_o ( intr_mbx_ready_o ), + .intr_abort_o ( intr_mbx_abort_o ), .alert_rx_i ( alert_rx_i ), .alert_tx_o ( alert_tx_o ), // Access to the control register @@ -209,7 +212,8 @@ module mbx // Interface to the host port .imbx_state_error_o ( imbx_state_error ), .imbx_pending_o ( imbx_pending ), - .imbx_irq_host_o ( hostif_event_intr ), + .imbx_irq_ready_o ( hostif_event_intr_ready ), + .imbx_irq_abort_o ( hostif_event_intr_abort ), .imbx_status_busy_update_o ( imbx_status_busy_valid ), .imbx_status_busy_o ( imbx_status_busy ), diff --git a/hw/ip/mbx/rtl/mbx_host_reg_top.sv b/hw/ip/mbx/rtl/mbx_host_reg_top.sv index eca6f583d4a8c..f37020112c8da 100644 --- a/hw/ip/mbx/rtl/mbx_host_reg_top.sv +++ b/hw/ip/mbx/rtl/mbx_host_reg_top.sv @@ -122,13 +122,18 @@ module mbx_host_reg_top ( // Format: __{wd|we|qs} // or _{wd|we|qs} if field == 1 or 0 logic intr_state_we; - logic intr_state_qs; - logic intr_state_wd; + logic intr_state_mbx_ready_qs; + logic intr_state_mbx_ready_wd; + logic intr_state_mbx_abort_qs; + logic intr_state_mbx_abort_wd; logic intr_enable_we; - logic intr_enable_qs; - logic intr_enable_wd; + logic intr_enable_mbx_ready_qs; + logic intr_enable_mbx_ready_wd; + logic intr_enable_mbx_abort_qs; + logic intr_enable_mbx_abort_wd; logic intr_test_we; - logic intr_test_wd; + logic intr_test_mbx_ready_wd; + logic intr_test_mbx_abort_wd; logic alert_test_we; logic alert_test_wd; logic control_re; @@ -177,46 +182,75 @@ module mbx_host_reg_top ( // Register instances // R[intr_state]: V(False) + // F[mbx_ready]: 0:0 prim_subreg #( .DW (1), .SwAccess(prim_subreg_pkg::SwAccessW1C), .RESVAL (1'h0), .Mubi (1'b0) - ) u_intr_state ( + ) u_intr_state_mbx_ready ( .clk_i (clk_i), .rst_ni (rst_ni), // from register interface .we (intr_state_we), - .wd (intr_state_wd), + .wd (intr_state_mbx_ready_wd), // from internal hardware - .de (hw2reg.intr_state.de), - .d (hw2reg.intr_state.d), + .de (hw2reg.intr_state.mbx_ready.de), + .d (hw2reg.intr_state.mbx_ready.d), // to internal hardware .qe (), - .q (reg2hw.intr_state.q), + .q (reg2hw.intr_state.mbx_ready.q), .ds (), // to register interface (read) - .qs (intr_state_qs) + .qs (intr_state_mbx_ready_qs) + ); + + // F[mbx_abort]: 1:1 + prim_subreg #( + .DW (1), + .SwAccess(prim_subreg_pkg::SwAccessW1C), + .RESVAL (1'h0), + .Mubi (1'b0) + ) u_intr_state_mbx_abort ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (intr_state_we), + .wd (intr_state_mbx_abort_wd), + + // from internal hardware + .de (hw2reg.intr_state.mbx_abort.de), + .d (hw2reg.intr_state.mbx_abort.d), + + // to internal hardware + .qe (), + .q (reg2hw.intr_state.mbx_abort.q), + .ds (), + + // to register interface (read) + .qs (intr_state_mbx_abort_qs) ); // R[intr_enable]: V(False) + // F[mbx_ready]: 0:0 prim_subreg #( .DW (1), .SwAccess(prim_subreg_pkg::SwAccessRW), .RESVAL (1'h0), .Mubi (1'b0) - ) u_intr_enable ( + ) u_intr_enable_mbx_ready ( .clk_i (clk_i), .rst_ni (rst_ni), // from register interface .we (intr_enable_we), - .wd (intr_enable_wd), + .wd (intr_enable_mbx_ready_wd), // from internal hardware .de (1'b0), @@ -224,32 +258,76 @@ module mbx_host_reg_top ( // to internal hardware .qe (), - .q (reg2hw.intr_enable.q), + .q (reg2hw.intr_enable.mbx_ready.q), .ds (), // to register interface (read) - .qs (intr_enable_qs) + .qs (intr_enable_mbx_ready_qs) + ); + + // F[mbx_abort]: 1:1 + prim_subreg #( + .DW (1), + .SwAccess(prim_subreg_pkg::SwAccessRW), + .RESVAL (1'h0), + .Mubi (1'b0) + ) u_intr_enable_mbx_abort ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (intr_enable_we), + .wd (intr_enable_mbx_abort_wd), + + // from internal hardware + .de (1'b0), + .d ('0), + + // to internal hardware + .qe (), + .q (reg2hw.intr_enable.mbx_abort.q), + .ds (), + + // to register interface (read) + .qs (intr_enable_mbx_abort_qs) ); // R[intr_test]: V(True) logic intr_test_qe; - logic [0:0] intr_test_flds_we; + logic [1:0] intr_test_flds_we; assign intr_test_qe = &intr_test_flds_we; + // F[mbx_ready]: 0:0 prim_subreg_ext #( .DW (1) - ) u_intr_test ( + ) u_intr_test_mbx_ready ( .re (1'b0), .we (intr_test_we), - .wd (intr_test_wd), + .wd (intr_test_mbx_ready_wd), .d ('0), .qre (), .qe (intr_test_flds_we[0]), - .q (reg2hw.intr_test.q), + .q (reg2hw.intr_test.mbx_ready.q), .ds (), .qs () ); - assign reg2hw.intr_test.qe = intr_test_qe; + assign reg2hw.intr_test.mbx_ready.qe = intr_test_qe; + + // F[mbx_abort]: 1:1 + prim_subreg_ext #( + .DW (1) + ) u_intr_test_mbx_abort ( + .re (1'b0), + .we (intr_test_we), + .wd (intr_test_mbx_abort_wd), + .d ('0), + .qre (), + .qe (intr_test_flds_we[1]), + .q (reg2hw.intr_test.mbx_abort.q), + .ds (), + .qs () + ); + assign reg2hw.intr_test.mbx_abort.qe = intr_test_qe; // R[alert_test]: V(True) @@ -758,13 +836,19 @@ module mbx_host_reg_top ( // Generate write-enables assign intr_state_we = addr_hit[0] & reg_we & !reg_error; - assign intr_state_wd = reg_wdata[0]; + assign intr_state_mbx_ready_wd = reg_wdata[0]; + + assign intr_state_mbx_abort_wd = reg_wdata[1]; assign intr_enable_we = addr_hit[1] & reg_we & !reg_error; - assign intr_enable_wd = reg_wdata[0]; + assign intr_enable_mbx_ready_wd = reg_wdata[0]; + + assign intr_enable_mbx_abort_wd = reg_wdata[1]; assign intr_test_we = addr_hit[2] & reg_we & !reg_error; - assign intr_test_wd = reg_wdata[0]; + assign intr_test_mbx_ready_wd = reg_wdata[0]; + + assign intr_test_mbx_abort_wd = reg_wdata[1]; assign alert_test_we = addr_hit[3] & reg_we & !reg_error; assign alert_test_wd = reg_wdata[0]; @@ -835,15 +919,18 @@ module mbx_host_reg_top ( reg_rdata_next = '0; unique case (1'b1) addr_hit[0]: begin - reg_rdata_next[0] = intr_state_qs; + reg_rdata_next[0] = intr_state_mbx_ready_qs; + reg_rdata_next[1] = intr_state_mbx_abort_qs; end addr_hit[1]: begin - reg_rdata_next[0] = intr_enable_qs; + reg_rdata_next[0] = intr_enable_mbx_ready_qs; + reg_rdata_next[1] = intr_enable_mbx_abort_qs; end addr_hit[2]: begin reg_rdata_next[0] = '0; + reg_rdata_next[1] = '0; end addr_hit[3]: begin diff --git a/hw/ip/mbx/rtl/mbx_hostif.sv b/hw/ip/mbx/rtl/mbx_hostif.sv index 43166fe80eecb..c1067ab5a240c 100644 --- a/hw/ip/mbx/rtl/mbx_hostif.sv +++ b/hw/ip/mbx/rtl/mbx_hostif.sv @@ -14,8 +14,10 @@ module mbx_hostif input tlul_pkg::tl_h2d_t tl_host_i, output tlul_pkg::tl_d2h_t tl_host_o, // Generated interrupt event - input logic event_intr_i, - output logic irq_o, + input logic event_intr_ready_i, + input logic event_intr_abort_i, + output logic intr_ready_o, + output logic intr_abort_o, // External errors input logic intg_err_i, // Alerts @@ -89,18 +91,31 @@ module mbx_hostif .devmode_i ( 1'b1 ) ); - // instantiate interrupt hardware primitive - prim_intr_hw #(.Width(1)) u_intr_hw ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .event_intr_i ( event_intr_i ), - .reg2hw_intr_enable_q_i ( reg2hw.intr_enable.q ), - .reg2hw_intr_test_q_i ( reg2hw.intr_test.q ), - .reg2hw_intr_test_qe_i ( reg2hw.intr_test.qe ), - .reg2hw_intr_state_q_i ( reg2hw.intr_state.q ), - .hw2reg_intr_state_de_o ( hw2reg.intr_state.de ), - .hw2reg_intr_state_d_o ( hw2reg.intr_state.d ), - .intr_o ( irq_o ) + // Instantiate interrupt hardware primitives for ready and abort IRQ + prim_intr_hw #(.Width(1)) u_intr_ready ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .event_intr_i ( event_intr_ready_i ), + .reg2hw_intr_enable_q_i ( reg2hw.intr_enable.mbx_ready.q ), + .reg2hw_intr_test_q_i ( reg2hw.intr_test.mbx_ready.q ), + .reg2hw_intr_test_qe_i ( reg2hw.intr_test.mbx_ready.qe ), + .reg2hw_intr_state_q_i ( reg2hw.intr_state.mbx_ready.q ), + .hw2reg_intr_state_de_o ( hw2reg.intr_state.mbx_ready.de ), + .hw2reg_intr_state_d_o ( hw2reg.intr_state.mbx_ready.d ), + .intr_o ( intr_ready_o ) + ); + + prim_intr_hw #(.Width(1)) u_intr_abort ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .event_intr_i ( event_intr_abort_i ), + .reg2hw_intr_enable_q_i ( reg2hw.intr_enable.mbx_abort.q ), + .reg2hw_intr_test_q_i ( reg2hw.intr_test.mbx_abort.q ), + .reg2hw_intr_test_qe_i ( reg2hw.intr_test.mbx_abort.qe ), + .reg2hw_intr_state_q_i ( reg2hw.intr_state.mbx_abort.q ), + .hw2reg_intr_state_de_o ( hw2reg.intr_state.mbx_abort.de ), + .hw2reg_intr_state_d_o ( hw2reg.intr_state.mbx_abort.d ), + .intr_o ( intr_abort_o ) ); // Control Register diff --git a/hw/ip/mbx/rtl/mbx_imbx.sv b/hw/ip/mbx/rtl/mbx_imbx.sv index eec5aa817d96f..b9019c2616be3 100644 --- a/hw/ip/mbx/rtl/mbx_imbx.sv +++ b/hw/ip/mbx/rtl/mbx_imbx.sv @@ -12,7 +12,8 @@ module mbx_imbx #( input logic rst_ni, output logic imbx_state_error_o, output logic imbx_pending_o, - output logic imbx_irq_host_o, + output logic imbx_irq_ready_o, + output logic imbx_irq_abort_o, output logic imbx_status_busy_update_o, output logic imbx_status_busy_o, // Access to the control and status registers of host interface @@ -130,7 +131,8 @@ module mbx_imbx #( // Generate host interrupt // on sys_write go, when host enters state to process the received objects // on abort - assign imbx_irq_host_o = mbx_read | mbx_sys_abort; + assign imbx_irq_ready_o = mbx_read; + assign imbx_irq_abort_o = mbx_sys_abort; mbx_fsm #( .CfgObMbx ( 0 ) diff --git a/hw/ip/mbx/rtl/mbx_reg_pkg.sv b/hw/ip/mbx/rtl/mbx_reg_pkg.sv index c98dbd260b049..a323869c6f0c4 100644 --- a/hw/ip/mbx/rtl/mbx_reg_pkg.sv +++ b/hw/ip/mbx/rtl/mbx_reg_pkg.sv @@ -18,16 +18,32 @@ package mbx_reg_pkg; /////////////////////////////////////////////// typedef struct packed { - logic q; + struct packed { + logic q; + } mbx_ready; + struct packed { + logic q; + } mbx_abort; } mbx_reg2hw_intr_state_reg_t; typedef struct packed { - logic q; + struct packed { + logic q; + } mbx_ready; + struct packed { + logic q; + } mbx_abort; } mbx_reg2hw_intr_enable_reg_t; typedef struct packed { - logic q; - logic qe; + struct packed { + logic q; + logic qe; + } mbx_ready; + struct packed { + logic q; + logic qe; + } mbx_abort; } mbx_reg2hw_intr_test_reg_t; typedef struct packed { @@ -113,8 +129,14 @@ package mbx_reg_pkg; } mbx_reg2hw_outbound_object_size_reg_t; typedef struct packed { - logic d; - logic de; + struct packed { + logic d; + logic de; + } mbx_ready; + struct packed { + logic d; + logic de; + } mbx_abort; } mbx_hw2reg_intr_state_reg_t; typedef struct packed { @@ -159,9 +181,9 @@ package mbx_reg_pkg; // Register -> HW type for host interface typedef struct packed { - mbx_reg2hw_intr_state_reg_t intr_state; // [222:222] - mbx_reg2hw_intr_enable_reg_t intr_enable; // [221:221] - mbx_reg2hw_intr_test_reg_t intr_test; // [220:219] + mbx_reg2hw_intr_state_reg_t intr_state; // [226:225] + mbx_reg2hw_intr_enable_reg_t intr_enable; // [224:223] + mbx_reg2hw_intr_test_reg_t intr_test; // [222:219] mbx_reg2hw_alert_test_reg_t alert_test; // [218:217] mbx_reg2hw_control_reg_t control; // [216:213] mbx_reg2hw_status_reg_t status; // [212:203] @@ -178,7 +200,7 @@ package mbx_reg_pkg; // HW -> register type for host interface typedef struct packed { - mbx_hw2reg_intr_state_reg_t intr_state; // [80:79] + mbx_hw2reg_intr_state_reg_t intr_state; // [82:79] mbx_hw2reg_control_reg_t control; // [78:77] mbx_hw2reg_status_reg_t status; // [76:72] mbx_hw2reg_inbound_write_ptr_reg_t inbound_write_ptr; // [71:42] @@ -204,8 +226,9 @@ package mbx_reg_pkg; parameter logic [HostAw-1:0] MBX_OUTBOUND_OBJECT_SIZE_OFFSET = 6'h 38; // Reset values for hwext registers and their fields for host interface - parameter logic [0:0] MBX_INTR_TEST_RESVAL = 1'h 0; + parameter logic [1:0] MBX_INTR_TEST_RESVAL = 2'h 0; parameter logic [0:0] MBX_INTR_TEST_MBX_READY_RESVAL = 1'h 0; + parameter logic [0:0] MBX_INTR_TEST_MBX_ABORT_RESVAL = 1'h 0; parameter logic [0:0] MBX_ALERT_TEST_RESVAL = 1'h 0; parameter logic [0:0] MBX_ALERT_TEST_FATAL_FAULT_RESVAL = 1'h 0; parameter logic [1:0] MBX_CONTROL_RESVAL = 2'h 0; From aa2ad5091c5f28ff3f5540cd5dbe4ae055daaecb Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Wed, 13 Sep 2023 06:27:35 -0700 Subject: [PATCH 18/88] [hw,mbx,rtl] Make DOE Interrupt Addr/Data an alias to host interface Signed-off-by: Robert Schilling --- hw/ip/mbx/data/mbx.hjson | 72 ++++++++++++----- hw/ip/mbx/rtl/mbx.sv | 14 +++- hw/ip/mbx/rtl/mbx_host_reg_top.sv | 62 ++++++++++++-- hw/ip/mbx/rtl/mbx_hostif.sv | 12 ++- hw/ip/mbx/rtl/mbx_reg_pkg.sv | 130 ++++++++++++++++++------------ hw/ip/mbx/rtl/mbx_sys_reg_top.sv | 84 +++++++++---------- hw/ip/mbx/rtl/mbx_sysif.sv | 8 ++ 7 files changed, 261 insertions(+), 121 deletions(-) diff --git a/hw/ip/mbx/data/mbx.hjson b/hw/ip/mbx/data/mbx.hjson index 1efdd5bdda39f..7a82b8bc3529e 100644 --- a/hw/ip/mbx/data/mbx.hjson +++ b/hw/ip/mbx/data/mbx.hjson @@ -72,6 +72,7 @@ host: [ { name: "CONTROL" desc: "DOE mailbox control register visible to the mailbox host" + hwext: "true" fields: [ { name: "abort" desc: "Alias of the DoE mailbox abort bit" @@ -90,10 +91,10 @@ hwqe: "true" } ] - hwext: "true" } { name: "STATUS" desc: "DOE mailbox status register visible to the mailbox host" + hwext: "true" fields: [ { name: "busy" desc: "Alias of the DoE mailbox busy bit" @@ -139,8 +140,7 @@ hwaccess: "hrw" hwqe: "true" } - ] - hwext: "true" + ] } { name: "ADDRESS_RANGE_REGWEN" desc: "Used to lock the inbound/outbound base/limit configuration registers." @@ -205,6 +205,7 @@ desc: '''Write pointer for the next inbound data write. This pointer is 4-byte aligned, the lower 2-bits are always zero. ''' + hwext: "true" fields: [ { name: "inbound_read_ptr" desc: "Write pointer for the next inbound data write." @@ -215,7 +216,6 @@ hwqe: "true" } ] - hwext: "true" } { name: "OUTBOUND_BASE_ADDRESS" desc: '''Base address of SRAM region, which is used to buffer the outbound mailbox data. @@ -251,6 +251,7 @@ desc: '''Read pointer for the next outbound data read. This pointer is 4-byte aligned, the lower 2-bits are always zero. ''' + hwext: "true" fields: [ { name: "outbound_write_ptr" desc: "Read pointer for the next outbound data read." @@ -261,7 +262,6 @@ hwqe: "true" } ] - hwext: "true" } { name: "OUTBOUND_OBJECT_SIZE" desc: '''Indicates the size of the data object to be transferred out. @@ -279,13 +279,45 @@ } ] } + { name: "DOE_INTR_MSG_ADDR" + desc: ''' + Software read-only alias of the DOE_INTR_MSG_ADDR register of the SYS interface for convenient access of the OT firmware. + Defined only for FW-to-FW mailboxes. + ''' + hwext: "true" + hwaccess: "hrw" + swaccess: "ro" + fields: [ + { name: "doe_intr_msg_addr" + desc: "Utilized by the mailbox responder to send an interrupt message to the requester via a write to the configured address." + bits: "31:0" + resval: "0x0" + } + ] + } + { name: "DOE_INTR_MSG_DATA" + desc: ''' + Software read-only alias of the DOE_INTR_MSG_DATA register of the SYS interface for convenient access of the OT firmware. + Defined only for FW-to-FW mailboxes. + ''' + hwext: "true" + hwaccess: "hrw" + swaccess: "ro" + fields: [ + { name: "doe_intr_msg_data" + desc: "Interrupt message data to be sent to the address configured in the DOE_INTR_MSG_ADDR register." + bits: "31:0" + resval: "0x0" + } + ] + } ] sys: [ - { name: "DOE_INTR_MSG_ADDR" - desc: ''' - Utilized by the mailbox responder to send an interrupt message to the requester via a write to the configured address. - Defined only for FW-to-FW mailboxes. - ''' + { name: "SYS_DOE_INTR_MSG_ADDR" + desc: ''' + Utilized by the mailbox responder to send an interrupt message to the requester via a write to the configured address. + Defined only for FW-to-FW mailboxes. + ''' fields: [ { name: "doe_intr_msg_addr" desc: "Utilized by the mailbox responder to send an interrupt message to the requester via a write to the configured address." @@ -297,7 +329,7 @@ } ] } - { name: "DOE_INTR_MSG_DATA" + { name: "SYS_DOE_INTR_MSG_DATA" desc: ''' Interrupt message data to be sent to the address configured in the DOE_INTR_MSG_ADDR register. Defined only for FW-to-FW mailboxes. @@ -315,11 +347,9 @@ } { name: "SYS_CONTROL" desc: "DOE mailbox control register." - hwext: "false" hwaccess: "hrw" hwqe: "true" hwext: "true" - fields: [ { name: "abort" desc: ''' @@ -355,7 +385,7 @@ } ] } - { name: "sys_status" + { name: "SYS_STATUS" desc: "DOE mailbox status register" fields: [ { name: "busy" @@ -400,26 +430,26 @@ When Set, this bit indicates the DOE instance has a data object available to be read by system firmware/software. The transition of this bit from Clear to Set is an interrupt triggering event. ''' - bits: "31" - resval: "0x0" - swaccess: "ro" - hwaccess: "hrw" + bits: "31" + resval: "0x0" + swaccess: "ro" + hwaccess: "hrw" } ] } { window: { - name: "wdata" + name: "WDATA" items: "1" swaccess: "wo" desc: '''DOE mailbox write data register. The DOE instance receives data objects via writes to this register. A successful write adds one DWORD to the data object being assembled in the DOE instance. A write of 1 to the DOE Go bit in the DOE Control Register marks the completion of the data transfer, i.e, final DWORD for the object has been written. - ''' + ''' } } { window: { - name: "rdata" + name: "RDATA" desc: '''DOE mailbox read data register If the Data Object Ready bit is Set, a read of this register returns the current DW of the data object. A write of any value to this register indicates a successful read of the current DWORD. diff --git a/hw/ip/mbx/rtl/mbx.sv b/hw/ip/mbx/rtl/mbx.sv index b9e6fb9b3f449..50c3e1bd2ba96 100644 --- a/hw/ip/mbx/rtl/mbx.sv +++ b/hw/ip/mbx/rtl/mbx.sv @@ -62,6 +62,10 @@ module mbx hostif_control_abort_set, hostif_status_busy_clear, hostif_status_error_set, hostif_status_error_clear; + // Alias signals from the sys interface + logic [CfgSramAddrWidth-1:0] sysif_intr_msg_addr; + logic [CfgSramDataWidth-1:0] sysif_intr_msg_data; + ////////////////////////////////////////////////////////////////////////////// // Signals for the Inbox ////////////////////////////////////////////////////////////////////////////// @@ -81,7 +85,8 @@ module mbx mbx_hostif #( .AlertAsyncOn ( AlertAsyncOn ), - .CfgSramAddrWidth( CfgSramAddrWidth ) + .CfgSramAddrWidth( CfgSramAddrWidth ), + .CfgSramDataWidth( CfgSramDataWidth ) ) u_hostif ( .clk_i ( clk_i ), .rst_ni ( rst_ni ), @@ -122,6 +127,9 @@ module mbx .hostif_ombx_object_size_o ( hostif_ombx_object_size_wdata ), .hostif_ombx_object_size_read_i ( hostif_ombx_object_size_read ), .hostif_ombx_object_size_i ( hostif_ombx_object_size_rdata ), + // Alias of the interrupt address and data registers from the SYS interface + .sysif_intr_msg_addr_i ( sysif_intr_msg_addr ), + .sysif_intr_msg_data_i ( sysif_intr_msg_data ), // Control inputs coming from the system registers interface .sysif_control_abort_write_i ( sysif_control_abort_write ) ); @@ -156,6 +164,7 @@ module mbx logic sysif_read_data_read_valid, sysif_read_data_write_valid; mbx_sysif #( + .CfgSramAddrWidth ( CfgSramAddrWidth ), .CfgSramDataWidth ( CfgSramDataWidth ), .DoeIrqSupport ( DoeIrqSupport ) ) u_sysif ( @@ -191,6 +200,9 @@ module mbx .sysif_status_ready_valid_i ( ombx_status_ready_valid ), .sysif_status_ready_i ( ombx_status_ready ), .sysif_status_ready_o ( sysif_status_ready ), + // Alias of the interrupt address and data registers to the host interface + .sysif_intr_msg_addr_o ( sysif_intr_msg_addr ), + .sysif_intr_msg_data_o ( sysif_intr_msg_data ), // Control lines for backpressuring the bus .imbx_pending_i ( imbx_pending ), .ombx_pending_i ( ombx_pending ), diff --git a/hw/ip/mbx/rtl/mbx_host_reg_top.sv b/hw/ip/mbx/rtl/mbx_host_reg_top.sv index f37020112c8da..996cbc150c1ea 100644 --- a/hw/ip/mbx/rtl/mbx_host_reg_top.sv +++ b/hw/ip/mbx/rtl/mbx_host_reg_top.sv @@ -21,7 +21,7 @@ module mbx_host_reg_top ( import mbx_reg_pkg::* ; - localparam int AW = 6; + localparam int AW = 7; localparam int DW = 32; localparam int DBW = DW/8; // Byte Width @@ -52,9 +52,9 @@ module mbx_host_reg_top ( // also check for spurious write enables logic reg_we_err; - logic [14:0] reg_we_check; + logic [16:0] reg_we_check; prim_reg_we_check #( - .OneHotWidth(15) + .OneHotWidth(17) ) u_prim_reg_we_check ( .clk_i(clk_i), .rst_ni(rst_ni), @@ -179,6 +179,10 @@ module mbx_host_reg_top ( logic outbound_object_size_we; logic [10:0] outbound_object_size_qs; logic [10:0] outbound_object_size_wd; + logic doe_intr_msg_addr_re; + logic [31:0] doe_intr_msg_addr_qs; + logic doe_intr_msg_data_re; + logic [31:0] doe_intr_msg_data_qs; // Register instances // R[intr_state]: V(False) @@ -790,8 +794,40 @@ module mbx_host_reg_top ( assign reg2hw.outbound_object_size.qe = outbound_object_size_qe; + // R[doe_intr_msg_addr]: V(True) + prim_subreg_ext #( + .DW (32) + ) u_doe_intr_msg_addr ( + .re (doe_intr_msg_addr_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.doe_intr_msg_addr.d), + .qre (), + .qe (), + .q (reg2hw.doe_intr_msg_addr.q), + .ds (), + .qs (doe_intr_msg_addr_qs) + ); + + + // R[doe_intr_msg_data]: V(True) + prim_subreg_ext #( + .DW (32) + ) u_doe_intr_msg_data ( + .re (doe_intr_msg_data_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.doe_intr_msg_data.d), + .qre (), + .qe (), + .q (reg2hw.doe_intr_msg_data.q), + .ds (), + .qs (doe_intr_msg_data_qs) + ); + - logic [14:0] addr_hit; + + logic [16:0] addr_hit; always_comb begin addr_hit = '0; addr_hit[ 0] = (reg_addr == MBX_INTR_STATE_OFFSET); @@ -809,6 +845,8 @@ module mbx_host_reg_top ( addr_hit[12] = (reg_addr == MBX_OUTBOUND_LIMIT_ADDRESS_OFFSET); addr_hit[13] = (reg_addr == MBX_OUTBOUND_READ_PTR_OFFSET); addr_hit[14] = (reg_addr == MBX_OUTBOUND_OBJECT_SIZE_OFFSET); + addr_hit[15] = (reg_addr == MBX_DOE_INTR_MSG_ADDR_OFFSET); + addr_hit[16] = (reg_addr == MBX_DOE_INTR_MSG_DATA_OFFSET); end assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ; @@ -830,7 +868,9 @@ module mbx_host_reg_top ( (addr_hit[11] & (|(MBX_HOST_PERMIT[11] & ~reg_be))) | (addr_hit[12] & (|(MBX_HOST_PERMIT[12] & ~reg_be))) | (addr_hit[13] & (|(MBX_HOST_PERMIT[13] & ~reg_be))) | - (addr_hit[14] & (|(MBX_HOST_PERMIT[14] & ~reg_be))))); + (addr_hit[14] & (|(MBX_HOST_PERMIT[14] & ~reg_be))) | + (addr_hit[15] & (|(MBX_HOST_PERMIT[15] & ~reg_be))) | + (addr_hit[16] & (|(MBX_HOST_PERMIT[16] & ~reg_be))))); end // Generate write-enables @@ -893,6 +933,8 @@ module mbx_host_reg_top ( assign outbound_object_size_we = addr_hit[14] & reg_we & !reg_error; assign outbound_object_size_wd = reg_wdata[10:0]; + assign doe_intr_msg_addr_re = addr_hit[15] & reg_re & !reg_error; + assign doe_intr_msg_data_re = addr_hit[16] & reg_re & !reg_error; // Assign write-enables to checker logic vector. always_comb begin @@ -912,6 +954,8 @@ module mbx_host_reg_top ( reg_we_check[12] = outbound_limit_address_gated_we; reg_we_check[13] = 1'b0; reg_we_check[14] = outbound_object_size_we; + reg_we_check[15] = 1'b0; + reg_we_check[16] = 1'b0; end // Read data return @@ -986,6 +1030,14 @@ module mbx_host_reg_top ( reg_rdata_next[10:0] = outbound_object_size_qs; end + addr_hit[15]: begin + reg_rdata_next[31:0] = doe_intr_msg_addr_qs; + end + + addr_hit[16]: begin + reg_rdata_next[31:0] = doe_intr_msg_data_qs; + end + default: begin reg_rdata_next = '1; end diff --git a/hw/ip/mbx/rtl/mbx_hostif.sv b/hw/ip/mbx/rtl/mbx_hostif.sv index c1067ab5a240c..834d4929fbb49 100644 --- a/hw/ip/mbx/rtl/mbx_hostif.sv +++ b/hw/ip/mbx/rtl/mbx_hostif.sv @@ -6,7 +6,8 @@ module mbx_hostif import mbx_reg_pkg::*; #( parameter logic [NumAlerts-1:0] AlertAsyncOn = {NumAlerts{1'b1}}, - parameter int unsigned CfgSramAddrWidth = 32 + parameter int unsigned CfgSramAddrWidth = 32, + parameter int unsigned CfgSramDataWidth = 32 ) ( input logic clk_i, input logic rst_ni, @@ -45,11 +46,14 @@ module mbx_hostif output logic [CfgSramAddrWidth-1:0] hostif_imbx_limit_o, output logic [CfgSramAddrWidth-1:0] hostif_ombx_base_o, output logic [CfgSramAddrWidth-1:0] hostif_ombx_limit_o, - // Read/Write access for the OB DW Count register + // Read/Write access for the object size register output logic hostif_ombx_object_size_write_o, output logic [10:0] hostif_ombx_object_size_o, input logic hostif_ombx_object_size_read_i, input logic [10:0] hostif_ombx_object_size_i, + // Alias of the interrupt address and data registers from the SYS interface + input logic [CfgSramAddrWidth-1:0] sysif_intr_msg_addr_i, + input logic [CfgSramDataWidth-1:0] sysif_intr_msg_data_i, // Control inputs coming from the system registers interface input logic sysif_control_abort_write_i ); @@ -186,4 +190,8 @@ module mbx_hostif // External write logic assign hostif_ombx_object_size_write_o = reg2hw.outbound_object_size.qe; assign hostif_ombx_object_size_o = reg2hw.outbound_object_size.q; + + // Alias of the IRQ addr and data register from the sys interface (RO) + assign hw2reg.doe_intr_msg_addr.d = sysif_intr_msg_addr_i; + assign hw2reg.doe_intr_msg_data.d = sysif_intr_msg_data_i; endmodule diff --git a/hw/ip/mbx/rtl/mbx_reg_pkg.sv b/hw/ip/mbx/rtl/mbx_reg_pkg.sv index a323869c6f0c4..02e5521bb266f 100644 --- a/hw/ip/mbx/rtl/mbx_reg_pkg.sv +++ b/hw/ip/mbx/rtl/mbx_reg_pkg.sv @@ -10,7 +10,7 @@ package mbx_reg_pkg; parameter int NumAlerts = 1; // Address widths within the block - parameter int HostAw = 6; + parameter int HostAw = 7; parameter int SysAw = 5; /////////////////////////////////////////////// @@ -128,6 +128,14 @@ package mbx_reg_pkg; logic qe; } mbx_reg2hw_outbound_object_size_reg_t; + typedef struct packed { + logic [31:0] q; + } mbx_reg2hw_doe_intr_msg_addr_reg_t; + + typedef struct packed { + logic [31:0] q; + } mbx_reg2hw_doe_intr_msg_data_reg_t; + typedef struct packed { struct packed { logic d; @@ -179,51 +187,65 @@ package mbx_reg_pkg; logic de; } mbx_hw2reg_outbound_object_size_reg_t; + typedef struct packed { + logic [31:0] d; + } mbx_hw2reg_doe_intr_msg_addr_reg_t; + + typedef struct packed { + logic [31:0] d; + } mbx_hw2reg_doe_intr_msg_data_reg_t; + // Register -> HW type for host interface typedef struct packed { - mbx_reg2hw_intr_state_reg_t intr_state; // [226:225] - mbx_reg2hw_intr_enable_reg_t intr_enable; // [224:223] - mbx_reg2hw_intr_test_reg_t intr_test; // [222:219] - mbx_reg2hw_alert_test_reg_t alert_test; // [218:217] - mbx_reg2hw_control_reg_t control; // [216:213] - mbx_reg2hw_status_reg_t status; // [212:203] - mbx_reg2hw_address_range_regwen_reg_t address_range_regwen; // [202:199] - mbx_reg2hw_address_range_valid_reg_t address_range_valid; // [198:198] - mbx_reg2hw_inbound_base_address_reg_t inbound_base_address; // [197:167] - mbx_reg2hw_inbound_limit_address_reg_t inbound_limit_address; // [166:136] - mbx_reg2hw_inbound_write_ptr_reg_t inbound_write_ptr; // [135:105] - mbx_reg2hw_outbound_base_address_reg_t outbound_base_address; // [104:74] - mbx_reg2hw_outbound_limit_address_reg_t outbound_limit_address; // [73:43] - mbx_reg2hw_outbound_read_ptr_reg_t outbound_read_ptr; // [42:12] - mbx_reg2hw_outbound_object_size_reg_t outbound_object_size; // [11:0] + mbx_reg2hw_intr_state_reg_t intr_state; // [290:289] + mbx_reg2hw_intr_enable_reg_t intr_enable; // [288:287] + mbx_reg2hw_intr_test_reg_t intr_test; // [286:283] + mbx_reg2hw_alert_test_reg_t alert_test; // [282:281] + mbx_reg2hw_control_reg_t control; // [280:277] + mbx_reg2hw_status_reg_t status; // [276:267] + mbx_reg2hw_address_range_regwen_reg_t address_range_regwen; // [266:263] + mbx_reg2hw_address_range_valid_reg_t address_range_valid; // [262:262] + mbx_reg2hw_inbound_base_address_reg_t inbound_base_address; // [261:231] + mbx_reg2hw_inbound_limit_address_reg_t inbound_limit_address; // [230:200] + mbx_reg2hw_inbound_write_ptr_reg_t inbound_write_ptr; // [199:169] + mbx_reg2hw_outbound_base_address_reg_t outbound_base_address; // [168:138] + mbx_reg2hw_outbound_limit_address_reg_t outbound_limit_address; // [137:107] + mbx_reg2hw_outbound_read_ptr_reg_t outbound_read_ptr; // [106:76] + mbx_reg2hw_outbound_object_size_reg_t outbound_object_size; // [75:64] + mbx_reg2hw_doe_intr_msg_addr_reg_t doe_intr_msg_addr; // [63:32] + mbx_reg2hw_doe_intr_msg_data_reg_t doe_intr_msg_data; // [31:0] } mbx_host_reg2hw_t; // HW -> register type for host interface typedef struct packed { - mbx_hw2reg_intr_state_reg_t intr_state; // [82:79] - mbx_hw2reg_control_reg_t control; // [78:77] - mbx_hw2reg_status_reg_t status; // [76:72] - mbx_hw2reg_inbound_write_ptr_reg_t inbound_write_ptr; // [71:42] - mbx_hw2reg_outbound_read_ptr_reg_t outbound_read_ptr; // [41:12] - mbx_hw2reg_outbound_object_size_reg_t outbound_object_size; // [11:0] + mbx_hw2reg_intr_state_reg_t intr_state; // [146:143] + mbx_hw2reg_control_reg_t control; // [142:141] + mbx_hw2reg_status_reg_t status; // [140:136] + mbx_hw2reg_inbound_write_ptr_reg_t inbound_write_ptr; // [135:106] + mbx_hw2reg_outbound_read_ptr_reg_t outbound_read_ptr; // [105:76] + mbx_hw2reg_outbound_object_size_reg_t outbound_object_size; // [75:64] + mbx_hw2reg_doe_intr_msg_addr_reg_t doe_intr_msg_addr; // [63:32] + mbx_hw2reg_doe_intr_msg_data_reg_t doe_intr_msg_data; // [31:0] } mbx_host_hw2reg_t; // Register offsets for host interface - parameter logic [HostAw-1:0] MBX_INTR_STATE_OFFSET = 6'h 0; - parameter logic [HostAw-1:0] MBX_INTR_ENABLE_OFFSET = 6'h 4; - parameter logic [HostAw-1:0] MBX_INTR_TEST_OFFSET = 6'h 8; - parameter logic [HostAw-1:0] MBX_ALERT_TEST_OFFSET = 6'h c; - parameter logic [HostAw-1:0] MBX_CONTROL_OFFSET = 6'h 10; - parameter logic [HostAw-1:0] MBX_STATUS_OFFSET = 6'h 14; - parameter logic [HostAw-1:0] MBX_ADDRESS_RANGE_REGWEN_OFFSET = 6'h 18; - parameter logic [HostAw-1:0] MBX_ADDRESS_RANGE_VALID_OFFSET = 6'h 1c; - parameter logic [HostAw-1:0] MBX_INBOUND_BASE_ADDRESS_OFFSET = 6'h 20; - parameter logic [HostAw-1:0] MBX_INBOUND_LIMIT_ADDRESS_OFFSET = 6'h 24; - parameter logic [HostAw-1:0] MBX_INBOUND_WRITE_PTR_OFFSET = 6'h 28; - parameter logic [HostAw-1:0] MBX_OUTBOUND_BASE_ADDRESS_OFFSET = 6'h 2c; - parameter logic [HostAw-1:0] MBX_OUTBOUND_LIMIT_ADDRESS_OFFSET = 6'h 30; - parameter logic [HostAw-1:0] MBX_OUTBOUND_READ_PTR_OFFSET = 6'h 34; - parameter logic [HostAw-1:0] MBX_OUTBOUND_OBJECT_SIZE_OFFSET = 6'h 38; + parameter logic [HostAw-1:0] MBX_INTR_STATE_OFFSET = 7'h 0; + parameter logic [HostAw-1:0] MBX_INTR_ENABLE_OFFSET = 7'h 4; + parameter logic [HostAw-1:0] MBX_INTR_TEST_OFFSET = 7'h 8; + parameter logic [HostAw-1:0] MBX_ALERT_TEST_OFFSET = 7'h c; + parameter logic [HostAw-1:0] MBX_CONTROL_OFFSET = 7'h 10; + parameter logic [HostAw-1:0] MBX_STATUS_OFFSET = 7'h 14; + parameter logic [HostAw-1:0] MBX_ADDRESS_RANGE_REGWEN_OFFSET = 7'h 18; + parameter logic [HostAw-1:0] MBX_ADDRESS_RANGE_VALID_OFFSET = 7'h 1c; + parameter logic [HostAw-1:0] MBX_INBOUND_BASE_ADDRESS_OFFSET = 7'h 20; + parameter logic [HostAw-1:0] MBX_INBOUND_LIMIT_ADDRESS_OFFSET = 7'h 24; + parameter logic [HostAw-1:0] MBX_INBOUND_WRITE_PTR_OFFSET = 7'h 28; + parameter logic [HostAw-1:0] MBX_OUTBOUND_BASE_ADDRESS_OFFSET = 7'h 2c; + parameter logic [HostAw-1:0] MBX_OUTBOUND_LIMIT_ADDRESS_OFFSET = 7'h 30; + parameter logic [HostAw-1:0] MBX_OUTBOUND_READ_PTR_OFFSET = 7'h 34; + parameter logic [HostAw-1:0] MBX_OUTBOUND_OBJECT_SIZE_OFFSET = 7'h 38; + parameter logic [HostAw-1:0] MBX_DOE_INTR_MSG_ADDR_OFFSET = 7'h 3c; + parameter logic [HostAw-1:0] MBX_DOE_INTR_MSG_DATA_OFFSET = 7'h 40; // Reset values for hwext registers and their fields for host interface parameter logic [1:0] MBX_INTR_TEST_RESVAL = 2'h 0; @@ -244,6 +266,10 @@ package mbx_reg_pkg; parameter logic [29:0] MBX_INBOUND_WRITE_PTR_INBOUND_READ_PTR_RESVAL = 30'h 0; parameter logic [31:0] MBX_OUTBOUND_READ_PTR_RESVAL = 32'h 0; parameter logic [29:0] MBX_OUTBOUND_READ_PTR_OUTBOUND_WRITE_PTR_RESVAL = 30'h 0; + parameter logic [31:0] MBX_DOE_INTR_MSG_ADDR_RESVAL = 32'h 0; + parameter logic [31:0] MBX_DOE_INTR_MSG_ADDR_DOE_INTR_MSG_ADDR_RESVAL = 32'h 0; + parameter logic [31:0] MBX_DOE_INTR_MSG_DATA_RESVAL = 32'h 0; + parameter logic [31:0] MBX_DOE_INTR_MSG_DATA_DOE_INTR_MSG_DATA_RESVAL = 32'h 0; // Register index for host interface typedef enum int { @@ -261,11 +287,13 @@ package mbx_reg_pkg; MBX_OUTBOUND_BASE_ADDRESS, MBX_OUTBOUND_LIMIT_ADDRESS, MBX_OUTBOUND_READ_PTR, - MBX_OUTBOUND_OBJECT_SIZE + MBX_OUTBOUND_OBJECT_SIZE, + MBX_DOE_INTR_MSG_ADDR, + MBX_DOE_INTR_MSG_DATA } mbx_host_id_e; // Register width information to check illegal writes for host interface - parameter logic [3:0] MBX_HOST_PERMIT [15] = '{ + parameter logic [3:0] MBX_HOST_PERMIT [17] = '{ 4'b 0001, // index[ 0] MBX_INTR_STATE 4'b 0001, // index[ 1] MBX_INTR_ENABLE 4'b 0001, // index[ 2] MBX_INTR_TEST @@ -280,7 +308,9 @@ package mbx_reg_pkg; 4'b 1111, // index[11] MBX_OUTBOUND_BASE_ADDRESS 4'b 1111, // index[12] MBX_OUTBOUND_LIMIT_ADDRESS 4'b 1111, // index[13] MBX_OUTBOUND_READ_PTR - 4'b 0011 // index[14] MBX_OUTBOUND_OBJECT_SIZE + 4'b 0011, // index[14] MBX_OUTBOUND_OBJECT_SIZE + 4'b 1111, // index[15] MBX_DOE_INTR_MSG_ADDR + 4'b 1111 // index[16] MBX_DOE_INTR_MSG_DATA }; ////////////////////////////////////////////// @@ -290,12 +320,12 @@ package mbx_reg_pkg; typedef struct packed { logic [31:0] q; logic qe; - } mbx_reg2hw_doe_intr_msg_addr_reg_t; + } mbx_reg2hw_sys_doe_intr_msg_addr_reg_t; typedef struct packed { logic [31:0] q; logic qe; - } mbx_reg2hw_doe_intr_msg_data_reg_t; + } mbx_reg2hw_sys_doe_intr_msg_data_reg_t; typedef struct packed { struct packed { @@ -375,8 +405,8 @@ package mbx_reg_pkg; // Register -> HW type for sys interface typedef struct packed { - mbx_reg2hw_doe_intr_msg_addr_reg_t doe_intr_msg_addr; // [79:47] - mbx_reg2hw_doe_intr_msg_data_reg_t doe_intr_msg_data; // [46:14] + mbx_reg2hw_sys_doe_intr_msg_addr_reg_t sys_doe_intr_msg_addr; // [79:47] + mbx_reg2hw_sys_doe_intr_msg_data_reg_t sys_doe_intr_msg_data; // [46:14] mbx_reg2hw_sys_control_reg_t sys_control; // [13:6] mbx_reg2hw_sys_status_reg_t sys_status; // [5:0] } mbx_sys_reg2hw_t; @@ -388,8 +418,8 @@ package mbx_reg_pkg; } mbx_sys_hw2reg_t; // Register offsets for sys interface - parameter logic [SysAw-1:0] MBX_DOE_INTR_MSG_ADDR_OFFSET = 5'h 0; - parameter logic [SysAw-1:0] MBX_DOE_INTR_MSG_DATA_OFFSET = 5'h 4; + parameter logic [SysAw-1:0] MBX_SYS_DOE_INTR_MSG_ADDR_OFFSET = 5'h 0; + parameter logic [SysAw-1:0] MBX_SYS_DOE_INTR_MSG_DATA_OFFSET = 5'h 4; parameter logic [SysAw-1:0] MBX_SYS_CONTROL_OFFSET = 5'h 8; parameter logic [SysAw-1:0] MBX_SYS_STATUS_OFFSET = 5'h c; @@ -410,16 +440,16 @@ package mbx_reg_pkg; // Register index for sys interface typedef enum int { - MBX_DOE_INTR_MSG_ADDR, - MBX_DOE_INTR_MSG_DATA, + MBX_SYS_DOE_INTR_MSG_ADDR, + MBX_SYS_DOE_INTR_MSG_DATA, MBX_SYS_CONTROL, MBX_SYS_STATUS } mbx_sys_id_e; // Register width information to check illegal writes for sys interface parameter logic [3:0] MBX_SYS_PERMIT [4] = '{ - 4'b 1111, // index[0] MBX_DOE_INTR_MSG_ADDR - 4'b 1111, // index[1] MBX_DOE_INTR_MSG_DATA + 4'b 1111, // index[0] MBX_SYS_DOE_INTR_MSG_ADDR + 4'b 1111, // index[1] MBX_SYS_DOE_INTR_MSG_DATA 4'b 1111, // index[2] MBX_SYS_CONTROL 4'b 1111 // index[3] MBX_SYS_STATUS }; diff --git a/hw/ip/mbx/rtl/mbx_sys_reg_top.sv b/hw/ip/mbx/rtl/mbx_sys_reg_top.sv index ad3c13d59fdd7..5ac0f7ce22e5f 100644 --- a/hw/ip/mbx/rtl/mbx_sys_reg_top.sv +++ b/hw/ip/mbx/rtl/mbx_sys_reg_top.sv @@ -173,12 +173,12 @@ module mbx_sys_reg_top ( // Define SW related signals // Format: __{wd|we|qs} // or _{wd|we|qs} if field == 1 or 0 - logic doe_intr_msg_addr_we; - logic [31:0] doe_intr_msg_addr_qs; - logic [31:0] doe_intr_msg_addr_wd; - logic doe_intr_msg_data_we; - logic [31:0] doe_intr_msg_data_qs; - logic [31:0] doe_intr_msg_data_wd; + logic sys_doe_intr_msg_addr_we; + logic [31:0] sys_doe_intr_msg_addr_qs; + logic [31:0] sys_doe_intr_msg_addr_wd; + logic sys_doe_intr_msg_data_we; + logic [31:0] sys_doe_intr_msg_data_qs; + logic [31:0] sys_doe_intr_msg_data_wd; logic sys_control_re; logic sys_control_we; logic sys_control_abort_wd; @@ -196,84 +196,84 @@ module mbx_sys_reg_top ( logic sys_status_ready_qs; // Register instances - // R[doe_intr_msg_addr]: V(False) - logic doe_intr_msg_addr_qe; - logic [0:0] doe_intr_msg_addr_flds_we; + // R[sys_doe_intr_msg_addr]: V(False) + logic sys_doe_intr_msg_addr_qe; + logic [0:0] sys_doe_intr_msg_addr_flds_we; prim_flop #( .Width(1), .ResetValue(0) - ) u_doe_intr_msg_addr0_qe ( + ) u_sys_doe_intr_msg_addr0_qe ( .clk_i(clk_i), .rst_ni(rst_ni), - .d_i(&doe_intr_msg_addr_flds_we), - .q_o(doe_intr_msg_addr_qe) + .d_i(&sys_doe_intr_msg_addr_flds_we), + .q_o(sys_doe_intr_msg_addr_qe) ); prim_subreg #( .DW (32), .SwAccess(prim_subreg_pkg::SwAccessRW), .RESVAL (32'h0), .Mubi (1'b0) - ) u_doe_intr_msg_addr ( + ) u_sys_doe_intr_msg_addr ( .clk_i (clk_i), .rst_ni (rst_ni), // from register interface - .we (doe_intr_msg_addr_we), - .wd (doe_intr_msg_addr_wd), + .we (sys_doe_intr_msg_addr_we), + .wd (sys_doe_intr_msg_addr_wd), // from internal hardware .de (1'b0), .d ('0), // to internal hardware - .qe (doe_intr_msg_addr_flds_we[0]), - .q (reg2hw.doe_intr_msg_addr.q), + .qe (sys_doe_intr_msg_addr_flds_we[0]), + .q (reg2hw.sys_doe_intr_msg_addr.q), .ds (), // to register interface (read) - .qs (doe_intr_msg_addr_qs) + .qs (sys_doe_intr_msg_addr_qs) ); - assign reg2hw.doe_intr_msg_addr.qe = doe_intr_msg_addr_qe; + assign reg2hw.sys_doe_intr_msg_addr.qe = sys_doe_intr_msg_addr_qe; - // R[doe_intr_msg_data]: V(False) - logic doe_intr_msg_data_qe; - logic [0:0] doe_intr_msg_data_flds_we; + // R[sys_doe_intr_msg_data]: V(False) + logic sys_doe_intr_msg_data_qe; + logic [0:0] sys_doe_intr_msg_data_flds_we; prim_flop #( .Width(1), .ResetValue(0) - ) u_doe_intr_msg_data0_qe ( + ) u_sys_doe_intr_msg_data0_qe ( .clk_i(clk_i), .rst_ni(rst_ni), - .d_i(&doe_intr_msg_data_flds_we), - .q_o(doe_intr_msg_data_qe) + .d_i(&sys_doe_intr_msg_data_flds_we), + .q_o(sys_doe_intr_msg_data_qe) ); prim_subreg #( .DW (32), .SwAccess(prim_subreg_pkg::SwAccessRW), .RESVAL (32'h0), .Mubi (1'b0) - ) u_doe_intr_msg_data ( + ) u_sys_doe_intr_msg_data ( .clk_i (clk_i), .rst_ni (rst_ni), // from register interface - .we (doe_intr_msg_data_we), - .wd (doe_intr_msg_data_wd), + .we (sys_doe_intr_msg_data_we), + .wd (sys_doe_intr_msg_data_wd), // from internal hardware .de (1'b0), .d ('0), // to internal hardware - .qe (doe_intr_msg_data_flds_we[0]), - .q (reg2hw.doe_intr_msg_data.q), + .qe (sys_doe_intr_msg_data_flds_we[0]), + .q (reg2hw.sys_doe_intr_msg_data.q), .ds (), // to register interface (read) - .qs (doe_intr_msg_data_qs) + .qs (sys_doe_intr_msg_data_qs) ); - assign reg2hw.doe_intr_msg_data.qe = doe_intr_msg_data_qe; + assign reg2hw.sys_doe_intr_msg_data.qe = sys_doe_intr_msg_data_qe; // R[sys_control]: V(True) @@ -498,8 +498,8 @@ module mbx_sys_reg_top ( logic [3:0] addr_hit; always_comb begin addr_hit = '0; - addr_hit[0] = (reg_addr == MBX_DOE_INTR_MSG_ADDR_OFFSET); - addr_hit[1] = (reg_addr == MBX_DOE_INTR_MSG_DATA_OFFSET); + addr_hit[0] = (reg_addr == MBX_SYS_DOE_INTR_MSG_ADDR_OFFSET); + addr_hit[1] = (reg_addr == MBX_SYS_DOE_INTR_MSG_DATA_OFFSET); addr_hit[2] = (reg_addr == MBX_SYS_CONTROL_OFFSET); addr_hit[3] = (reg_addr == MBX_SYS_STATUS_OFFSET); end @@ -516,12 +516,12 @@ module mbx_sys_reg_top ( end // Generate write-enables - assign doe_intr_msg_addr_we = addr_hit[0] & reg_we & !reg_error; + assign sys_doe_intr_msg_addr_we = addr_hit[0] & reg_we & !reg_error; - assign doe_intr_msg_addr_wd = reg_wdata[31:0]; - assign doe_intr_msg_data_we = addr_hit[1] & reg_we & !reg_error; + assign sys_doe_intr_msg_addr_wd = reg_wdata[31:0]; + assign sys_doe_intr_msg_data_we = addr_hit[1] & reg_we & !reg_error; - assign doe_intr_msg_data_wd = reg_wdata[31:0]; + assign sys_doe_intr_msg_data_wd = reg_wdata[31:0]; assign sys_control_re = addr_hit[2] & reg_re & !reg_error; assign sys_control_we = addr_hit[2] & reg_we & !reg_error; @@ -539,8 +539,8 @@ module mbx_sys_reg_top ( // Assign write-enables to checker logic vector. always_comb begin reg_we_check = '0; - reg_we_check[0] = doe_intr_msg_addr_we; - reg_we_check[1] = doe_intr_msg_data_we; + reg_we_check[0] = sys_doe_intr_msg_addr_we; + reg_we_check[1] = sys_doe_intr_msg_data_we; reg_we_check[2] = sys_control_we; reg_we_check[3] = sys_status_we; end @@ -550,11 +550,11 @@ module mbx_sys_reg_top ( reg_rdata_next = '0; unique case (1'b1) addr_hit[0]: begin - reg_rdata_next[31:0] = doe_intr_msg_addr_qs; + reg_rdata_next[31:0] = sys_doe_intr_msg_addr_qs; end addr_hit[1]: begin - reg_rdata_next[31:0] = doe_intr_msg_data_qs; + reg_rdata_next[31:0] = sys_doe_intr_msg_data_qs; end addr_hit[2]: begin diff --git a/hw/ip/mbx/rtl/mbx_sysif.sv b/hw/ip/mbx/rtl/mbx_sysif.sv index 7cb416539bd9d..585937100104d 100644 --- a/hw/ip/mbx/rtl/mbx_sysif.sv +++ b/hw/ip/mbx/rtl/mbx_sysif.sv @@ -5,6 +5,7 @@ module mbx_sysif import tlul_pkg::*; #( + parameter int unsigned CfgSramAddrWidth = 32, parameter int unsigned CfgSramDataWidth = 32, // PCIe capabilities parameter bit DoeIrqSupport = 1'b1 @@ -37,6 +38,9 @@ module mbx_sysif input logic sysif_status_ready_valid_i, input logic sysif_status_ready_i, output logic sysif_status_ready_o, + // Alias of the interrupt address and data registers to the host interface + output logic [CfgSramAddrWidth-1:0] sysif_intr_msg_addr_o, + output logic [CfgSramDataWidth-1:0] sysif_intr_msg_data_o, // Control lines for backpressuring the bus input logic imbx_pending_i, input logic ombx_pending_i, @@ -243,6 +247,10 @@ module mbx_sysif .qs () ); + // Forward IRQ addr and data register to the host interface + assign sysif_intr_msg_addr_o = reg2hw.sys_doe_intr_msg_addr.q; + assign sysif_intr_msg_data_o = reg2hw.sys_doe_intr_msg_data.q; + // Assertions `ASSERT(DataWidthCheck_A, CfgSramDataWidth == top_pkg::TL_DW) endmodule From d8c98552306df3a670de7a2268d6e9079a5e2ed5 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Tue, 12 Sep 2023 06:06:42 -0700 Subject: [PATCH 19/88] [hw,mbx,rtl] Recoverable alert on invalid memory access Signed-off-by: Robert Schilling --- hw/ip/mbx/data/mbx.hjson | 3 +++ hw/ip/mbx/rtl/mbx.sv | 6 +++++- hw/ip/mbx/rtl/mbx_host_reg_top.sv | 35 ++++++++++++++++++++++++------- hw/ip/mbx/rtl/mbx_hostif.sv | 18 ++++++++++++---- hw/ip/mbx/rtl/mbx_reg_pkg.sv | 23 +++++++++++++------- hw/ip/mbx/rtl/mbx_sramrwarb.sv | 3 ++- 6 files changed, 67 insertions(+), 21 deletions(-) diff --git a/hw/ip/mbx/data/mbx.hjson b/hw/ip/mbx/data/mbx.hjson index 7a82b8bc3529e..3cadf75018d18 100644 --- a/hw/ip/mbx/data/mbx.hjson +++ b/hw/ip/mbx/data/mbx.hjson @@ -58,6 +58,9 @@ { name: "fatal_fault" desc: "This fatal alert is triggered when a fatal TL-UL bus integrity fault is detected." } + { name: "recov_fault", + desc: "This recoverable alert is triggered when memory with invalid ECC (e.g., uninitialized memory) or at an invalid address is accessed." + } ] countermeasures: [ { name: "BUS.INTEGRITY" diff --git a/hw/ip/mbx/rtl/mbx.sv b/hw/ip/mbx/rtl/mbx.sv index 50c3e1bd2ba96..77127ee8eb55d 100644 --- a/hw/ip/mbx/rtl/mbx.sv +++ b/hw/ip/mbx/rtl/mbx.sv @@ -41,6 +41,8 @@ module mbx // Collect all error sources logic sysif_intg_err, tl_sram_intg_err, imbx_state_error, alert_signal; + logic sram_err; + assign alert_signal = sysif_intg_err | tl_sram_intg_err | imbx_state_error; @@ -93,11 +95,12 @@ module mbx // Device port to the host side .tl_host_i ( tl_host_i ), .tl_host_o ( tl_host_o ), - .intg_err_i ( alert_signal ), .event_intr_ready_i ( hostif_event_intr_ready ), .event_intr_abort_i ( hostif_event_intr_abort ), .intr_ready_o ( intr_mbx_ready_o ), .intr_abort_o ( intr_mbx_abort_o ), + .intg_err_i ( alert_signal ), + .sram_err_i ( sram_err ), .alert_rx_i ( alert_rx_i ), .alert_tx_o ( alert_tx_o ), // Access to the control register @@ -258,6 +261,7 @@ module mbx .tl_host_o ( tl_sram_o ), .tl_host_i ( tl_sram_i ), .intg_err_o ( tl_sram_intg_err ), + .sram_err_o ( sram_err ), // Interface to the inbound mailbox .imbx_sram_write_req_i ( imbx_sram_write_req ), .imbx_sram_write_gnt_o ( imbx_sram_write_gnt ), diff --git a/hw/ip/mbx/rtl/mbx_host_reg_top.sv b/hw/ip/mbx/rtl/mbx_host_reg_top.sv index 996cbc150c1ea..a733d4ca37371 100644 --- a/hw/ip/mbx/rtl/mbx_host_reg_top.sv +++ b/hw/ip/mbx/rtl/mbx_host_reg_top.sv @@ -135,7 +135,8 @@ module mbx_host_reg_top ( logic intr_test_mbx_ready_wd; logic intr_test_mbx_abort_wd; logic alert_test_we; - logic alert_test_wd; + logic alert_test_fatal_fault_wd; + logic alert_test_recov_fault_wd; logic control_re; logic control_we; logic control_abort_qs; @@ -336,22 +337,39 @@ module mbx_host_reg_top ( // R[alert_test]: V(True) logic alert_test_qe; - logic [0:0] alert_test_flds_we; + logic [1:0] alert_test_flds_we; assign alert_test_qe = &alert_test_flds_we; + // F[fatal_fault]: 0:0 prim_subreg_ext #( .DW (1) - ) u_alert_test ( + ) u_alert_test_fatal_fault ( .re (1'b0), .we (alert_test_we), - .wd (alert_test_wd), + .wd (alert_test_fatal_fault_wd), .d ('0), .qre (), .qe (alert_test_flds_we[0]), - .q (reg2hw.alert_test.q), + .q (reg2hw.alert_test.fatal_fault.q), .ds (), .qs () ); - assign reg2hw.alert_test.qe = alert_test_qe; + assign reg2hw.alert_test.fatal_fault.qe = alert_test_qe; + + // F[recov_fault]: 1:1 + prim_subreg_ext #( + .DW (1) + ) u_alert_test_recov_fault ( + .re (1'b0), + .we (alert_test_we), + .wd (alert_test_recov_fault_wd), + .d ('0), + .qre (), + .qe (alert_test_flds_we[1]), + .q (reg2hw.alert_test.recov_fault.q), + .ds (), + .qs () + ); + assign reg2hw.alert_test.recov_fault.qe = alert_test_qe; // R[control]: V(True) @@ -891,7 +909,9 @@ module mbx_host_reg_top ( assign intr_test_mbx_abort_wd = reg_wdata[1]; assign alert_test_we = addr_hit[3] & reg_we & !reg_error; - assign alert_test_wd = reg_wdata[0]; + assign alert_test_fatal_fault_wd = reg_wdata[0]; + + assign alert_test_recov_fault_wd = reg_wdata[1]; assign control_re = addr_hit[4] & reg_re & !reg_error; assign control_we = addr_hit[4] & reg_we & !reg_error; @@ -979,6 +999,7 @@ module mbx_host_reg_top ( addr_hit[3]: begin reg_rdata_next[0] = '0; + reg_rdata_next[1] = '0; end addr_hit[4]: begin diff --git a/hw/ip/mbx/rtl/mbx_hostif.sv b/hw/ip/mbx/rtl/mbx_hostif.sv index 834d4929fbb49..73250d9eef93f 100644 --- a/hw/ip/mbx/rtl/mbx_hostif.sv +++ b/hw/ip/mbx/rtl/mbx_hostif.sv @@ -21,6 +21,7 @@ module mbx_hostif output logic intr_abort_o, // External errors input logic intg_err_i, + input logic sram_err_i, // Alerts input prim_alert_pkg::alert_rx_t [NumAlerts-1:0] alert_rx_i, output prim_alert_pkg::alert_tx_t [NumAlerts-1:0] alert_tx_o, @@ -60,16 +61,25 @@ module mbx_hostif mbx_reg_pkg::mbx_host_reg2hw_t reg2hw; mbx_reg_pkg::mbx_host_hw2reg_t hw2reg; - // Alerts + ////////////////////////////////////////////////////////////////////////////// + // Assertions + ////////////////////////////////////////////////////////////////////////////// logic tlul_intg_err; logic [NumAlerts-1:0] alert_test, alerts; - assign alert_test = {reg2hw.alert_test.q & reg2hw.alert_test.qe}; - assign alerts[0] = tlul_intg_err | intg_err_i; + assign alert_test = { + reg2hw.alert_test.recov_fault.q & reg2hw.alert_test.recov_fault.qe, + reg2hw.alert_test.fatal_fault.q & reg2hw.alert_test.fatal_fault.qe + }; + + assign alerts[0] = tlul_intg_err | intg_err_i; + assign alerts[1] = sram_err_i; + + localparam logic [NumAlerts-1:0] IsFatal = {1'b0, 1'b1}; for (genvar i = 0; i < NumAlerts; i++) begin : gen_alert_tx prim_alert_sender #( .AsyncOn ( AlertAsyncOn[i] ), - .IsFatal ( 1'b1 ) + .IsFatal ( IsFatal[i] ) ) u_prim_alert_sender ( .clk_i ( clk_i ), .rst_ni ( rst_ni ), diff --git a/hw/ip/mbx/rtl/mbx_reg_pkg.sv b/hw/ip/mbx/rtl/mbx_reg_pkg.sv index 02e5521bb266f..e8fb2a2792523 100644 --- a/hw/ip/mbx/rtl/mbx_reg_pkg.sv +++ b/hw/ip/mbx/rtl/mbx_reg_pkg.sv @@ -7,7 +7,7 @@ package mbx_reg_pkg; // Param list - parameter int NumAlerts = 1; + parameter int NumAlerts = 2; // Address widths within the block parameter int HostAw = 7; @@ -47,8 +47,14 @@ package mbx_reg_pkg; } mbx_reg2hw_intr_test_reg_t; typedef struct packed { - logic q; - logic qe; + struct packed { + logic q; + logic qe; + } fatal_fault; + struct packed { + logic q; + logic qe; + } recov_fault; } mbx_reg2hw_alert_test_reg_t; typedef struct packed { @@ -197,10 +203,10 @@ package mbx_reg_pkg; // Register -> HW type for host interface typedef struct packed { - mbx_reg2hw_intr_state_reg_t intr_state; // [290:289] - mbx_reg2hw_intr_enable_reg_t intr_enable; // [288:287] - mbx_reg2hw_intr_test_reg_t intr_test; // [286:283] - mbx_reg2hw_alert_test_reg_t alert_test; // [282:281] + mbx_reg2hw_intr_state_reg_t intr_state; // [292:291] + mbx_reg2hw_intr_enable_reg_t intr_enable; // [290:289] + mbx_reg2hw_intr_test_reg_t intr_test; // [288:285] + mbx_reg2hw_alert_test_reg_t alert_test; // [284:281] mbx_reg2hw_control_reg_t control; // [280:277] mbx_reg2hw_status_reg_t status; // [276:267] mbx_reg2hw_address_range_regwen_reg_t address_range_regwen; // [266:263] @@ -251,8 +257,9 @@ package mbx_reg_pkg; parameter logic [1:0] MBX_INTR_TEST_RESVAL = 2'h 0; parameter logic [0:0] MBX_INTR_TEST_MBX_READY_RESVAL = 1'h 0; parameter logic [0:0] MBX_INTR_TEST_MBX_ABORT_RESVAL = 1'h 0; - parameter logic [0:0] MBX_ALERT_TEST_RESVAL = 1'h 0; + parameter logic [1:0] MBX_ALERT_TEST_RESVAL = 2'h 0; parameter logic [0:0] MBX_ALERT_TEST_FATAL_FAULT_RESVAL = 1'h 0; + parameter logic [0:0] MBX_ALERT_TEST_RECOV_FAULT_RESVAL = 1'h 0; parameter logic [1:0] MBX_CONTROL_RESVAL = 2'h 0; parameter logic [0:0] MBX_CONTROL_ABORT_RESVAL = 1'h 0; parameter logic [0:0] MBX_CONTROL_DOE_INTR_EN_RESVAL = 1'h 0; diff --git a/hw/ip/mbx/rtl/mbx_sramrwarb.sv b/hw/ip/mbx/rtl/mbx_sramrwarb.sv index 7768870d1d6f0..091e1d448d6eb 100644 --- a/hw/ip/mbx/rtl/mbx_sramrwarb.sv +++ b/hw/ip/mbx/rtl/mbx_sramrwarb.sv @@ -14,6 +14,7 @@ module mbx_sramrwarb output tlul_pkg::tl_h2d_t tl_host_o, input tlul_pkg::tl_d2h_t tl_host_i, output logic intg_err_o, + output logic sram_err_o, // Interface to the inbound mailbox input logic imbx_sram_write_req_i, @@ -96,7 +97,7 @@ module mbx_sramrwarb .valid_o ( sram_valid ), .rdata_o ( ombx_sram_read_resp_o ), .rdata_intg_o ( ), - .err_o ( ), + .err_o ( sram_err_o ), .intg_err_o ( intg_err_o ), // Bus interface .tl_o ( tl_host_o ), From d533e83ab25cbbf76eb3bc09817aef280a4e3857 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Mon, 18 Sep 2023 03:52:53 -0700 Subject: [PATCH 20/88] [hw,mbx,rtl] Remove Async message support registers Signed-off-by: Robert Schilling --- hw/ip/mbx/data/mbx.hjson | 29 ------------- hw/ip/mbx/rtl/mbx.sv | 14 ++----- hw/ip/mbx/rtl/mbx_host_reg_top.sv | 25 +---------- hw/ip/mbx/rtl/mbx_hostif.sv | 5 --- hw/ip/mbx/rtl/mbx_reg_pkg.sv | 69 +++++++++++-------------------- hw/ip/mbx/rtl/mbx_sys_reg_top.sv | 60 +++------------------------ hw/ip/mbx/rtl/mbx_sysif.sv | 29 ------------- 7 files changed, 33 insertions(+), 198 deletions(-) diff --git a/hw/ip/mbx/data/mbx.hjson b/hw/ip/mbx/data/mbx.hjson index 3cadf75018d18..f8608a89df47b 100644 --- a/hw/ip/mbx/data/mbx.hjson +++ b/hw/ip/mbx/data/mbx.hjson @@ -123,17 +123,6 @@ hwaccess: "hrw" hwqe: "true" } - { name: "async_msg_status" - desc: ''' - When Set, this bit indicates the DOE instance has one or more asynchronous messages to transfer - The transition of this bit from Clear to Set is an interrupt triggering event - ''' - bits: "3" - resval: "0x0" - swaccess: "rw" - hwaccess: "hrw" - hwqe: "true" - } { name: "ready" desc: "Alias of the DoE mailbox ready bit" @@ -370,14 +359,6 @@ resval: "0x0" swaccess: "rw" } - { name: "async_msg_en" - desc: ''' - If DOE Async Message Support is Set, this bit, when Set, enables the use of the DOE Async Message mechanism. - ''' - bits: "3" - resval: "0x0" - swaccess: "rw" - } { name: "go" desc: ''' A write of 1 to this bit indicates to the DOE instance that it can start consuming the data object transferred through the DOE Write Data Mailbox register. @@ -418,16 +399,6 @@ swaccess: "ro" hwaccess: "hrw" } - { name: "async_msg_status" - desc: ''' - When Set, this bit indicates the DOE instance has one or more asynchronous messages to transfer. - The transition of this bit from Clear to Set is an interrupt triggering event. - ''' - bits: "3" - resval: "0x0" - swaccess: "ro" - hwaccess: "hrw" - } { name: "ready" desc: ''' When Set, this bit indicates the DOE instance has a data object available to be read by system firmware/software. diff --git a/hw/ip/mbx/rtl/mbx.sv b/hw/ip/mbx/rtl/mbx.sv index 77127ee8eb55d..e27b47d18d471 100644 --- a/hw/ip/mbx/rtl/mbx.sv +++ b/hw/ip/mbx/rtl/mbx.sv @@ -56,12 +56,10 @@ module mbx logic sysif_control_abort_write; // Status signal inputs from the sysif to the hostif - logic sysif_status_busy, sysif_status_doe_intr_status, sysif_status_async_msg_status, - sysif_status_error, sysif_status_ready; + logic sysif_status_busy, sysif_status_doe_intr_status, sysif_status_error, sysif_status_ready; // Setter signals from the hostif to the sysif - logic hostif_status_doe_intr_status_set, hostif_status_async_msg_status_set, - hostif_control_abort_set, hostif_status_busy_clear, + logic hostif_status_doe_intr_status_set, hostif_control_abort_set, hostif_status_busy_clear, hostif_status_error_set, hostif_status_error_clear; // Alias signals from the sys interface @@ -110,8 +108,6 @@ module mbx .hostif_status_busy_i ( sysif_status_busy ), .hostif_status_doe_intr_status_set_o ( hostif_status_doe_intr_status_set ), .hostif_status_doe_intr_status_i ( sysif_status_doe_intr_status ), - .hostif_status_async_msg_status_set_o( hostif_status_async_msg_status_set ), - .hostif_status_async_msg_status_i ( sysif_status_async_msg_status ), .hostif_status_error_set_o ( hostif_status_error_set ), .hostif_status_error_clear_o ( hostif_status_error_clear ), .hostif_status_error_i ( sysif_status_error ), @@ -140,7 +136,7 @@ module mbx ////////////////////////////////////////////////////////////////////////////// // Control and Status signals of the system interface ////////////////////////////////////////////////////////////////////////////// - logic sysif_control_go_set, sysif_control_abort_set, sysif_control_async_msg_en; + logic sysif_control_go_set, sysif_control_abort_set; ////////////////////////////////////////////////////////////////////////////// // Signals for the Inbox @@ -182,7 +178,6 @@ module mbx .doe_intr_o ( doe_intr_o ), // Access to the control register .sysif_control_abort_set_o ( sysif_control_abort_set ), - .sysif_control_async_msg_en_o ( sysif_control_async_msg_en ), .sysif_control_go_set_o ( sysif_control_go_set ), // Access to the status register .sysif_status_busy_valid_i ( imbx_status_busy_valid ), @@ -197,9 +192,6 @@ module mbx .sysif_status_error_clear_i ( hostif_status_error_clear ), .sysif_status_error_o ( sysif_status_error ), - .sysif_status_async_msg_status_set_i ( hostif_status_async_msg_status_set ), - .sysif_status_async_msg_status_o ( sysif_status_async_msg_status ), - .sysif_status_ready_valid_i ( ombx_status_ready_valid ), .sysif_status_ready_i ( ombx_status_ready ), .sysif_status_ready_o ( sysif_status_ready ), diff --git a/hw/ip/mbx/rtl/mbx_host_reg_top.sv b/hw/ip/mbx/rtl/mbx_host_reg_top.sv index a733d4ca37371..2bce11feaafd3 100644 --- a/hw/ip/mbx/rtl/mbx_host_reg_top.sv +++ b/hw/ip/mbx/rtl/mbx_host_reg_top.sv @@ -151,8 +151,6 @@ module mbx_host_reg_top ( logic status_doe_intr_status_wd; logic status_error_qs; logic status_error_wd; - logic status_async_msg_status_qs; - logic status_async_msg_status_wd; logic status_ready_qs; logic status_ready_wd; logic address_range_regwen_we; @@ -411,7 +409,7 @@ module mbx_host_reg_top ( // R[status]: V(True) logic status_qe; - logic [4:0] status_flds_we; + logic [3:0] status_flds_we; assign status_qe = &status_flds_we; // F[busy]: 0:0 prim_subreg_ext #( @@ -461,22 +459,6 @@ module mbx_host_reg_top ( ); assign reg2hw.status.error.qe = status_qe; - // F[async_msg_status]: 3:3 - prim_subreg_ext #( - .DW (1) - ) u_status_async_msg_status ( - .re (status_re), - .we (status_we), - .wd (status_async_msg_status_wd), - .d (hw2reg.status.async_msg_status.d), - .qre (), - .qe (status_flds_we[3]), - .q (reg2hw.status.async_msg_status.q), - .ds (), - .qs (status_async_msg_status_qs) - ); - assign reg2hw.status.async_msg_status.qe = status_qe; - // F[ready]: 31:31 prim_subreg_ext #( .DW (1) @@ -486,7 +468,7 @@ module mbx_host_reg_top ( .wd (status_ready_wd), .d (hw2reg.status.ready.d), .qre (), - .qe (status_flds_we[4]), + .qe (status_flds_we[3]), .q (reg2hw.status.ready.q), .ds (), .qs (status_ready_qs) @@ -927,8 +909,6 @@ module mbx_host_reg_top ( assign status_error_wd = reg_wdata[2]; - assign status_async_msg_status_wd = reg_wdata[3]; - assign status_ready_wd = reg_wdata[31]; assign address_range_regwen_we = addr_hit[6] & reg_we & !reg_error; @@ -1011,7 +991,6 @@ module mbx_host_reg_top ( reg_rdata_next[0] = status_busy_qs; reg_rdata_next[1] = status_doe_intr_status_qs; reg_rdata_next[2] = status_error_qs; - reg_rdata_next[3] = status_async_msg_status_qs; reg_rdata_next[31] = status_ready_qs; end diff --git a/hw/ip/mbx/rtl/mbx_hostif.sv b/hw/ip/mbx/rtl/mbx_hostif.sv index 73250d9eef93f..50f84cb435a32 100644 --- a/hw/ip/mbx/rtl/mbx_hostif.sv +++ b/hw/ip/mbx/rtl/mbx_hostif.sv @@ -32,11 +32,9 @@ module mbx_hostif output logic hostif_status_doe_intr_status_set_o, output logic hostif_status_error_set_o, output logic hostif_status_error_clear_o, - output logic hostif_status_async_msg_status_set_o, input logic hostif_status_busy_i, input logic hostif_status_doe_intr_status_i, input logic hostif_status_error_i, - input logic hostif_status_async_msg_status_i, input logic hostif_status_ready_i, // Access to the IB/OB RD/WR pointers input logic [CfgSramAddrWidth-1:0] hostif_imbx_write_ptr_i, @@ -167,7 +165,6 @@ module mbx_hostif assign hw2reg.status.busy.d = hostif_status_busy_i; assign hw2reg.status.doe_intr_status.d = hostif_status_doe_intr_status_i; assign hw2reg.status.error.d = hostif_status_error_i; - assign hw2reg.status.async_msg_status.d = hostif_status_async_msg_status_i; assign hw2reg.status.ready.d = hostif_status_ready_i; // External write logic assign hostif_status_busy_clear_o = reg2hw.status.busy.qe & ~reg2hw.status.busy.q; @@ -175,8 +172,6 @@ module mbx_hostif reg2hw.status.doe_intr_status.q; assign hostif_status_error_set_o = reg2hw.status.error.qe & reg2hw.status.error.q; assign hostif_status_error_clear_o = reg2hw.status.error.qe & ~reg2hw.status.error.q; - assign hostif_status_async_msg_status_set_o = - reg2hw.status.async_msg_status.qe & reg2hw.status.async_msg_status.q; // Address config valid assign hostif_address_range_valid_o = reg2hw.address_range_valid.q; diff --git a/hw/ip/mbx/rtl/mbx_reg_pkg.sv b/hw/ip/mbx/rtl/mbx_reg_pkg.sv index e8fb2a2792523..75959992086b0 100644 --- a/hw/ip/mbx/rtl/mbx_reg_pkg.sv +++ b/hw/ip/mbx/rtl/mbx_reg_pkg.sv @@ -20,41 +20,41 @@ package mbx_reg_pkg; typedef struct packed { struct packed { logic q; - } mbx_ready; + } mbx_abort; struct packed { logic q; - } mbx_abort; + } mbx_ready; } mbx_reg2hw_intr_state_reg_t; typedef struct packed { struct packed { logic q; - } mbx_ready; + } mbx_abort; struct packed { logic q; - } mbx_abort; + } mbx_ready; } mbx_reg2hw_intr_enable_reg_t; typedef struct packed { struct packed { logic q; logic qe; - } mbx_ready; + } mbx_abort; struct packed { logic q; logic qe; - } mbx_abort; + } mbx_ready; } mbx_reg2hw_intr_test_reg_t; typedef struct packed { struct packed { logic q; logic qe; - } fatal_fault; + } recov_fault; struct packed { logic q; logic qe; - } recov_fault; + } fatal_fault; } mbx_reg2hw_alert_test_reg_t; typedef struct packed { @@ -73,10 +73,6 @@ package mbx_reg_pkg; logic q; logic qe; } ready; - struct packed { - logic q; - logic qe; - } async_msg_status; struct packed { logic q; logic qe; @@ -172,9 +168,6 @@ package mbx_reg_pkg; struct packed { logic d; } error; - struct packed { - logic d; - } async_msg_status; struct packed { logic d; } ready; @@ -203,12 +196,12 @@ package mbx_reg_pkg; // Register -> HW type for host interface typedef struct packed { - mbx_reg2hw_intr_state_reg_t intr_state; // [292:291] - mbx_reg2hw_intr_enable_reg_t intr_enable; // [290:289] - mbx_reg2hw_intr_test_reg_t intr_test; // [288:285] - mbx_reg2hw_alert_test_reg_t alert_test; // [284:281] - mbx_reg2hw_control_reg_t control; // [280:277] - mbx_reg2hw_status_reg_t status; // [276:267] + mbx_reg2hw_intr_state_reg_t intr_state; // [290:289] + mbx_reg2hw_intr_enable_reg_t intr_enable; // [288:287] + mbx_reg2hw_intr_test_reg_t intr_test; // [286:283] + mbx_reg2hw_alert_test_reg_t alert_test; // [282:279] + mbx_reg2hw_control_reg_t control; // [278:275] + mbx_reg2hw_status_reg_t status; // [274:267] mbx_reg2hw_address_range_regwen_reg_t address_range_regwen; // [266:263] mbx_reg2hw_address_range_valid_reg_t address_range_valid; // [262:262] mbx_reg2hw_inbound_base_address_reg_t inbound_base_address; // [261:231] @@ -224,9 +217,9 @@ package mbx_reg_pkg; // HW -> register type for host interface typedef struct packed { - mbx_hw2reg_intr_state_reg_t intr_state; // [146:143] - mbx_hw2reg_control_reg_t control; // [142:141] - mbx_hw2reg_status_reg_t status; // [140:136] + mbx_hw2reg_intr_state_reg_t intr_state; // [145:142] + mbx_hw2reg_control_reg_t control; // [141:140] + mbx_hw2reg_status_reg_t status; // [139:136] mbx_hw2reg_inbound_write_ptr_reg_t inbound_write_ptr; // [135:106] mbx_hw2reg_outbound_read_ptr_reg_t outbound_read_ptr; // [105:76] mbx_hw2reg_outbound_object_size_reg_t outbound_object_size; // [75:64] @@ -267,7 +260,6 @@ package mbx_reg_pkg; parameter logic [0:0] MBX_STATUS_BUSY_RESVAL = 1'h 1; parameter logic [0:0] MBX_STATUS_DOE_INTR_STATUS_RESVAL = 1'h 0; parameter logic [0:0] MBX_STATUS_ERROR_RESVAL = 1'h 0; - parameter logic [0:0] MBX_STATUS_ASYNC_MSG_STATUS_RESVAL = 1'h 0; parameter logic [0:0] MBX_STATUS_READY_RESVAL = 1'h 0; parameter logic [31:0] MBX_INBOUND_WRITE_PTR_RESVAL = 32'h 0; parameter logic [29:0] MBX_INBOUND_WRITE_PTR_INBOUND_READ_PTR_RESVAL = 30'h 0; @@ -339,10 +331,6 @@ package mbx_reg_pkg; logic q; logic qe; } go; - struct packed { - logic q; - logic qe; - } async_msg_en; struct packed { logic q; logic qe; @@ -357,9 +345,6 @@ package mbx_reg_pkg; struct packed { logic q; } ready; - struct packed { - logic q; - } async_msg_status; struct packed { logic q; } error; @@ -379,9 +364,6 @@ package mbx_reg_pkg; struct packed { logic d; } doe_intr_en; - struct packed { - logic d; - } async_msg_en; struct packed { logic d; } go; @@ -400,10 +382,6 @@ package mbx_reg_pkg; logic d; logic de; } error; - struct packed { - logic d; - logic de; - } async_msg_status; struct packed { logic d; logic de; @@ -412,16 +390,16 @@ package mbx_reg_pkg; // Register -> HW type for sys interface typedef struct packed { - mbx_reg2hw_sys_doe_intr_msg_addr_reg_t sys_doe_intr_msg_addr; // [79:47] - mbx_reg2hw_sys_doe_intr_msg_data_reg_t sys_doe_intr_msg_data; // [46:14] - mbx_reg2hw_sys_control_reg_t sys_control; // [13:6] - mbx_reg2hw_sys_status_reg_t sys_status; // [5:0] + mbx_reg2hw_sys_doe_intr_msg_addr_reg_t sys_doe_intr_msg_addr; // [76:44] + mbx_reg2hw_sys_doe_intr_msg_data_reg_t sys_doe_intr_msg_data; // [43:11] + mbx_reg2hw_sys_control_reg_t sys_control; // [10:5] + mbx_reg2hw_sys_status_reg_t sys_status; // [4:0] } mbx_sys_reg2hw_t; // HW -> register type for sys interface typedef struct packed { - mbx_hw2reg_sys_control_reg_t sys_control; // [13:10] - mbx_hw2reg_sys_status_reg_t sys_status; // [9:0] + mbx_hw2reg_sys_control_reg_t sys_control; // [10:8] + mbx_hw2reg_sys_status_reg_t sys_status; // [7:0] } mbx_sys_hw2reg_t; // Register offsets for sys interface @@ -434,7 +412,6 @@ package mbx_reg_pkg; parameter logic [31:0] MBX_SYS_CONTROL_RESVAL = 32'h 0; parameter logic [0:0] MBX_SYS_CONTROL_ABORT_RESVAL = 1'h 0; parameter logic [0:0] MBX_SYS_CONTROL_DOE_INTR_EN_RESVAL = 1'h 0; - parameter logic [0:0] MBX_SYS_CONTROL_ASYNC_MSG_EN_RESVAL = 1'h 0; parameter logic [0:0] MBX_SYS_CONTROL_GO_RESVAL = 1'h 0; // Window parameters for sys interface diff --git a/hw/ip/mbx/rtl/mbx_sys_reg_top.sv b/hw/ip/mbx/rtl/mbx_sys_reg_top.sv index 5ac0f7ce22e5f..00e63ce084714 100644 --- a/hw/ip/mbx/rtl/mbx_sys_reg_top.sv +++ b/hw/ip/mbx/rtl/mbx_sys_reg_top.sv @@ -184,15 +184,12 @@ module mbx_sys_reg_top ( logic sys_control_abort_wd; logic sys_control_doe_intr_en_qs; logic sys_control_doe_intr_en_wd; - logic sys_control_async_msg_en_qs; - logic sys_control_async_msg_en_wd; logic sys_control_go_wd; logic sys_status_we; logic sys_status_busy_qs; logic sys_status_doe_intr_status_qs; logic sys_status_doe_intr_status_wd; logic sys_status_error_qs; - logic sys_status_async_msg_status_qs; logic sys_status_ready_qs; // Register instances @@ -278,7 +275,7 @@ module mbx_sys_reg_top ( // R[sys_control]: V(True) logic sys_control_qe; - logic [3:0] sys_control_flds_we; + logic [2:0] sys_control_flds_we; assign sys_control_qe = &sys_control_flds_we; // F[abort]: 0:0 prim_subreg_ext #( @@ -312,22 +309,6 @@ module mbx_sys_reg_top ( ); assign reg2hw.sys_control.doe_intr_en.qe = sys_control_qe; - // F[async_msg_en]: 3:3 - prim_subreg_ext #( - .DW (1) - ) u_sys_control_async_msg_en ( - .re (sys_control_re), - .we (sys_control_we), - .wd (sys_control_async_msg_en_wd), - .d (hw2reg.sys_control.async_msg_en.d), - .qre (), - .qe (sys_control_flds_we[2]), - .q (reg2hw.sys_control.async_msg_en.q), - .ds (), - .qs (sys_control_async_msg_en_qs) - ); - assign reg2hw.sys_control.async_msg_en.qe = sys_control_qe; - // F[go]: 31:31 prim_subreg_ext #( .DW (1) @@ -337,7 +318,7 @@ module mbx_sys_reg_top ( .wd (sys_control_go_wd), .d (hw2reg.sys_control.go.d), .qre (), - .qe (sys_control_flds_we[3]), + .qe (sys_control_flds_we[2]), .q (reg2hw.sys_control.go.q), .ds (), .qs () @@ -347,14 +328,14 @@ module mbx_sys_reg_top ( // R[sys_status]: V(False) logic sys_status_qe; - logic [4:0] sys_status_flds_we; + logic [3:0] sys_status_flds_we; prim_flop #( .Width(1), .ResetValue(0) ) u_sys_status0_qe ( .clk_i(clk_i), .rst_ni(rst_ni), - .d_i(&(sys_status_flds_we | 5'h1d)), + .d_i(&(sys_status_flds_we | 4'hd)), .q_o(sys_status_qe) ); // F[busy]: 0:0 @@ -439,33 +420,6 @@ module mbx_sys_reg_top ( .qs (sys_status_error_qs) ); - // F[async_msg_status]: 3:3 - prim_subreg #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessRO), - .RESVAL (1'h0), - .Mubi (1'b0) - ) u_sys_status_async_msg_status ( - .clk_i (clk_i), - .rst_ni (rst_ni), - - // from register interface - .we (1'b0), - .wd ('0), - - // from internal hardware - .de (hw2reg.sys_status.async_msg_status.de), - .d (hw2reg.sys_status.async_msg_status.d), - - // to internal hardware - .qe (sys_status_flds_we[3]), - .q (reg2hw.sys_status.async_msg_status.q), - .ds (), - - // to register interface (read) - .qs (sys_status_async_msg_status_qs) - ); - // F[ready]: 31:31 prim_subreg #( .DW (1), @@ -485,7 +439,7 @@ module mbx_sys_reg_top ( .d (hw2reg.sys_status.ready.d), // to internal hardware - .qe (sys_status_flds_we[4]), + .qe (sys_status_flds_we[3]), .q (reg2hw.sys_status.ready.q), .ds (), @@ -529,8 +483,6 @@ module mbx_sys_reg_top ( assign sys_control_doe_intr_en_wd = reg_wdata[1]; - assign sys_control_async_msg_en_wd = reg_wdata[3]; - assign sys_control_go_wd = reg_wdata[31]; assign sys_status_we = addr_hit[3] & reg_we & !reg_error; @@ -560,7 +512,6 @@ module mbx_sys_reg_top ( addr_hit[2]: begin reg_rdata_next[0] = '0; reg_rdata_next[1] = sys_control_doe_intr_en_qs; - reg_rdata_next[3] = sys_control_async_msg_en_qs; reg_rdata_next[31] = '0; end @@ -568,7 +519,6 @@ module mbx_sys_reg_top ( reg_rdata_next[0] = sys_status_busy_qs; reg_rdata_next[1] = sys_status_doe_intr_status_qs; reg_rdata_next[2] = sys_status_error_qs; - reg_rdata_next[3] = sys_status_async_msg_status_qs; reg_rdata_next[31] = sys_status_ready_qs; end diff --git a/hw/ip/mbx/rtl/mbx_sysif.sv b/hw/ip/mbx/rtl/mbx_sysif.sv index 585937100104d..84823d2cc6bdb 100644 --- a/hw/ip/mbx/rtl/mbx_sysif.sv +++ b/hw/ip/mbx/rtl/mbx_sysif.sv @@ -22,7 +22,6 @@ module mbx_sysif output logic doe_intr_o, // Access to the control register output logic sysif_control_abort_set_o, - output logic sysif_control_async_msg_en_o, output logic sysif_control_go_set_o, // Access to the status register input logic sysif_status_busy_valid_i, @@ -33,8 +32,6 @@ module mbx_sysif input logic sysif_status_error_set_i, input logic sysif_status_error_clear_i, output logic sysif_status_error_o, - input logic sysif_status_async_msg_status_set_i, - output logic sysif_status_async_msg_status_o, input logic sysif_status_ready_valid_i, input logic sysif_status_ready_i, output logic sysif_status_ready_o, @@ -105,31 +102,7 @@ module mbx_sysif .qs () ); - // Manual implementation of the async_msg_en bit - // SWAccess: RW - // HWAccess: RO - prim_subreg #( - .DW (1), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (1'h0) - ) u_sys_control_async_msg_en ( - .clk_i (clk_i), - .rst_ni (rst_ni), - // from register interface - .we (reg2hw.sys_control.async_msg_en.qe), - .wd (reg2hw.sys_control.async_msg_en.q), - // HWAccess: hro - .de (1'b0), - .d (1'b0), - // to internal hardware - .qe (), - .q (sysif_control_async_msg_en_o), - .ds (hw2reg.sys_control.async_msg_en.d), - .qs () - ); - // Fiddle out status register bits for external write logic - assign sysif_status_async_msg_status_o = reg2hw.sys_status.async_msg_status.q; assign sysif_status_doe_intr_status_o = reg2hw.sys_status.doe_intr_status.q; assign sysif_status_busy_o = reg2hw.sys_status.busy.q; assign sysif_status_ready_o = reg2hw.sys_status.ready.q; @@ -149,8 +122,6 @@ module mbx_sysif // Set by the Host firmware (w1s) // Cleared by the Sys firmware (w1c) - assign hw2reg.sys_status.async_msg_status.de = sysif_status_async_msg_status_set_i; - assign hw2reg.sys_status.async_msg_status.d = sysif_status_async_msg_status_set_i; assign hw2reg.sys_status.ready.de = sysif_status_ready_valid_i; assign hw2reg.sys_status.ready.d = sysif_status_ready_i; From 256b98795a29a3eec9127c9f057f895da65affb7 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Mon, 18 Sep 2023 09:04:39 -0700 Subject: [PATCH 21/88] [hw,mbx,rtl] Remove hostif.status.ready register Signed-off-by: Robert Schilling --- hw/ip/mbx/data/mbx.hjson | 9 --------- hw/ip/mbx/rtl/mbx.sv | 4 +--- hw/ip/mbx/rtl/mbx_host_reg_top.sv | 23 +---------------------- hw/ip/mbx/rtl/mbx_hostif.sv | 2 -- hw/ip/mbx/rtl/mbx_reg_pkg.sv | 30 +++++++++++------------------- hw/ip/mbx/rtl/mbx_sysif.sv | 2 -- 6 files changed, 13 insertions(+), 57 deletions(-) diff --git a/hw/ip/mbx/data/mbx.hjson b/hw/ip/mbx/data/mbx.hjson index f8608a89df47b..cf3d97b85821b 100644 --- a/hw/ip/mbx/data/mbx.hjson +++ b/hw/ip/mbx/data/mbx.hjson @@ -123,15 +123,6 @@ hwaccess: "hrw" hwqe: "true" } - { - name: "ready" - desc: "Alias of the DoE mailbox ready bit" - bits: "31" - resval: "0x0" - swaccess: "rw" - hwaccess: "hrw" - hwqe: "true" - } ] } { name: "ADDRESS_RANGE_REGWEN" diff --git a/hw/ip/mbx/rtl/mbx.sv b/hw/ip/mbx/rtl/mbx.sv index e27b47d18d471..ebc2cd1a6dd06 100644 --- a/hw/ip/mbx/rtl/mbx.sv +++ b/hw/ip/mbx/rtl/mbx.sv @@ -56,7 +56,7 @@ module mbx logic sysif_control_abort_write; // Status signal inputs from the sysif to the hostif - logic sysif_status_busy, sysif_status_doe_intr_status, sysif_status_error, sysif_status_ready; + logic sysif_status_busy, sysif_status_doe_intr_status, sysif_status_error; // Setter signals from the hostif to the sysif logic hostif_status_doe_intr_status_set, hostif_control_abort_set, hostif_status_busy_clear, @@ -111,7 +111,6 @@ module mbx .hostif_status_error_set_o ( hostif_status_error_set ), .hostif_status_error_clear_o ( hostif_status_error_clear ), .hostif_status_error_i ( sysif_status_error ), - .hostif_status_ready_i ( sysif_status_ready ), // Access to the IB/OB RD/WR Pointers .hostif_imbx_write_ptr_i ( imbx_sram_write_ptr ), .hostif_ombx_read_ptr_i ( ombx_sram_read_ptr ), @@ -194,7 +193,6 @@ module mbx .sysif_status_ready_valid_i ( ombx_status_ready_valid ), .sysif_status_ready_i ( ombx_status_ready ), - .sysif_status_ready_o ( sysif_status_ready ), // Alias of the interrupt address and data registers to the host interface .sysif_intr_msg_addr_o ( sysif_intr_msg_addr ), .sysif_intr_msg_data_o ( sysif_intr_msg_data ), diff --git a/hw/ip/mbx/rtl/mbx_host_reg_top.sv b/hw/ip/mbx/rtl/mbx_host_reg_top.sv index 2bce11feaafd3..e94f32ad9a98c 100644 --- a/hw/ip/mbx/rtl/mbx_host_reg_top.sv +++ b/hw/ip/mbx/rtl/mbx_host_reg_top.sv @@ -151,8 +151,6 @@ module mbx_host_reg_top ( logic status_doe_intr_status_wd; logic status_error_qs; logic status_error_wd; - logic status_ready_qs; - logic status_ready_wd; logic address_range_regwen_we; logic [3:0] address_range_regwen_qs; logic [3:0] address_range_regwen_wd; @@ -409,7 +407,7 @@ module mbx_host_reg_top ( // R[status]: V(True) logic status_qe; - logic [3:0] status_flds_we; + logic [2:0] status_flds_we; assign status_qe = &status_flds_we; // F[busy]: 0:0 prim_subreg_ext #( @@ -459,22 +457,6 @@ module mbx_host_reg_top ( ); assign reg2hw.status.error.qe = status_qe; - // F[ready]: 31:31 - prim_subreg_ext #( - .DW (1) - ) u_status_ready ( - .re (status_re), - .we (status_we), - .wd (status_ready_wd), - .d (hw2reg.status.ready.d), - .qre (), - .qe (status_flds_we[3]), - .q (reg2hw.status.ready.q), - .ds (), - .qs (status_ready_qs) - ); - assign reg2hw.status.ready.qe = status_qe; - // R[address_range_regwen]: V(False) prim_subreg #( @@ -908,8 +890,6 @@ module mbx_host_reg_top ( assign status_doe_intr_status_wd = reg_wdata[1]; assign status_error_wd = reg_wdata[2]; - - assign status_ready_wd = reg_wdata[31]; assign address_range_regwen_we = addr_hit[6] & reg_we & !reg_error; assign address_range_regwen_wd = reg_wdata[3:0]; @@ -991,7 +971,6 @@ module mbx_host_reg_top ( reg_rdata_next[0] = status_busy_qs; reg_rdata_next[1] = status_doe_intr_status_qs; reg_rdata_next[2] = status_error_qs; - reg_rdata_next[31] = status_ready_qs; end addr_hit[6]: begin diff --git a/hw/ip/mbx/rtl/mbx_hostif.sv b/hw/ip/mbx/rtl/mbx_hostif.sv index 50f84cb435a32..f5ceb7569157c 100644 --- a/hw/ip/mbx/rtl/mbx_hostif.sv +++ b/hw/ip/mbx/rtl/mbx_hostif.sv @@ -35,7 +35,6 @@ module mbx_hostif input logic hostif_status_busy_i, input logic hostif_status_doe_intr_status_i, input logic hostif_status_error_i, - input logic hostif_status_ready_i, // Access to the IB/OB RD/WR pointers input logic [CfgSramAddrWidth-1:0] hostif_imbx_write_ptr_i, input logic [CfgSramAddrWidth-1:0] hostif_ombx_read_ptr_i, @@ -165,7 +164,6 @@ module mbx_hostif assign hw2reg.status.busy.d = hostif_status_busy_i; assign hw2reg.status.doe_intr_status.d = hostif_status_doe_intr_status_i; assign hw2reg.status.error.d = hostif_status_error_i; - assign hw2reg.status.ready.d = hostif_status_ready_i; // External write logic assign hostif_status_busy_clear_o = reg2hw.status.busy.qe & ~reg2hw.status.busy.q; assign hostif_status_doe_intr_status_set_o = reg2hw.status.doe_intr_status.qe & diff --git a/hw/ip/mbx/rtl/mbx_reg_pkg.sv b/hw/ip/mbx/rtl/mbx_reg_pkg.sv index 75959992086b0..357b46ffe3c6f 100644 --- a/hw/ip/mbx/rtl/mbx_reg_pkg.sv +++ b/hw/ip/mbx/rtl/mbx_reg_pkg.sv @@ -69,10 +69,6 @@ package mbx_reg_pkg; } mbx_reg2hw_control_reg_t; typedef struct packed { - struct packed { - logic q; - logic qe; - } ready; struct packed { logic q; logic qe; @@ -168,9 +164,6 @@ package mbx_reg_pkg; struct packed { logic d; } error; - struct packed { - logic d; - } ready; } mbx_hw2reg_status_reg_t; typedef struct packed { @@ -196,12 +189,12 @@ package mbx_reg_pkg; // Register -> HW type for host interface typedef struct packed { - mbx_reg2hw_intr_state_reg_t intr_state; // [290:289] - mbx_reg2hw_intr_enable_reg_t intr_enable; // [288:287] - mbx_reg2hw_intr_test_reg_t intr_test; // [286:283] - mbx_reg2hw_alert_test_reg_t alert_test; // [282:279] - mbx_reg2hw_control_reg_t control; // [278:275] - mbx_reg2hw_status_reg_t status; // [274:267] + mbx_reg2hw_intr_state_reg_t intr_state; // [288:287] + mbx_reg2hw_intr_enable_reg_t intr_enable; // [286:285] + mbx_reg2hw_intr_test_reg_t intr_test; // [284:281] + mbx_reg2hw_alert_test_reg_t alert_test; // [280:277] + mbx_reg2hw_control_reg_t control; // [276:273] + mbx_reg2hw_status_reg_t status; // [272:267] mbx_reg2hw_address_range_regwen_reg_t address_range_regwen; // [266:263] mbx_reg2hw_address_range_valid_reg_t address_range_valid; // [262:262] mbx_reg2hw_inbound_base_address_reg_t inbound_base_address; // [261:231] @@ -217,9 +210,9 @@ package mbx_reg_pkg; // HW -> register type for host interface typedef struct packed { - mbx_hw2reg_intr_state_reg_t intr_state; // [145:142] - mbx_hw2reg_control_reg_t control; // [141:140] - mbx_hw2reg_status_reg_t status; // [139:136] + mbx_hw2reg_intr_state_reg_t intr_state; // [144:141] + mbx_hw2reg_control_reg_t control; // [140:139] + mbx_hw2reg_status_reg_t status; // [138:136] mbx_hw2reg_inbound_write_ptr_reg_t inbound_write_ptr; // [135:106] mbx_hw2reg_outbound_read_ptr_reg_t outbound_read_ptr; // [105:76] mbx_hw2reg_outbound_object_size_reg_t outbound_object_size; // [75:64] @@ -256,11 +249,10 @@ package mbx_reg_pkg; parameter logic [1:0] MBX_CONTROL_RESVAL = 2'h 0; parameter logic [0:0] MBX_CONTROL_ABORT_RESVAL = 1'h 0; parameter logic [0:0] MBX_CONTROL_DOE_INTR_EN_RESVAL = 1'h 0; - parameter logic [31:0] MBX_STATUS_RESVAL = 32'h 1; + parameter logic [2:0] MBX_STATUS_RESVAL = 3'h 1; parameter logic [0:0] MBX_STATUS_BUSY_RESVAL = 1'h 1; parameter logic [0:0] MBX_STATUS_DOE_INTR_STATUS_RESVAL = 1'h 0; parameter logic [0:0] MBX_STATUS_ERROR_RESVAL = 1'h 0; - parameter logic [0:0] MBX_STATUS_READY_RESVAL = 1'h 0; parameter logic [31:0] MBX_INBOUND_WRITE_PTR_RESVAL = 32'h 0; parameter logic [29:0] MBX_INBOUND_WRITE_PTR_INBOUND_READ_PTR_RESVAL = 30'h 0; parameter logic [31:0] MBX_OUTBOUND_READ_PTR_RESVAL = 32'h 0; @@ -298,7 +290,7 @@ package mbx_reg_pkg; 4'b 0001, // index[ 2] MBX_INTR_TEST 4'b 0001, // index[ 3] MBX_ALERT_TEST 4'b 0001, // index[ 4] MBX_CONTROL - 4'b 1111, // index[ 5] MBX_STATUS + 4'b 0001, // index[ 5] MBX_STATUS 4'b 0001, // index[ 6] MBX_ADDRESS_RANGE_REGWEN 4'b 0001, // index[ 7] MBX_ADDRESS_RANGE_VALID 4'b 1111, // index[ 8] MBX_INBOUND_BASE_ADDRESS diff --git a/hw/ip/mbx/rtl/mbx_sysif.sv b/hw/ip/mbx/rtl/mbx_sysif.sv index 84823d2cc6bdb..4188ec8e745d3 100644 --- a/hw/ip/mbx/rtl/mbx_sysif.sv +++ b/hw/ip/mbx/rtl/mbx_sysif.sv @@ -34,7 +34,6 @@ module mbx_sysif output logic sysif_status_error_o, input logic sysif_status_ready_valid_i, input logic sysif_status_ready_i, - output logic sysif_status_ready_o, // Alias of the interrupt address and data registers to the host interface output logic [CfgSramAddrWidth-1:0] sysif_intr_msg_addr_o, output logic [CfgSramDataWidth-1:0] sysif_intr_msg_data_o, @@ -105,7 +104,6 @@ module mbx_sysif // Fiddle out status register bits for external write logic assign sysif_status_doe_intr_status_o = reg2hw.sys_status.doe_intr_status.q; assign sysif_status_busy_o = reg2hw.sys_status.busy.q; - assign sysif_status_ready_o = reg2hw.sys_status.ready.q; assign sysif_status_error_o = reg2hw.sys_status.error.q; // External read logic From 6ae3245ec1d6e5efa1cb204a25fcb587d3e0f608 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Tue, 5 Sep 2023 04:35:04 -0700 Subject: [PATCH 22/88] [hw,mbx,rtl] Outbound mailbox implementation Signed-off-by: Robert Schilling --- hw/ip/mbx/mbx.core | 1 + hw/ip/mbx/rtl/mbx.sv | 52 +++++++- hw/ip/mbx/rtl/mbx_fsm.sv | 10 +- hw/ip/mbx/rtl/mbx_imbx.sv | 2 +- hw/ip/mbx/rtl/mbx_ombx.sv | 260 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 313 insertions(+), 12 deletions(-) create mode 100644 hw/ip/mbx/rtl/mbx_ombx.sv diff --git a/hw/ip/mbx/mbx.core b/hw/ip/mbx/mbx.core index 122b020b61f7e..d0351c15d18bb 100644 --- a/hw/ip/mbx/mbx.core +++ b/hw/ip/mbx/mbx.core @@ -20,6 +20,7 @@ filesets: - rtl/mbx_sramrwarb.sv - rtl/mbx_fsm.sv - rtl/mbx_imbx.sv + - rtl/mbx_ombx.sv file_type: systemVerilogSource files_verilator_waiver: diff --git a/hw/ip/mbx/rtl/mbx.sv b/hw/ip/mbx/rtl/mbx.sv index ebc2cd1a6dd06..389f1e6f54899 100644 --- a/hw/ip/mbx/rtl/mbx.sv +++ b/hw/ip/mbx/rtl/mbx.sv @@ -11,6 +11,7 @@ module mbx parameter logic [NumAlerts-1:0] AlertAsyncOn = {NumAlerts{1'b1}}, parameter int unsigned CfgSramAddrWidth = 32, parameter int unsigned CfgSramDataWidth = 32, + parameter int unsigned CfgOmbxDwCntWidth = 11, parameter bit DoeIrqSupport = 1'b1 ) ( input logic clk_i, @@ -40,11 +41,12 @@ module mbx ////////////////////////////////////////////////////////////////////////////// // Collect all error sources - logic sysif_intg_err, tl_sram_intg_err, imbx_state_error, alert_signal; - logic sram_err; + logic sysif_intg_err, tl_sram_intg_err, imbx_state_error, ombx_state_error; + logic alert_signal, sram_err; assign alert_signal = sysif_intg_err | tl_sram_intg_err | + ombx_state_error | imbx_state_error; ////////////////////////////////////////////////////////////////////////////// @@ -81,7 +83,7 @@ module mbx logic [CfgSramAddrWidth-1:0] ombx_sram_read_ptr; logic hostif_ombx_object_size_write, hostif_ombx_object_size_read; - logic [10:0] hostif_ombx_object_size_wdata, hostif_ombx_object_size_rdata; + logic [CfgOmbxDwCntWidth-1:0] hostif_ombx_object_size_wdata, hostif_ombx_object_size_rdata; mbx_hostif #( .AlertAsyncOn ( AlertAsyncOn ), @@ -158,7 +160,7 @@ module mbx // Interface signals for SRAM host access to read the memory and serve it to the outbox logic ombx_sram_read_req, ombx_sram_read_gnt; logic ombx_sram_read_resp_vld; - logic [CfgSramDataWidth-1:0] sysif_read_data; + logic [CfgSramDataWidth-1:0] ombx_sram_read_data, sysif_read_data; logic sysif_read_data_read_valid, sysif_read_data_write_valid; mbx_sysif #( @@ -225,7 +227,7 @@ module mbx .hostif_control_abort_set_i ( hostif_control_abort_set ), .hostif_status_busy_clear_i ( hostif_status_busy_clear ), .hostif_status_error_set_i ( hostif_status_error_set ), - + // SRAM range configuration .hostif_range_valid_i ( hostif_address_range_valid ), .hostif_base_i ( hostif_imbx_base ), .hostif_limit_i ( hostif_imbx_limit ), @@ -240,6 +242,44 @@ module mbx .hostif_sram_write_ptr_o ( imbx_sram_write_ptr ) ); + + mbx_ombx #( + .CfgSramAddrWidth ( CfgSramAddrWidth ), + .CfgSramDataWidth ( CfgSramDataWidth ), + .CfgOmbxDwCntWidth (CfgOmbxDwCntWidth ) + ) u_ombx ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + // Interface to the host port + .ombx_state_error_o ( ombx_state_error ), + .ombx_pending_o ( ombx_pending ), + .ombx_status_ready_update_o ( ombx_status_ready_valid ), + .ombx_status_ready_o ( ombx_status_ready ), + // SRAM range configuration + .hostif_range_valid_i ( hostif_address_range_valid ), + .hostif_base_i ( hostif_ombx_base ), + .hostif_limit_i ( hostif_ombx_limit ), + // Control signals from the host and system interface + .hostif_control_abort_set_i ( hostif_control_abort_set ), + .hostif_status_error_set_i ( hostif_status_error_set ), + .sysif_control_abort_set_i ( sysif_control_abort_set ), + .sysif_read_data_read_valid_i ( sysif_read_data_read_valid ), + .sysif_read_data_write_valid_i ( sysif_read_data_write_valid ), + // Interface for the object size register + .hostif_ombx_object_size_write_i( hostif_ombx_object_size_write ), + .hostif_ombx_object_size_i ( hostif_ombx_object_size_wdata ), + .hostif_ombx_object_size_read_o ( hostif_ombx_object_size_read ), + .hostif_ombx_object_size_o ( hostif_ombx_object_size_rdata ), + // DOE data coming from the SRAM + .ombx_read_data_o ( sysif_read_data ), + // Host interface to access private SRAM + .ombx_sram_read_req_o ( ombx_sram_read_req ), + .ombx_sram_read_gnt_i ( ombx_sram_read_gnt ), + .ombx_sram_read_ptr_o ( ombx_sram_read_ptr ), + .ombx_sram_read_resp_valid_i ( ombx_sram_read_resp_vld ), + .ombx_sram_read_resp_i ( ombx_sram_read_data ) + ); + // Host port connection to access the private SRAM. // Arbitrates between inbound and outbound mailbox mbx_sramrwarb #( @@ -263,7 +303,7 @@ module mbx .ombx_sram_read_gnt_o ( ombx_sram_read_gnt ), .ombx_sram_read_ptr_i ( ombx_sram_read_ptr ), .ombx_sram_read_resp_vld_o ( ombx_sram_read_resp_vld ), - .ombx_sram_read_resp_o ( sysif_read_data ) + .ombx_sram_read_resp_o ( ombx_sram_read_data ) ); endmodule diff --git a/hw/ip/mbx/rtl/mbx_fsm.sv b/hw/ip/mbx/rtl/mbx_fsm.sv index 9bc23f1519ed9..43bb2c144ad90 100644 --- a/hw/ip/mbx/rtl/mbx_fsm.sv +++ b/hw/ip/mbx/rtl/mbx_fsm.sv @@ -5,7 +5,7 @@ `include "prim_assert.sv" module mbx_fsm #( - parameter bit CfgObMbx = 1'b1 // 1'b1: Obmbx, 1'b0: Ibmbx + parameter bit CfgOmbx = 1'b1 // 1'b1: Obmbx, 1'b0: Ibmbx ) ( input logic clk_i, input logic rst_ni, @@ -60,18 +60,18 @@ module mbx_fsm #( logic ob_set_ready, ob_clear_ready; // Outbound mailbox is ready - assign ob_set_ready = CfgObMbx + assign ob_set_ready = CfgOmbx & mbx_idle & mbx_range_valid_i & writer_close_mbx_i & ~sysif_control_abort_set_i; // MbxRead is a common state for imbx and ombx // Exit of MbxRead is used to clear imbx.Busy and ombx.Ready - assign ob_clear_ready = CfgObMbx & (hostif_status_error_set_i | + assign ob_clear_ready = CfgOmbx & (hostif_status_error_set_i | sysif_control_abort_set_i | mbx_read_o & sys_read_all_i); - assign mbx_ob_ready_update_o = CfgObMbx & (ob_set_ready | ob_clear_ready); // MUTEX(set,clr) + assign mbx_ob_ready_update_o = CfgOmbx & (ob_set_ready | ob_clear_ready); // MUTEX(set,clr) assign mbx_ob_ready_o = ob_set_ready; always_comb begin @@ -80,7 +80,7 @@ module mbx_fsm #( unique case (ctrl_state_q) MbxIdle: begin - if (CfgObMbx) begin + if (CfgOmbx) begin if (mbx_range_valid_i & writer_close_mbx_i) begin ctrl_state_d = MbxRead; end diff --git a/hw/ip/mbx/rtl/mbx_imbx.sv b/hw/ip/mbx/rtl/mbx_imbx.sv index b9019c2616be3..0f41621412eca 100644 --- a/hw/ip/mbx/rtl/mbx_imbx.sv +++ b/hw/ip/mbx/rtl/mbx_imbx.sv @@ -135,7 +135,7 @@ module mbx_imbx #( assign imbx_irq_abort_o = mbx_sys_abort; mbx_fsm #( - .CfgObMbx ( 0 ) + .CfgOmbx ( 0 ) ) u_mbxfsm( .clk_i ( clk_i ), .rst_ni ( rst_ni ), diff --git a/hw/ip/mbx/rtl/mbx_ombx.sv b/hw/ip/mbx/rtl/mbx_ombx.sv new file mode 100644 index 0000000000000..ced32adedfbc2 --- /dev/null +++ b/hw/ip/mbx/rtl/mbx_ombx.sv @@ -0,0 +1,260 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +`include "prim_assert.sv" + +module mbx_ombx #( + parameter int unsigned CfgSramAddrWidth = 32, + parameter int unsigned CfgSramDataWidth = 32, + parameter int unsigned CfgOmbxDwCntWidth = 11 +) ( + input logic clk_i, + input logic rst_ni, + output logic ombx_state_error_o, + output logic ombx_pending_o, + output logic ombx_status_ready_update_o, + output logic ombx_status_ready_o, + input logic hostif_range_valid_i, + input logic [CfgSramAddrWidth-1:0] hostif_base_i, + input logic [CfgSramAddrWidth-1:0] hostif_limit_i, + // Control signals from the host and system interface + input logic hostif_control_abort_set_i, + input logic hostif_status_error_set_i, + input logic sysif_status_ready_i, + input logic sysif_control_abort_set_i, + input logic sysif_read_data_read_valid_i, + input logic sysif_read_data_write_valid_i, + // Interface for the object size register + input logic hostif_ombx_object_size_write_i, + input logic [CfgOmbxDwCntWidth-1:0] hostif_ombx_object_size_i, + output logic hostif_ombx_object_size_read_o, + output logic [CfgOmbxDwCntWidth-1:0] hostif_ombx_object_size_o, + // DOE data coming from the SRAM + output logic [CfgSramDataWidth-1:0] ombx_read_data_o, + // Host interface to the private SRAM + output logic ombx_sram_read_req_o, + input logic ombx_sram_read_gnt_i, + output logic [CfgSramAddrWidth-1:0] ombx_sram_read_ptr_o, + input logic ombx_sram_read_resp_valid_i, + input logic [CfgSramDataWidth-1:0] ombx_sram_read_resp_i +); + localparam int unsigned LCFG_SRM_ADDRINC = CfgSramDataWidth / 8; + + logic [CfgSramAddrWidth-1:0] sram_read_ptr_d, sram_read_ptr_q; + logic [CfgSramAddrWidth-1:0] sram_read_ptr_limit_d, sram_read_ptr_limit_q; + + // Status signals from the FSM + logic mbx_empty, mbx_read, mbx_sys_abort; + logic set_pop_entry, clear_pop_entry; + + // Generate the read request + // - mbx reader ACK the current RdData and pop another DW from outbound mailbox + // 1st pop is initiated by mbx owner writes ObDwCnt + logic read_req, pop_entry_q; + assign read_req = pop_entry_q | + (mbx_read & sysif_read_data_write_valid_i & + (sram_read_ptr_q <= sram_read_ptr_limit_q)); + + // Backpressure the next read data until the current write data brings back the data from SRAM + // Exclude last ack + logic set_pending, clear_pending; + + // Block the request from TLUL until the SRAM read is complete + assign set_pending = mbx_read & sysif_read_data_write_valid_i & + (sram_read_ptr_q <= sram_read_ptr_limit_q); + assign clear_pending = ombx_sram_read_resp_valid_i; + + prim_flop #( + .Width(1) + ) u_pending ( + .clk_i ( clk_i ), + .rst_ni( rst_ni ), + .d_i ( set_pending | (ombx_pending_o & ~clear_pending) ), + .q_o ( ombx_pending_o ) + ); + + // Create a sticky TLUL read request until its granted + logic req_q; + assign ombx_sram_read_req_o = read_req | req_q; + + prim_flop #( + .Width(1) + ) u_req_state ( + .clk_i ( clk_i ), + .rst_ni( rst_ni ), + .d_i ( ombx_sram_read_req_o & ~ombx_sram_read_gnt_i ), + .q_o ( req_q ) + ); + + logic writer_close_mbx; + // move FSM to MBRead (Ready) after the 1st read comes back + assign writer_close_mbx = mbx_empty & ombx_sram_read_resp_valid_i; + + // Terminate mbx_read state (Ready = 1 -> 0) if ombx is already drained (sram_read is not issued) + logic sys_read_all; + assign sys_read_all = mbx_read & + sysif_read_data_write_valid_i & + (sram_read_ptr_q == sram_read_ptr_limit_q); + + logic host_clear_abort; + assign host_clear_abort = hostif_control_abort_set_i & mbx_sys_abort; + + // SRAM read pointer management + logic load_read_ptr, advance_read_ptr; + + // Rewind the read pointer to the base + assign load_read_ptr = set_pop_entry | sys_read_all | host_clear_abort; + + // Advance the read pointer when one request went through + assign advance_read_ptr = ombx_sram_read_req_o; + + always_comb begin + sram_read_ptr_d = sram_read_ptr_q; + + if (load_read_ptr) begin + sram_read_ptr_d = hostif_base_i; + end else if (advance_read_ptr) begin + sram_read_ptr_d = sram_read_ptr_q + LCFG_SRM_ADDRINC; + end + end + + prim_generic_flop_en #( + .Width(CfgSramAddrWidth) + ) u_sram_read_ptr ( + .clk_i ( clk_i ), + .rst_ni( rst_ni ), + .en_i ( load_read_ptr | advance_read_ptr ), + .d_i ( sram_read_ptr_d ), + .q_o ( sram_read_ptr_q ) + ); + assign ombx_sram_read_ptr_o = sram_read_ptr_q; + + // Advance the SRAM read response to read data + prim_generic_flop_en #( + .Width(CfgSramDataWidth) + ) u_sram_read_data ( + .clk_i ( clk_i ), + .rst_ni( rst_ni ), + .en_i ( ombx_sram_read_resp_valid_i | sys_read_all ), + .d_i ( {CfgSramDataWidth{~sys_read_all}} & ombx_sram_read_resp_i ), + .q_o ( ombx_read_data_o ) + ); + + logic host_write_ob_dw_count_q; + logic ombx_dw_count_update_valid_q; + + prim_flop #( + .Width(1) + ) u_host_write_ob_dw_count ( + .clk_i ( clk_i ), + .rst_ni( rst_ni ), + .d_i ( hostif_ombx_object_size_write_i & ~ombx_dw_count_update_valid_q ), + .q_o ( host_write_ob_dw_count_q ) + ); + + + logic [CfgOmbxDwCntWidth-1:0] hostif_ob_object_size_minus_one; + assign hostif_ob_object_size_minus_one = hostif_ombx_object_size_i - 1; + // Zero out OMBX DW Count on the abort + assign hostif_ombx_object_size_o = {CfgOmbxDwCntWidth{~sysif_control_abort_set_i}} & + hostif_ob_object_size_minus_one; + + assign hostif_ombx_object_size_read_o = (read_req & ombx_sram_read_gnt_i) | + sysif_control_abort_set_i; + prim_flop #( + .Width(1) + ) u_host_ombx_dw_count_update_valid ( + .clk_i ( clk_i ), + .rst_ni( rst_ni ), + .d_i ( hostif_ombx_object_size_read_o ), + .q_o ( ombx_dw_count_update_valid_q ) + ); + + // Compute the read pointer limit after DW count is written + assign sram_read_ptr_limit_d = hostif_base_i + {hostif_ombx_object_size_i, 2'b0}; + + prim_generic_flop_en #( + .Width(CfgSramAddrWidth) + ) u_sram_read_ptr_limit ( + .clk_i ( clk_i ), + .rst_ni( rst_ni ), + // Factor in ~mbx_read because HW update can trigger host_write_ob_dw_count_q + .en_i ( host_write_ob_dw_count_q & ~mbx_read ), + .d_i ( sram_read_ptr_limit_d ), + .q_o ( sram_read_ptr_limit_q ) + ); + + // mbx_empty means the ombx has not been read yet (not really empty) + // Add (|hostif_ombx_object_size_i) to exclude the write-0-DwCnt initialization + assign set_pop_entry = mbx_empty & host_write_ob_dw_count_q & (|hostif_ombx_object_size_i); + assign clear_pop_entry = ombx_sram_read_gnt_i; + + prim_flop #( + .Width(1) + ) u_pop_entry ( + .clk_i ( clk_i ), + .rst_ni( rst_ni ), + .d_i ( set_pop_entry | (pop_entry_q & ~clear_pop_entry) ), + .q_o ( pop_entry_q ) + ); + + mbx_fsm #( + .CfgOmbx ( 1 ) + ) u_mbxfsm( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .mbx_range_valid_i ( hostif_range_valid_i ), + .hostif_abort_ack_i ( hostif_control_abort_set_i ), + .hostif_status_error_set_i ( hostif_status_error_set_i ), + .hostif_status_busy_clear_i( 1'b0 ), + .sysif_control_abort_set_i ( sysif_control_abort_set_i ), + .sys_read_all_i ( sys_read_all ), + .writer_close_mbx_i ( writer_close_mbx ), + .writer_write_valid_i ( 1'b0 ), + // Status signals + .mbx_empty_o ( mbx_empty ), + .mbx_write_o ( ), + .mbx_read_o ( mbx_read ), + .mbx_sys_abort_o ( mbx_sys_abort ), + .mbx_ob_ready_update_o ( ombx_status_ready_update_o ), + .mbx_ob_ready_o ( ombx_status_ready_o ), + .mbx_state_error_o ( ombx_state_error_o ) + ); + + ////////////////////////////////////////////////////////////////////////////// + // Assertions + ////////////////////////////////////////////////////////////////////////////// + + // Read req should e de-asserted after the read is ACKed by the TLUL adapter + `ASSERT_NEVER(DeassertReqAfterAck_A, ombx_sram_read_req_o & ombx_sram_read_resp_valid_i) + // When reading from the ombx doe_status.ready must have been asserted + `ASSERT_NEVER(ReadyAssertedWhenRead_A, ombx_sram_read_req_o & + ~(pop_entry_q | sysif_status_ready_i)) + // System write-to-read data is non-posted. No subsequential read or write comes before the + // write is ACKed + `ASSERT_NEVER(NoReadBeforeWriteAcked_A, ombx_pending_o & + (sysif_read_data_read_valid_i | sysif_read_data_write_valid_i)) + // Never read the SRAM if it is empty + logic ombx_is_empty; + assign ombx_is_empty = (sram_read_ptr_q == sram_read_ptr_limit_q); + `ASSERT_NEVER(NeverReadWhenEmpty_A, ombx_sram_read_req_o & ombx_is_empty) + // Never let the read pointer run out of the limit + `ASSERT_NEVER(NeverRunOutOfLimit_A, sram_read_ptr_q > sram_read_ptr_limit_q) + +`ifdef INC_ASSERT + + logic[CfgSramAddrWidth-1:0] sram_read_ptr_assert_q; + prim_flop #( + .Width(CfgSramAddrWidth) + ) u_sram_ptr_assert ( + .clk_i ( clk_i ), + .rst_ni( rst_ni ), + .d_i ( sram_read_ptr_d ), + .q_o ( sram_read_ptr_assert_q ) + ); + // A granted write by the host adapter must advance the write pointer + `ASSERT_IF(GntMustAdvanceReadPtr_A, sram_read_ptr_assert_q == sram_read_ptr_q, + ombx_sram_read_gnt_i) +`endif +endmodule From a47b7a9f360efef518c0f1be0ffa85607e458af2 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Fri, 8 Sep 2023 09:04:43 -0700 Subject: [PATCH 23/88] [hw,mbx,rtl] Clarifications to the ombx signalling Signed-off-by: Robert Schilling --- hw/ip/mbx/lint/mbx.waiver | 13 +++ hw/ip/mbx/rtl/mbx.sv | 117 +++++++++++----------- hw/ip/mbx/rtl/mbx_fsm.sv | 21 ++-- hw/ip/mbx/rtl/mbx_hostif.sv | 63 ++++++------ hw/ip/mbx/rtl/mbx_imbx.sv | 39 ++++---- hw/ip/mbx/rtl/mbx_ombx.sv | 194 ++++++++++++++++++++---------------- hw/ip/mbx/rtl/mbx_sysif.sv | 4 +- 7 files changed, 244 insertions(+), 207 deletions(-) diff --git a/hw/ip/mbx/lint/mbx.waiver b/hw/ip/mbx/lint/mbx.waiver index b09dfae2ed0bf..1b2ca889b1ad5 100644 --- a/hw/ip/mbx/lint/mbx.waiver +++ b/hw/ip/mbx/lint/mbx.waiver @@ -3,3 +3,16 @@ # SPDX-License-Identifier: Apache-2.0 # # waiver file for mbx + +waive -rules INPUT_NOT_READ -location {mbx_imbx.sv} -regexp {Input port 'sysif_status_busy_i' is not read from} \ + -comment "Signal only used for assertions" +waive -rules INPUT_NOT_READ -location {mbx_imbx.sv} -regexp {Input port 'hostif_imbx_write_ptr_i[1:0]' is not read from} \ + -comment "Write pointer is always 4B aligned" +waive -rules INPUT_NOT_READ -location {mbx_imbx.sv} -regexp {Input port 'hostif_imbx_read_ptr_i[1:0]' is not read from} \ + -comment "Read pointer is always 4B aligned" +waive -rules INPUT_NOT_READ -location {mbx_ombx.sv} -regexp {Input port 'sysif_status_ready_i' is not read from} \ + -comment "Signal only used for assertions" +waive -rules INPUT_NOT_READ -location {mbx_ombx.sv} -regexp {Input port 'sysif_read_data_read_valid_i' is not read from} \ + -comment "Signal only used for assertions" +waive -rules NOT_READ -location {mbx_ombx.sv} -regexp {Signal 'ombx_is_empty' is not read from} \ + -comment "Signal only used for assertions" diff --git a/hw/ip/mbx/rtl/mbx.sv b/hw/ip/mbx/rtl/mbx.sv index 389f1e6f54899..069dfa6e79773 100644 --- a/hw/ip/mbx/rtl/mbx.sv +++ b/hw/ip/mbx/rtl/mbx.sv @@ -11,7 +11,7 @@ module mbx parameter logic [NumAlerts-1:0] AlertAsyncOn = {NumAlerts{1'b1}}, parameter int unsigned CfgSramAddrWidth = 32, parameter int unsigned CfgSramDataWidth = 32, - parameter int unsigned CfgOmbxDwCntWidth = 11, + parameter int unsigned CfgObjectSizeWidth = 11, parameter bit DoeIrqSupport = 1'b1 ) ( input logic clk_i, @@ -55,13 +55,13 @@ module mbx logic hostif_event_intr_ready, hostif_event_intr_abort; logic hostif_address_range_valid; - logic sysif_control_abort_write; + logic sysif_control_abort_set; // Status signal inputs from the sysif to the hostif logic sysif_status_busy, sysif_status_doe_intr_status, sysif_status_error; // Setter signals from the hostif to the sysif - logic hostif_status_doe_intr_status_set, hostif_control_abort_set, hostif_status_busy_clear, + logic hostif_status_doe_intr_status_set, hostif_control_abort_clear, hostif_status_busy_clear, hostif_status_error_set, hostif_status_error_clear; // Alias signals from the sys interface @@ -82,13 +82,14 @@ module mbx logic [CfgSramAddrWidth-1:0] hostif_ombx_base, hostif_ombx_limit; logic [CfgSramAddrWidth-1:0] ombx_sram_read_ptr; - logic hostif_ombx_object_size_write, hostif_ombx_object_size_read; - logic [CfgOmbxDwCntWidth-1:0] hostif_ombx_object_size_wdata, hostif_ombx_object_size_rdata; + logic hostif_ombx_object_size_write, hostif_ombx_object_size_update; + logic [CfgObjectSizeWidth-1:0] hostif_ombx_object_size_wdata, hostif_ombx_object_size_rdata; mbx_hostif #( - .AlertAsyncOn ( AlertAsyncOn ), - .CfgSramAddrWidth( CfgSramAddrWidth ), - .CfgSramDataWidth( CfgSramDataWidth ) + .AlertAsyncOn ( AlertAsyncOn ), + .CfgSramAddrWidth ( CfgSramAddrWidth ), + .CfgSramDataWidth ( CfgSramDataWidth ), + .CfgObjectSizeWidth( CfgObjectSizeWidth ) ) u_hostif ( .clk_i ( clk_i ), .rst_ni ( rst_ni ), @@ -104,11 +105,11 @@ module mbx .alert_rx_i ( alert_rx_i ), .alert_tx_o ( alert_tx_o ), // Access to the control register - .hostif_control_abort_set_o ( hostif_control_abort_set ), + .hostif_control_abort_clear_o ( hostif_control_abort_clear ), // Access to the status register .hostif_status_busy_clear_o ( hostif_status_busy_clear ), .hostif_status_busy_i ( sysif_status_busy ), - .hostif_status_doe_intr_status_set_o ( hostif_status_doe_intr_status_set ), + .hostif_status_doe_intr_status_set_o ( hostif_status_doe_intr_status_set ), .hostif_status_doe_intr_status_i ( sysif_status_doe_intr_status ), .hostif_status_error_set_o ( hostif_status_error_set ), .hostif_status_error_clear_o ( hostif_status_error_clear ), @@ -125,19 +126,19 @@ module mbx // Read/Write access for the OB DW Count register .hostif_ombx_object_size_write_o ( hostif_ombx_object_size_write ), .hostif_ombx_object_size_o ( hostif_ombx_object_size_wdata ), - .hostif_ombx_object_size_read_i ( hostif_ombx_object_size_read ), + .hostif_ombx_object_size_update_i ( hostif_ombx_object_size_update ), .hostif_ombx_object_size_i ( hostif_ombx_object_size_rdata ), // Alias of the interrupt address and data registers from the SYS interface .sysif_intr_msg_addr_i ( sysif_intr_msg_addr ), .sysif_intr_msg_data_i ( sysif_intr_msg_data ), // Control inputs coming from the system registers interface - .sysif_control_abort_write_i ( sysif_control_abort_write ) + .sysif_control_abort_set_i ( sysif_control_abort_set ) ); ////////////////////////////////////////////////////////////////////////////// // Control and Status signals of the system interface ////////////////////////////////////////////////////////////////////////////// - logic sysif_control_go_set, sysif_control_abort_set; + logic sysif_control_go_set; ////////////////////////////////////////////////////////////////////////////// // Signals for the Inbox @@ -184,15 +185,11 @@ module mbx .sysif_status_busy_valid_i ( imbx_status_busy_valid ), .sysif_status_busy_i ( imbx_status_busy ), .sysif_status_busy_o ( sysif_status_busy ), - - - .sysif_status_doe_intr_status_set_i ( hostif_status_doe_intr_status_set ), + .sysif_status_doe_intr_status_set_i ( hostif_status_doe_intr_status_set ), .sysif_status_doe_intr_status_o ( sysif_status_doe_intr_status ), - .sysif_status_error_set_i ( hostif_status_error_set ), .sysif_status_error_clear_i ( hostif_status_error_clear ), - .sysif_status_error_o ( sysif_status_error ), - + .sysif_status_error_o ( sysif_status_error ), .sysif_status_ready_valid_i ( ombx_status_ready_valid ), .sysif_status_ready_i ( ombx_status_ready ), // Alias of the interrupt address and data registers to the host interface @@ -223,61 +220,61 @@ module mbx .imbx_irq_abort_o ( hostif_event_intr_abort ), .imbx_status_busy_update_o ( imbx_status_busy_valid ), .imbx_status_busy_o ( imbx_status_busy ), - - .hostif_control_abort_set_i ( hostif_control_abort_set ), - .hostif_status_busy_clear_i ( hostif_status_busy_clear ), - .hostif_status_error_set_i ( hostif_status_error_set ), + .hostif_control_abort_clear_i( hostif_control_abort_clear ), + .hostif_status_busy_clear_i ( hostif_status_busy_clear ), + .hostif_status_error_set_i ( hostif_status_error_set ), // SRAM range configuration - .hostif_range_valid_i ( hostif_address_range_valid ), - .hostif_base_i ( hostif_imbx_base ), - .hostif_limit_i ( hostif_imbx_limit ), + .hostif_range_valid_i ( hostif_address_range_valid ), + .hostif_base_i ( hostif_imbx_base ), + .hostif_limit_i ( hostif_imbx_limit ), // Interface to the system port - .sysif_status_busy_i ( sysif_status_busy ), - .sysif_control_go_set_i ( sysif_control_go_set ), - .sysif_control_abort_set_i ( sysif_control_abort_set ), - .sysif_data_write_valid_i ( sysif_write_data_write_valid ), + .sysif_status_busy_i ( sysif_status_busy ), + .sysif_control_go_set_i ( sysif_control_go_set ), + .sysif_control_abort_set_i ( sysif_control_abort_set ), + .sysif_data_write_valid_i ( sysif_write_data_write_valid ), // Host interface to access private SRAM - .hostif_sram_write_req_o ( imbx_sram_write_req ), - .hostif_sram_write_gnt_i ( imbx_sram_write_gnt ), - .hostif_sram_write_ptr_o ( imbx_sram_write_ptr ) + .hostif_sram_write_req_o ( imbx_sram_write_req ), + .hostif_sram_write_gnt_i ( imbx_sram_write_gnt ), + .hostif_sram_write_ptr_o ( imbx_sram_write_ptr ) ); mbx_ombx #( - .CfgSramAddrWidth ( CfgSramAddrWidth ), - .CfgSramDataWidth ( CfgSramDataWidth ), - .CfgOmbxDwCntWidth (CfgOmbxDwCntWidth ) + .CfgSramAddrWidth ( CfgSramAddrWidth ), + .CfgSramDataWidth ( CfgSramDataWidth ), + .CfgObjectSizeWidth ( CfgObjectSizeWidth ) ) u_ombx ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), // Interface to the host port - .ombx_state_error_o ( ombx_state_error ), - .ombx_pending_o ( ombx_pending ), - .ombx_status_ready_update_o ( ombx_status_ready_valid ), - .ombx_status_ready_o ( ombx_status_ready ), + .ombx_state_error_o ( ombx_state_error ), + .ombx_pending_o ( ombx_pending ), + .ombx_status_ready_update_o ( ombx_status_ready_valid ), + .ombx_status_ready_o ( ombx_status_ready ), // SRAM range configuration - .hostif_range_valid_i ( hostif_address_range_valid ), - .hostif_base_i ( hostif_ombx_base ), - .hostif_limit_i ( hostif_ombx_limit ), + .hostif_range_valid_i ( hostif_address_range_valid ), + .hostif_base_i ( hostif_ombx_base ), + .hostif_limit_i ( hostif_ombx_limit ), // Control signals from the host and system interface - .hostif_control_abort_set_i ( hostif_control_abort_set ), - .hostif_status_error_set_i ( hostif_status_error_set ), - .sysif_control_abort_set_i ( sysif_control_abort_set ), - .sysif_read_data_read_valid_i ( sysif_read_data_read_valid ), - .sysif_read_data_write_valid_i ( sysif_read_data_write_valid ), + // Writing a 1 to control.abort register clears the abort condition + .hostif_control_abort_clear_i ( hostif_control_abort_clear ), + .hostif_status_error_set_i ( hostif_status_error_set ), + .sysif_control_abort_set_i ( sysif_control_abort_set ), + .sysif_read_data_read_valid_i ( sysif_read_data_read_valid ), + .sysif_read_data_write_valid_i ( sysif_read_data_write_valid ), // Interface for the object size register - .hostif_ombx_object_size_write_i( hostif_ombx_object_size_write ), - .hostif_ombx_object_size_i ( hostif_ombx_object_size_wdata ), - .hostif_ombx_object_size_read_o ( hostif_ombx_object_size_read ), - .hostif_ombx_object_size_o ( hostif_ombx_object_size_rdata ), + .hostif_ombx_object_size_write_i ( hostif_ombx_object_size_write ), + .hostif_ombx_object_size_i ( hostif_ombx_object_size_wdata ), + .hostif_ombx_object_size_update_o( hostif_ombx_object_size_update ), + .hostif_ombx_object_size_o ( hostif_ombx_object_size_rdata ), // DOE data coming from the SRAM - .ombx_read_data_o ( sysif_read_data ), + .ombx_read_data_o ( sysif_read_data ), // Host interface to access private SRAM - .ombx_sram_read_req_o ( ombx_sram_read_req ), - .ombx_sram_read_gnt_i ( ombx_sram_read_gnt ), - .ombx_sram_read_ptr_o ( ombx_sram_read_ptr ), - .ombx_sram_read_resp_valid_i ( ombx_sram_read_resp_vld ), - .ombx_sram_read_resp_i ( ombx_sram_read_data ) + .ombx_sram_read_req_o ( ombx_sram_read_req ), + .ombx_sram_read_gnt_i ( ombx_sram_read_gnt ), + .ombx_sram_read_ptr_o ( ombx_sram_read_ptr ), + .ombx_sram_read_resp_valid_i ( ombx_sram_read_resp_vld ), + .ombx_sram_read_resp_i ( ombx_sram_read_data ) ); // Host port connection to access the private SRAM. diff --git a/hw/ip/mbx/rtl/mbx_fsm.sv b/hw/ip/mbx/rtl/mbx_fsm.sv index 43bb2c144ad90..0f0c70c3d245e 100644 --- a/hw/ip/mbx/rtl/mbx_fsm.sv +++ b/hw/ip/mbx/rtl/mbx_fsm.sv @@ -23,8 +23,8 @@ module mbx_fsm #( output logic mbx_write_o, output logic mbx_read_o, output logic mbx_sys_abort_o, - output logic mbx_ob_ready_update_o, - output logic mbx_ob_ready_o, + output logic mbx_ready_update_o, + output logic mbx_ready_o, output logic mbx_state_error_o ); typedef enum logic [1:0] { @@ -58,21 +58,22 @@ module mbx_fsm #( assign mbx_read_o = (ctrl_state_q == MbxRead); assign mbx_sys_abort_o = (ctrl_state_q == MbxSysAbortHost); - logic ob_set_ready, ob_clear_ready; + logic ombx_set_ready, ombx_clear_ready; // Outbound mailbox is ready - assign ob_set_ready = CfgOmbx + assign ombx_set_ready = CfgOmbx & mbx_idle - & mbx_range_valid_i & writer_close_mbx_i + & mbx_range_valid_i + & writer_close_mbx_i & ~sysif_control_abort_set_i; // MbxRead is a common state for imbx and ombx // Exit of MbxRead is used to clear imbx.Busy and ombx.Ready - assign ob_clear_ready = CfgOmbx & (hostif_status_error_set_i | - sysif_control_abort_set_i | - mbx_read_o & sys_read_all_i); + assign ombx_clear_ready = CfgOmbx & (hostif_status_error_set_i | + sysif_control_abort_set_i | + mbx_read_o & sys_read_all_i); - assign mbx_ob_ready_update_o = CfgOmbx & (ob_set_ready | ob_clear_ready); // MUTEX(set,clr) - assign mbx_ob_ready_o = ob_set_ready; + assign mbx_ready_update_o = CfgOmbx & (ombx_set_ready | ombx_clear_ready); // MUTEX(set,clr) + assign mbx_ready_o = ombx_set_ready; always_comb begin ctrl_state_d = ctrl_state_q; diff --git a/hw/ip/mbx/rtl/mbx_hostif.sv b/hw/ip/mbx/rtl/mbx_hostif.sv index f5ceb7569157c..872536015b699 100644 --- a/hw/ip/mbx/rtl/mbx_hostif.sv +++ b/hw/ip/mbx/rtl/mbx_hostif.sv @@ -7,26 +7,28 @@ module mbx_hostif #( parameter logic [NumAlerts-1:0] AlertAsyncOn = {NumAlerts{1'b1}}, parameter int unsigned CfgSramAddrWidth = 32, - parameter int unsigned CfgSramDataWidth = 32 + parameter int unsigned CfgSramDataWidth = 32, + parameter int unsigned CfgObjectSizeWidth = 11 ) ( - input logic clk_i, - input logic rst_ni, + input logic clk_i, + input logic rst_ni, // Device port to the host side - input tlul_pkg::tl_h2d_t tl_host_i, - output tlul_pkg::tl_d2h_t tl_host_o, + input tlul_pkg::tl_h2d_t tl_host_i, + output tlul_pkg::tl_d2h_t tl_host_o, // Generated interrupt event - input logic event_intr_ready_i, - input logic event_intr_abort_i, - output logic intr_ready_o, - output logic intr_abort_o, + input logic event_intr_ready_i, + input logic event_intr_abort_i, + output logic intr_ready_o, + output logic intr_abort_o, // External errors - input logic intg_err_i, - input logic sram_err_i, + input logic intg_err_i, + input logic sram_err_i, // Alerts input prim_alert_pkg::alert_rx_t [NumAlerts-1:0] alert_rx_i, output prim_alert_pkg::alert_tx_t [NumAlerts-1:0] alert_tx_o, // Access to the control register - output logic hostif_control_abort_set_o, + // Writing a 1 to control.abort register clears the abort condition + output logic hostif_control_abort_clear_o, // Access to the status register output logic hostif_status_busy_clear_o, output logic hostif_status_doe_intr_status_set_o, @@ -36,24 +38,24 @@ module mbx_hostif input logic hostif_status_doe_intr_status_i, input logic hostif_status_error_i, // Access to the IB/OB RD/WR pointers - input logic [CfgSramAddrWidth-1:0] hostif_imbx_write_ptr_i, - input logic [CfgSramAddrWidth-1:0] hostif_ombx_read_ptr_i, + input logic [CfgSramAddrWidth-1:0] hostif_imbx_write_ptr_i, + input logic [CfgSramAddrWidth-1:0] hostif_ombx_read_ptr_i, // Base/Limit for in/outbound mailbox - output logic hostif_address_range_valid_o, - output logic [CfgSramAddrWidth-1:0] hostif_imbx_base_o, - output logic [CfgSramAddrWidth-1:0] hostif_imbx_limit_o, - output logic [CfgSramAddrWidth-1:0] hostif_ombx_base_o, - output logic [CfgSramAddrWidth-1:0] hostif_ombx_limit_o, + output logic hostif_address_range_valid_o, + output logic [CfgSramAddrWidth-1:0] hostif_imbx_base_o, + output logic [CfgSramAddrWidth-1:0] hostif_imbx_limit_o, + output logic [CfgSramAddrWidth-1:0] hostif_ombx_base_o, + output logic [CfgSramAddrWidth-1:0] hostif_ombx_limit_o, // Read/Write access for the object size register - output logic hostif_ombx_object_size_write_o, - output logic [10:0] hostif_ombx_object_size_o, - input logic hostif_ombx_object_size_read_i, - input logic [10:0] hostif_ombx_object_size_i, + output logic hostif_ombx_object_size_write_o, + output logic [CfgObjectSizeWidth-1:0] hostif_ombx_object_size_o, + input logic hostif_ombx_object_size_update_i, + input logic [CfgObjectSizeWidth-1:0] hostif_ombx_object_size_i, // Alias of the interrupt address and data registers from the SYS interface - input logic [CfgSramAddrWidth-1:0] sysif_intr_msg_addr_i, - input logic [CfgSramDataWidth-1:0] sysif_intr_msg_data_i, + input logic [CfgSramAddrWidth-1:0] sysif_intr_msg_addr_i, + input logic [CfgSramDataWidth-1:0] sysif_intr_msg_data_i, // Control inputs coming from the system registers interface - input logic sysif_control_abort_write_i + input logic sysif_control_abort_set_i ); mbx_reg_pkg::mbx_host_reg2hw_t reg2hw; mbx_reg_pkg::mbx_host_hw2reg_t hw2reg; @@ -134,15 +136,16 @@ module mbx_hostif logic abort_d, abort_q; assign hw2reg.control.abort.d = abort_q; // External write logic - assign hostif_control_abort_set_o = reg2hw.control.abort.qe & reg2hw.control.abort.q; + // Writing a 1 to control.abort means clearing the abort condition + assign hostif_control_abort_clear_o = reg2hw.control.abort.qe & reg2hw.control.abort.q; // Abort computation from system and host interface always_comb begin abort_d = abort_q; - if (sysif_control_abort_write_i) begin + if (sysif_control_abort_set_i) begin abort_d = 1'b1; - end else if (hostif_control_abort_set_o) begin + end else if (hostif_control_abort_clear_o) begin abort_d = 1'b0; end end @@ -189,7 +192,7 @@ module mbx_hostif // Outbound object size Register // External read logic assign hw2reg.outbound_object_size.d = hostif_ombx_object_size_i; - assign hw2reg.outbound_object_size.de = hostif_ombx_object_size_read_i; + assign hw2reg.outbound_object_size.de = hostif_ombx_object_size_update_i; // External write logic assign hostif_ombx_object_size_write_o = reg2hw.outbound_object_size.qe; assign hostif_ombx_object_size_o = reg2hw.outbound_object_size.q; diff --git a/hw/ip/mbx/rtl/mbx_imbx.sv b/hw/ip/mbx/rtl/mbx_imbx.sv index 0f41621412eca..dca8786ba63c0 100644 --- a/hw/ip/mbx/rtl/mbx_imbx.sv +++ b/hw/ip/mbx/rtl/mbx_imbx.sv @@ -17,7 +17,8 @@ module mbx_imbx #( output logic imbx_status_busy_update_o, output logic imbx_status_busy_o, // Access to the control and status registers of host interface - input logic hostif_control_abort_set_i, + // Writing a 1 to control.abort register clears the abort condition + input logic hostif_control_abort_clear_i, input logic hostif_status_busy_clear_i, input logic hostif_status_error_set_i, // Range configuration for the private SRAM @@ -64,7 +65,7 @@ module mbx_imbx #( logic sys_clear_abort; logic load_write_ptr, advance_write_ptr; - assign sys_clear_abort = hostif_control_abort_set_i & mbx_sys_abort; + assign sys_clear_abort = hostif_control_abort_clear_i & mbx_sys_abort; // Rewind the write pointer to the base assign load_write_ptr = mbx_empty | sys_clear_abort | @@ -137,24 +138,24 @@ module mbx_imbx #( mbx_fsm #( .CfgOmbx ( 0 ) ) u_mbxfsm( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .mbx_range_valid_i ( hostif_range_valid_i ), - .hostif_abort_ack_i ( hostif_control_abort_set_i ), - .hostif_status_error_set_i ( hostif_status_error_set_i ), - .hostif_status_busy_clear_i( hostif_status_busy_clear_i ), - .sysif_control_abort_set_i ( sysif_control_abort_set_i ), - .sys_read_all_i ( 1'b0 ), - .writer_close_mbx_i ( sysif_control_go_set_i ), - .writer_write_valid_i ( sysif_data_write_valid_i ), + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .mbx_range_valid_i ( hostif_range_valid_i ), + .hostif_abort_ack_i ( hostif_control_abort_clear_i ), + .hostif_status_error_set_i ( hostif_status_error_set_i ), + .hostif_status_busy_clear_i( hostif_status_busy_clear_i ), + .sysif_control_abort_set_i ( sysif_control_abort_set_i ), + .sys_read_all_i ( 1'b0 ), + .writer_close_mbx_i ( sysif_control_go_set_i ), + .writer_write_valid_i ( sysif_data_write_valid_i ), // Status signals - .mbx_empty_o ( mbx_empty ), - .mbx_write_o ( mbx_write ), - .mbx_read_o ( mbx_read ), - .mbx_sys_abort_o ( mbx_sys_abort ), - .mbx_ob_ready_update_o ( ), - .mbx_ob_ready_o ( ), - .mbx_state_error_o ( imbx_state_error_o ) + .mbx_empty_o ( mbx_empty ), + .mbx_write_o ( mbx_write ), + .mbx_read_o ( mbx_read ), + .mbx_sys_abort_o ( mbx_sys_abort ), + .mbx_ready_update_o ( ), + .mbx_ready_o ( ), + .mbx_state_error_o ( imbx_state_error_o ) ); ////////////////////////////////////////////////////////////////////////////// diff --git a/hw/ip/mbx/rtl/mbx_ombx.sv b/hw/ip/mbx/rtl/mbx_ombx.sv index ced32adedfbc2..fbd3ca12e13a7 100644 --- a/hw/ip/mbx/rtl/mbx_ombx.sv +++ b/hw/ip/mbx/rtl/mbx_ombx.sv @@ -7,7 +7,7 @@ module mbx_ombx #( parameter int unsigned CfgSramAddrWidth = 32, parameter int unsigned CfgSramDataWidth = 32, - parameter int unsigned CfgOmbxDwCntWidth = 11 + parameter int unsigned CfgObjectSizeWidth = 11 ) ( input logic clk_i, input logic rst_ni, @@ -15,11 +15,12 @@ module mbx_ombx #( output logic ombx_pending_o, output logic ombx_status_ready_update_o, output logic ombx_status_ready_o, - input logic hostif_range_valid_i, + input logic hostif_range_valid_i, input logic [CfgSramAddrWidth-1:0] hostif_base_i, input logic [CfgSramAddrWidth-1:0] hostif_limit_i, // Control signals from the host and system interface - input logic hostif_control_abort_set_i, + // Writing a 1 to control.abort register clears the abort condition + input logic hostif_control_abort_clear_i, input logic hostif_status_error_set_i, input logic sysif_status_ready_i, input logic sysif_control_abort_set_i, @@ -27,9 +28,9 @@ module mbx_ombx #( input logic sysif_read_data_write_valid_i, // Interface for the object size register input logic hostif_ombx_object_size_write_i, - input logic [CfgOmbxDwCntWidth-1:0] hostif_ombx_object_size_i, - output logic hostif_ombx_object_size_read_o, - output logic [CfgOmbxDwCntWidth-1:0] hostif_ombx_object_size_o, + input logic [CfgObjectSizeWidth-1:0] hostif_ombx_object_size_i, + output logic hostif_ombx_object_size_update_o, + output logic [CfgObjectSizeWidth-1:0] hostif_ombx_object_size_o, // DOE data coming from the SRAM output logic [CfgSramDataWidth-1:0] ombx_read_data_o, // Host interface to the private SRAM @@ -46,23 +47,42 @@ module mbx_ombx #( // Status signals from the FSM logic mbx_empty, mbx_read, mbx_sys_abort; - logic set_pop_entry, clear_pop_entry; + logic set_first_req, clear_first_req; // Generate the read request - // - mbx reader ACK the current RdData and pop another DW from outbound mailbox - // 1st pop is initiated by mbx owner writes ObDwCnt - logic read_req, pop_entry_q; - assign read_req = pop_entry_q | - (mbx_read & sysif_read_data_write_valid_i & - (sram_read_ptr_q <= sram_read_ptr_limit_q)); + // - Mbx reader ACK the current read data and initate the first request + // First is initiated by mbx owner writes object size register + // Note that pointer comparison with hostif_limit_i is inclusive, while comparison with internal + // limit of the object size is exclusive + logic read_req, first_req_q; + assign read_req = first_req_q | + (mbx_read & sysif_read_data_write_valid_i & + (sram_read_ptr_q <= hostif_limit_i) & + (sram_read_ptr_q < sram_read_ptr_limit_q)); + + // Create a sticky TLUL read request until its granted + logic req_q; + assign ombx_sram_read_req_o = read_req | req_q; + + prim_flop #( + .Width(1) + ) u_req_state ( + .clk_i ( clk_i ), + .rst_ni( rst_ni ), + .d_i ( ombx_sram_read_req_o & ~ombx_sram_read_gnt_i ), + .q_o ( req_q ) + ); // Backpressure the next read data until the current write data brings back the data from SRAM // Exclude last ack logic set_pending, clear_pending; // Block the request from TLUL until the SRAM read is complete + // Note that pointer comparison with hostif_limit_i is inclusive, while comparison with internal + // limit of the object size is exclusive assign set_pending = mbx_read & sysif_read_data_write_valid_i & - (sram_read_ptr_q <= sram_read_ptr_limit_q); + (sram_read_ptr_q <= hostif_limit_i) & + (sram_read_ptr_q < sram_read_ptr_limit_q); assign clear_pending = ombx_sram_read_resp_valid_i; prim_flop #( @@ -74,40 +94,27 @@ module mbx_ombx #( .q_o ( ombx_pending_o ) ); - // Create a sticky TLUL read request until its granted - logic req_q; - assign ombx_sram_read_req_o = read_req | req_q; - - prim_flop #( - .Width(1) - ) u_req_state ( - .clk_i ( clk_i ), - .rst_ni( rst_ni ), - .d_i ( ombx_sram_read_req_o & ~ombx_sram_read_gnt_i ), - .q_o ( req_q ) - ); - logic writer_close_mbx; - // move FSM to MBRead (Ready) after the 1st read comes back + // move FSM to MbxRead (Ready) after the 1st read comes back assign writer_close_mbx = mbx_empty & ombx_sram_read_resp_valid_i; // Terminate mbx_read state (Ready = 1 -> 0) if ombx is already drained (sram_read is not issued) logic sys_read_all; - assign sys_read_all = mbx_read & - sysif_read_data_write_valid_i & - (sram_read_ptr_q == sram_read_ptr_limit_q); + assign sys_read_all = mbx_read & + sysif_read_data_write_valid_i & + (sram_read_ptr_q == sram_read_ptr_limit_q); logic host_clear_abort; - assign host_clear_abort = hostif_control_abort_set_i & mbx_sys_abort; + assign host_clear_abort = hostif_control_abort_clear_i & mbx_sys_abort; // SRAM read pointer management logic load_read_ptr, advance_read_ptr; // Rewind the read pointer to the base - assign load_read_ptr = set_pop_entry | sys_read_all | host_clear_abort; + assign load_read_ptr = set_first_req | sys_read_all | host_clear_abort; // Advance the read pointer when one request went through - assign advance_read_ptr = ombx_sram_read_req_o; + assign advance_read_ptr = ombx_sram_read_req_o & ombx_sram_read_gnt_i; always_comb begin sram_read_ptr_d = sram_read_ptr_q; @@ -130,107 +137,122 @@ module mbx_ombx #( ); assign ombx_sram_read_ptr_o = sram_read_ptr_q; + // Clear ombx read data register in case of all data is read, an error happens, + // or the requester aborts the transaction + logic clear_read_data; + assign clear_read_data = sys_read_all | + hostif_status_error_set_i | + sysif_control_abort_set_i; // Advance the SRAM read response to read data prim_generic_flop_en #( .Width(CfgSramDataWidth) ) u_sram_read_data ( - .clk_i ( clk_i ), - .rst_ni( rst_ni ), - .en_i ( ombx_sram_read_resp_valid_i | sys_read_all ), - .d_i ( {CfgSramDataWidth{~sys_read_all}} & ombx_sram_read_resp_i ), - .q_o ( ombx_read_data_o ) + .clk_i ( clk_i ), + .rst_ni( rst_ni ), + .en_i ( ombx_sram_read_resp_valid_i | clear_read_data ), + .d_i ( {CfgSramDataWidth{~clear_read_data}} & ombx_sram_read_resp_i ), + .q_o ( ombx_read_data_o ) ); - logic host_write_ob_dw_count_q; - logic ombx_dw_count_update_valid_q; + // The following logic creates the status signals to update the hostif.object_size register, + // which is part of the host interface. + + logic host_write_object_size_q; + logic ombx_object_size_update_valid_q; + + // The following flop creates an indicator that hostif.object_size has been written such that + // in the next cycle, the read pointer limit can be updated and the first transfer from the + // SRAM to the internal data flop can be initiated. Only update the object size when not a + // transfer was successful. prim_flop #( .Width(1) - ) u_host_write_ob_dw_count ( - .clk_i ( clk_i ), - .rst_ni( rst_ni ), - .d_i ( hostif_ombx_object_size_write_i & ~ombx_dw_count_update_valid_q ), - .q_o ( host_write_ob_dw_count_q ) + ) u_host_write_object_size ( + .clk_i ( clk_i ), + .rst_ni( rst_ni ), + .d_i ( hostif_ombx_object_size_write_i & ~ombx_object_size_update_valid_q ), + .q_o ( host_write_object_size_q ) ); - - logic [CfgOmbxDwCntWidth-1:0] hostif_ob_object_size_minus_one; + logic [CfgObjectSizeWidth-1:0] hostif_ob_object_size_minus_one; + // Update the hostif.object_size register on every transaction or when aborting the transaction + assign hostif_ombx_object_size_update_o = (read_req & ombx_sram_read_gnt_i) | + sysif_control_abort_set_i; + // The updated value is the decremented by 1 size or zero-ed out if the transaction is aborted assign hostif_ob_object_size_minus_one = hostif_ombx_object_size_i - 1; - // Zero out OMBX DW Count on the abort - assign hostif_ombx_object_size_o = {CfgOmbxDwCntWidth{~sysif_control_abort_set_i}} & - hostif_ob_object_size_minus_one; + assign hostif_ombx_object_size_o = {CfgObjectSizeWidth{~sysif_control_abort_set_i}} & + hostif_ob_object_size_minus_one; - assign hostif_ombx_object_size_read_o = (read_req & ombx_sram_read_gnt_i) | - sysif_control_abort_set_i; prim_flop #( .Width(1) - ) u_host_ombx_dw_count_update_valid ( + ) u_host_object_size_update_valid ( .clk_i ( clk_i ), .rst_ni( rst_ni ), - .d_i ( hostif_ombx_object_size_read_o ), - .q_o ( ombx_dw_count_update_valid_q ) + .d_i ( hostif_ombx_object_size_update_o ), + .q_o ( ombx_object_size_update_valid_q ) ); - // Compute the read pointer limit after DW count is written - assign sram_read_ptr_limit_d = hostif_base_i + {hostif_ombx_object_size_i, 2'b0}; + // Compute the read pointer limit after object size is written + assign sram_read_ptr_limit_d = hostif_base_i + + CfgSramAddrWidth'({hostif_ombx_object_size_i, 2'b0}); prim_generic_flop_en #( .Width(CfgSramAddrWidth) ) u_sram_read_ptr_limit ( .clk_i ( clk_i ), .rst_ni( rst_ni ), - // Factor in ~mbx_read because HW update can trigger host_write_ob_dw_count_q - .en_i ( host_write_ob_dw_count_q & ~mbx_read ), + // Factor in ~mbx_read because HW update can trigger host_write_object_size_q + .en_i ( host_write_object_size_q & ~mbx_read ), .d_i ( sram_read_ptr_limit_d ), .q_o ( sram_read_ptr_limit_q ) ); - // mbx_empty means the ombx has not been read yet (not really empty) - // Add (|hostif_ombx_object_size_i) to exclude the write-0-DwCnt initialization - assign set_pop_entry = mbx_empty & host_write_ob_dw_count_q & (|hostif_ombx_object_size_i); - assign clear_pop_entry = ombx_sram_read_gnt_i; + // Logic to initiate the first read (mbx_empty) from the SRAM to the requester + // Only starts the transmitting if the mailbox is configured properly + // (SRAM range is valid and the object size has been written to a non-zero) + // value. mbx_empty means there hasn't been read anything but range is valid. + assign set_first_req = mbx_empty & host_write_object_size_q & (|hostif_ombx_object_size_i); + assign clear_first_req = ombx_sram_read_gnt_i; prim_flop #( .Width(1) ) u_pop_entry ( .clk_i ( clk_i ), .rst_ni( rst_ni ), - .d_i ( set_pop_entry | (pop_entry_q & ~clear_pop_entry) ), - .q_o ( pop_entry_q ) + .d_i ( set_first_req | (first_req_q & ~clear_first_req) ), + .q_o ( first_req_q ) ); mbx_fsm #( .CfgOmbx ( 1 ) ) u_mbxfsm( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .mbx_range_valid_i ( hostif_range_valid_i ), - .hostif_abort_ack_i ( hostif_control_abort_set_i ), - .hostif_status_error_set_i ( hostif_status_error_set_i ), - .hostif_status_busy_clear_i( 1'b0 ), - .sysif_control_abort_set_i ( sysif_control_abort_set_i ), - .sys_read_all_i ( sys_read_all ), - .writer_close_mbx_i ( writer_close_mbx ), - .writer_write_valid_i ( 1'b0 ), + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .mbx_range_valid_i ( hostif_range_valid_i ), + .hostif_abort_ack_i ( hostif_control_abort_clear_i ), + .hostif_status_error_set_i ( hostif_status_error_set_i ), + .hostif_status_busy_clear_i( 1'b0 ), + .sysif_control_abort_set_i ( sysif_control_abort_set_i ), + .sys_read_all_i ( sys_read_all ), + .writer_close_mbx_i ( writer_close_mbx ), + .writer_write_valid_i ( 1'b0 ), // Status signals - .mbx_empty_o ( mbx_empty ), - .mbx_write_o ( ), - .mbx_read_o ( mbx_read ), - .mbx_sys_abort_o ( mbx_sys_abort ), - .mbx_ob_ready_update_o ( ombx_status_ready_update_o ), - .mbx_ob_ready_o ( ombx_status_ready_o ), - .mbx_state_error_o ( ombx_state_error_o ) + .mbx_empty_o ( mbx_empty ), + .mbx_write_o ( ), + .mbx_read_o ( mbx_read ), + .mbx_sys_abort_o ( mbx_sys_abort ), + .mbx_ready_update_o ( ombx_status_ready_update_o ), + .mbx_ready_o ( ombx_status_ready_o ), + .mbx_state_error_o ( ombx_state_error_o ) ); ////////////////////////////////////////////////////////////////////////////// // Assertions ////////////////////////////////////////////////////////////////////////////// - // Read req should e de-asserted after the read is ACKed by the TLUL adapter - `ASSERT_NEVER(DeassertReqAfterAck_A, ombx_sram_read_req_o & ombx_sram_read_resp_valid_i) // When reading from the ombx doe_status.ready must have been asserted `ASSERT_NEVER(ReadyAssertedWhenRead_A, ombx_sram_read_req_o & - ~(pop_entry_q | sysif_status_ready_i)) + ~(first_req_q | sysif_status_ready_i)) // System write-to-read data is non-posted. No subsequential read or write comes before the // write is ACKed `ASSERT_NEVER(NoReadBeforeWriteAcked_A, ombx_pending_o & diff --git a/hw/ip/mbx/rtl/mbx_sysif.sv b/hw/ip/mbx/rtl/mbx_sysif.sv index 4188ec8e745d3..d77cfcac95db4 100644 --- a/hw/ip/mbx/rtl/mbx_sysif.sv +++ b/hw/ip/mbx/rtl/mbx_sysif.sv @@ -127,7 +127,7 @@ module mbx_sysif // We use the register window to access the internal bus signals, allowing the mailbox to halt // the bus if there are too many outstanding requests. logic reg_wdata_we; - logic [top_pkg::TL_DW-1:0] reg_wdata_wdata, reg_wdata_rdata; + logic [top_pkg::TL_DW-1:0] reg_wdata_wdata; tlul_adapter_reg #( .RegAw ( SysAw ), .RegDw ( top_pkg::TL_DW ), @@ -169,7 +169,7 @@ module mbx_sysif .we_o ( read_data_write_valid_o ), .re_o ( read_data_read_valid_o ), .addr_o ( ), - // Write values are ignored. A Write simply means the read has occured. + // Write values are ignored. A Write simply means the read has occurred. .wdata_o ( ), .be_o ( ), .busy_i ( ombx_pending_i ), From ae10c2207f9ed2b32a06752061a5b335b7eb99d3 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Wed, 13 Sep 2023 07:07:29 -0700 Subject: [PATCH 24/88] [hw,mbx,rtl] Let the ombx create the DOE interrupt Signed-off-by: Robert Schilling --- hw/ip/mbx/data/mbx.hjson | 4 ++-- hw/ip/mbx/rtl/mbx.sv | 7 ++++--- hw/ip/mbx/rtl/mbx_hostif.sv | 15 ++++++--------- hw/ip/mbx/rtl/mbx_ombx.sv | 4 ++++ hw/ip/mbx/rtl/mbx_sysif.sv | 5 +++-- 5 files changed, 19 insertions(+), 16 deletions(-) diff --git a/hw/ip/mbx/data/mbx.hjson b/hw/ip/mbx/data/mbx.hjson index cf3d97b85821b..7784e32827026 100644 --- a/hw/ip/mbx/data/mbx.hjson +++ b/hw/ip/mbx/data/mbx.hjson @@ -108,7 +108,7 @@ hwqe: "true" } { name: "doe_intr_status" - desc: "Alias of the DoE mailbox interrupt status bit" + desc: "Alias of the DoE mailbox interrupt status bit" bits: "1" resval: "0x0" swaccess: "rw" @@ -116,7 +116,7 @@ hwqe: "true" } { name: "error" - desc: "Alias of the DoE mailbox error bit" + desc: "Alias of the DoE mailbox error bit" bits: "2" resval: "0x0" swaccess: "rw" diff --git a/hw/ip/mbx/rtl/mbx.sv b/hw/ip/mbx/rtl/mbx.sv index 069dfa6e79773..b965b77c54db7 100644 --- a/hw/ip/mbx/rtl/mbx.sv +++ b/hw/ip/mbx/rtl/mbx.sv @@ -61,7 +61,7 @@ module mbx logic sysif_status_busy, sysif_status_doe_intr_status, sysif_status_error; // Setter signals from the hostif to the sysif - logic hostif_status_doe_intr_status_set, hostif_control_abort_clear, hostif_status_busy_clear, + logic hostif_control_abort_clear, hostif_status_busy_clear, hostif_status_error_set, hostif_status_error_clear; // Alias signals from the sys interface @@ -109,7 +109,6 @@ module mbx // Access to the status register .hostif_status_busy_clear_o ( hostif_status_busy_clear ), .hostif_status_busy_i ( sysif_status_busy ), - .hostif_status_doe_intr_status_set_o ( hostif_status_doe_intr_status_set ), .hostif_status_doe_intr_status_i ( sysif_status_doe_intr_status ), .hostif_status_error_set_o ( hostif_status_error_set ), .hostif_status_error_clear_o ( hostif_status_error_clear ), @@ -157,6 +156,7 @@ module mbx ////////////////////////////////////////////////////////////////////////////// logic ombx_pending; logic ombx_status_ready_valid, ombx_status_ready; + logic ombx_doe_intr_status_set; // Interface signals for SRAM host access to read the memory and serve it to the outbox logic ombx_sram_read_req, ombx_sram_read_gnt; @@ -185,7 +185,7 @@ module mbx .sysif_status_busy_valid_i ( imbx_status_busy_valid ), .sysif_status_busy_i ( imbx_status_busy ), .sysif_status_busy_o ( sysif_status_busy ), - .sysif_status_doe_intr_status_set_i ( hostif_status_doe_intr_status_set ), + .sysif_status_doe_intr_status_set_i ( ombx_doe_intr_status_set ), .sysif_status_doe_intr_status_o ( sysif_status_doe_intr_status ), .sysif_status_error_set_i ( hostif_status_error_set ), .sysif_status_error_clear_i ( hostif_status_error_clear ), @@ -246,6 +246,7 @@ module mbx ) u_ombx ( .clk_i ( clk_i ), .rst_ni ( rst_ni ), + .ombx_doe_intr_status_set_o ( ombx_doe_intr_status_set ), // Interface to the host port .ombx_state_error_o ( ombx_state_error ), .ombx_pending_o ( ombx_pending ), diff --git a/hw/ip/mbx/rtl/mbx_hostif.sv b/hw/ip/mbx/rtl/mbx_hostif.sv index 872536015b699..e3fd9840d7260 100644 --- a/hw/ip/mbx/rtl/mbx_hostif.sv +++ b/hw/ip/mbx/rtl/mbx_hostif.sv @@ -30,13 +30,12 @@ module mbx_hostif // Writing a 1 to control.abort register clears the abort condition output logic hostif_control_abort_clear_o, // Access to the status register - output logic hostif_status_busy_clear_o, - output logic hostif_status_doe_intr_status_set_o, - output logic hostif_status_error_set_o, - output logic hostif_status_error_clear_o, - input logic hostif_status_busy_i, - input logic hostif_status_doe_intr_status_i, - input logic hostif_status_error_i, + output logic hostif_status_busy_clear_o, + output logic hostif_status_error_set_o, + output logic hostif_status_error_clear_o, + input logic hostif_status_busy_i, + input logic hostif_status_doe_intr_status_i, + input logic hostif_status_error_i, // Access to the IB/OB RD/WR pointers input logic [CfgSramAddrWidth-1:0] hostif_imbx_write_ptr_i, input logic [CfgSramAddrWidth-1:0] hostif_ombx_read_ptr_i, @@ -169,8 +168,6 @@ module mbx_hostif assign hw2reg.status.error.d = hostif_status_error_i; // External write logic assign hostif_status_busy_clear_o = reg2hw.status.busy.qe & ~reg2hw.status.busy.q; - assign hostif_status_doe_intr_status_set_o = reg2hw.status.doe_intr_status.qe & - reg2hw.status.doe_intr_status.q; assign hostif_status_error_set_o = reg2hw.status.error.qe & reg2hw.status.error.q; assign hostif_status_error_clear_o = reg2hw.status.error.qe & ~reg2hw.status.error.q; diff --git a/hw/ip/mbx/rtl/mbx_ombx.sv b/hw/ip/mbx/rtl/mbx_ombx.sv index fbd3ca12e13a7..8084c25cab32b 100644 --- a/hw/ip/mbx/rtl/mbx_ombx.sv +++ b/hw/ip/mbx/rtl/mbx_ombx.sv @@ -12,6 +12,7 @@ module mbx_ombx #( input logic clk_i, input logic rst_ni, output logic ombx_state_error_o, + output logic ombx_doe_intr_status_set_o, output logic ombx_pending_o, output logic ombx_status_ready_update_o, output logic ombx_status_ready_o, @@ -223,6 +224,9 @@ module mbx_ombx #( .q_o ( first_req_q ) ); + // Create an DOE interrupt request when the obmx FSM turns into the ready state + assign ombx_doe_intr_status_set_o = ombx_status_ready_o & ombx_status_ready_update_o; + mbx_fsm #( .CfgOmbx ( 1 ) ) u_mbxfsm( diff --git a/hw/ip/mbx/rtl/mbx_sysif.sv b/hw/ip/mbx/rtl/mbx_sysif.sv index d77cfcac95db4..68803d24a953d 100644 --- a/hw/ip/mbx/rtl/mbx_sysif.sv +++ b/hw/ip/mbx/rtl/mbx_sysif.sv @@ -110,9 +110,10 @@ module mbx_sysif assign hw2reg.sys_status.busy.de = sysif_status_busy_valid_i; assign hw2reg.sys_status.busy.d = sysif_status_busy_i; - // Set by the Host firmware (w1s) + // Set by the outbound handler if the DOE interrupt is enabled. Setting this bit creates a DOE + // interrupt to the system side. // Cleared by the Sys firmware (w1c) - assign hw2reg.sys_status.doe_intr_status.de = sysif_status_doe_intr_status_set_i; + assign hw2reg.sys_status.doe_intr_status.de = sysif_status_doe_intr_status_set_i & doe_intr_en_o; assign hw2reg.sys_status.doe_intr_status.d = sysif_status_doe_intr_status_set_i; assign hw2reg.sys_status.error.de = sysif_status_error_set_i | sysif_status_error_clear_i; From 127808085b714a2903734548f8983bf6c3e71cbd Mon Sep 17 00:00:00 2001 From: Andreas Kurth Date: Tue, 19 Sep 2023 10:29:50 +0000 Subject: [PATCH 25/88] [mbx] Rename OT-facing port to `core` This is in-line with our conventions. Signed-off-by: Andreas Kurth --- hw/ip/mbx/data/mbx.hjson | 8 +-- hw/ip/mbx/mbx.core | 2 +- hw/ip/mbx/rtl/mbx.sv | 10 +-- ...bx_host_reg_top.sv => mbx_core_reg_top.sv} | 40 ++++++------ hw/ip/mbx/rtl/mbx_hostif.sv | 6 +- hw/ip/mbx/rtl/mbx_reg_pkg.sv | 62 +++++++++---------- hw/ip/mbx/rtl/mbx_sysif.sv | 2 +- 7 files changed, 65 insertions(+), 65 deletions(-) rename hw/ip/mbx/rtl/{mbx_host_reg_top.sv => mbx_core_reg_top.sv} (95%) diff --git a/hw/ip/mbx/data/mbx.hjson b/hw/ip/mbx/data/mbx.hjson index 7784e32827026..5d673d71252e4 100644 --- a/hw/ip/mbx/data/mbx.hjson +++ b/hw/ip/mbx/data/mbx.hjson @@ -19,7 +19,7 @@ clocking: [{clock: "clk_i", reset: "rst_ni", primary: true}] bus_interfaces: [ - { protocol: "tlul", direction: "device", name: "host" } + { protocol: "tlul", direction: "device", name: "core" } { protocol: "tlul", direction: "host", name: "sram" } { protocol: "tlul", direction: "device", name: "sys" } ] @@ -72,9 +72,9 @@ ] regwidth: "32" registers: { - host: [ + core: [ { name: "CONTROL" - desc: "DOE mailbox control register visible to the mailbox host" + desc: "DOE mailbox control register visible to OpenTitan" hwext: "true" fields: [ { name: "abort" @@ -96,7 +96,7 @@ ] } { name: "STATUS" - desc: "DOE mailbox status register visible to the mailbox host" + desc: "DOE mailbox status register visible to OpenTitan" hwext: "true" fields: [ { name: "busy" diff --git a/hw/ip/mbx/mbx.core b/hw/ip/mbx/mbx.core index d0351c15d18bb..4f966427c2512 100644 --- a/hw/ip/mbx/mbx.core +++ b/hw/ip/mbx/mbx.core @@ -13,7 +13,7 @@ filesets: files: - rtl/mbx_reg_pkg.sv - rtl/mbx.sv - - rtl/mbx_host_reg_top.sv + - rtl/mbx_core_reg_top.sv - rtl/mbx_sys_reg_top.sv - rtl/mbx_hostif.sv - rtl/mbx_sysif.sv diff --git a/hw/ip/mbx/rtl/mbx.sv b/hw/ip/mbx/rtl/mbx.sv index b965b77c54db7..4b02e6744a823 100644 --- a/hw/ip/mbx/rtl/mbx.sv +++ b/hw/ip/mbx/rtl/mbx.sv @@ -26,9 +26,9 @@ module mbx // Alerts input prim_alert_pkg::alert_rx_t [NumAlerts-1:0] alert_rx_i, output prim_alert_pkg::alert_tx_t [NumAlerts-1:0] alert_tx_o, - // Device port facing OT-host - input tlul_pkg::tl_h2d_t tl_host_i, - output tlul_pkg::tl_d2h_t tl_host_o, + // Device port facing OpenTitan + input tlul_pkg::tl_h2d_t core_tl_d_i, + output tlul_pkg::tl_d2h_t core_tl_d_o, // Device port facing CTN Xbar input tlul_pkg::tl_h2d_t tl_sys_i, output tlul_pkg::tl_d2h_t tl_sys_o, @@ -94,8 +94,8 @@ module mbx .clk_i ( clk_i ), .rst_ni ( rst_ni ), // Device port to the host side - .tl_host_i ( tl_host_i ), - .tl_host_o ( tl_host_o ), + .tl_host_i ( core_tl_d_i ), + .tl_host_o ( core_tl_d_o ), .event_intr_ready_i ( hostif_event_intr_ready ), .event_intr_abort_i ( hostif_event_intr_abort ), .intr_ready_o ( intr_mbx_ready_o ), diff --git a/hw/ip/mbx/rtl/mbx_host_reg_top.sv b/hw/ip/mbx/rtl/mbx_core_reg_top.sv similarity index 95% rename from hw/ip/mbx/rtl/mbx_host_reg_top.sv rename to hw/ip/mbx/rtl/mbx_core_reg_top.sv index e94f32ad9a98c..9287f2a60891c 100644 --- a/hw/ip/mbx/rtl/mbx_host_reg_top.sv +++ b/hw/ip/mbx/rtl/mbx_core_reg_top.sv @@ -6,14 +6,14 @@ `include "prim_assert.sv" -module mbx_host_reg_top ( +module mbx_core_reg_top ( input clk_i, input rst_ni, input tlul_pkg::tl_h2d_t tl_i, output tlul_pkg::tl_d2h_t tl_o, // To HW - output mbx_reg_pkg::mbx_host_reg2hw_t reg2hw, // Write - input mbx_reg_pkg::mbx_host_hw2reg_t hw2reg, // Read + output mbx_reg_pkg::mbx_core_reg2hw_t reg2hw, // Write + input mbx_reg_pkg::mbx_core_hw2reg_t hw2reg, // Read // Integrity check errors output logic intg_err_o @@ -836,23 +836,23 @@ module mbx_host_reg_top ( // Check sub-word write is permitted always_comb begin wr_err = (reg_we & - ((addr_hit[ 0] & (|(MBX_HOST_PERMIT[ 0] & ~reg_be))) | - (addr_hit[ 1] & (|(MBX_HOST_PERMIT[ 1] & ~reg_be))) | - (addr_hit[ 2] & (|(MBX_HOST_PERMIT[ 2] & ~reg_be))) | - (addr_hit[ 3] & (|(MBX_HOST_PERMIT[ 3] & ~reg_be))) | - (addr_hit[ 4] & (|(MBX_HOST_PERMIT[ 4] & ~reg_be))) | - (addr_hit[ 5] & (|(MBX_HOST_PERMIT[ 5] & ~reg_be))) | - (addr_hit[ 6] & (|(MBX_HOST_PERMIT[ 6] & ~reg_be))) | - (addr_hit[ 7] & (|(MBX_HOST_PERMIT[ 7] & ~reg_be))) | - (addr_hit[ 8] & (|(MBX_HOST_PERMIT[ 8] & ~reg_be))) | - (addr_hit[ 9] & (|(MBX_HOST_PERMIT[ 9] & ~reg_be))) | - (addr_hit[10] & (|(MBX_HOST_PERMIT[10] & ~reg_be))) | - (addr_hit[11] & (|(MBX_HOST_PERMIT[11] & ~reg_be))) | - (addr_hit[12] & (|(MBX_HOST_PERMIT[12] & ~reg_be))) | - (addr_hit[13] & (|(MBX_HOST_PERMIT[13] & ~reg_be))) | - (addr_hit[14] & (|(MBX_HOST_PERMIT[14] & ~reg_be))) | - (addr_hit[15] & (|(MBX_HOST_PERMIT[15] & ~reg_be))) | - (addr_hit[16] & (|(MBX_HOST_PERMIT[16] & ~reg_be))))); + ((addr_hit[ 0] & (|(MBX_CORE_PERMIT[ 0] & ~reg_be))) | + (addr_hit[ 1] & (|(MBX_CORE_PERMIT[ 1] & ~reg_be))) | + (addr_hit[ 2] & (|(MBX_CORE_PERMIT[ 2] & ~reg_be))) | + (addr_hit[ 3] & (|(MBX_CORE_PERMIT[ 3] & ~reg_be))) | + (addr_hit[ 4] & (|(MBX_CORE_PERMIT[ 4] & ~reg_be))) | + (addr_hit[ 5] & (|(MBX_CORE_PERMIT[ 5] & ~reg_be))) | + (addr_hit[ 6] & (|(MBX_CORE_PERMIT[ 6] & ~reg_be))) | + (addr_hit[ 7] & (|(MBX_CORE_PERMIT[ 7] & ~reg_be))) | + (addr_hit[ 8] & (|(MBX_CORE_PERMIT[ 8] & ~reg_be))) | + (addr_hit[ 9] & (|(MBX_CORE_PERMIT[ 9] & ~reg_be))) | + (addr_hit[10] & (|(MBX_CORE_PERMIT[10] & ~reg_be))) | + (addr_hit[11] & (|(MBX_CORE_PERMIT[11] & ~reg_be))) | + (addr_hit[12] & (|(MBX_CORE_PERMIT[12] & ~reg_be))) | + (addr_hit[13] & (|(MBX_CORE_PERMIT[13] & ~reg_be))) | + (addr_hit[14] & (|(MBX_CORE_PERMIT[14] & ~reg_be))) | + (addr_hit[15] & (|(MBX_CORE_PERMIT[15] & ~reg_be))) | + (addr_hit[16] & (|(MBX_CORE_PERMIT[16] & ~reg_be))))); end // Generate write-enables diff --git a/hw/ip/mbx/rtl/mbx_hostif.sv b/hw/ip/mbx/rtl/mbx_hostif.sv index e3fd9840d7260..af4d29b645194 100644 --- a/hw/ip/mbx/rtl/mbx_hostif.sv +++ b/hw/ip/mbx/rtl/mbx_hostif.sv @@ -56,8 +56,8 @@ module mbx_hostif // Control inputs coming from the system registers interface input logic sysif_control_abort_set_i ); - mbx_reg_pkg::mbx_host_reg2hw_t reg2hw; - mbx_reg_pkg::mbx_host_hw2reg_t hw2reg; + mbx_reg_pkg::mbx_core_reg2hw_t reg2hw; + mbx_reg_pkg::mbx_core_hw2reg_t hw2reg; ////////////////////////////////////////////////////////////////////////////// // Assertions @@ -92,7 +92,7 @@ module mbx_hostif // SEC_CM: BUS.INTEGRITY // SEC_CM: ADDRESS_RANGE.CONFIG.REGWEN_MUBI - mbx_host_reg_top u_regs( + mbx_core_reg_top u_regs( .clk_i ( clk_i ), .rst_ni ( rst_ni ), .tl_i ( tl_host_i ), diff --git a/hw/ip/mbx/rtl/mbx_reg_pkg.sv b/hw/ip/mbx/rtl/mbx_reg_pkg.sv index 357b46ffe3c6f..d0063ef7206cc 100644 --- a/hw/ip/mbx/rtl/mbx_reg_pkg.sv +++ b/hw/ip/mbx/rtl/mbx_reg_pkg.sv @@ -10,11 +10,11 @@ package mbx_reg_pkg; parameter int NumAlerts = 2; // Address widths within the block - parameter int HostAw = 7; + parameter int CoreAw = 7; parameter int SysAw = 5; /////////////////////////////////////////////// - // Typedefs for registers for host interface // + // Typedefs for registers for core interface // /////////////////////////////////////////////// typedef struct packed { @@ -187,7 +187,7 @@ package mbx_reg_pkg; logic [31:0] d; } mbx_hw2reg_doe_intr_msg_data_reg_t; - // Register -> HW type for host interface + // Register -> HW type for core interface typedef struct packed { mbx_reg2hw_intr_state_reg_t intr_state; // [288:287] mbx_reg2hw_intr_enable_reg_t intr_enable; // [286:285] @@ -206,9 +206,9 @@ package mbx_reg_pkg; mbx_reg2hw_outbound_object_size_reg_t outbound_object_size; // [75:64] mbx_reg2hw_doe_intr_msg_addr_reg_t doe_intr_msg_addr; // [63:32] mbx_reg2hw_doe_intr_msg_data_reg_t doe_intr_msg_data; // [31:0] - } mbx_host_reg2hw_t; + } mbx_core_reg2hw_t; - // HW -> register type for host interface + // HW -> register type for core interface typedef struct packed { mbx_hw2reg_intr_state_reg_t intr_state; // [144:141] mbx_hw2reg_control_reg_t control; // [140:139] @@ -218,28 +218,28 @@ package mbx_reg_pkg; mbx_hw2reg_outbound_object_size_reg_t outbound_object_size; // [75:64] mbx_hw2reg_doe_intr_msg_addr_reg_t doe_intr_msg_addr; // [63:32] mbx_hw2reg_doe_intr_msg_data_reg_t doe_intr_msg_data; // [31:0] - } mbx_host_hw2reg_t; - - // Register offsets for host interface - parameter logic [HostAw-1:0] MBX_INTR_STATE_OFFSET = 7'h 0; - parameter logic [HostAw-1:0] MBX_INTR_ENABLE_OFFSET = 7'h 4; - parameter logic [HostAw-1:0] MBX_INTR_TEST_OFFSET = 7'h 8; - parameter logic [HostAw-1:0] MBX_ALERT_TEST_OFFSET = 7'h c; - parameter logic [HostAw-1:0] MBX_CONTROL_OFFSET = 7'h 10; - parameter logic [HostAw-1:0] MBX_STATUS_OFFSET = 7'h 14; - parameter logic [HostAw-1:0] MBX_ADDRESS_RANGE_REGWEN_OFFSET = 7'h 18; - parameter logic [HostAw-1:0] MBX_ADDRESS_RANGE_VALID_OFFSET = 7'h 1c; - parameter logic [HostAw-1:0] MBX_INBOUND_BASE_ADDRESS_OFFSET = 7'h 20; - parameter logic [HostAw-1:0] MBX_INBOUND_LIMIT_ADDRESS_OFFSET = 7'h 24; - parameter logic [HostAw-1:0] MBX_INBOUND_WRITE_PTR_OFFSET = 7'h 28; - parameter logic [HostAw-1:0] MBX_OUTBOUND_BASE_ADDRESS_OFFSET = 7'h 2c; - parameter logic [HostAw-1:0] MBX_OUTBOUND_LIMIT_ADDRESS_OFFSET = 7'h 30; - parameter logic [HostAw-1:0] MBX_OUTBOUND_READ_PTR_OFFSET = 7'h 34; - parameter logic [HostAw-1:0] MBX_OUTBOUND_OBJECT_SIZE_OFFSET = 7'h 38; - parameter logic [HostAw-1:0] MBX_DOE_INTR_MSG_ADDR_OFFSET = 7'h 3c; - parameter logic [HostAw-1:0] MBX_DOE_INTR_MSG_DATA_OFFSET = 7'h 40; - - // Reset values for hwext registers and their fields for host interface + } mbx_core_hw2reg_t; + + // Register offsets for core interface + parameter logic [CoreAw-1:0] MBX_INTR_STATE_OFFSET = 7'h 0; + parameter logic [CoreAw-1:0] MBX_INTR_ENABLE_OFFSET = 7'h 4; + parameter logic [CoreAw-1:0] MBX_INTR_TEST_OFFSET = 7'h 8; + parameter logic [CoreAw-1:0] MBX_ALERT_TEST_OFFSET = 7'h c; + parameter logic [CoreAw-1:0] MBX_CONTROL_OFFSET = 7'h 10; + parameter logic [CoreAw-1:0] MBX_STATUS_OFFSET = 7'h 14; + parameter logic [CoreAw-1:0] MBX_ADDRESS_RANGE_REGWEN_OFFSET = 7'h 18; + parameter logic [CoreAw-1:0] MBX_ADDRESS_RANGE_VALID_OFFSET = 7'h 1c; + parameter logic [CoreAw-1:0] MBX_INBOUND_BASE_ADDRESS_OFFSET = 7'h 20; + parameter logic [CoreAw-1:0] MBX_INBOUND_LIMIT_ADDRESS_OFFSET = 7'h 24; + parameter logic [CoreAw-1:0] MBX_INBOUND_WRITE_PTR_OFFSET = 7'h 28; + parameter logic [CoreAw-1:0] MBX_OUTBOUND_BASE_ADDRESS_OFFSET = 7'h 2c; + parameter logic [CoreAw-1:0] MBX_OUTBOUND_LIMIT_ADDRESS_OFFSET = 7'h 30; + parameter logic [CoreAw-1:0] MBX_OUTBOUND_READ_PTR_OFFSET = 7'h 34; + parameter logic [CoreAw-1:0] MBX_OUTBOUND_OBJECT_SIZE_OFFSET = 7'h 38; + parameter logic [CoreAw-1:0] MBX_DOE_INTR_MSG_ADDR_OFFSET = 7'h 3c; + parameter logic [CoreAw-1:0] MBX_DOE_INTR_MSG_DATA_OFFSET = 7'h 40; + + // Reset values for hwext registers and their fields for core interface parameter logic [1:0] MBX_INTR_TEST_RESVAL = 2'h 0; parameter logic [0:0] MBX_INTR_TEST_MBX_READY_RESVAL = 1'h 0; parameter logic [0:0] MBX_INTR_TEST_MBX_ABORT_RESVAL = 1'h 0; @@ -262,7 +262,7 @@ package mbx_reg_pkg; parameter logic [31:0] MBX_DOE_INTR_MSG_DATA_RESVAL = 32'h 0; parameter logic [31:0] MBX_DOE_INTR_MSG_DATA_DOE_INTR_MSG_DATA_RESVAL = 32'h 0; - // Register index for host interface + // Register index for core interface typedef enum int { MBX_INTR_STATE, MBX_INTR_ENABLE, @@ -281,10 +281,10 @@ package mbx_reg_pkg; MBX_OUTBOUND_OBJECT_SIZE, MBX_DOE_INTR_MSG_ADDR, MBX_DOE_INTR_MSG_DATA - } mbx_host_id_e; + } mbx_core_id_e; - // Register width information to check illegal writes for host interface - parameter logic [3:0] MBX_HOST_PERMIT [17] = '{ + // Register width information to check illegal writes for core interface + parameter logic [3:0] MBX_CORE_PERMIT [17] = '{ 4'b 0001, // index[ 0] MBX_INTR_STATE 4'b 0001, // index[ 1] MBX_INTR_ENABLE 4'b 0001, // index[ 2] MBX_INTR_TEST diff --git a/hw/ip/mbx/rtl/mbx_sysif.sv b/hw/ip/mbx/rtl/mbx_sysif.sv index 68803d24a953d..f4a9388038e94 100644 --- a/hw/ip/mbx/rtl/mbx_sysif.sv +++ b/hw/ip/mbx/rtl/mbx_sysif.sv @@ -119,7 +119,7 @@ module mbx_sysif assign hw2reg.sys_status.error.de = sysif_status_error_set_i | sysif_status_error_clear_i; assign hw2reg.sys_status.error.d = sysif_status_error_set_i; - // Set by the Host firmware (w1s) + // Set by OT firmware (w1s) // Cleared by the Sys firmware (w1c) assign hw2reg.sys_status.ready.de = sysif_status_ready_valid_i; assign hw2reg.sys_status.ready.d = sysif_status_ready_i; From 62a27afed659dde4cbfdffda11f18aa895ccd53b Mon Sep 17 00:00:00 2001 From: Andreas Kurth Date: Tue, 19 Sep 2023 10:41:47 +0000 Subject: [PATCH 26/88] [mbx] Rename SoC-facing port to `soc` This is hopefully less ambiguous to OT devs than `sys`. Signed-off-by: Andreas Kurth --- hw/ip/mbx/data/mbx.hjson | 18 +- hw/ip/mbx/mbx.core | 2 +- hw/ip/mbx/rtl/mbx.sv | 10 +- hw/ip/mbx/rtl/mbx_reg_pkg.sv | 88 +++--- ...{mbx_sys_reg_top.sv => mbx_soc_reg_top.sv} | 274 +++++++++--------- hw/ip/mbx/rtl/mbx_sysif.sv | 58 ++-- 6 files changed, 225 insertions(+), 225 deletions(-) rename hw/ip/mbx/rtl/{mbx_sys_reg_top.sv => mbx_soc_reg_top.sv} (59%) diff --git a/hw/ip/mbx/data/mbx.hjson b/hw/ip/mbx/data/mbx.hjson index 5d673d71252e4..f0fcf7d980b72 100644 --- a/hw/ip/mbx/data/mbx.hjson +++ b/hw/ip/mbx/data/mbx.hjson @@ -21,7 +21,7 @@ bus_interfaces: [ { protocol: "tlul", direction: "device", name: "core" } { protocol: "tlul", direction: "host", name: "sram" } - { protocol: "tlul", direction: "device", name: "sys" } + { protocol: "tlul", direction: "device", name: "soc" } ] inter_signal_list: [ { struct: "logic", @@ -264,7 +264,7 @@ } { name: "DOE_INTR_MSG_ADDR" desc: ''' - Software read-only alias of the DOE_INTR_MSG_ADDR register of the SYS interface for convenient access of the OT firmware. + Software read-only alias of the DOE_INTR_MSG_ADDR register of the SoC interface for convenient access of the OT firmware. Defined only for FW-to-FW mailboxes. ''' hwext: "true" @@ -280,7 +280,7 @@ } { name: "DOE_INTR_MSG_DATA" desc: ''' - Software read-only alias of the DOE_INTR_MSG_DATA register of the SYS interface for convenient access of the OT firmware. + Software read-only alias of the DOE_INTR_MSG_DATA register of the SoC interface for convenient access of the OT firmware. Defined only for FW-to-FW mailboxes. ''' hwext: "true" @@ -295,8 +295,8 @@ ] } ] - sys: [ - { name: "SYS_DOE_INTR_MSG_ADDR" + soc: [ + { name: "SOC_DOE_INTR_MSG_ADDR" desc: ''' Utilized by the mailbox responder to send an interrupt message to the requester via a write to the configured address. Defined only for FW-to-FW mailboxes. @@ -312,7 +312,7 @@ } ] } - { name: "SYS_DOE_INTR_MSG_DATA" + { name: "SOC_DOE_INTR_MSG_DATA" desc: ''' Interrupt message data to be sent to the address configured in the DOE_INTR_MSG_ADDR register. Defined only for FW-to-FW mailboxes. @@ -328,7 +328,7 @@ } ] } - { name: "SYS_CONTROL" + { name: "SOC_CONTROL" desc: "DOE mailbox control register." hwaccess: "hrw" hwqe: "true" @@ -360,7 +360,7 @@ } ] } - { name: "SYS_STATUS" + { name: "SOC_STATUS" desc: "DOE mailbox status register" fields: [ { name: "busy" @@ -392,7 +392,7 @@ } { name: "ready" desc: ''' - When Set, this bit indicates the DOE instance has a data object available to be read by system firmware/software. + When Set, this bit indicates the DOE instance has a data object available to be read by SoC firmware/software. The transition of this bit from Clear to Set is an interrupt triggering event. ''' bits: "31" diff --git a/hw/ip/mbx/mbx.core b/hw/ip/mbx/mbx.core index 4f966427c2512..0eea0defa5da4 100644 --- a/hw/ip/mbx/mbx.core +++ b/hw/ip/mbx/mbx.core @@ -14,7 +14,7 @@ filesets: - rtl/mbx_reg_pkg.sv - rtl/mbx.sv - rtl/mbx_core_reg_top.sv - - rtl/mbx_sys_reg_top.sv + - rtl/mbx_soc_reg_top.sv - rtl/mbx_hostif.sv - rtl/mbx_sysif.sv - rtl/mbx_sramrwarb.sv diff --git a/hw/ip/mbx/rtl/mbx.sv b/hw/ip/mbx/rtl/mbx.sv index 4b02e6744a823..8e339a79b5fa0 100644 --- a/hw/ip/mbx/rtl/mbx.sv +++ b/hw/ip/mbx/rtl/mbx.sv @@ -29,9 +29,9 @@ module mbx // Device port facing OpenTitan input tlul_pkg::tl_h2d_t core_tl_d_i, output tlul_pkg::tl_d2h_t core_tl_d_o, - // Device port facing CTN Xbar - input tlul_pkg::tl_h2d_t tl_sys_i, - output tlul_pkg::tl_d2h_t tl_sys_o, + // Device port facing SoC + input tlul_pkg::tl_h2d_t soc_tl_d_i, + output tlul_pkg::tl_d2h_t soc_tl_d_o, // Host port to access private SRAM input tlul_pkg::tl_d2h_t tl_sram_i, output tlul_pkg::tl_h2d_t tl_sram_o @@ -171,8 +171,8 @@ module mbx ) u_sysif ( .clk_i ( clk_i ), .rst_ni ( rst_ni ), - .tl_sys_i ( tl_sys_i ), - .tl_sys_o ( tl_sys_o ), + .tl_sys_i ( soc_tl_d_i ), + .tl_sys_o ( soc_tl_d_o ), .intg_err_o ( sysif_intg_err ), // System interrupt support .doe_intr_support_o ( doe_intr_support_o ), diff --git a/hw/ip/mbx/rtl/mbx_reg_pkg.sv b/hw/ip/mbx/rtl/mbx_reg_pkg.sv index d0063ef7206cc..7aa87d6d4ac5e 100644 --- a/hw/ip/mbx/rtl/mbx_reg_pkg.sv +++ b/hw/ip/mbx/rtl/mbx_reg_pkg.sv @@ -11,7 +11,7 @@ package mbx_reg_pkg; // Address widths within the block parameter int CoreAw = 7; - parameter int SysAw = 5; + parameter int SocAw = 5; /////////////////////////////////////////////// // Typedefs for registers for core interface // @@ -305,18 +305,18 @@ package mbx_reg_pkg; }; ////////////////////////////////////////////// - // Typedefs for registers for sys interface // + // Typedefs for registers for soc interface // ////////////////////////////////////////////// typedef struct packed { logic [31:0] q; logic qe; - } mbx_reg2hw_sys_doe_intr_msg_addr_reg_t; + } mbx_reg2hw_soc_doe_intr_msg_addr_reg_t; typedef struct packed { logic [31:0] q; logic qe; - } mbx_reg2hw_sys_doe_intr_msg_data_reg_t; + } mbx_reg2hw_soc_doe_intr_msg_data_reg_t; typedef struct packed { struct packed { @@ -331,7 +331,7 @@ package mbx_reg_pkg; logic q; logic qe; } abort; - } mbx_reg2hw_sys_control_reg_t; + } mbx_reg2hw_soc_control_reg_t; typedef struct packed { struct packed { @@ -347,7 +347,7 @@ package mbx_reg_pkg; struct packed { logic q; } busy; - } mbx_reg2hw_sys_status_reg_t; + } mbx_reg2hw_soc_status_reg_t; typedef struct packed { struct packed { @@ -359,7 +359,7 @@ package mbx_reg_pkg; struct packed { logic d; } go; - } mbx_hw2reg_sys_control_reg_t; + } mbx_hw2reg_soc_control_reg_t; typedef struct packed { struct packed { @@ -378,56 +378,56 @@ package mbx_reg_pkg; logic d; logic de; } ready; - } mbx_hw2reg_sys_status_reg_t; + } mbx_hw2reg_soc_status_reg_t; - // Register -> HW type for sys interface + // Register -> HW type for soc interface typedef struct packed { - mbx_reg2hw_sys_doe_intr_msg_addr_reg_t sys_doe_intr_msg_addr; // [76:44] - mbx_reg2hw_sys_doe_intr_msg_data_reg_t sys_doe_intr_msg_data; // [43:11] - mbx_reg2hw_sys_control_reg_t sys_control; // [10:5] - mbx_reg2hw_sys_status_reg_t sys_status; // [4:0] - } mbx_sys_reg2hw_t; + mbx_reg2hw_soc_doe_intr_msg_addr_reg_t soc_doe_intr_msg_addr; // [76:44] + mbx_reg2hw_soc_doe_intr_msg_data_reg_t soc_doe_intr_msg_data; // [43:11] + mbx_reg2hw_soc_control_reg_t soc_control; // [10:5] + mbx_reg2hw_soc_status_reg_t soc_status; // [4:0] + } mbx_soc_reg2hw_t; - // HW -> register type for sys interface + // HW -> register type for soc interface typedef struct packed { - mbx_hw2reg_sys_control_reg_t sys_control; // [10:8] - mbx_hw2reg_sys_status_reg_t sys_status; // [7:0] - } mbx_sys_hw2reg_t; + mbx_hw2reg_soc_control_reg_t soc_control; // [10:8] + mbx_hw2reg_soc_status_reg_t soc_status; // [7:0] + } mbx_soc_hw2reg_t; - // Register offsets for sys interface - parameter logic [SysAw-1:0] MBX_SYS_DOE_INTR_MSG_ADDR_OFFSET = 5'h 0; - parameter logic [SysAw-1:0] MBX_SYS_DOE_INTR_MSG_DATA_OFFSET = 5'h 4; - parameter logic [SysAw-1:0] MBX_SYS_CONTROL_OFFSET = 5'h 8; - parameter logic [SysAw-1:0] MBX_SYS_STATUS_OFFSET = 5'h c; + // Register offsets for soc interface + parameter logic [SocAw-1:0] MBX_SOC_DOE_INTR_MSG_ADDR_OFFSET = 5'h 0; + parameter logic [SocAw-1:0] MBX_SOC_DOE_INTR_MSG_DATA_OFFSET = 5'h 4; + parameter logic [SocAw-1:0] MBX_SOC_CONTROL_OFFSET = 5'h 8; + parameter logic [SocAw-1:0] MBX_SOC_STATUS_OFFSET = 5'h c; - // Reset values for hwext registers and their fields for sys interface - parameter logic [31:0] MBX_SYS_CONTROL_RESVAL = 32'h 0; - parameter logic [0:0] MBX_SYS_CONTROL_ABORT_RESVAL = 1'h 0; - parameter logic [0:0] MBX_SYS_CONTROL_DOE_INTR_EN_RESVAL = 1'h 0; - parameter logic [0:0] MBX_SYS_CONTROL_GO_RESVAL = 1'h 0; + // Reset values for hwext registers and their fields for soc interface + parameter logic [31:0] MBX_SOC_CONTROL_RESVAL = 32'h 0; + parameter logic [0:0] MBX_SOC_CONTROL_ABORT_RESVAL = 1'h 0; + parameter logic [0:0] MBX_SOC_CONTROL_DOE_INTR_EN_RESVAL = 1'h 0; + parameter logic [0:0] MBX_SOC_CONTROL_GO_RESVAL = 1'h 0; - // Window parameters for sys interface - parameter logic [SysAw-1:0] MBX_WDATA_OFFSET = 5'h 10; + // Window parameters for soc interface + parameter logic [SocAw-1:0] MBX_WDATA_OFFSET = 5'h 10; parameter int unsigned MBX_WDATA_SIZE = 'h 4; parameter int unsigned MBX_WDATA_IDX = 0; - parameter logic [SysAw-1:0] MBX_RDATA_OFFSET = 5'h 14; + parameter logic [SocAw-1:0] MBX_RDATA_OFFSET = 5'h 14; parameter int unsigned MBX_RDATA_SIZE = 'h 4; parameter int unsigned MBX_RDATA_IDX = 1; - // Register index for sys interface + // Register index for soc interface typedef enum int { - MBX_SYS_DOE_INTR_MSG_ADDR, - MBX_SYS_DOE_INTR_MSG_DATA, - MBX_SYS_CONTROL, - MBX_SYS_STATUS - } mbx_sys_id_e; - - // Register width information to check illegal writes for sys interface - parameter logic [3:0] MBX_SYS_PERMIT [4] = '{ - 4'b 1111, // index[0] MBX_SYS_DOE_INTR_MSG_ADDR - 4'b 1111, // index[1] MBX_SYS_DOE_INTR_MSG_DATA - 4'b 1111, // index[2] MBX_SYS_CONTROL - 4'b 1111 // index[3] MBX_SYS_STATUS + MBX_SOC_DOE_INTR_MSG_ADDR, + MBX_SOC_DOE_INTR_MSG_DATA, + MBX_SOC_CONTROL, + MBX_SOC_STATUS + } mbx_soc_id_e; + + // Register width information to check illegal writes for soc interface + parameter logic [3:0] MBX_SOC_PERMIT [4] = '{ + 4'b 1111, // index[0] MBX_SOC_DOE_INTR_MSG_ADDR + 4'b 1111, // index[1] MBX_SOC_DOE_INTR_MSG_DATA + 4'b 1111, // index[2] MBX_SOC_CONTROL + 4'b 1111 // index[3] MBX_SOC_STATUS }; endpackage diff --git a/hw/ip/mbx/rtl/mbx_sys_reg_top.sv b/hw/ip/mbx/rtl/mbx_soc_reg_top.sv similarity index 59% rename from hw/ip/mbx/rtl/mbx_sys_reg_top.sv rename to hw/ip/mbx/rtl/mbx_soc_reg_top.sv index 00e63ce084714..8cded912d8966 100644 --- a/hw/ip/mbx/rtl/mbx_sys_reg_top.sv +++ b/hw/ip/mbx/rtl/mbx_soc_reg_top.sv @@ -6,7 +6,7 @@ `include "prim_assert.sv" -module mbx_sys_reg_top ( +module mbx_soc_reg_top ( input clk_i, input rst_ni, input tlul_pkg::tl_h2d_t tl_i, @@ -17,8 +17,8 @@ module mbx_sys_reg_top ( input tlul_pkg::tl_d2h_t tl_win_i [2], // To HW - output mbx_reg_pkg::mbx_sys_reg2hw_t reg2hw, // Write - input mbx_reg_pkg::mbx_sys_hw2reg_t hw2reg, // Read + output mbx_reg_pkg::mbx_soc_reg2hw_t reg2hw, // Write + input mbx_reg_pkg::mbx_soc_hw2reg_t hw2reg, // Read // Integrity check errors output logic intg_err_o @@ -173,170 +173,170 @@ module mbx_sys_reg_top ( // Define SW related signals // Format: __{wd|we|qs} // or _{wd|we|qs} if field == 1 or 0 - logic sys_doe_intr_msg_addr_we; - logic [31:0] sys_doe_intr_msg_addr_qs; - logic [31:0] sys_doe_intr_msg_addr_wd; - logic sys_doe_intr_msg_data_we; - logic [31:0] sys_doe_intr_msg_data_qs; - logic [31:0] sys_doe_intr_msg_data_wd; - logic sys_control_re; - logic sys_control_we; - logic sys_control_abort_wd; - logic sys_control_doe_intr_en_qs; - logic sys_control_doe_intr_en_wd; - logic sys_control_go_wd; - logic sys_status_we; - logic sys_status_busy_qs; - logic sys_status_doe_intr_status_qs; - logic sys_status_doe_intr_status_wd; - logic sys_status_error_qs; - logic sys_status_ready_qs; + logic soc_doe_intr_msg_addr_we; + logic [31:0] soc_doe_intr_msg_addr_qs; + logic [31:0] soc_doe_intr_msg_addr_wd; + logic soc_doe_intr_msg_data_we; + logic [31:0] soc_doe_intr_msg_data_qs; + logic [31:0] soc_doe_intr_msg_data_wd; + logic soc_control_re; + logic soc_control_we; + logic soc_control_abort_wd; + logic soc_control_doe_intr_en_qs; + logic soc_control_doe_intr_en_wd; + logic soc_control_go_wd; + logic soc_status_we; + logic soc_status_busy_qs; + logic soc_status_doe_intr_status_qs; + logic soc_status_doe_intr_status_wd; + logic soc_status_error_qs; + logic soc_status_ready_qs; // Register instances - // R[sys_doe_intr_msg_addr]: V(False) - logic sys_doe_intr_msg_addr_qe; - logic [0:0] sys_doe_intr_msg_addr_flds_we; + // R[soc_doe_intr_msg_addr]: V(False) + logic soc_doe_intr_msg_addr_qe; + logic [0:0] soc_doe_intr_msg_addr_flds_we; prim_flop #( .Width(1), .ResetValue(0) - ) u_sys_doe_intr_msg_addr0_qe ( + ) u_soc_doe_intr_msg_addr0_qe ( .clk_i(clk_i), .rst_ni(rst_ni), - .d_i(&sys_doe_intr_msg_addr_flds_we), - .q_o(sys_doe_intr_msg_addr_qe) + .d_i(&soc_doe_intr_msg_addr_flds_we), + .q_o(soc_doe_intr_msg_addr_qe) ); prim_subreg #( .DW (32), .SwAccess(prim_subreg_pkg::SwAccessRW), .RESVAL (32'h0), .Mubi (1'b0) - ) u_sys_doe_intr_msg_addr ( + ) u_soc_doe_intr_msg_addr ( .clk_i (clk_i), .rst_ni (rst_ni), // from register interface - .we (sys_doe_intr_msg_addr_we), - .wd (sys_doe_intr_msg_addr_wd), + .we (soc_doe_intr_msg_addr_we), + .wd (soc_doe_intr_msg_addr_wd), // from internal hardware .de (1'b0), .d ('0), // to internal hardware - .qe (sys_doe_intr_msg_addr_flds_we[0]), - .q (reg2hw.sys_doe_intr_msg_addr.q), + .qe (soc_doe_intr_msg_addr_flds_we[0]), + .q (reg2hw.soc_doe_intr_msg_addr.q), .ds (), // to register interface (read) - .qs (sys_doe_intr_msg_addr_qs) + .qs (soc_doe_intr_msg_addr_qs) ); - assign reg2hw.sys_doe_intr_msg_addr.qe = sys_doe_intr_msg_addr_qe; + assign reg2hw.soc_doe_intr_msg_addr.qe = soc_doe_intr_msg_addr_qe; - // R[sys_doe_intr_msg_data]: V(False) - logic sys_doe_intr_msg_data_qe; - logic [0:0] sys_doe_intr_msg_data_flds_we; + // R[soc_doe_intr_msg_data]: V(False) + logic soc_doe_intr_msg_data_qe; + logic [0:0] soc_doe_intr_msg_data_flds_we; prim_flop #( .Width(1), .ResetValue(0) - ) u_sys_doe_intr_msg_data0_qe ( + ) u_soc_doe_intr_msg_data0_qe ( .clk_i(clk_i), .rst_ni(rst_ni), - .d_i(&sys_doe_intr_msg_data_flds_we), - .q_o(sys_doe_intr_msg_data_qe) + .d_i(&soc_doe_intr_msg_data_flds_we), + .q_o(soc_doe_intr_msg_data_qe) ); prim_subreg #( .DW (32), .SwAccess(prim_subreg_pkg::SwAccessRW), .RESVAL (32'h0), .Mubi (1'b0) - ) u_sys_doe_intr_msg_data ( + ) u_soc_doe_intr_msg_data ( .clk_i (clk_i), .rst_ni (rst_ni), // from register interface - .we (sys_doe_intr_msg_data_we), - .wd (sys_doe_intr_msg_data_wd), + .we (soc_doe_intr_msg_data_we), + .wd (soc_doe_intr_msg_data_wd), // from internal hardware .de (1'b0), .d ('0), // to internal hardware - .qe (sys_doe_intr_msg_data_flds_we[0]), - .q (reg2hw.sys_doe_intr_msg_data.q), + .qe (soc_doe_intr_msg_data_flds_we[0]), + .q (reg2hw.soc_doe_intr_msg_data.q), .ds (), // to register interface (read) - .qs (sys_doe_intr_msg_data_qs) + .qs (soc_doe_intr_msg_data_qs) ); - assign reg2hw.sys_doe_intr_msg_data.qe = sys_doe_intr_msg_data_qe; + assign reg2hw.soc_doe_intr_msg_data.qe = soc_doe_intr_msg_data_qe; - // R[sys_control]: V(True) - logic sys_control_qe; - logic [2:0] sys_control_flds_we; - assign sys_control_qe = &sys_control_flds_we; + // R[soc_control]: V(True) + logic soc_control_qe; + logic [2:0] soc_control_flds_we; + assign soc_control_qe = &soc_control_flds_we; // F[abort]: 0:0 prim_subreg_ext #( .DW (1) - ) u_sys_control_abort ( + ) u_soc_control_abort ( .re (1'b0), - .we (sys_control_we), - .wd (sys_control_abort_wd), - .d (hw2reg.sys_control.abort.d), + .we (soc_control_we), + .wd (soc_control_abort_wd), + .d (hw2reg.soc_control.abort.d), .qre (), - .qe (sys_control_flds_we[0]), - .q (reg2hw.sys_control.abort.q), + .qe (soc_control_flds_we[0]), + .q (reg2hw.soc_control.abort.q), .ds (), .qs () ); - assign reg2hw.sys_control.abort.qe = sys_control_qe; + assign reg2hw.soc_control.abort.qe = soc_control_qe; // F[doe_intr_en]: 1:1 prim_subreg_ext #( .DW (1) - ) u_sys_control_doe_intr_en ( - .re (sys_control_re), - .we (sys_control_we), - .wd (sys_control_doe_intr_en_wd), - .d (hw2reg.sys_control.doe_intr_en.d), + ) u_soc_control_doe_intr_en ( + .re (soc_control_re), + .we (soc_control_we), + .wd (soc_control_doe_intr_en_wd), + .d (hw2reg.soc_control.doe_intr_en.d), .qre (), - .qe (sys_control_flds_we[1]), - .q (reg2hw.sys_control.doe_intr_en.q), + .qe (soc_control_flds_we[1]), + .q (reg2hw.soc_control.doe_intr_en.q), .ds (), - .qs (sys_control_doe_intr_en_qs) + .qs (soc_control_doe_intr_en_qs) ); - assign reg2hw.sys_control.doe_intr_en.qe = sys_control_qe; + assign reg2hw.soc_control.doe_intr_en.qe = soc_control_qe; // F[go]: 31:31 prim_subreg_ext #( .DW (1) - ) u_sys_control_go ( + ) u_soc_control_go ( .re (1'b0), - .we (sys_control_we), - .wd (sys_control_go_wd), - .d (hw2reg.sys_control.go.d), + .we (soc_control_we), + .wd (soc_control_go_wd), + .d (hw2reg.soc_control.go.d), .qre (), - .qe (sys_control_flds_we[2]), - .q (reg2hw.sys_control.go.q), + .qe (soc_control_flds_we[2]), + .q (reg2hw.soc_control.go.q), .ds (), .qs () ); - assign reg2hw.sys_control.go.qe = sys_control_qe; + assign reg2hw.soc_control.go.qe = soc_control_qe; - // R[sys_status]: V(False) - logic sys_status_qe; - logic [3:0] sys_status_flds_we; + // R[soc_status]: V(False) + logic soc_status_qe; + logic [3:0] soc_status_flds_we; prim_flop #( .Width(1), .ResetValue(0) - ) u_sys_status0_qe ( + ) u_soc_status0_qe ( .clk_i(clk_i), .rst_ni(rst_ni), - .d_i(&(sys_status_flds_we | 4'hd)), - .q_o(sys_status_qe) + .d_i(&(soc_status_flds_we | 4'hd)), + .q_o(soc_status_qe) ); // F[busy]: 0:0 prim_subreg #( @@ -344,7 +344,7 @@ module mbx_sys_reg_top ( .SwAccess(prim_subreg_pkg::SwAccessRO), .RESVAL (1'h1), .Mubi (1'b0) - ) u_sys_status_busy ( + ) u_soc_status_busy ( .clk_i (clk_i), .rst_ni (rst_ni), @@ -353,16 +353,16 @@ module mbx_sys_reg_top ( .wd ('0), // from internal hardware - .de (hw2reg.sys_status.busy.de), - .d (hw2reg.sys_status.busy.d), + .de (hw2reg.soc_status.busy.de), + .d (hw2reg.soc_status.busy.d), // to internal hardware - .qe (sys_status_flds_we[0]), - .q (reg2hw.sys_status.busy.q), + .qe (soc_status_flds_we[0]), + .q (reg2hw.soc_status.busy.q), .ds (), // to register interface (read) - .qs (sys_status_busy_qs) + .qs (soc_status_busy_qs) ); // F[doe_intr_status]: 1:1 @@ -371,27 +371,27 @@ module mbx_sys_reg_top ( .SwAccess(prim_subreg_pkg::SwAccessW1C), .RESVAL (1'h0), .Mubi (1'b0) - ) u_sys_status_doe_intr_status ( + ) u_soc_status_doe_intr_status ( .clk_i (clk_i), .rst_ni (rst_ni), // from register interface - .we (sys_status_we), - .wd (sys_status_doe_intr_status_wd), + .we (soc_status_we), + .wd (soc_status_doe_intr_status_wd), // from internal hardware - .de (hw2reg.sys_status.doe_intr_status.de), - .d (hw2reg.sys_status.doe_intr_status.d), + .de (hw2reg.soc_status.doe_intr_status.de), + .d (hw2reg.soc_status.doe_intr_status.d), // to internal hardware - .qe (sys_status_flds_we[1]), - .q (reg2hw.sys_status.doe_intr_status.q), + .qe (soc_status_flds_we[1]), + .q (reg2hw.soc_status.doe_intr_status.q), .ds (), // to register interface (read) - .qs (sys_status_doe_intr_status_qs) + .qs (soc_status_doe_intr_status_qs) ); - assign reg2hw.sys_status.doe_intr_status.qe = sys_status_qe; + assign reg2hw.soc_status.doe_intr_status.qe = soc_status_qe; // F[error]: 2:2 prim_subreg #( @@ -399,7 +399,7 @@ module mbx_sys_reg_top ( .SwAccess(prim_subreg_pkg::SwAccessRO), .RESVAL (1'h0), .Mubi (1'b0) - ) u_sys_status_error ( + ) u_soc_status_error ( .clk_i (clk_i), .rst_ni (rst_ni), @@ -408,16 +408,16 @@ module mbx_sys_reg_top ( .wd ('0), // from internal hardware - .de (hw2reg.sys_status.error.de), - .d (hw2reg.sys_status.error.d), + .de (hw2reg.soc_status.error.de), + .d (hw2reg.soc_status.error.d), // to internal hardware - .qe (sys_status_flds_we[2]), - .q (reg2hw.sys_status.error.q), + .qe (soc_status_flds_we[2]), + .q (reg2hw.soc_status.error.q), .ds (), // to register interface (read) - .qs (sys_status_error_qs) + .qs (soc_status_error_qs) ); // F[ready]: 31:31 @@ -426,7 +426,7 @@ module mbx_sys_reg_top ( .SwAccess(prim_subreg_pkg::SwAccessRO), .RESVAL (1'h0), .Mubi (1'b0) - ) u_sys_status_ready ( + ) u_soc_status_ready ( .clk_i (clk_i), .rst_ni (rst_ni), @@ -435,16 +435,16 @@ module mbx_sys_reg_top ( .wd ('0), // from internal hardware - .de (hw2reg.sys_status.ready.de), - .d (hw2reg.sys_status.ready.d), + .de (hw2reg.soc_status.ready.de), + .d (hw2reg.soc_status.ready.d), // to internal hardware - .qe (sys_status_flds_we[3]), - .q (reg2hw.sys_status.ready.q), + .qe (soc_status_flds_we[3]), + .q (reg2hw.soc_status.ready.q), .ds (), // to register interface (read) - .qs (sys_status_ready_qs) + .qs (soc_status_ready_qs) ); @@ -452,10 +452,10 @@ module mbx_sys_reg_top ( logic [3:0] addr_hit; always_comb begin addr_hit = '0; - addr_hit[0] = (reg_addr == MBX_SYS_DOE_INTR_MSG_ADDR_OFFSET); - addr_hit[1] = (reg_addr == MBX_SYS_DOE_INTR_MSG_DATA_OFFSET); - addr_hit[2] = (reg_addr == MBX_SYS_CONTROL_OFFSET); - addr_hit[3] = (reg_addr == MBX_SYS_STATUS_OFFSET); + addr_hit[0] = (reg_addr == MBX_SOC_DOE_INTR_MSG_ADDR_OFFSET); + addr_hit[1] = (reg_addr == MBX_SOC_DOE_INTR_MSG_DATA_OFFSET); + addr_hit[2] = (reg_addr == MBX_SOC_CONTROL_OFFSET); + addr_hit[3] = (reg_addr == MBX_SOC_STATUS_OFFSET); end assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ; @@ -463,38 +463,38 @@ module mbx_sys_reg_top ( // Check sub-word write is permitted always_comb begin wr_err = (reg_we & - ((addr_hit[0] & (|(MBX_SYS_PERMIT[0] & ~reg_be))) | - (addr_hit[1] & (|(MBX_SYS_PERMIT[1] & ~reg_be))) | - (addr_hit[2] & (|(MBX_SYS_PERMIT[2] & ~reg_be))) | - (addr_hit[3] & (|(MBX_SYS_PERMIT[3] & ~reg_be))))); + ((addr_hit[0] & (|(MBX_SOC_PERMIT[0] & ~reg_be))) | + (addr_hit[1] & (|(MBX_SOC_PERMIT[1] & ~reg_be))) | + (addr_hit[2] & (|(MBX_SOC_PERMIT[2] & ~reg_be))) | + (addr_hit[3] & (|(MBX_SOC_PERMIT[3] & ~reg_be))))); end // Generate write-enables - assign sys_doe_intr_msg_addr_we = addr_hit[0] & reg_we & !reg_error; + assign soc_doe_intr_msg_addr_we = addr_hit[0] & reg_we & !reg_error; - assign sys_doe_intr_msg_addr_wd = reg_wdata[31:0]; - assign sys_doe_intr_msg_data_we = addr_hit[1] & reg_we & !reg_error; + assign soc_doe_intr_msg_addr_wd = reg_wdata[31:0]; + assign soc_doe_intr_msg_data_we = addr_hit[1] & reg_we & !reg_error; - assign sys_doe_intr_msg_data_wd = reg_wdata[31:0]; - assign sys_control_re = addr_hit[2] & reg_re & !reg_error; - assign sys_control_we = addr_hit[2] & reg_we & !reg_error; + assign soc_doe_intr_msg_data_wd = reg_wdata[31:0]; + assign soc_control_re = addr_hit[2] & reg_re & !reg_error; + assign soc_control_we = addr_hit[2] & reg_we & !reg_error; - assign sys_control_abort_wd = reg_wdata[0]; + assign soc_control_abort_wd = reg_wdata[0]; - assign sys_control_doe_intr_en_wd = reg_wdata[1]; + assign soc_control_doe_intr_en_wd = reg_wdata[1]; - assign sys_control_go_wd = reg_wdata[31]; - assign sys_status_we = addr_hit[3] & reg_we & !reg_error; + assign soc_control_go_wd = reg_wdata[31]; + assign soc_status_we = addr_hit[3] & reg_we & !reg_error; - assign sys_status_doe_intr_status_wd = reg_wdata[1]; + assign soc_status_doe_intr_status_wd = reg_wdata[1]; // Assign write-enables to checker logic vector. always_comb begin reg_we_check = '0; - reg_we_check[0] = sys_doe_intr_msg_addr_we; - reg_we_check[1] = sys_doe_intr_msg_data_we; - reg_we_check[2] = sys_control_we; - reg_we_check[3] = sys_status_we; + reg_we_check[0] = soc_doe_intr_msg_addr_we; + reg_we_check[1] = soc_doe_intr_msg_data_we; + reg_we_check[2] = soc_control_we; + reg_we_check[3] = soc_status_we; end // Read data return @@ -502,24 +502,24 @@ module mbx_sys_reg_top ( reg_rdata_next = '0; unique case (1'b1) addr_hit[0]: begin - reg_rdata_next[31:0] = sys_doe_intr_msg_addr_qs; + reg_rdata_next[31:0] = soc_doe_intr_msg_addr_qs; end addr_hit[1]: begin - reg_rdata_next[31:0] = sys_doe_intr_msg_data_qs; + reg_rdata_next[31:0] = soc_doe_intr_msg_data_qs; end addr_hit[2]: begin reg_rdata_next[0] = '0; - reg_rdata_next[1] = sys_control_doe_intr_en_qs; + reg_rdata_next[1] = soc_control_doe_intr_en_qs; reg_rdata_next[31] = '0; end addr_hit[3]: begin - reg_rdata_next[0] = sys_status_busy_qs; - reg_rdata_next[1] = sys_status_doe_intr_status_qs; - reg_rdata_next[2] = sys_status_error_qs; - reg_rdata_next[31] = sys_status_ready_qs; + reg_rdata_next[0] = soc_status_busy_qs; + reg_rdata_next[1] = soc_status_doe_intr_status_qs; + reg_rdata_next[2] = soc_status_error_qs; + reg_rdata_next[31] = soc_status_ready_qs; end default: begin diff --git a/hw/ip/mbx/rtl/mbx_sysif.sv b/hw/ip/mbx/rtl/mbx_sysif.sv index f4a9388038e94..8d198dc522465 100644 --- a/hw/ip/mbx/rtl/mbx_sysif.sv +++ b/hw/ip/mbx/rtl/mbx_sysif.sv @@ -49,15 +49,15 @@ module mbx_sysif ); import mbx_reg_pkg::*; - mbx_sys_reg2hw_t reg2hw; - mbx_sys_hw2reg_t hw2reg; + mbx_soc_reg2hw_t reg2hw; + mbx_soc_hw2reg_t hw2reg; // Interface for the custom register interface with bus blocking support tlul_pkg::tl_h2d_t tl_win_h2d[2]; tlul_pkg::tl_d2h_t tl_win_d2h[2]; // SEC_CM: BUS.INTEGRITY - mbx_sys_reg_top u_sys_regs ( + mbx_soc_reg_top u_soc_regs ( .clk_i ( clk_i ), .rst_ni ( rst_ni ), .tl_i ( tl_sys_i ), @@ -69,14 +69,14 @@ module mbx_sysif ); assign doe_intr_support_o = DoeIrqSupport; - assign doe_intr_o = reg2hw.sys_status.doe_intr_status.q; + assign doe_intr_o = reg2hw.soc_status.doe_intr_status.q; // Control register - assign sysif_control_abort_set_o = reg2hw.sys_control.abort.qe & reg2hw.sys_control.abort.q; - assign hw2reg.sys_control.abort.d = 1'b0; + assign sysif_control_abort_set_o = reg2hw.soc_control.abort.qe & reg2hw.soc_control.abort.q; + assign hw2reg.soc_control.abort.d = 1'b0; - assign sysif_control_go_set_o = reg2hw.sys_control.go.qe & reg2hw.sys_control.go.q; - assign hw2reg.sys_control.go.d = 1'b0; + assign sysif_control_go_set_o = reg2hw.soc_control.go.qe & reg2hw.soc_control.go.q; + assign hw2reg.soc_control.go.d = 1'b0; // Manual implementation of the doe_intr_en bit // SWAccess: RW @@ -85,44 +85,44 @@ module mbx_sysif .DW (1), .SwAccess(prim_subreg_pkg::SwAccessRW), .RESVAL (1'h0) - ) u_sys_control_doe_intr_en ( + ) u_soc_control_doe_intr_en ( .clk_i (clk_i), .rst_ni (rst_ni), // from register interface - .we (reg2hw.sys_control.doe_intr_en.qe), - .wd (reg2hw.sys_control.doe_intr_en.q), + .we (reg2hw.soc_control.doe_intr_en.qe), + .wd (reg2hw.soc_control.doe_intr_en.q), // HWAccess: hro .de (1'b0), .d (1'b0), // to internal hardware .qe (), .q (doe_intr_en_o), - .ds (hw2reg.sys_control.doe_intr_en.d), + .ds (hw2reg.soc_control.doe_intr_en.d), .qs () ); // Fiddle out status register bits for external write logic - assign sysif_status_doe_intr_status_o = reg2hw.sys_status.doe_intr_status.q; - assign sysif_status_busy_o = reg2hw.sys_status.busy.q; - assign sysif_status_error_o = reg2hw.sys_status.error.q; + assign sysif_status_doe_intr_status_o = reg2hw.soc_status.doe_intr_status.q; + assign sysif_status_busy_o = reg2hw.soc_status.busy.q; + assign sysif_status_error_o = reg2hw.soc_status.error.q; // External read logic - assign hw2reg.sys_status.busy.de = sysif_status_busy_valid_i; - assign hw2reg.sys_status.busy.d = sysif_status_busy_i; + assign hw2reg.soc_status.busy.de = sysif_status_busy_valid_i; + assign hw2reg.soc_status.busy.d = sysif_status_busy_i; // Set by the outbound handler if the DOE interrupt is enabled. Setting this bit creates a DOE // interrupt to the system side. - // Cleared by the Sys firmware (w1c) - assign hw2reg.sys_status.doe_intr_status.de = sysif_status_doe_intr_status_set_i & doe_intr_en_o; - assign hw2reg.sys_status.doe_intr_status.d = sysif_status_doe_intr_status_set_i; + // Cleared by SoC firmware (w1c) + assign hw2reg.soc_status.doe_intr_status.de = sysif_status_doe_intr_status_set_i & doe_intr_en_o; + assign hw2reg.soc_status.doe_intr_status.d = sysif_status_doe_intr_status_set_i; - assign hw2reg.sys_status.error.de = sysif_status_error_set_i | sysif_status_error_clear_i; - assign hw2reg.sys_status.error.d = sysif_status_error_set_i; + assign hw2reg.soc_status.error.de = sysif_status_error_set_i | sysif_status_error_clear_i; + assign hw2reg.soc_status.error.d = sysif_status_error_set_i; // Set by OT firmware (w1s) - // Cleared by the Sys firmware (w1c) - assign hw2reg.sys_status.ready.de = sysif_status_ready_valid_i; - assign hw2reg.sys_status.ready.d = sysif_status_ready_i; + // Cleared by SoC firmware (w1c) + assign hw2reg.soc_status.ready.de = sysif_status_ready_valid_i; + assign hw2reg.soc_status.ready.d = sysif_status_ready_i; // Dedicated TLUL adapter for implementing the write data mailbox register via a register window. // We use the register window to access the internal bus signals, allowing the mailbox to halt @@ -130,7 +130,7 @@ module mbx_sysif logic reg_wdata_we; logic [top_pkg::TL_DW-1:0] reg_wdata_wdata; tlul_adapter_reg #( - .RegAw ( SysAw ), + .RegAw ( SocAw ), .RegDw ( top_pkg::TL_DW ), .EnableDataIntgGen ( 0 ) ) u_wdata_reg_if ( @@ -156,7 +156,7 @@ module mbx_sysif // the bus if there are too many outstanding requests. The register is implemented as hwext // outside of this hierarchy tlul_adapter_reg #( - .RegAw ( SysAw ), + .RegAw ( SocAw ), .RegDw ( top_pkg::TL_DW ), .EnableDataIntgGen ( 0 ) ) u_rdata_reg_if ( @@ -218,8 +218,8 @@ module mbx_sysif ); // Forward IRQ addr and data register to the host interface - assign sysif_intr_msg_addr_o = reg2hw.sys_doe_intr_msg_addr.q; - assign sysif_intr_msg_data_o = reg2hw.sys_doe_intr_msg_data.q; + assign sysif_intr_msg_addr_o = reg2hw.soc_doe_intr_msg_addr.q; + assign sysif_intr_msg_data_o = reg2hw.soc_doe_intr_msg_data.q; // Assertions `ASSERT(DataWidthCheck_A, CfgSramDataWidth == top_pkg::TL_DW) From 671b1ca939f4b339f1e6f24441978851bcd87239 Mon Sep 17 00:00:00 2001 From: Andreas Kurth Date: Tue, 19 Sep 2023 10:43:28 +0000 Subject: [PATCH 27/88] [mbx/rtl] Fix signal names of TL-UL `sram` ports Signed-off-by: Andreas Kurth --- hw/ip/mbx/rtl/mbx.sv | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/ip/mbx/rtl/mbx.sv b/hw/ip/mbx/rtl/mbx.sv index 8e339a79b5fa0..e22bb4ccdec03 100644 --- a/hw/ip/mbx/rtl/mbx.sv +++ b/hw/ip/mbx/rtl/mbx.sv @@ -33,8 +33,8 @@ module mbx input tlul_pkg::tl_h2d_t soc_tl_d_i, output tlul_pkg::tl_d2h_t soc_tl_d_o, // Host port to access private SRAM - input tlul_pkg::tl_d2h_t tl_sram_i, - output tlul_pkg::tl_h2d_t tl_sram_o + input tlul_pkg::tl_d2h_t sram_tl_h_i, + output tlul_pkg::tl_h2d_t sram_tl_h_o ); ////////////////////////////////////////////////////////////////////////////// // General signals for the mailbox @@ -286,8 +286,8 @@ module mbx ) u_sramrwarb ( .clk_i ( clk_i ), .rst_ni ( rst_ni ), - .tl_host_o ( tl_sram_o ), - .tl_host_i ( tl_sram_i ), + .tl_host_o ( sram_tl_h_o ), + .tl_host_i ( sram_tl_h_i ), .intg_err_o ( tl_sram_intg_err ), .sram_err_o ( sram_err ), // Interface to the inbound mailbox From 5ef9a7199cae6b728de5b93e5e8dfc69cd08f25c Mon Sep 17 00:00:00 2001 From: Andreas Kurth Date: Tue, 19 Sep 2023 14:10:46 +0000 Subject: [PATCH 28/88] [mbx/rtl] Add missing reg WE onehot check assertion Signed-off-by: Andreas Kurth --- hw/ip/mbx/rtl/mbx.sv | 4 ++++ hw/ip/mbx/rtl/mbx_hostif.sv | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/hw/ip/mbx/rtl/mbx.sv b/hw/ip/mbx/rtl/mbx.sv index e22bb4ccdec03..b44265b5c4b2c 100644 --- a/hw/ip/mbx/rtl/mbx.sv +++ b/hw/ip/mbx/rtl/mbx.sv @@ -304,4 +304,8 @@ module mbx .ombx_sram_read_resp_o ( ombx_sram_read_data ) ); + // Assertions + `ASSERT_PRIM_REG_WE_ONEHOT_ERROR_TRIGGER_ALERT(RegWeOnehotCheck_A, + u_sysif.u_soc_regs, + alert_tx_o[0]) endmodule diff --git a/hw/ip/mbx/rtl/mbx_hostif.sv b/hw/ip/mbx/rtl/mbx_hostif.sv index af4d29b645194..4ab481f0b475f 100644 --- a/hw/ip/mbx/rtl/mbx_hostif.sv +++ b/hw/ip/mbx/rtl/mbx_hostif.sv @@ -197,4 +197,9 @@ module mbx_hostif // Alias of the IRQ addr and data register from the sys interface (RO) assign hw2reg.doe_intr_msg_addr.d = sysif_intr_msg_addr_i; assign hw2reg.doe_intr_msg_data.d = sysif_intr_msg_data_i; + + // Assertions + `ASSERT_PRIM_REG_WE_ONEHOT_ERROR_TRIGGER_ALERT(RegWeOnehotCheck_A, + u_regs, + alert_tx_o[0]) endmodule From 376088cf099d5d4019eac5ac370b45200ff20d34 Mon Sep 17 00:00:00 2001 From: Andreas Kurth Date: Wed, 20 Sep 2023 10:20:02 +0000 Subject: [PATCH 29/88] [mbx/rtl] Add missing connections to/from `mbx_soc_reg_top` Signed-off-by: Andreas Kurth --- hw/ip/mbx/rtl/mbx_sysif.sv | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/ip/mbx/rtl/mbx_sysif.sv b/hw/ip/mbx/rtl/mbx_sysif.sv index 8d198dc522465..35b172a97a535 100644 --- a/hw/ip/mbx/rtl/mbx_sysif.sv +++ b/hw/ip/mbx/rtl/mbx_sysif.sv @@ -64,6 +64,8 @@ module mbx_sysif .tl_o ( tl_sys_o ), .tl_win_o ( tl_win_h2d ), .tl_win_i ( tl_win_d2h ), + .reg2hw ( reg2hw ), + .hw2reg ( hw2reg ), .intg_err_o ( intg_err_o ), .devmode_i ( 1'b1 ) ); From 04589fe448649177b83de1317301fe07acc55555 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Mon, 18 Sep 2023 10:35:04 -0700 Subject: [PATCH 30/88] [hw,mbx,rtl] Move error bit from HOST.STATUS to HOST.CONTROL Signed-off-by: Robert Schilling --- hw/ip/mbx/data/mbx.hjson | 20 ++++++++------ hw/ip/mbx/rtl/mbx.sv | 32 ++++++++++----------- hw/ip/mbx/rtl/mbx_core_reg_top.sv | 46 +++++++++++++++---------------- hw/ip/mbx/rtl/mbx_fsm.sv | 8 +++--- hw/ip/mbx/rtl/mbx_hostif.sv | 14 ++++++---- hw/ip/mbx/rtl/mbx_imbx.sv | 8 +++--- hw/ip/mbx/rtl/mbx_ombx.sv | 6 ++-- hw/ip/mbx/rtl/mbx_reg_pkg.sv | 28 +++++++++---------- hw/ip/mbx/rtl/mbx_sysif.sv | 4 +-- 9 files changed, 85 insertions(+), 81 deletions(-) diff --git a/hw/ip/mbx/data/mbx.hjson b/hw/ip/mbx/data/mbx.hjson index f0fcf7d980b72..378340a4202bc 100644 --- a/hw/ip/mbx/data/mbx.hjson +++ b/hw/ip/mbx/data/mbx.hjson @@ -93,6 +93,18 @@ hwaccess: "hrw" hwqe: "true" } + { name: "error" + desc: ''' + Set by firmware to signal an error, i.e., unable to provide a response to request. + Set by hardware, on SYS.WDATA or SYS.RDATA performing an invalid access. + Cleared by the hardware when SYS sets CONTROL.ABORT. + ''' + bits: "2" + resval: "0x0" + swaccess: "rw" + hwaccess: "hrw" + hwqe: "true" + } ] } { name: "STATUS" @@ -115,14 +127,6 @@ hwaccess: "hrw" hwqe: "true" } - { name: "error" - desc: "Alias of the DoE mailbox error bit" - bits: "2" - resval: "0x0" - swaccess: "rw" - hwaccess: "hrw" - hwqe: "true" - } ] } { name: "ADDRESS_RANGE_REGWEN" diff --git a/hw/ip/mbx/rtl/mbx.sv b/hw/ip/mbx/rtl/mbx.sv index b44265b5c4b2c..163a8d0deaf49 100644 --- a/hw/ip/mbx/rtl/mbx.sv +++ b/hw/ip/mbx/rtl/mbx.sv @@ -61,8 +61,8 @@ module mbx logic sysif_status_busy, sysif_status_doe_intr_status, sysif_status_error; // Setter signals from the hostif to the sysif - logic hostif_control_abort_clear, hostif_status_busy_clear, - hostif_status_error_set, hostif_status_error_clear; + logic hostif_status_doe_intr_status_set, hostif_status_busy_clear, + hostif_control_abort_clear, hostif_control_error_set; // Alias signals from the sys interface logic [CfgSramAddrWidth-1:0] sysif_intr_msg_addr; @@ -106,13 +106,12 @@ module mbx .alert_tx_o ( alert_tx_o ), // Access to the control register .hostif_control_abort_clear_o ( hostif_control_abort_clear ), + .hostif_control_error_set_o ( hostif_control_error_set ), + .hostif_control_error_i ( sysif_status_error ), // Access to the status register .hostif_status_busy_clear_o ( hostif_status_busy_clear ), .hostif_status_busy_i ( sysif_status_busy ), .hostif_status_doe_intr_status_i ( sysif_status_doe_intr_status ), - .hostif_status_error_set_o ( hostif_status_error_set ), - .hostif_status_error_clear_o ( hostif_status_error_clear ), - .hostif_status_error_i ( sysif_status_error ), // Access to the IB/OB RD/WR Pointers .hostif_imbx_write_ptr_i ( imbx_sram_write_ptr ), .hostif_ombx_read_ptr_i ( ombx_sram_read_ptr ), @@ -187,8 +186,7 @@ module mbx .sysif_status_busy_o ( sysif_status_busy ), .sysif_status_doe_intr_status_set_i ( ombx_doe_intr_status_set ), .sysif_status_doe_intr_status_o ( sysif_status_doe_intr_status ), - .sysif_status_error_set_i ( hostif_status_error_set ), - .sysif_status_error_clear_i ( hostif_status_error_clear ), + .sysif_status_error_set_i ( hostif_control_error_set ), .sysif_status_error_o ( sysif_status_error ), .sysif_status_ready_valid_i ( ombx_status_ready_valid ), .sysif_status_ready_i ( ombx_status_ready ), @@ -211,18 +209,18 @@ module mbx .CfgSramAddrWidth( CfgSramAddrWidth ), .CfgSramDataWidth( CfgSramDataWidth ) ) u_imbx ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), // Interface to the host port - .imbx_state_error_o ( imbx_state_error ), - .imbx_pending_o ( imbx_pending ), - .imbx_irq_ready_o ( hostif_event_intr_ready ), - .imbx_irq_abort_o ( hostif_event_intr_abort ), - .imbx_status_busy_update_o ( imbx_status_busy_valid ), - .imbx_status_busy_o ( imbx_status_busy ), + .imbx_state_error_o ( imbx_state_error ), + .imbx_pending_o ( imbx_pending ), + .imbx_irq_ready_o ( hostif_event_intr_ready ), + .imbx_irq_abort_o ( hostif_event_intr_abort ), + .imbx_status_busy_update_o ( imbx_status_busy_valid ), + .imbx_status_busy_o ( imbx_status_busy ), .hostif_control_abort_clear_i( hostif_control_abort_clear ), + .hostif_control_error_set_i ( hostif_control_error_set ), .hostif_status_busy_clear_i ( hostif_status_busy_clear ), - .hostif_status_error_set_i ( hostif_status_error_set ), // SRAM range configuration .hostif_range_valid_i ( hostif_address_range_valid ), .hostif_base_i ( hostif_imbx_base ), @@ -259,7 +257,7 @@ module mbx // Control signals from the host and system interface // Writing a 1 to control.abort register clears the abort condition .hostif_control_abort_clear_i ( hostif_control_abort_clear ), - .hostif_status_error_set_i ( hostif_status_error_set ), + .hostif_control_error_set_i ( hostif_control_error_set ), .sysif_control_abort_set_i ( sysif_control_abort_set ), .sysif_read_data_read_valid_i ( sysif_read_data_read_valid ), .sysif_read_data_write_valid_i ( sysif_read_data_write_valid ), diff --git a/hw/ip/mbx/rtl/mbx_core_reg_top.sv b/hw/ip/mbx/rtl/mbx_core_reg_top.sv index 9287f2a60891c..aab1f90e84a65 100644 --- a/hw/ip/mbx/rtl/mbx_core_reg_top.sv +++ b/hw/ip/mbx/rtl/mbx_core_reg_top.sv @@ -143,14 +143,14 @@ module mbx_core_reg_top ( logic control_abort_wd; logic control_doe_intr_en_qs; logic control_doe_intr_en_wd; + logic control_error_qs; + logic control_error_wd; logic status_re; logic status_we; logic status_busy_qs; logic status_busy_wd; logic status_doe_intr_status_qs; logic status_doe_intr_status_wd; - logic status_error_qs; - logic status_error_wd; logic address_range_regwen_we; logic [3:0] address_range_regwen_qs; logic [3:0] address_range_regwen_wd; @@ -370,7 +370,7 @@ module mbx_core_reg_top ( // R[control]: V(True) logic control_qe; - logic [1:0] control_flds_we; + logic [2:0] control_flds_we; assign control_qe = &control_flds_we; // F[abort]: 0:0 prim_subreg_ext #( @@ -404,10 +404,26 @@ module mbx_core_reg_top ( ); assign reg2hw.control.doe_intr_en.qe = control_qe; + // F[error]: 2:2 + prim_subreg_ext #( + .DW (1) + ) u_control_error ( + .re (control_re), + .we (control_we), + .wd (control_error_wd), + .d (hw2reg.control.error.d), + .qre (), + .qe (control_flds_we[2]), + .q (reg2hw.control.error.q), + .ds (), + .qs (control_error_qs) + ); + assign reg2hw.control.error.qe = control_qe; + // R[status]: V(True) logic status_qe; - logic [2:0] status_flds_we; + logic [1:0] status_flds_we; assign status_qe = &status_flds_we; // F[busy]: 0:0 prim_subreg_ext #( @@ -441,22 +457,6 @@ module mbx_core_reg_top ( ); assign reg2hw.status.doe_intr_status.qe = status_qe; - // F[error]: 2:2 - prim_subreg_ext #( - .DW (1) - ) u_status_error ( - .re (status_re), - .we (status_we), - .wd (status_error_wd), - .d (hw2reg.status.error.d), - .qre (), - .qe (status_flds_we[2]), - .q (reg2hw.status.error.q), - .ds (), - .qs (status_error_qs) - ); - assign reg2hw.status.error.qe = status_qe; - // R[address_range_regwen]: V(False) prim_subreg #( @@ -882,14 +882,14 @@ module mbx_core_reg_top ( assign control_abort_wd = reg_wdata[0]; assign control_doe_intr_en_wd = reg_wdata[1]; + + assign control_error_wd = reg_wdata[2]; assign status_re = addr_hit[5] & reg_re & !reg_error; assign status_we = addr_hit[5] & reg_we & !reg_error; assign status_busy_wd = reg_wdata[0]; assign status_doe_intr_status_wd = reg_wdata[1]; - - assign status_error_wd = reg_wdata[2]; assign address_range_regwen_we = addr_hit[6] & reg_we & !reg_error; assign address_range_regwen_wd = reg_wdata[3:0]; @@ -965,12 +965,12 @@ module mbx_core_reg_top ( addr_hit[4]: begin reg_rdata_next[0] = control_abort_qs; reg_rdata_next[1] = control_doe_intr_en_qs; + reg_rdata_next[2] = control_error_qs; end addr_hit[5]: begin reg_rdata_next[0] = status_busy_qs; reg_rdata_next[1] = status_doe_intr_status_qs; - reg_rdata_next[2] = status_error_qs; end addr_hit[6]: begin diff --git a/hw/ip/mbx/rtl/mbx_fsm.sv b/hw/ip/mbx/rtl/mbx_fsm.sv index 0f0c70c3d245e..86d56d1ebb36b 100644 --- a/hw/ip/mbx/rtl/mbx_fsm.sv +++ b/hw/ip/mbx/rtl/mbx_fsm.sv @@ -12,8 +12,8 @@ module mbx_fsm #( // Control input signals input logic mbx_range_valid_i, input logic hostif_abort_ack_i, - input logic hostif_status_error_set_i, input logic hostif_status_busy_clear_i, + input logic hostif_control_error_set_i, input logic sysif_control_abort_set_i, input logic sys_read_all_i, input logic writer_write_valid_i, @@ -68,7 +68,7 @@ module mbx_fsm #( // MbxRead is a common state for imbx and ombx // Exit of MbxRead is used to clear imbx.Busy and ombx.Ready - assign ombx_clear_ready = CfgOmbx & (hostif_status_error_set_i | + assign ombx_clear_ready = CfgOmbx & (hostif_control_error_set_i | sysif_control_abort_set_i | mbx_read_o & sys_read_all_i); @@ -100,7 +100,7 @@ module mbx_fsm #( // Inbound mailbox being written by the system = writer // Outbound mailbox: not applicable MbxWrite: begin - if (hostif_status_error_set_i) begin // Host asserts an error + if (hostif_control_error_set_i) begin // Host asserts an error ctrl_state_d = MbxIdle; end else if (sysif_control_abort_set_i) begin // System wants to abort ctrl_state_d = MbxSysAbortHost; @@ -112,7 +112,7 @@ module mbx_fsm #( // Inbound mailbox being read by the reader = host // Outbound mailbox being read by the reader = system MbxRead: begin - if (hostif_status_error_set_i) begin // Host asserts an error + if (hostif_control_error_set_i) begin // Host asserts an error ctrl_state_d = MbxIdle; end else if (sysif_control_abort_set_i) begin // System wants to abort ctrl_state_d = MbxSysAbortHost; diff --git a/hw/ip/mbx/rtl/mbx_hostif.sv b/hw/ip/mbx/rtl/mbx_hostif.sv index 4ab481f0b475f..dfd370d5dfb48 100644 --- a/hw/ip/mbx/rtl/mbx_hostif.sv +++ b/hw/ip/mbx/rtl/mbx_hostif.sv @@ -29,13 +29,13 @@ module mbx_hostif // Access to the control register // Writing a 1 to control.abort register clears the abort condition output logic hostif_control_abort_clear_o, + output logic hostif_control_error_set_o, + input logic hostif_control_error_i, // Access to the status register output logic hostif_status_busy_clear_o, - output logic hostif_status_error_set_o, - output logic hostif_status_error_clear_o, + output logic hostif_status_doe_intr_status_set_o, input logic hostif_status_busy_i, input logic hostif_status_doe_intr_status_i, - input logic hostif_status_error_i, // Access to the IB/OB RD/WR pointers input logic [CfgSramAddrWidth-1:0] hostif_imbx_write_ptr_i, input logic [CfgSramAddrWidth-1:0] hostif_ombx_read_ptr_i, @@ -158,6 +158,9 @@ module mbx_hostif .q_o ( abort_q ) ); + assign hostif_control_error_set_o = reg2hw.control.error.qe & reg2hw.control.error.q; + assign hw2reg.control.error.d = hostif_control_error_i; + // Status Register // It is implemented as hwext and implemented in a different hierarchy and only providing an // alias. Thus manually assigning the external signals @@ -165,11 +168,10 @@ module mbx_hostif // External read logic assign hw2reg.status.busy.d = hostif_status_busy_i; assign hw2reg.status.doe_intr_status.d = hostif_status_doe_intr_status_i; - assign hw2reg.status.error.d = hostif_status_error_i; // External write logic assign hostif_status_busy_clear_o = reg2hw.status.busy.qe & ~reg2hw.status.busy.q; - assign hostif_status_error_set_o = reg2hw.status.error.qe & reg2hw.status.error.q; - assign hostif_status_error_clear_o = reg2hw.status.error.qe & ~reg2hw.status.error.q; + assign hostif_status_doe_intr_status_set_o = reg2hw.status.doe_intr_status.qe & + reg2hw.status.doe_intr_status.q; // Address config valid assign hostif_address_range_valid_o = reg2hw.address_range_valid.q; diff --git a/hw/ip/mbx/rtl/mbx_imbx.sv b/hw/ip/mbx/rtl/mbx_imbx.sv index dca8786ba63c0..28dcc59fd1a3b 100644 --- a/hw/ip/mbx/rtl/mbx_imbx.sv +++ b/hw/ip/mbx/rtl/mbx_imbx.sv @@ -19,8 +19,8 @@ module mbx_imbx #( // Access to the control and status registers of host interface // Writing a 1 to control.abort register clears the abort condition input logic hostif_control_abort_clear_i, + input logic hostif_control_error_set_i, input logic hostif_status_busy_clear_i, - input logic hostif_status_error_set_i, // Range configuration for the private SRAM input logic hostif_range_valid_i, input logic [CfgSramAddrWidth-1:0] hostif_base_i, @@ -115,13 +115,13 @@ module mbx_imbx #( logic imbx_set_busy, imbx_clear_busy; assign imbx_set_busy = (mbx_write & sysif_control_go_set_i & - ~hostif_status_error_set_i & + ~hostif_control_error_set_i & ~sysif_control_abort_set_i) | sysif_control_abort_set_i; // Exit of mailbox read is used to clear imbx.busy and imbx.ready // Not yet qualified with mbx_read - assign imbx_clear_busy = hostif_status_error_set_i | + assign imbx_clear_busy = hostif_control_error_set_i | sysif_control_abort_set_i | hostif_status_busy_clear_i; @@ -142,8 +142,8 @@ module mbx_imbx #( .rst_ni ( rst_ni ), .mbx_range_valid_i ( hostif_range_valid_i ), .hostif_abort_ack_i ( hostif_control_abort_clear_i ), - .hostif_status_error_set_i ( hostif_status_error_set_i ), .hostif_status_busy_clear_i( hostif_status_busy_clear_i ), + .hostif_control_error_set_i( hostif_control_error_set_i ), .sysif_control_abort_set_i ( sysif_control_abort_set_i ), .sys_read_all_i ( 1'b0 ), .writer_close_mbx_i ( sysif_control_go_set_i ), diff --git a/hw/ip/mbx/rtl/mbx_ombx.sv b/hw/ip/mbx/rtl/mbx_ombx.sv index 8084c25cab32b..97296d59a73b4 100644 --- a/hw/ip/mbx/rtl/mbx_ombx.sv +++ b/hw/ip/mbx/rtl/mbx_ombx.sv @@ -22,7 +22,7 @@ module mbx_ombx #( // Control signals from the host and system interface // Writing a 1 to control.abort register clears the abort condition input logic hostif_control_abort_clear_i, - input logic hostif_status_error_set_i, + input logic hostif_control_error_set_i, input logic sysif_status_ready_i, input logic sysif_control_abort_set_i, input logic sysif_read_data_read_valid_i, @@ -142,7 +142,7 @@ module mbx_ombx #( // or the requester aborts the transaction logic clear_read_data; assign clear_read_data = sys_read_all | - hostif_status_error_set_i | + hostif_control_error_set_i | sysif_control_abort_set_i; // Advance the SRAM read response to read data prim_generic_flop_en #( @@ -234,8 +234,8 @@ module mbx_ombx #( .rst_ni ( rst_ni ), .mbx_range_valid_i ( hostif_range_valid_i ), .hostif_abort_ack_i ( hostif_control_abort_clear_i ), - .hostif_status_error_set_i ( hostif_status_error_set_i ), .hostif_status_busy_clear_i( 1'b0 ), + .hostif_control_error_set_i( hostif_control_error_set_i ), .sysif_control_abort_set_i ( sysif_control_abort_set_i ), .sys_read_all_i ( sys_read_all ), .writer_close_mbx_i ( writer_close_mbx ), diff --git a/hw/ip/mbx/rtl/mbx_reg_pkg.sv b/hw/ip/mbx/rtl/mbx_reg_pkg.sv index 7aa87d6d4ac5e..139ef56dacd78 100644 --- a/hw/ip/mbx/rtl/mbx_reg_pkg.sv +++ b/hw/ip/mbx/rtl/mbx_reg_pkg.sv @@ -58,6 +58,10 @@ package mbx_reg_pkg; } mbx_reg2hw_alert_test_reg_t; typedef struct packed { + struct packed { + logic q; + logic qe; + } error; struct packed { logic q; logic qe; @@ -69,10 +73,6 @@ package mbx_reg_pkg; } mbx_reg2hw_control_reg_t; typedef struct packed { - struct packed { - logic q; - logic qe; - } error; struct packed { logic q; logic qe; @@ -152,6 +152,9 @@ package mbx_reg_pkg; struct packed { logic d; } doe_intr_en; + struct packed { + logic d; + } error; } mbx_hw2reg_control_reg_t; typedef struct packed { @@ -161,9 +164,6 @@ package mbx_reg_pkg; struct packed { logic d; } doe_intr_status; - struct packed { - logic d; - } error; } mbx_hw2reg_status_reg_t; typedef struct packed { @@ -193,8 +193,8 @@ package mbx_reg_pkg; mbx_reg2hw_intr_enable_reg_t intr_enable; // [286:285] mbx_reg2hw_intr_test_reg_t intr_test; // [284:281] mbx_reg2hw_alert_test_reg_t alert_test; // [280:277] - mbx_reg2hw_control_reg_t control; // [276:273] - mbx_reg2hw_status_reg_t status; // [272:267] + mbx_reg2hw_control_reg_t control; // [276:271] + mbx_reg2hw_status_reg_t status; // [270:267] mbx_reg2hw_address_range_regwen_reg_t address_range_regwen; // [266:263] mbx_reg2hw_address_range_valid_reg_t address_range_valid; // [262:262] mbx_reg2hw_inbound_base_address_reg_t inbound_base_address; // [261:231] @@ -211,8 +211,8 @@ package mbx_reg_pkg; // HW -> register type for core interface typedef struct packed { mbx_hw2reg_intr_state_reg_t intr_state; // [144:141] - mbx_hw2reg_control_reg_t control; // [140:139] - mbx_hw2reg_status_reg_t status; // [138:136] + mbx_hw2reg_control_reg_t control; // [140:138] + mbx_hw2reg_status_reg_t status; // [137:136] mbx_hw2reg_inbound_write_ptr_reg_t inbound_write_ptr; // [135:106] mbx_hw2reg_outbound_read_ptr_reg_t outbound_read_ptr; // [105:76] mbx_hw2reg_outbound_object_size_reg_t outbound_object_size; // [75:64] @@ -246,13 +246,13 @@ package mbx_reg_pkg; parameter logic [1:0] MBX_ALERT_TEST_RESVAL = 2'h 0; parameter logic [0:0] MBX_ALERT_TEST_FATAL_FAULT_RESVAL = 1'h 0; parameter logic [0:0] MBX_ALERT_TEST_RECOV_FAULT_RESVAL = 1'h 0; - parameter logic [1:0] MBX_CONTROL_RESVAL = 2'h 0; + parameter logic [2:0] MBX_CONTROL_RESVAL = 3'h 0; parameter logic [0:0] MBX_CONTROL_ABORT_RESVAL = 1'h 0; parameter logic [0:0] MBX_CONTROL_DOE_INTR_EN_RESVAL = 1'h 0; - parameter logic [2:0] MBX_STATUS_RESVAL = 3'h 1; + parameter logic [0:0] MBX_CONTROL_ERROR_RESVAL = 1'h 0; + parameter logic [1:0] MBX_STATUS_RESVAL = 2'h 1; parameter logic [0:0] MBX_STATUS_BUSY_RESVAL = 1'h 1; parameter logic [0:0] MBX_STATUS_DOE_INTR_STATUS_RESVAL = 1'h 0; - parameter logic [0:0] MBX_STATUS_ERROR_RESVAL = 1'h 0; parameter logic [31:0] MBX_INBOUND_WRITE_PTR_RESVAL = 32'h 0; parameter logic [29:0] MBX_INBOUND_WRITE_PTR_INBOUND_READ_PTR_RESVAL = 30'h 0; parameter logic [31:0] MBX_OUTBOUND_READ_PTR_RESVAL = 32'h 0; diff --git a/hw/ip/mbx/rtl/mbx_sysif.sv b/hw/ip/mbx/rtl/mbx_sysif.sv index 35b172a97a535..22e2997aeaf2f 100644 --- a/hw/ip/mbx/rtl/mbx_sysif.sv +++ b/hw/ip/mbx/rtl/mbx_sysif.sv @@ -30,7 +30,6 @@ module mbx_sysif input logic sysif_status_doe_intr_status_set_i, output logic sysif_status_doe_intr_status_o, input logic sysif_status_error_set_i, - input logic sysif_status_error_clear_i, output logic sysif_status_error_o, input logic sysif_status_ready_valid_i, input logic sysif_status_ready_i, @@ -118,7 +117,8 @@ module mbx_sysif assign hw2reg.soc_status.doe_intr_status.de = sysif_status_doe_intr_status_set_i & doe_intr_en_o; assign hw2reg.soc_status.doe_intr_status.d = sysif_status_doe_intr_status_set_i; - assign hw2reg.soc_status.error.de = sysif_status_error_set_i | sysif_status_error_clear_i; + // Error is cleared when writing the abort bit + assign hw2reg.soc_status.error.de = sysif_status_error_set_i | sysif_control_abort_set_o; assign hw2reg.soc_status.error.d = sysif_status_error_set_i; // Set by OT firmware (w1s) From 762c39badb2a3a4e1d5ce13b4ff00ac3752ba03d Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Mon, 18 Sep 2023 13:02:12 -0700 Subject: [PATCH 31/88] [hw,mbx,rtl] Invalid range config sets busy Signed-off-by: Robert Schilling --- hw/ip/mbx/rtl/mbx_imbx.sv | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/ip/mbx/rtl/mbx_imbx.sv b/hw/ip/mbx/rtl/mbx_imbx.sv index 28dcc59fd1a3b..4953ee28215cd 100644 --- a/hw/ip/mbx/rtl/mbx_imbx.sv +++ b/hw/ip/mbx/rtl/mbx_imbx.sv @@ -117,7 +117,8 @@ module mbx_imbx #( sysif_control_go_set_i & ~hostif_control_error_set_i & ~sysif_control_abort_set_i) | - sysif_control_abort_set_i; + sysif_control_abort_set_i | + ~hostif_range_valid_i; // Exit of mailbox read is used to clear imbx.busy and imbx.ready // Not yet qualified with mbx_read From f34afd0429f823628db5ba3a96c07971b6a0dbbc Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Wed, 20 Sep 2023 00:54:53 -0700 Subject: [PATCH 32/88] [hw,mbx,rtl] Make registers explicitly read-only in hardware Signed-off-by: Robert Schilling --- hw/ip/mbx/data/mbx.hjson | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/hw/ip/mbx/data/mbx.hjson b/hw/ip/mbx/data/mbx.hjson index 378340a4202bc..af21486d2da6e 100644 --- a/hw/ip/mbx/data/mbx.hjson +++ b/hw/ip/mbx/data/mbx.hjson @@ -132,6 +132,7 @@ { name: "ADDRESS_RANGE_REGWEN" desc: "Used to lock the inbound/outbound base/limit configuration registers." swaccess: "rw0c" + hwaccess: "hro" fields: [ { name: "regwen" desc: ''' @@ -162,13 +163,14 @@ This address is 4-byte aligned, the lower 2-bits are ignored. ''' regwen: "ADDRESS_RANGE_REGWEN" + swaccess: "rw" + hwaccess: "hro" + hwqe: "true" fields: [ { name: "base_address" desc: "Base address of SRAM region, which is used to back up the inbound mailbox data." bits: "31:2" resval: "0x0" - swaccess: "rw" - hwqe: "true" } ] } @@ -178,13 +180,14 @@ This address is 4-byte aligned, the lower 2-bits are ignored. ''' regwen: "ADDRESS_RANGE_REGWEN" + swaccess: "rw" + hwaccess: "hro" + hwqe: "true" fields: [ { name: "limit" desc: "Limit Address to mark the end of the inbound mailbox memory range in the private SRAM." bits: "31:2" resval: "0x0" - swaccess: "rw" - hwqe: "true" } ] } @@ -209,13 +212,14 @@ This address is 4-byte aligned, the lower 2-bits are ignored. ''' regwen: "ADDRESS_RANGE_REGWEN" + swaccess: "rw" + hwaccess: "hro" + hwqe: "true" fields: [ { name: "base_address" desc: "Base address of SRAM region, which is used to buffer the outbound mailbox data." bits: "31:2" resval: "0x0" - swaccess: "rw" - hwqe: "true" } ] } @@ -224,13 +228,14 @@ This address is 4-byte aligned, the lower 2-bits are ignored. ''' regwen: "ADDRESS_RANGE_REGWEN" + swaccess: "rw" + hwaccess: "hro" + hwqe: "true" fields: [ { name: "limit" desc: "Limit Address to mark the end of the outbound mailbox memory range in the private SRAM." bits: "31:2" resval: "0x0" - swaccess: "rw" - hwqe: "true" } ] } From a860c072c86dedf716acb52ad034c068c6c67812 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Wed, 20 Sep 2023 05:49:13 -0700 Subject: [PATCH 33/88] [hw,mbx,rtl] More concise register definition Signed-off-by: Robert Schilling --- hw/ip/mbx/data/mbx.hjson | 46 +++++-------- hw/ip/mbx/lint/mbx.waiver | 25 ++++++- hw/ip/mbx/rtl/mbx.sv | 14 ++-- hw/ip/mbx/rtl/mbx_core_reg_top.sv | 110 +++++++----------------------- hw/ip/mbx/rtl/mbx_hostif.sv | 13 ++-- hw/ip/mbx/rtl/mbx_reg_pkg.sv | 77 +++++---------------- hw/ip/mbx/rtl/mbx_soc_reg_top.sv | 62 ++++------------- hw/ip/mbx/rtl/mbx_sysif.sv | 6 +- 8 files changed, 109 insertions(+), 244 deletions(-) diff --git a/hw/ip/mbx/data/mbx.hjson b/hw/ip/mbx/data/mbx.hjson index af21486d2da6e..69bc0d28fe4df 100644 --- a/hw/ip/mbx/data/mbx.hjson +++ b/hw/ip/mbx/data/mbx.hjson @@ -89,9 +89,8 @@ desc: "Alias of the DoE mailbox interrupt enable bit" bits: "1" resval: "0x0" - swaccess: "rw" - hwaccess: "hrw" - hwqe: "true" + swaccess: "ro" + hwaccess: "hwo" } { name: "error" desc: ''' @@ -110,6 +109,7 @@ { name: "STATUS" desc: "DOE mailbox status register visible to OpenTitan" hwext: "true" + hwqe: "true" fields: [ { name: "busy" desc: "Alias of the DoE mailbox busy bit" @@ -117,22 +117,20 @@ resval: "0x1" swaccess: "rw" hwaccess: "hrw" - hwqe: "true" } { name: "doe_intr_status" desc: "Alias of the DoE mailbox interrupt status bit" bits: "1" resval: "0x0" - swaccess: "rw" - hwaccess: "hrw" - hwqe: "true" + swaccess: "ro" + hwaccess: "hwo" } ] } { name: "ADDRESS_RANGE_REGWEN" desc: "Used to lock the inbound/outbound base/limit configuration registers." swaccess: "rw0c" - hwaccess: "hro" + hwaccess: "none" fields: [ { name: "regwen" desc: ''' @@ -165,7 +163,6 @@ regwen: "ADDRESS_RANGE_REGWEN" swaccess: "rw" hwaccess: "hro" - hwqe: "true" fields: [ { name: "base_address" desc: "Base address of SRAM region, which is used to back up the inbound mailbox data." @@ -174,15 +171,13 @@ } ] } - { - name: "INBOUND_LIMIT_ADDRESS" + { name: "INBOUND_LIMIT_ADDRESS" desc: '''Limit Address to mark the end of the inbound mailbox memory range in the private SRAM.. This address is 4-byte aligned, the lower 2-bits are ignored. ''' regwen: "ADDRESS_RANGE_REGWEN" swaccess: "rw" hwaccess: "hro" - hwqe: "true" fields: [ { name: "limit" desc: "Limit Address to mark the end of the inbound mailbox memory range in the private SRAM." @@ -202,8 +197,7 @@ bits: "31:2" resval: "0x0" swaccess: "ro" - hwaccess: "hrw" - hwqe: "true" + hwaccess: "hwo" } ] } @@ -214,7 +208,6 @@ regwen: "ADDRESS_RANGE_REGWEN" swaccess: "rw" hwaccess: "hro" - hwqe: "true" fields: [ { name: "base_address" desc: "Base address of SRAM region, which is used to buffer the outbound mailbox data." @@ -230,7 +223,6 @@ regwen: "ADDRESS_RANGE_REGWEN" swaccess: "rw" hwaccess: "hro" - hwqe: "true" fields: [ { name: "limit" desc: "Limit Address to mark the end of the outbound mailbox memory range in the private SRAM." @@ -250,8 +242,7 @@ bits: "31:2" resval: "0x0" swaccess: "ro" - hwaccess: "hrw" - hwqe: "true" + hwaccess: "hwo" } ] } @@ -277,7 +268,7 @@ Defined only for FW-to-FW mailboxes. ''' hwext: "true" - hwaccess: "hrw" + hwaccess: "hwo" swaccess: "ro" fields: [ { name: "doe_intr_msg_addr" @@ -293,7 +284,7 @@ Defined only for FW-to-FW mailboxes. ''' hwext: "true" - hwaccess: "hrw" + hwaccess: "hwo" swaccess: "ro" fields: [ { name: "doe_intr_msg_data" @@ -310,14 +301,13 @@ Utilized by the mailbox responder to send an interrupt message to the requester via a write to the configured address. Defined only for FW-to-FW mailboxes. ''' + swaccess: "rw" + hwaccess: "hro" fields: [ { name: "doe_intr_msg_addr" desc: "Utilized by the mailbox responder to send an interrupt message to the requester via a write to the configured address." bits: "31:0" resval: "0x0" - swaccess: "rw" - hwaccess: "hro" - hwqe: "true" } ] } @@ -326,14 +316,13 @@ Interrupt message data to be sent to the address configured in the DOE_INTR_MSG_ADDR register. Defined only for FW-to-FW mailboxes. ''' + swaccess: "rw" + hwaccess: "hro" fields: [ { name: "doe_intr_msg_data" desc: "Interrupt message data to be sent to the address configured in the DOE_INTR_MSG_ADDR register." bits: "31:0" resval: "0x0" - swaccess: "rw" - hwaccess: "hro" - hwqe: "true" } ] } @@ -357,7 +346,7 @@ ''' bits: "1" resval: "0x0" - swaccess: "rw" + swaccess: "ro" } { name: "go" desc: ''' @@ -387,7 +376,6 @@ resval: "0x0" swaccess: "rw1c" hwaccess: "hrw" - hwqe: "true" } { name: "error" desc: ''' @@ -407,7 +395,7 @@ bits: "31" resval: "0x0" swaccess: "ro" - hwaccess: "hrw" + hwaccess: "hwo" } ] } diff --git a/hw/ip/mbx/lint/mbx.waiver b/hw/ip/mbx/lint/mbx.waiver index 1b2ca889b1ad5..b22813b2134cf 100644 --- a/hw/ip/mbx/lint/mbx.waiver +++ b/hw/ip/mbx/lint/mbx.waiver @@ -4,15 +4,34 @@ # # waiver file for mbx -waive -rules INPUT_NOT_READ -location {mbx_imbx.sv} -regexp {Input port 'sysif_status_busy_i' is not read from} \ +waive -rules INPUT_NOT_READ -location {mbx_imbx.sv} -regexp {Input port 'sysif_status_busy_i' is not read from} \ -comment "Signal only used for assertions" -waive -rules INPUT_NOT_READ -location {mbx_imbx.sv} -regexp {Input port 'hostif_imbx_write_ptr_i[1:0]' is not read from} \ +waive -rules HIER_BRANCH_NOT_READ: -location {mbx_imbx.sv} -regexp {Net 'sysif_status_busy_i' is not read from} \ + -comment "Signal only used for assertions" + +waive -rules INPUT_NOT_READ -location {mbx_hostif.sv} -regexp {Input port 'hostif_imbx_write_ptr_i\[1:0\]' is not read from} \ + -comment "Write pointer is always 4B aligned" +waive -rules HIER_BRANCH_NOT_READ -location {mbx_hostif.sv} -regexp {Net 'hostif_imbx_write_ptr_i\[1:0\]' is not read from} \ -comment "Write pointer is always 4B aligned" -waive -rules INPUT_NOT_READ -location {mbx_imbx.sv} -regexp {Input port 'hostif_imbx_read_ptr_i[1:0]' is not read from} \ +waive -rules INPUT_NOT_READ -location {mbx_hostif.sv} -regexp {Input port 'hostif_ombx_read_ptr_i\[1:0\]' is not read from} \ -comment "Read pointer is always 4B aligned" +waive -rules HIER_BRANCH_NOT_READ -location {mbx_hostif.sv} -regexp {Net 'hostif_ombx_read_ptr_i\[1:0\]' is not read from} \ + -comment "Read pointer is always 4B aligned" + waive -rules INPUT_NOT_READ -location {mbx_ombx.sv} -regexp {Input port 'sysif_status_ready_i' is not read from} \ -comment "Signal only used for assertions" +waive -rules HIER_BRANCH_NOT_READ -location {mbx_ombx.sv} -regexp {Net 'sysif_status_ready_i' is not read from} \ + -comment "Signal only used for assertions" + +# sysif_read_data_read_valid_i and all connected signals are only used for assertions waive -rules INPUT_NOT_READ -location {mbx_ombx.sv} -regexp {Input port 'sysif_read_data_read_valid_i' is not read from} \ -comment "Signal only used for assertions" +waive -rules HIER_BRANCH_NOT_READ -location {mbx_ombx.sv} -regexp {Net 'sysif_read_data_read_valid_i' is not read from} \ + -comment "Signal only used for assertions" +waive -rules HIER_NET_NOT_READ: -location {mbx.sv} -regexp {Net 'sysif_read_data_read_valid' is not read from} \ + -comment "Signal only used for assertions" +waive -rules HIER_NET_NOT_READ: -location {mbx.sv} -regexp {Connected net 'sysif_read_data_read_valid_i' at} \ + -comment "Signal only used for assertions" + waive -rules NOT_READ -location {mbx_ombx.sv} -regexp {Signal 'ombx_is_empty' is not read from} \ -comment "Signal only used for assertions" diff --git a/hw/ip/mbx/rtl/mbx.sv b/hw/ip/mbx/rtl/mbx.sv index 163a8d0deaf49..cc04037d4ace8 100644 --- a/hw/ip/mbx/rtl/mbx.sv +++ b/hw/ip/mbx/rtl/mbx.sv @@ -58,11 +58,10 @@ module mbx logic sysif_control_abort_set; // Status signal inputs from the sysif to the hostif - logic sysif_status_busy, sysif_status_doe_intr_status, sysif_status_error; + logic sysif_status_busy, sysif_status_error; // Setter signals from the hostif to the sysif - logic hostif_status_doe_intr_status_set, hostif_status_busy_clear, - hostif_control_abort_clear, hostif_control_error_set; + logic hostif_status_busy_clear, hostif_control_abort_clear, hostif_control_error_set; // Alias signals from the sys interface logic [CfgSramAddrWidth-1:0] sysif_intr_msg_addr; @@ -111,7 +110,7 @@ module mbx // Access to the status register .hostif_status_busy_clear_o ( hostif_status_busy_clear ), .hostif_status_busy_i ( sysif_status_busy ), - .hostif_status_doe_intr_status_i ( sysif_status_doe_intr_status ), + .hostif_status_doe_intr_status_i ( doe_intr_o ), // Access to the IB/OB RD/WR Pointers .hostif_imbx_write_ptr_i ( imbx_sram_write_ptr ), .hostif_ombx_read_ptr_i ( ombx_sram_read_ptr ), @@ -129,8 +128,10 @@ module mbx // Alias of the interrupt address and data registers from the SYS interface .sysif_intr_msg_addr_i ( sysif_intr_msg_addr ), .sysif_intr_msg_data_i ( sysif_intr_msg_data ), - // Control inputs coming from the system registers interface - .sysif_control_abort_set_i ( sysif_control_abort_set ) + // Control and status inputs coming from the system registers interface + .sysif_control_abort_set_i ( sysif_control_abort_set ), + .sysif_doe_intr_en_i ( doe_intr_en_o ) + ); ////////////////////////////////////////////////////////////////////////////// @@ -185,7 +186,6 @@ module mbx .sysif_status_busy_i ( imbx_status_busy ), .sysif_status_busy_o ( sysif_status_busy ), .sysif_status_doe_intr_status_set_i ( ombx_doe_intr_status_set ), - .sysif_status_doe_intr_status_o ( sysif_status_doe_intr_status ), .sysif_status_error_set_i ( hostif_control_error_set ), .sysif_status_error_o ( sysif_status_error ), .sysif_status_ready_valid_i ( ombx_status_ready_valid ), diff --git a/hw/ip/mbx/rtl/mbx_core_reg_top.sv b/hw/ip/mbx/rtl/mbx_core_reg_top.sv index aab1f90e84a65..71272b308d1a7 100644 --- a/hw/ip/mbx/rtl/mbx_core_reg_top.sv +++ b/hw/ip/mbx/rtl/mbx_core_reg_top.sv @@ -142,7 +142,6 @@ module mbx_core_reg_top ( logic control_abort_qs; logic control_abort_wd; logic control_doe_intr_en_qs; - logic control_doe_intr_en_wd; logic control_error_qs; logic control_error_wd; logic status_re; @@ -150,7 +149,6 @@ module mbx_core_reg_top ( logic status_busy_qs; logic status_busy_wd; logic status_doe_intr_status_qs; - logic status_doe_intr_status_wd; logic address_range_regwen_we; logic [3:0] address_range_regwen_qs; logic [3:0] address_range_regwen_wd; @@ -371,7 +369,10 @@ module mbx_core_reg_top ( // R[control]: V(True) logic control_qe; logic [2:0] control_flds_we; - assign control_qe = &control_flds_we; + // This ignores QEs that are set to constant 0 due to read-only fields. + logic unused_control_flds_we; + assign unused_control_flds_we = ^(control_flds_we & 3'h2); + assign control_qe = &(control_flds_we | 3'h2); // F[abort]: 0:0 prim_subreg_ext #( .DW (1) @@ -393,16 +394,15 @@ module mbx_core_reg_top ( .DW (1) ) u_control_doe_intr_en ( .re (control_re), - .we (control_we), - .wd (control_doe_intr_en_wd), + .we (1'b0), + .wd ('0), .d (hw2reg.control.doe_intr_en.d), .qre (), .qe (control_flds_we[1]), - .q (reg2hw.control.doe_intr_en.q), + .q (), .ds (), .qs (control_doe_intr_en_qs) ); - assign reg2hw.control.doe_intr_en.qe = control_qe; // F[error]: 2:2 prim_subreg_ext #( @@ -424,7 +424,10 @@ module mbx_core_reg_top ( // R[status]: V(True) logic status_qe; logic [1:0] status_flds_we; - assign status_qe = &status_flds_we; + // This ignores QEs that are set to constant 0 due to read-only fields. + logic unused_status_flds_we; + assign unused_status_flds_we = ^(status_flds_we & 2'h2); + assign status_qe = &(status_flds_we | 2'h2); // F[busy]: 0:0 prim_subreg_ext #( .DW (1) @@ -446,16 +449,15 @@ module mbx_core_reg_top ( .DW (1) ) u_status_doe_intr_status ( .re (status_re), - .we (status_we), - .wd (status_doe_intr_status_wd), + .we (1'b0), + .wd ('0), .d (hw2reg.status.doe_intr_status.d), .qre (), .qe (status_flds_we[1]), - .q (reg2hw.status.doe_intr_status.q), + .q (), .ds (), .qs (status_doe_intr_status_qs) ); - assign reg2hw.status.doe_intr_status.qe = status_qe; // R[address_range_regwen]: V(False) @@ -478,7 +480,7 @@ module mbx_core_reg_top ( // to internal hardware .qe (), - .q (reg2hw.address_range_regwen.q), + .q (), .ds (), // to register interface (read) @@ -515,17 +517,6 @@ module mbx_core_reg_top ( // R[inbound_base_address]: V(False) - logic inbound_base_address_qe; - logic [0:0] inbound_base_address_flds_we; - prim_flop #( - .Width(1), - .ResetValue(0) - ) u_inbound_base_address0_qe ( - .clk_i(clk_i), - .rst_ni(rst_ni), - .d_i(&inbound_base_address_flds_we), - .q_o(inbound_base_address_qe) - ); // Create REGWEN-gated WE signal logic inbound_base_address_gated_we; assign inbound_base_address_gated_we = @@ -549,28 +540,16 @@ module mbx_core_reg_top ( .d ('0), // to internal hardware - .qe (inbound_base_address_flds_we[0]), + .qe (), .q (reg2hw.inbound_base_address.q), .ds (), // to register interface (read) .qs (inbound_base_address_qs) ); - assign reg2hw.inbound_base_address.qe = inbound_base_address_qe; // R[inbound_limit_address]: V(False) - logic inbound_limit_address_qe; - logic [0:0] inbound_limit_address_flds_we; - prim_flop #( - .Width(1), - .ResetValue(0) - ) u_inbound_limit_address0_qe ( - .clk_i(clk_i), - .rst_ni(rst_ni), - .d_i(&inbound_limit_address_flds_we), - .q_o(inbound_limit_address_qe) - ); // Create REGWEN-gated WE signal logic inbound_limit_address_gated_we; assign inbound_limit_address_gated_we = @@ -594,21 +573,16 @@ module mbx_core_reg_top ( .d ('0), // to internal hardware - .qe (inbound_limit_address_flds_we[0]), + .qe (), .q (reg2hw.inbound_limit_address.q), .ds (), // to register interface (read) .qs (inbound_limit_address_qs) ); - assign reg2hw.inbound_limit_address.qe = inbound_limit_address_qe; // R[inbound_write_ptr]: V(True) - logic inbound_write_ptr_qe; - logic [0:0] inbound_write_ptr_flds_we; - // In case all fields are read-only the aggregated register QE will be zero as well. - assign inbound_write_ptr_qe = &inbound_write_ptr_flds_we; prim_subreg_ext #( .DW (30) ) u_inbound_write_ptr ( @@ -617,26 +591,14 @@ module mbx_core_reg_top ( .wd ('0), .d (hw2reg.inbound_write_ptr.d), .qre (), - .qe (inbound_write_ptr_flds_we[0]), - .q (reg2hw.inbound_write_ptr.q), + .qe (), + .q (), .ds (), .qs (inbound_write_ptr_qs) ); - assign reg2hw.inbound_write_ptr.qe = inbound_write_ptr_qe; // R[outbound_base_address]: V(False) - logic outbound_base_address_qe; - logic [0:0] outbound_base_address_flds_we; - prim_flop #( - .Width(1), - .ResetValue(0) - ) u_outbound_base_address0_qe ( - .clk_i(clk_i), - .rst_ni(rst_ni), - .d_i(&outbound_base_address_flds_we), - .q_o(outbound_base_address_qe) - ); // Create REGWEN-gated WE signal logic outbound_base_address_gated_we; assign outbound_base_address_gated_we = @@ -660,28 +622,16 @@ module mbx_core_reg_top ( .d ('0), // to internal hardware - .qe (outbound_base_address_flds_we[0]), + .qe (), .q (reg2hw.outbound_base_address.q), .ds (), // to register interface (read) .qs (outbound_base_address_qs) ); - assign reg2hw.outbound_base_address.qe = outbound_base_address_qe; // R[outbound_limit_address]: V(False) - logic outbound_limit_address_qe; - logic [0:0] outbound_limit_address_flds_we; - prim_flop #( - .Width(1), - .ResetValue(0) - ) u_outbound_limit_address0_qe ( - .clk_i(clk_i), - .rst_ni(rst_ni), - .d_i(&outbound_limit_address_flds_we), - .q_o(outbound_limit_address_qe) - ); // Create REGWEN-gated WE signal logic outbound_limit_address_gated_we; assign outbound_limit_address_gated_we = @@ -705,21 +655,16 @@ module mbx_core_reg_top ( .d ('0), // to internal hardware - .qe (outbound_limit_address_flds_we[0]), + .qe (), .q (reg2hw.outbound_limit_address.q), .ds (), // to register interface (read) .qs (outbound_limit_address_qs) ); - assign reg2hw.outbound_limit_address.qe = outbound_limit_address_qe; // R[outbound_read_ptr]: V(True) - logic outbound_read_ptr_qe; - logic [0:0] outbound_read_ptr_flds_we; - // In case all fields are read-only the aggregated register QE will be zero as well. - assign outbound_read_ptr_qe = &outbound_read_ptr_flds_we; prim_subreg_ext #( .DW (30) ) u_outbound_read_ptr ( @@ -728,12 +673,11 @@ module mbx_core_reg_top ( .wd ('0), .d (hw2reg.outbound_read_ptr.d), .qre (), - .qe (outbound_read_ptr_flds_we[0]), - .q (reg2hw.outbound_read_ptr.q), + .qe (), + .q (), .ds (), .qs (outbound_read_ptr_qs) ); - assign reg2hw.outbound_read_ptr.qe = outbound_read_ptr_qe; // R[outbound_object_size]: V(False) @@ -786,7 +730,7 @@ module mbx_core_reg_top ( .d (hw2reg.doe_intr_msg_addr.d), .qre (), .qe (), - .q (reg2hw.doe_intr_msg_addr.q), + .q (), .ds (), .qs (doe_intr_msg_addr_qs) ); @@ -802,7 +746,7 @@ module mbx_core_reg_top ( .d (hw2reg.doe_intr_msg_data.d), .qre (), .qe (), - .q (reg2hw.doe_intr_msg_data.q), + .q (), .ds (), .qs (doe_intr_msg_data_qs) ); @@ -881,15 +825,11 @@ module mbx_core_reg_top ( assign control_abort_wd = reg_wdata[0]; - assign control_doe_intr_en_wd = reg_wdata[1]; - assign control_error_wd = reg_wdata[2]; assign status_re = addr_hit[5] & reg_re & !reg_error; assign status_we = addr_hit[5] & reg_we & !reg_error; assign status_busy_wd = reg_wdata[0]; - - assign status_doe_intr_status_wd = reg_wdata[1]; assign address_range_regwen_we = addr_hit[6] & reg_we & !reg_error; assign address_range_regwen_wd = reg_wdata[3:0]; diff --git a/hw/ip/mbx/rtl/mbx_hostif.sv b/hw/ip/mbx/rtl/mbx_hostif.sv index dfd370d5dfb48..f501a48cbe209 100644 --- a/hw/ip/mbx/rtl/mbx_hostif.sv +++ b/hw/ip/mbx/rtl/mbx_hostif.sv @@ -33,7 +33,6 @@ module mbx_hostif input logic hostif_control_error_i, // Access to the status register output logic hostif_status_busy_clear_o, - output logic hostif_status_doe_intr_status_set_o, input logic hostif_status_busy_i, input logic hostif_status_doe_intr_status_i, // Access to the IB/OB RD/WR pointers @@ -54,7 +53,8 @@ module mbx_hostif input logic [CfgSramAddrWidth-1:0] sysif_intr_msg_addr_i, input logic [CfgSramDataWidth-1:0] sysif_intr_msg_data_i, // Control inputs coming from the system registers interface - input logic sysif_control_abort_set_i + input logic sysif_control_abort_set_i, + input logic sysif_doe_intr_en_i ); mbx_reg_pkg::mbx_core_reg2hw_t reg2hw; mbx_reg_pkg::mbx_core_hw2reg_t hw2reg; @@ -138,6 +138,9 @@ module mbx_hostif // Writing a 1 to control.abort means clearing the abort condition assign hostif_control_abort_clear_o = reg2hw.control.abort.qe & reg2hw.control.abort.q; + assign hw2reg.control.doe_intr_en.d = sysif_doe_intr_en_i; + + // Abort computation from system and host interface always_comb begin abort_d = abort_q; @@ -158,7 +161,7 @@ module mbx_hostif .q_o ( abort_q ) ); - assign hostif_control_error_set_o = reg2hw.control.error.qe & reg2hw.control.error.q; + assign hostif_control_error_set_o = reg2hw.control.error.qe & reg2hw.control.error.q; assign hw2reg.control.error.d = hostif_control_error_i; // Status Register @@ -169,9 +172,7 @@ module mbx_hostif assign hw2reg.status.busy.d = hostif_status_busy_i; assign hw2reg.status.doe_intr_status.d = hostif_status_doe_intr_status_i; // External write logic - assign hostif_status_busy_clear_o = reg2hw.status.busy.qe & ~reg2hw.status.busy.q; - assign hostif_status_doe_intr_status_set_o = reg2hw.status.doe_intr_status.qe & - reg2hw.status.doe_intr_status.q; + assign hostif_status_busy_clear_o = reg2hw.status.busy.qe & ~reg2hw.status.busy.q; // Address config valid assign hostif_address_range_valid_o = reg2hw.address_range_valid.q; diff --git a/hw/ip/mbx/rtl/mbx_reg_pkg.sv b/hw/ip/mbx/rtl/mbx_reg_pkg.sv index 139ef56dacd78..041a037cfe9ba 100644 --- a/hw/ip/mbx/rtl/mbx_reg_pkg.sv +++ b/hw/ip/mbx/rtl/mbx_reg_pkg.sv @@ -62,10 +62,6 @@ package mbx_reg_pkg; logic q; logic qe; } error; - struct packed { - logic q; - logic qe; - } doe_intr_en; struct packed { logic q; logic qe; @@ -73,67 +69,37 @@ package mbx_reg_pkg; } mbx_reg2hw_control_reg_t; typedef struct packed { - struct packed { - logic q; - logic qe; - } doe_intr_status; struct packed { logic q; logic qe; } busy; } mbx_reg2hw_status_reg_t; - typedef struct packed { - logic [3:0] q; - } mbx_reg2hw_address_range_regwen_reg_t; - typedef struct packed { logic q; } mbx_reg2hw_address_range_valid_reg_t; typedef struct packed { logic [29:0] q; - logic qe; } mbx_reg2hw_inbound_base_address_reg_t; typedef struct packed { logic [29:0] q; - logic qe; } mbx_reg2hw_inbound_limit_address_reg_t; typedef struct packed { logic [29:0] q; - logic qe; - } mbx_reg2hw_inbound_write_ptr_reg_t; - - typedef struct packed { - logic [29:0] q; - logic qe; } mbx_reg2hw_outbound_base_address_reg_t; typedef struct packed { logic [29:0] q; - logic qe; } mbx_reg2hw_outbound_limit_address_reg_t; - typedef struct packed { - logic [29:0] q; - logic qe; - } mbx_reg2hw_outbound_read_ptr_reg_t; - typedef struct packed { logic [10:0] q; logic qe; } mbx_reg2hw_outbound_object_size_reg_t; - typedef struct packed { - logic [31:0] q; - } mbx_reg2hw_doe_intr_msg_addr_reg_t; - - typedef struct packed { - logic [31:0] q; - } mbx_reg2hw_doe_intr_msg_data_reg_t; - typedef struct packed { struct packed { logic d; @@ -189,23 +155,18 @@ package mbx_reg_pkg; // Register -> HW type for core interface typedef struct packed { - mbx_reg2hw_intr_state_reg_t intr_state; // [288:287] - mbx_reg2hw_intr_enable_reg_t intr_enable; // [286:285] - mbx_reg2hw_intr_test_reg_t intr_test; // [284:281] - mbx_reg2hw_alert_test_reg_t alert_test; // [280:277] - mbx_reg2hw_control_reg_t control; // [276:271] - mbx_reg2hw_status_reg_t status; // [270:267] - mbx_reg2hw_address_range_regwen_reg_t address_range_regwen; // [266:263] - mbx_reg2hw_address_range_valid_reg_t address_range_valid; // [262:262] - mbx_reg2hw_inbound_base_address_reg_t inbound_base_address; // [261:231] - mbx_reg2hw_inbound_limit_address_reg_t inbound_limit_address; // [230:200] - mbx_reg2hw_inbound_write_ptr_reg_t inbound_write_ptr; // [199:169] - mbx_reg2hw_outbound_base_address_reg_t outbound_base_address; // [168:138] - mbx_reg2hw_outbound_limit_address_reg_t outbound_limit_address; // [137:107] - mbx_reg2hw_outbound_read_ptr_reg_t outbound_read_ptr; // [106:76] - mbx_reg2hw_outbound_object_size_reg_t outbound_object_size; // [75:64] - mbx_reg2hw_doe_intr_msg_addr_reg_t doe_intr_msg_addr; // [63:32] - mbx_reg2hw_doe_intr_msg_data_reg_t doe_intr_msg_data; // [31:0] + mbx_reg2hw_intr_state_reg_t intr_state; // [150:149] + mbx_reg2hw_intr_enable_reg_t intr_enable; // [148:147] + mbx_reg2hw_intr_test_reg_t intr_test; // [146:143] + mbx_reg2hw_alert_test_reg_t alert_test; // [142:139] + mbx_reg2hw_control_reg_t control; // [138:135] + mbx_reg2hw_status_reg_t status; // [134:133] + mbx_reg2hw_address_range_valid_reg_t address_range_valid; // [132:132] + mbx_reg2hw_inbound_base_address_reg_t inbound_base_address; // [131:102] + mbx_reg2hw_inbound_limit_address_reg_t inbound_limit_address; // [101:72] + mbx_reg2hw_outbound_base_address_reg_t outbound_base_address; // [71:42] + mbx_reg2hw_outbound_limit_address_reg_t outbound_limit_address; // [41:12] + mbx_reg2hw_outbound_object_size_reg_t outbound_object_size; // [11:0] } mbx_core_reg2hw_t; // HW -> register type for core interface @@ -310,12 +271,10 @@ package mbx_reg_pkg; typedef struct packed { logic [31:0] q; - logic qe; } mbx_reg2hw_soc_doe_intr_msg_addr_reg_t; typedef struct packed { logic [31:0] q; - logic qe; } mbx_reg2hw_soc_doe_intr_msg_data_reg_t; typedef struct packed { @@ -334,15 +293,11 @@ package mbx_reg_pkg; } mbx_reg2hw_soc_control_reg_t; typedef struct packed { - struct packed { - logic q; - } ready; struct packed { logic q; } error; struct packed { logic q; - logic qe; } doe_intr_status; struct packed { logic q; @@ -382,10 +337,10 @@ package mbx_reg_pkg; // Register -> HW type for soc interface typedef struct packed { - mbx_reg2hw_soc_doe_intr_msg_addr_reg_t soc_doe_intr_msg_addr; // [76:44] - mbx_reg2hw_soc_doe_intr_msg_data_reg_t soc_doe_intr_msg_data; // [43:11] - mbx_reg2hw_soc_control_reg_t soc_control; // [10:5] - mbx_reg2hw_soc_status_reg_t soc_status; // [4:0] + mbx_reg2hw_soc_doe_intr_msg_addr_reg_t soc_doe_intr_msg_addr; // [72:41] + mbx_reg2hw_soc_doe_intr_msg_data_reg_t soc_doe_intr_msg_data; // [40:9] + mbx_reg2hw_soc_control_reg_t soc_control; // [8:3] + mbx_reg2hw_soc_status_reg_t soc_status; // [2:0] } mbx_soc_reg2hw_t; // HW -> register type for soc interface diff --git a/hw/ip/mbx/rtl/mbx_soc_reg_top.sv b/hw/ip/mbx/rtl/mbx_soc_reg_top.sv index 8cded912d8966..7256559d62e2a 100644 --- a/hw/ip/mbx/rtl/mbx_soc_reg_top.sv +++ b/hw/ip/mbx/rtl/mbx_soc_reg_top.sv @@ -183,7 +183,6 @@ module mbx_soc_reg_top ( logic soc_control_we; logic soc_control_abort_wd; logic soc_control_doe_intr_en_qs; - logic soc_control_doe_intr_en_wd; logic soc_control_go_wd; logic soc_status_we; logic soc_status_busy_qs; @@ -194,17 +193,6 @@ module mbx_soc_reg_top ( // Register instances // R[soc_doe_intr_msg_addr]: V(False) - logic soc_doe_intr_msg_addr_qe; - logic [0:0] soc_doe_intr_msg_addr_flds_we; - prim_flop #( - .Width(1), - .ResetValue(0) - ) u_soc_doe_intr_msg_addr0_qe ( - .clk_i(clk_i), - .rst_ni(rst_ni), - .d_i(&soc_doe_intr_msg_addr_flds_we), - .q_o(soc_doe_intr_msg_addr_qe) - ); prim_subreg #( .DW (32), .SwAccess(prim_subreg_pkg::SwAccessRW), @@ -223,28 +211,16 @@ module mbx_soc_reg_top ( .d ('0), // to internal hardware - .qe (soc_doe_intr_msg_addr_flds_we[0]), + .qe (), .q (reg2hw.soc_doe_intr_msg_addr.q), .ds (), // to register interface (read) .qs (soc_doe_intr_msg_addr_qs) ); - assign reg2hw.soc_doe_intr_msg_addr.qe = soc_doe_intr_msg_addr_qe; // R[soc_doe_intr_msg_data]: V(False) - logic soc_doe_intr_msg_data_qe; - logic [0:0] soc_doe_intr_msg_data_flds_we; - prim_flop #( - .Width(1), - .ResetValue(0) - ) u_soc_doe_intr_msg_data0_qe ( - .clk_i(clk_i), - .rst_ni(rst_ni), - .d_i(&soc_doe_intr_msg_data_flds_we), - .q_o(soc_doe_intr_msg_data_qe) - ); prim_subreg #( .DW (32), .SwAccess(prim_subreg_pkg::SwAccessRW), @@ -263,20 +239,22 @@ module mbx_soc_reg_top ( .d ('0), // to internal hardware - .qe (soc_doe_intr_msg_data_flds_we[0]), + .qe (), .q (reg2hw.soc_doe_intr_msg_data.q), .ds (), // to register interface (read) .qs (soc_doe_intr_msg_data_qs) ); - assign reg2hw.soc_doe_intr_msg_data.qe = soc_doe_intr_msg_data_qe; // R[soc_control]: V(True) logic soc_control_qe; logic [2:0] soc_control_flds_we; - assign soc_control_qe = &soc_control_flds_we; + // This ignores QEs that are set to constant 0 due to read-only fields. + logic unused_soc_control_flds_we; + assign unused_soc_control_flds_we = ^(soc_control_flds_we & 3'h2); + assign soc_control_qe = &(soc_control_flds_we | 3'h2); // F[abort]: 0:0 prim_subreg_ext #( .DW (1) @@ -298,8 +276,8 @@ module mbx_soc_reg_top ( .DW (1) ) u_soc_control_doe_intr_en ( .re (soc_control_re), - .we (soc_control_we), - .wd (soc_control_doe_intr_en_wd), + .we (1'b0), + .wd ('0), .d (hw2reg.soc_control.doe_intr_en.d), .qre (), .qe (soc_control_flds_we[1]), @@ -327,17 +305,6 @@ module mbx_soc_reg_top ( // R[soc_status]: V(False) - logic soc_status_qe; - logic [3:0] soc_status_flds_we; - prim_flop #( - .Width(1), - .ResetValue(0) - ) u_soc_status0_qe ( - .clk_i(clk_i), - .rst_ni(rst_ni), - .d_i(&(soc_status_flds_we | 4'hd)), - .q_o(soc_status_qe) - ); // F[busy]: 0:0 prim_subreg #( .DW (1), @@ -357,7 +324,7 @@ module mbx_soc_reg_top ( .d (hw2reg.soc_status.busy.d), // to internal hardware - .qe (soc_status_flds_we[0]), + .qe (), .q (reg2hw.soc_status.busy.q), .ds (), @@ -384,14 +351,13 @@ module mbx_soc_reg_top ( .d (hw2reg.soc_status.doe_intr_status.d), // to internal hardware - .qe (soc_status_flds_we[1]), + .qe (), .q (reg2hw.soc_status.doe_intr_status.q), .ds (), // to register interface (read) .qs (soc_status_doe_intr_status_qs) ); - assign reg2hw.soc_status.doe_intr_status.qe = soc_status_qe; // F[error]: 2:2 prim_subreg #( @@ -412,7 +378,7 @@ module mbx_soc_reg_top ( .d (hw2reg.soc_status.error.d), // to internal hardware - .qe (soc_status_flds_we[2]), + .qe (), .q (reg2hw.soc_status.error.q), .ds (), @@ -439,8 +405,8 @@ module mbx_soc_reg_top ( .d (hw2reg.soc_status.ready.d), // to internal hardware - .qe (soc_status_flds_we[3]), - .q (reg2hw.soc_status.ready.q), + .qe (), + .q (), .ds (), // to register interface (read) @@ -481,8 +447,6 @@ module mbx_soc_reg_top ( assign soc_control_abort_wd = reg_wdata[0]; - assign soc_control_doe_intr_en_wd = reg_wdata[1]; - assign soc_control_go_wd = reg_wdata[31]; assign soc_status_we = addr_hit[3] & reg_we & !reg_error; diff --git a/hw/ip/mbx/rtl/mbx_sysif.sv b/hw/ip/mbx/rtl/mbx_sysif.sv index 22e2997aeaf2f..9ab4bc61a43be 100644 --- a/hw/ip/mbx/rtl/mbx_sysif.sv +++ b/hw/ip/mbx/rtl/mbx_sysif.sv @@ -28,7 +28,6 @@ module mbx_sysif input logic sysif_status_busy_i, output logic sysif_status_busy_o, input logic sysif_status_doe_intr_status_set_i, - output logic sysif_status_doe_intr_status_o, input logic sysif_status_error_set_i, output logic sysif_status_error_o, input logic sysif_status_ready_valid_i, @@ -103,9 +102,8 @@ module mbx_sysif ); // Fiddle out status register bits for external write logic - assign sysif_status_doe_intr_status_o = reg2hw.soc_status.doe_intr_status.q; - assign sysif_status_busy_o = reg2hw.soc_status.busy.q; - assign sysif_status_error_o = reg2hw.soc_status.error.q; + assign sysif_status_busy_o = reg2hw.soc_status.busy.q; + assign sysif_status_error_o = reg2hw.soc_status.error.q; // External read logic assign hw2reg.soc_status.busy.de = sysif_status_busy_valid_i; From 8f1713c4f1f2ac90eeb7e7e0c79f4313c3d454bd Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Wed, 20 Sep 2023 07:04:28 -0700 Subject: [PATCH 34/88] [hw,mbx,rtl] Rename DOE IRQ signals on host side Signed-off-by: Robert Schilling --- hw/ip/mbx/data/mbx.hjson | 18 ++++----- hw/ip/mbx/rtl/mbx.sv | 13 +++--- hw/ip/mbx/rtl/mbx_core_reg_top.sv | 67 +++++++++++++++---------------- hw/ip/mbx/rtl/mbx_hostif.sv | 26 ++++++------ hw/ip/mbx/rtl/mbx_ombx.sv | 4 +- hw/ip/mbx/rtl/mbx_reg_pkg.sv | 20 ++++----- hw/ip/mbx/rtl/mbx_sysif.sv | 6 +-- 7 files changed, 74 insertions(+), 80 deletions(-) diff --git a/hw/ip/mbx/data/mbx.hjson b/hw/ip/mbx/data/mbx.hjson index 69bc0d28fe4df..0e5e1d900f0f1 100644 --- a/hw/ip/mbx/data/mbx.hjson +++ b/hw/ip/mbx/data/mbx.hjson @@ -85,20 +85,13 @@ hwaccess: "hrw" hwqe: "true" } - { name: "doe_intr_en" - desc: "Alias of the DoE mailbox interrupt enable bit" - bits: "1" - resval: "0x0" - swaccess: "ro" - hwaccess: "hwo" - } { name: "error" desc: ''' Set by firmware to signal an error, i.e., unable to provide a response to request. Set by hardware, on SYS.WDATA or SYS.RDATA performing an invalid access. Cleared by the hardware when SYS sets CONTROL.ABORT. ''' - bits: "2" + bits: "1" resval: "0x0" swaccess: "rw" hwaccess: "hrw" @@ -118,13 +111,20 @@ swaccess: "rw" hwaccess: "hrw" } - { name: "doe_intr_status" + { name: "sys_intr_state" desc: "Alias of the DoE mailbox interrupt status bit" bits: "1" resval: "0x0" swaccess: "ro" hwaccess: "hwo" } + { name: "sys_intr_enable" + desc: "Alias of the DoE mailbox interrupt enable bit" + bits: "2" + resval: "0x0" + swaccess: "ro" + hwaccess: "hwo" + } ] } { name: "ADDRESS_RANGE_REGWEN" diff --git a/hw/ip/mbx/rtl/mbx.sv b/hw/ip/mbx/rtl/mbx.sv index cc04037d4ace8..2a48323cd15cd 100644 --- a/hw/ip/mbx/rtl/mbx.sv +++ b/hw/ip/mbx/rtl/mbx.sv @@ -110,7 +110,8 @@ module mbx // Access to the status register .hostif_status_busy_clear_o ( hostif_status_busy_clear ), .hostif_status_busy_i ( sysif_status_busy ), - .hostif_status_doe_intr_status_i ( doe_intr_o ), + .hostif_status_sys_intr_en_i ( doe_intr_en_o ), + .hostif_status_sys_intr_state_i ( doe_intr_o ), // Access to the IB/OB RD/WR Pointers .hostif_imbx_write_ptr_i ( imbx_sram_write_ptr ), .hostif_ombx_read_ptr_i ( ombx_sram_read_ptr ), @@ -129,9 +130,7 @@ module mbx .sysif_intr_msg_addr_i ( sysif_intr_msg_addr ), .sysif_intr_msg_data_i ( sysif_intr_msg_data ), // Control and status inputs coming from the system registers interface - .sysif_control_abort_set_i ( sysif_control_abort_set ), - .sysif_doe_intr_en_i ( doe_intr_en_o ) - + .sysif_control_abort_set_i ( sysif_control_abort_set ) ); ////////////////////////////////////////////////////////////////////////////// @@ -156,7 +155,7 @@ module mbx ////////////////////////////////////////////////////////////////////////////// logic ombx_pending; logic ombx_status_ready_valid, ombx_status_ready; - logic ombx_doe_intr_status_set; + logic ombx_doe_intr_state_set; // Interface signals for SRAM host access to read the memory and serve it to the outbox logic ombx_sram_read_req, ombx_sram_read_gnt; @@ -185,7 +184,7 @@ module mbx .sysif_status_busy_valid_i ( imbx_status_busy_valid ), .sysif_status_busy_i ( imbx_status_busy ), .sysif_status_busy_o ( sysif_status_busy ), - .sysif_status_doe_intr_status_set_i ( ombx_doe_intr_status_set ), + .sysif_status_doe_intr_state_set_i ( ombx_doe_intr_state_set ), .sysif_status_error_set_i ( hostif_control_error_set ), .sysif_status_error_o ( sysif_status_error ), .sysif_status_ready_valid_i ( ombx_status_ready_valid ), @@ -244,7 +243,7 @@ module mbx ) u_ombx ( .clk_i ( clk_i ), .rst_ni ( rst_ni ), - .ombx_doe_intr_status_set_o ( ombx_doe_intr_status_set ), + .ombx_doe_intr_state_set_o ( ombx_doe_intr_state_set ), // Interface to the host port .ombx_state_error_o ( ombx_state_error ), .ombx_pending_o ( ombx_pending ), diff --git a/hw/ip/mbx/rtl/mbx_core_reg_top.sv b/hw/ip/mbx/rtl/mbx_core_reg_top.sv index 71272b308d1a7..c4946947bd2f2 100644 --- a/hw/ip/mbx/rtl/mbx_core_reg_top.sv +++ b/hw/ip/mbx/rtl/mbx_core_reg_top.sv @@ -141,14 +141,14 @@ module mbx_core_reg_top ( logic control_we; logic control_abort_qs; logic control_abort_wd; - logic control_doe_intr_en_qs; logic control_error_qs; logic control_error_wd; logic status_re; logic status_we; logic status_busy_qs; logic status_busy_wd; - logic status_doe_intr_status_qs; + logic status_sys_intr_state_qs; + logic status_sys_intr_enable_qs; logic address_range_regwen_we; logic [3:0] address_range_regwen_qs; logic [3:0] address_range_regwen_wd; @@ -368,11 +368,8 @@ module mbx_core_reg_top ( // R[control]: V(True) logic control_qe; - logic [2:0] control_flds_we; - // This ignores QEs that are set to constant 0 due to read-only fields. - logic unused_control_flds_we; - assign unused_control_flds_we = ^(control_flds_we & 3'h2); - assign control_qe = &(control_flds_we | 3'h2); + logic [1:0] control_flds_we; + assign control_qe = &control_flds_we; // F[abort]: 0:0 prim_subreg_ext #( .DW (1) @@ -389,22 +386,7 @@ module mbx_core_reg_top ( ); assign reg2hw.control.abort.qe = control_qe; - // F[doe_intr_en]: 1:1 - prim_subreg_ext #( - .DW (1) - ) u_control_doe_intr_en ( - .re (control_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.control.doe_intr_en.d), - .qre (), - .qe (control_flds_we[1]), - .q (), - .ds (), - .qs (control_doe_intr_en_qs) - ); - - // F[error]: 2:2 + // F[error]: 1:1 prim_subreg_ext #( .DW (1) ) u_control_error ( @@ -413,7 +395,7 @@ module mbx_core_reg_top ( .wd (control_error_wd), .d (hw2reg.control.error.d), .qre (), - .qe (control_flds_we[2]), + .qe (control_flds_we[1]), .q (reg2hw.control.error.q), .ds (), .qs (control_error_qs) @@ -423,11 +405,11 @@ module mbx_core_reg_top ( // R[status]: V(True) logic status_qe; - logic [1:0] status_flds_we; + logic [2:0] status_flds_we; // This ignores QEs that are set to constant 0 due to read-only fields. logic unused_status_flds_we; - assign unused_status_flds_we = ^(status_flds_we & 2'h2); - assign status_qe = &(status_flds_we | 2'h2); + assign unused_status_flds_we = ^(status_flds_we & 3'h6); + assign status_qe = &(status_flds_we | 3'h6); // F[busy]: 0:0 prim_subreg_ext #( .DW (1) @@ -444,19 +426,34 @@ module mbx_core_reg_top ( ); assign reg2hw.status.busy.qe = status_qe; - // F[doe_intr_status]: 1:1 + // F[sys_intr_state]: 1:1 prim_subreg_ext #( .DW (1) - ) u_status_doe_intr_status ( + ) u_status_sys_intr_state ( .re (status_re), .we (1'b0), .wd ('0), - .d (hw2reg.status.doe_intr_status.d), + .d (hw2reg.status.sys_intr_state.d), .qre (), .qe (status_flds_we[1]), .q (), .ds (), - .qs (status_doe_intr_status_qs) + .qs (status_sys_intr_state_qs) + ); + + // F[sys_intr_enable]: 2:2 + prim_subreg_ext #( + .DW (1) + ) u_status_sys_intr_enable ( + .re (status_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status.sys_intr_enable.d), + .qre (), + .qe (status_flds_we[2]), + .q (), + .ds (), + .qs (status_sys_intr_enable_qs) ); @@ -825,7 +822,7 @@ module mbx_core_reg_top ( assign control_abort_wd = reg_wdata[0]; - assign control_error_wd = reg_wdata[2]; + assign control_error_wd = reg_wdata[1]; assign status_re = addr_hit[5] & reg_re & !reg_error; assign status_we = addr_hit[5] & reg_we & !reg_error; @@ -904,13 +901,13 @@ module mbx_core_reg_top ( addr_hit[4]: begin reg_rdata_next[0] = control_abort_qs; - reg_rdata_next[1] = control_doe_intr_en_qs; - reg_rdata_next[2] = control_error_qs; + reg_rdata_next[1] = control_error_qs; end addr_hit[5]: begin reg_rdata_next[0] = status_busy_qs; - reg_rdata_next[1] = status_doe_intr_status_qs; + reg_rdata_next[1] = status_sys_intr_state_qs; + reg_rdata_next[2] = status_sys_intr_enable_qs; end addr_hit[6]: begin diff --git a/hw/ip/mbx/rtl/mbx_hostif.sv b/hw/ip/mbx/rtl/mbx_hostif.sv index f501a48cbe209..e4331dfa7f83e 100644 --- a/hw/ip/mbx/rtl/mbx_hostif.sv +++ b/hw/ip/mbx/rtl/mbx_hostif.sv @@ -34,7 +34,8 @@ module mbx_hostif // Access to the status register output logic hostif_status_busy_clear_o, input logic hostif_status_busy_i, - input logic hostif_status_doe_intr_status_i, + input logic hostif_status_sys_intr_en_i, + input logic hostif_status_sys_intr_state_i, // Access to the IB/OB RD/WR pointers input logic [CfgSramAddrWidth-1:0] hostif_imbx_write_ptr_i, input logic [CfgSramAddrWidth-1:0] hostif_ombx_read_ptr_i, @@ -53,8 +54,7 @@ module mbx_hostif input logic [CfgSramAddrWidth-1:0] sysif_intr_msg_addr_i, input logic [CfgSramDataWidth-1:0] sysif_intr_msg_data_i, // Control inputs coming from the system registers interface - input logic sysif_control_abort_set_i, - input logic sysif_doe_intr_en_i + input logic sysif_control_abort_set_i ); mbx_reg_pkg::mbx_core_reg2hw_t reg2hw; mbx_reg_pkg::mbx_core_hw2reg_t hw2reg; @@ -131,15 +131,7 @@ module mbx_hostif ); // Control Register - // External read logic logic abort_d, abort_q; - assign hw2reg.control.abort.d = abort_q; - // External write logic - // Writing a 1 to control.abort means clearing the abort condition - assign hostif_control_abort_clear_o = reg2hw.control.abort.qe & reg2hw.control.abort.q; - - assign hw2reg.control.doe_intr_en.d = sysif_doe_intr_en_i; - // Abort computation from system and host interface always_comb begin @@ -161,16 +153,22 @@ module mbx_hostif .q_o ( abort_q ) ); + // Writing a 1 to control.abort means clearing the abort condition + assign hostif_control_abort_clear_o = reg2hw.control.abort.qe & reg2hw.control.abort.q; + assign hw2reg.control.abort.d = abort_q; + assign hostif_control_error_set_o = reg2hw.control.error.qe & reg2hw.control.error.q; - assign hw2reg.control.error.d = hostif_control_error_i; + assign hw2reg.control.error.d = hostif_control_error_i; // Status Register // It is implemented as hwext and implemented in a different hierarchy and only providing an // alias. Thus manually assigning the external signals // External read logic - assign hw2reg.status.busy.d = hostif_status_busy_i; - assign hw2reg.status.doe_intr_status.d = hostif_status_doe_intr_status_i; + assign hw2reg.status.busy.d = hostif_status_busy_i; + assign hw2reg.status.sys_intr_enable.d = hostif_status_sys_intr_en_i; + assign hw2reg.status.sys_intr_state.d = hostif_status_sys_intr_state_i; + // External write logic assign hostif_status_busy_clear_o = reg2hw.status.busy.qe & ~reg2hw.status.busy.q; diff --git a/hw/ip/mbx/rtl/mbx_ombx.sv b/hw/ip/mbx/rtl/mbx_ombx.sv index 97296d59a73b4..8cffd2c5e112c 100644 --- a/hw/ip/mbx/rtl/mbx_ombx.sv +++ b/hw/ip/mbx/rtl/mbx_ombx.sv @@ -12,7 +12,7 @@ module mbx_ombx #( input logic clk_i, input logic rst_ni, output logic ombx_state_error_o, - output logic ombx_doe_intr_status_set_o, + output logic ombx_doe_intr_state_set_o, output logic ombx_pending_o, output logic ombx_status_ready_update_o, output logic ombx_status_ready_o, @@ -225,7 +225,7 @@ module mbx_ombx #( ); // Create an DOE interrupt request when the obmx FSM turns into the ready state - assign ombx_doe_intr_status_set_o = ombx_status_ready_o & ombx_status_ready_update_o; + assign ombx_doe_intr_state_set_o = ombx_status_ready_o & ombx_status_ready_update_o; mbx_fsm #( .CfgOmbx ( 1 ) diff --git a/hw/ip/mbx/rtl/mbx_reg_pkg.sv b/hw/ip/mbx/rtl/mbx_reg_pkg.sv index 041a037cfe9ba..bd3eb6e85811d 100644 --- a/hw/ip/mbx/rtl/mbx_reg_pkg.sv +++ b/hw/ip/mbx/rtl/mbx_reg_pkg.sv @@ -115,9 +115,6 @@ package mbx_reg_pkg; struct packed { logic d; } abort; - struct packed { - logic d; - } doe_intr_en; struct packed { logic d; } error; @@ -129,7 +126,10 @@ package mbx_reg_pkg; } busy; struct packed { logic d; - } doe_intr_status; + } sys_intr_state; + struct packed { + logic d; + } sys_intr_enable; } mbx_hw2reg_status_reg_t; typedef struct packed { @@ -172,8 +172,8 @@ package mbx_reg_pkg; // HW -> register type for core interface typedef struct packed { mbx_hw2reg_intr_state_reg_t intr_state; // [144:141] - mbx_hw2reg_control_reg_t control; // [140:138] - mbx_hw2reg_status_reg_t status; // [137:136] + mbx_hw2reg_control_reg_t control; // [140:139] + mbx_hw2reg_status_reg_t status; // [138:136] mbx_hw2reg_inbound_write_ptr_reg_t inbound_write_ptr; // [135:106] mbx_hw2reg_outbound_read_ptr_reg_t outbound_read_ptr; // [105:76] mbx_hw2reg_outbound_object_size_reg_t outbound_object_size; // [75:64] @@ -207,13 +207,13 @@ package mbx_reg_pkg; parameter logic [1:0] MBX_ALERT_TEST_RESVAL = 2'h 0; parameter logic [0:0] MBX_ALERT_TEST_FATAL_FAULT_RESVAL = 1'h 0; parameter logic [0:0] MBX_ALERT_TEST_RECOV_FAULT_RESVAL = 1'h 0; - parameter logic [2:0] MBX_CONTROL_RESVAL = 3'h 0; + parameter logic [1:0] MBX_CONTROL_RESVAL = 2'h 0; parameter logic [0:0] MBX_CONTROL_ABORT_RESVAL = 1'h 0; - parameter logic [0:0] MBX_CONTROL_DOE_INTR_EN_RESVAL = 1'h 0; parameter logic [0:0] MBX_CONTROL_ERROR_RESVAL = 1'h 0; - parameter logic [1:0] MBX_STATUS_RESVAL = 2'h 1; + parameter logic [2:0] MBX_STATUS_RESVAL = 3'h 1; parameter logic [0:0] MBX_STATUS_BUSY_RESVAL = 1'h 1; - parameter logic [0:0] MBX_STATUS_DOE_INTR_STATUS_RESVAL = 1'h 0; + parameter logic [0:0] MBX_STATUS_SYS_INTR_STATE_RESVAL = 1'h 0; + parameter logic [0:0] MBX_STATUS_SYS_INTR_ENABLE_RESVAL = 1'h 0; parameter logic [31:0] MBX_INBOUND_WRITE_PTR_RESVAL = 32'h 0; parameter logic [29:0] MBX_INBOUND_WRITE_PTR_INBOUND_READ_PTR_RESVAL = 30'h 0; parameter logic [31:0] MBX_OUTBOUND_READ_PTR_RESVAL = 32'h 0; diff --git a/hw/ip/mbx/rtl/mbx_sysif.sv b/hw/ip/mbx/rtl/mbx_sysif.sv index 9ab4bc61a43be..74340d178b462 100644 --- a/hw/ip/mbx/rtl/mbx_sysif.sv +++ b/hw/ip/mbx/rtl/mbx_sysif.sv @@ -27,7 +27,7 @@ module mbx_sysif input logic sysif_status_busy_valid_i, input logic sysif_status_busy_i, output logic sysif_status_busy_o, - input logic sysif_status_doe_intr_status_set_i, + input logic sysif_status_doe_intr_state_set_i, input logic sysif_status_error_set_i, output logic sysif_status_error_o, input logic sysif_status_ready_valid_i, @@ -112,8 +112,8 @@ module mbx_sysif // Set by the outbound handler if the DOE interrupt is enabled. Setting this bit creates a DOE // interrupt to the system side. // Cleared by SoC firmware (w1c) - assign hw2reg.soc_status.doe_intr_status.de = sysif_status_doe_intr_status_set_i & doe_intr_en_o; - assign hw2reg.soc_status.doe_intr_status.d = sysif_status_doe_intr_status_set_i; + assign hw2reg.soc_status.doe_intr_status.de = sysif_status_doe_intr_state_set_i & doe_intr_en_o; + assign hw2reg.soc_status.doe_intr_status.d = sysif_status_doe_intr_state_set_i; // Error is cleared when writing the abort bit assign hw2reg.soc_status.error.de = sysif_status_error_set_i | sysif_control_abort_set_o; From 391fceacc3cb04ab30516d9c1981bac8828dfcad Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Wed, 20 Sep 2023 07:08:00 -0700 Subject: [PATCH 35/88] [hw,mbx,rtl] Raise a system IRQ if host raises an error Signed-off-by: Robert Schilling --- hw/ip/mbx/rtl/mbx_ombx.sv | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hw/ip/mbx/rtl/mbx_ombx.sv b/hw/ip/mbx/rtl/mbx_ombx.sv index 8cffd2c5e112c..9013089d16b61 100644 --- a/hw/ip/mbx/rtl/mbx_ombx.sv +++ b/hw/ip/mbx/rtl/mbx_ombx.sv @@ -224,8 +224,10 @@ module mbx_ombx #( .q_o ( first_req_q ) ); - // Create an DOE interrupt request when the obmx FSM turns into the ready state - assign ombx_doe_intr_state_set_o = ombx_status_ready_o & ombx_status_ready_update_o; + // Create an DOE interrupt request when the obmx FSM turns into the ready state or when an error + // is raised + assign ombx_doe_intr_state_set_o = (ombx_status_ready_o & ombx_status_ready_update_o) | + hostif_control_error_set_i; mbx_fsm #( .CfgOmbx ( 1 ) From f6cb5897384aea5cb863507c75548e70c94f12c1 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Wed, 20 Sep 2023 14:47:17 -0700 Subject: [PATCH 36/88] [hw,mbx,rtl] Busy is fully hardware controlled Signed-off-by: Robert Schilling --- hw/ip/mbx/data/mbx.hjson | 6 +++--- hw/ip/mbx/rtl/mbx.sv | 9 ++++++--- hw/ip/mbx/rtl/mbx_core_reg_top.sv | 20 ++++++-------------- hw/ip/mbx/rtl/mbx_fsm.sv | 7 +++---- hw/ip/mbx/rtl/mbx_hostif.sv | 6 +----- hw/ip/mbx/rtl/mbx_imbx.sv | 19 ++++++++----------- hw/ip/mbx/rtl/mbx_ombx.sv | 17 ++++++++--------- hw/ip/mbx/rtl/mbx_reg_pkg.sv | 18 +++++------------- 8 files changed, 40 insertions(+), 62 deletions(-) diff --git a/hw/ip/mbx/data/mbx.hjson b/hw/ip/mbx/data/mbx.hjson index 0e5e1d900f0f1..f490ef694d95f 100644 --- a/hw/ip/mbx/data/mbx.hjson +++ b/hw/ip/mbx/data/mbx.hjson @@ -87,7 +87,7 @@ } { name: "error" desc: ''' - Set by firmware to signal an error, i.e., unable to provide a response to request. + Set by firmware to signal an error, e.g. unable to provide a response to request. Set by hardware, on SYS.WDATA or SYS.RDATA performing an invalid access. Cleared by the hardware when SYS sets CONTROL.ABORT. ''' @@ -108,8 +108,8 @@ desc: "Alias of the DoE mailbox busy bit" bits: "0" resval: "0x1" - swaccess: "rw" - hwaccess: "hrw" + swaccess: "ro" + hwaccess: "hwo" } { name: "sys_intr_state" desc: "Alias of the DoE mailbox interrupt status bit" diff --git a/hw/ip/mbx/rtl/mbx.sv b/hw/ip/mbx/rtl/mbx.sv index 2a48323cd15cd..7f5ea4da2b778 100644 --- a/hw/ip/mbx/rtl/mbx.sv +++ b/hw/ip/mbx/rtl/mbx.sv @@ -61,7 +61,7 @@ module mbx logic sysif_status_busy, sysif_status_error; // Setter signals from the hostif to the sysif - logic hostif_status_busy_clear, hostif_control_abort_clear, hostif_control_error_set; + logic hostif_control_abort_clear, hostif_control_error_set; // Alias signals from the sys interface logic [CfgSramAddrWidth-1:0] sysif_intr_msg_addr; @@ -108,7 +108,6 @@ module mbx .hostif_control_error_set_o ( hostif_control_error_set ), .hostif_control_error_i ( sysif_status_error ), // Access to the status register - .hostif_status_busy_clear_o ( hostif_status_busy_clear ), .hostif_status_busy_i ( sysif_status_busy ), .hostif_status_sys_intr_en_i ( doe_intr_en_o ), .hostif_status_sys_intr_state_i ( doe_intr_o ), @@ -144,6 +143,9 @@ module mbx logic imbx_pending; logic imbx_status_busy_valid, imbx_status_busy; + // Communication from the outbox to the inbox that all data has been read + logic sys_read_all; + // Interface signals for SRAM host access to write the incoming data to memory logic imbx_sram_write_req, imbx_sram_write_gnt; logic imbx_sram_write_resp_vld; @@ -219,7 +221,7 @@ module mbx .imbx_status_busy_o ( imbx_status_busy ), .hostif_control_abort_clear_i( hostif_control_abort_clear ), .hostif_control_error_set_i ( hostif_control_error_set ), - .hostif_status_busy_clear_i ( hostif_status_busy_clear ), + .sys_read_all_i ( sys_read_all ), // SRAM range configuration .hostif_range_valid_i ( hostif_address_range_valid ), .hostif_base_i ( hostif_imbx_base ), @@ -253,6 +255,7 @@ module mbx .hostif_range_valid_i ( hostif_address_range_valid ), .hostif_base_i ( hostif_ombx_base ), .hostif_limit_i ( hostif_ombx_limit ), + .sys_read_all_o ( sys_read_all ), // Control signals from the host and system interface // Writing a 1 to control.abort register clears the abort condition .hostif_control_abort_clear_i ( hostif_control_abort_clear ), diff --git a/hw/ip/mbx/rtl/mbx_core_reg_top.sv b/hw/ip/mbx/rtl/mbx_core_reg_top.sv index c4946947bd2f2..040a742bbb965 100644 --- a/hw/ip/mbx/rtl/mbx_core_reg_top.sv +++ b/hw/ip/mbx/rtl/mbx_core_reg_top.sv @@ -144,9 +144,7 @@ module mbx_core_reg_top ( logic control_error_qs; logic control_error_wd; logic status_re; - logic status_we; logic status_busy_qs; - logic status_busy_wd; logic status_sys_intr_state_qs; logic status_sys_intr_enable_qs; logic address_range_regwen_we; @@ -406,25 +404,22 @@ module mbx_core_reg_top ( // R[status]: V(True) logic status_qe; logic [2:0] status_flds_we; - // This ignores QEs that are set to constant 0 due to read-only fields. - logic unused_status_flds_we; - assign unused_status_flds_we = ^(status_flds_we & 3'h6); - assign status_qe = &(status_flds_we | 3'h6); + // In case all fields are read-only the aggregated register QE will be zero as well. + assign status_qe = &status_flds_we; // F[busy]: 0:0 prim_subreg_ext #( .DW (1) ) u_status_busy ( .re (status_re), - .we (status_we), - .wd (status_busy_wd), + .we (1'b0), + .wd ('0), .d (hw2reg.status.busy.d), .qre (), .qe (status_flds_we[0]), - .q (reg2hw.status.busy.q), + .q (), .ds (), .qs (status_busy_qs) ); - assign reg2hw.status.busy.qe = status_qe; // F[sys_intr_state]: 1:1 prim_subreg_ext #( @@ -824,9 +819,6 @@ module mbx_core_reg_top ( assign control_error_wd = reg_wdata[1]; assign status_re = addr_hit[5] & reg_re & !reg_error; - assign status_we = addr_hit[5] & reg_we & !reg_error; - - assign status_busy_wd = reg_wdata[0]; assign address_range_regwen_we = addr_hit[6] & reg_we & !reg_error; assign address_range_regwen_wd = reg_wdata[3:0]; @@ -861,7 +853,7 @@ module mbx_core_reg_top ( reg_we_check[2] = intr_test_we; reg_we_check[3] = alert_test_we; reg_we_check[4] = control_we; - reg_we_check[5] = status_we; + reg_we_check[5] = 1'b0; reg_we_check[6] = address_range_regwen_we; reg_we_check[7] = address_range_valid_we; reg_we_check[8] = inbound_base_address_gated_we; diff --git a/hw/ip/mbx/rtl/mbx_fsm.sv b/hw/ip/mbx/rtl/mbx_fsm.sv index 86d56d1ebb36b..6ec460ed1d8b8 100644 --- a/hw/ip/mbx/rtl/mbx_fsm.sv +++ b/hw/ip/mbx/rtl/mbx_fsm.sv @@ -12,7 +12,6 @@ module mbx_fsm #( // Control input signals input logic mbx_range_valid_i, input logic hostif_abort_ack_i, - input logic hostif_status_busy_clear_i, input logic hostif_control_error_set_i, input logic sysif_control_abort_set_i, input logic sys_read_all_i, @@ -116,9 +115,9 @@ module mbx_fsm #( ctrl_state_d = MbxIdle; end else if (sysif_control_abort_set_i) begin // System wants to abort ctrl_state_d = MbxSysAbortHost; - end else if (sys_read_all_i | hostif_status_busy_clear_i) begin - // Inbound mailbox: Host (FW) finishes the read - // Outbound mailbox: Object reader (HW) finishes the read + end else if (sys_read_all_i) begin + // Inbound and outbound mailbox go back to idle after all data has + // been read by the sys requester ctrl_state_d = MbxIdle; end end diff --git a/hw/ip/mbx/rtl/mbx_hostif.sv b/hw/ip/mbx/rtl/mbx_hostif.sv index e4331dfa7f83e..7902f56523ddc 100644 --- a/hw/ip/mbx/rtl/mbx_hostif.sv +++ b/hw/ip/mbx/rtl/mbx_hostif.sv @@ -32,7 +32,6 @@ module mbx_hostif output logic hostif_control_error_set_o, input logic hostif_control_error_i, // Access to the status register - output logic hostif_status_busy_clear_o, input logic hostif_status_busy_i, input logic hostif_status_sys_intr_en_i, input logic hostif_status_sys_intr_state_i, @@ -155,7 +154,7 @@ module mbx_hostif // Writing a 1 to control.abort means clearing the abort condition assign hostif_control_abort_clear_o = reg2hw.control.abort.qe & reg2hw.control.abort.q; - assign hw2reg.control.abort.d = abort_q; + assign hw2reg.control.abort.d = abort_q; assign hostif_control_error_set_o = reg2hw.control.error.qe & reg2hw.control.error.q; assign hw2reg.control.error.d = hostif_control_error_i; @@ -169,9 +168,6 @@ module mbx_hostif assign hw2reg.status.sys_intr_enable.d = hostif_status_sys_intr_en_i; assign hw2reg.status.sys_intr_state.d = hostif_status_sys_intr_state_i; - // External write logic - assign hostif_status_busy_clear_o = reg2hw.status.busy.qe & ~reg2hw.status.busy.q; - // Address config valid assign hostif_address_range_valid_o = reg2hw.address_range_valid.q; diff --git a/hw/ip/mbx/rtl/mbx_imbx.sv b/hw/ip/mbx/rtl/mbx_imbx.sv index 4953ee28215cd..709938199f6a7 100644 --- a/hw/ip/mbx/rtl/mbx_imbx.sv +++ b/hw/ip/mbx/rtl/mbx_imbx.sv @@ -20,11 +20,11 @@ module mbx_imbx #( // Writing a 1 to control.abort register clears the abort condition input logic hostif_control_abort_clear_i, input logic hostif_control_error_set_i, - input logic hostif_status_busy_clear_i, // Range configuration for the private SRAM input logic hostif_range_valid_i, input logic [CfgSramAddrWidth-1:0] hostif_base_i, input logic [CfgSramAddrWidth-1:0] hostif_limit_i, + input logic sys_read_all_i, // Device interface from the system side input logic sysif_status_busy_i, input logic sysif_control_go_set_i, @@ -68,8 +68,7 @@ module mbx_imbx #( assign sys_clear_abort = hostif_control_abort_clear_i & mbx_sys_abort; // Rewind the write pointer to the base - assign load_write_ptr = mbx_empty | sys_clear_abort | - (mbx_read & hostif_status_busy_clear_i); + assign load_write_ptr = mbx_empty | sys_clear_abort | (mbx_read & sys_read_all_i); // Advance the write pointer when the valid write command is granted by the tlul_adaptor_host assign advance_write_ptr = hostif_sram_write_req_o & hostif_sram_write_gnt_i; @@ -115,16 +114,15 @@ module mbx_imbx #( logic imbx_set_busy, imbx_clear_busy; assign imbx_set_busy = (mbx_write & sysif_control_go_set_i & - ~hostif_control_error_set_i & + ~hostif_control_error_set_i & ~sysif_control_abort_set_i) | sysif_control_abort_set_i | ~hostif_range_valid_i; - // Exit of mailbox read is used to clear imbx.busy and imbx.ready - // Not yet qualified with mbx_read - assign imbx_clear_busy = hostif_control_error_set_i | - sysif_control_abort_set_i | - hostif_status_busy_clear_i; + // Clear the busy signal if + // - all data has been been read from the outbound mailbox + // - the host acknowledges an abort request from the sys + assign imbx_clear_busy = sys_read_all_i | hostif_control_abort_clear_i; // External busy update interface assign imbx_status_busy_update_o = imbx_set_busy | imbx_clear_busy; @@ -143,10 +141,9 @@ module mbx_imbx #( .rst_ni ( rst_ni ), .mbx_range_valid_i ( hostif_range_valid_i ), .hostif_abort_ack_i ( hostif_control_abort_clear_i ), - .hostif_status_busy_clear_i( hostif_status_busy_clear_i ), .hostif_control_error_set_i( hostif_control_error_set_i ), .sysif_control_abort_set_i ( sysif_control_abort_set_i ), - .sys_read_all_i ( 1'b0 ), + .sys_read_all_i ( sys_read_all_i ), .writer_close_mbx_i ( sysif_control_go_set_i ), .writer_write_valid_i ( sysif_data_write_valid_i ), // Status signals diff --git a/hw/ip/mbx/rtl/mbx_ombx.sv b/hw/ip/mbx/rtl/mbx_ombx.sv index 9013089d16b61..d36af6ab6e3c0 100644 --- a/hw/ip/mbx/rtl/mbx_ombx.sv +++ b/hw/ip/mbx/rtl/mbx_ombx.sv @@ -19,6 +19,7 @@ module mbx_ombx #( input logic hostif_range_valid_i, input logic [CfgSramAddrWidth-1:0] hostif_base_i, input logic [CfgSramAddrWidth-1:0] hostif_limit_i, + output logic sys_read_all_o, // Control signals from the host and system interface // Writing a 1 to control.abort register clears the abort condition input logic hostif_control_abort_clear_i, @@ -100,10 +101,9 @@ module mbx_ombx #( assign writer_close_mbx = mbx_empty & ombx_sram_read_resp_valid_i; // Terminate mbx_read state (Ready = 1 -> 0) if ombx is already drained (sram_read is not issued) - logic sys_read_all; - assign sys_read_all = mbx_read & - sysif_read_data_write_valid_i & - (sram_read_ptr_q == sram_read_ptr_limit_q); + assign sys_read_all_o = mbx_read & + sysif_read_data_write_valid_i & + (sram_read_ptr_q == sram_read_ptr_limit_q); logic host_clear_abort; assign host_clear_abort = hostif_control_abort_clear_i & mbx_sys_abort; @@ -112,7 +112,7 @@ module mbx_ombx #( logic load_read_ptr, advance_read_ptr; // Rewind the read pointer to the base - assign load_read_ptr = set_first_req | sys_read_all | host_clear_abort; + assign load_read_ptr = set_first_req | sys_read_all_o | host_clear_abort; // Advance the read pointer when one request went through assign advance_read_ptr = ombx_sram_read_req_o & ombx_sram_read_gnt_i; @@ -141,7 +141,7 @@ module mbx_ombx #( // Clear ombx read data register in case of all data is read, an error happens, // or the requester aborts the transaction logic clear_read_data; - assign clear_read_data = sys_read_all | + assign clear_read_data = sys_read_all_o | hostif_control_error_set_i | sysif_control_abort_set_i; // Advance the SRAM read response to read data @@ -224,7 +224,7 @@ module mbx_ombx #( .q_o ( first_req_q ) ); - // Create an DOE interrupt request when the obmx FSM turns into the ready state or when an error + // Create a DOE interrupt request when the obmx FSM turns into the ready state or when an error // is raised assign ombx_doe_intr_state_set_o = (ombx_status_ready_o & ombx_status_ready_update_o) | hostif_control_error_set_i; @@ -236,10 +236,9 @@ module mbx_ombx #( .rst_ni ( rst_ni ), .mbx_range_valid_i ( hostif_range_valid_i ), .hostif_abort_ack_i ( hostif_control_abort_clear_i ), - .hostif_status_busy_clear_i( 1'b0 ), .hostif_control_error_set_i( hostif_control_error_set_i ), .sysif_control_abort_set_i ( sysif_control_abort_set_i ), - .sys_read_all_i ( sys_read_all ), + .sys_read_all_i ( sys_read_all_o ), .writer_close_mbx_i ( writer_close_mbx ), .writer_write_valid_i ( 1'b0 ), // Status signals diff --git a/hw/ip/mbx/rtl/mbx_reg_pkg.sv b/hw/ip/mbx/rtl/mbx_reg_pkg.sv index bd3eb6e85811d..588de5c54a537 100644 --- a/hw/ip/mbx/rtl/mbx_reg_pkg.sv +++ b/hw/ip/mbx/rtl/mbx_reg_pkg.sv @@ -68,13 +68,6 @@ package mbx_reg_pkg; } abort; } mbx_reg2hw_control_reg_t; - typedef struct packed { - struct packed { - logic q; - logic qe; - } busy; - } mbx_reg2hw_status_reg_t; - typedef struct packed { logic q; } mbx_reg2hw_address_range_valid_reg_t; @@ -155,12 +148,11 @@ package mbx_reg_pkg; // Register -> HW type for core interface typedef struct packed { - mbx_reg2hw_intr_state_reg_t intr_state; // [150:149] - mbx_reg2hw_intr_enable_reg_t intr_enable; // [148:147] - mbx_reg2hw_intr_test_reg_t intr_test; // [146:143] - mbx_reg2hw_alert_test_reg_t alert_test; // [142:139] - mbx_reg2hw_control_reg_t control; // [138:135] - mbx_reg2hw_status_reg_t status; // [134:133] + mbx_reg2hw_intr_state_reg_t intr_state; // [148:147] + mbx_reg2hw_intr_enable_reg_t intr_enable; // [146:145] + mbx_reg2hw_intr_test_reg_t intr_test; // [144:141] + mbx_reg2hw_alert_test_reg_t alert_test; // [140:137] + mbx_reg2hw_control_reg_t control; // [136:133] mbx_reg2hw_address_range_valid_reg_t address_range_valid; // [132:132] mbx_reg2hw_inbound_base_address_reg_t inbound_base_address; // [131:102] mbx_reg2hw_inbound_limit_address_reg_t inbound_limit_address; // [101:72] From 063d5aa341ab651d79b5dbb04a459bf61ad1eadb Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Wed, 20 Sep 2023 15:24:29 -0700 Subject: [PATCH 37/88] [hw,mbx,rtl] Fix permissions on CORE.STATUS and SOC.CONTROL Signed-off-by: Robert Schilling --- hw/ip/mbx/data/mbx.hjson | 3 +-- hw/ip/mbx/rtl/mbx_core_reg_top.sv | 10 +++------- hw/ip/mbx/rtl/mbx_soc_reg_top.sv | 12 ++++++------ 3 files changed, 10 insertions(+), 15 deletions(-) diff --git a/hw/ip/mbx/data/mbx.hjson b/hw/ip/mbx/data/mbx.hjson index f490ef694d95f..58160b4c83655 100644 --- a/hw/ip/mbx/data/mbx.hjson +++ b/hw/ip/mbx/data/mbx.hjson @@ -102,7 +102,6 @@ { name: "STATUS" desc: "DOE mailbox status register visible to OpenTitan" hwext: "true" - hwqe: "true" fields: [ { name: "busy" desc: "Alias of the DoE mailbox busy bit" @@ -346,7 +345,7 @@ ''' bits: "1" resval: "0x0" - swaccess: "ro" + swaccess: "rw" } { name: "go" desc: ''' diff --git a/hw/ip/mbx/rtl/mbx_core_reg_top.sv b/hw/ip/mbx/rtl/mbx_core_reg_top.sv index 040a742bbb965..290220f8437f3 100644 --- a/hw/ip/mbx/rtl/mbx_core_reg_top.sv +++ b/hw/ip/mbx/rtl/mbx_core_reg_top.sv @@ -402,10 +402,6 @@ module mbx_core_reg_top ( // R[status]: V(True) - logic status_qe; - logic [2:0] status_flds_we; - // In case all fields are read-only the aggregated register QE will be zero as well. - assign status_qe = &status_flds_we; // F[busy]: 0:0 prim_subreg_ext #( .DW (1) @@ -415,7 +411,7 @@ module mbx_core_reg_top ( .wd ('0), .d (hw2reg.status.busy.d), .qre (), - .qe (status_flds_we[0]), + .qe (), .q (), .ds (), .qs (status_busy_qs) @@ -430,7 +426,7 @@ module mbx_core_reg_top ( .wd ('0), .d (hw2reg.status.sys_intr_state.d), .qre (), - .qe (status_flds_we[1]), + .qe (), .q (), .ds (), .qs (status_sys_intr_state_qs) @@ -445,7 +441,7 @@ module mbx_core_reg_top ( .wd ('0), .d (hw2reg.status.sys_intr_enable.d), .qre (), - .qe (status_flds_we[2]), + .qe (), .q (), .ds (), .qs (status_sys_intr_enable_qs) diff --git a/hw/ip/mbx/rtl/mbx_soc_reg_top.sv b/hw/ip/mbx/rtl/mbx_soc_reg_top.sv index 7256559d62e2a..83ea87657d931 100644 --- a/hw/ip/mbx/rtl/mbx_soc_reg_top.sv +++ b/hw/ip/mbx/rtl/mbx_soc_reg_top.sv @@ -183,6 +183,7 @@ module mbx_soc_reg_top ( logic soc_control_we; logic soc_control_abort_wd; logic soc_control_doe_intr_en_qs; + logic soc_control_doe_intr_en_wd; logic soc_control_go_wd; logic soc_status_we; logic soc_status_busy_qs; @@ -251,10 +252,7 @@ module mbx_soc_reg_top ( // R[soc_control]: V(True) logic soc_control_qe; logic [2:0] soc_control_flds_we; - // This ignores QEs that are set to constant 0 due to read-only fields. - logic unused_soc_control_flds_we; - assign unused_soc_control_flds_we = ^(soc_control_flds_we & 3'h2); - assign soc_control_qe = &(soc_control_flds_we | 3'h2); + assign soc_control_qe = &soc_control_flds_we; // F[abort]: 0:0 prim_subreg_ext #( .DW (1) @@ -276,8 +274,8 @@ module mbx_soc_reg_top ( .DW (1) ) u_soc_control_doe_intr_en ( .re (soc_control_re), - .we (1'b0), - .wd ('0), + .we (soc_control_we), + .wd (soc_control_doe_intr_en_wd), .d (hw2reg.soc_control.doe_intr_en.d), .qre (), .qe (soc_control_flds_we[1]), @@ -447,6 +445,8 @@ module mbx_soc_reg_top ( assign soc_control_abort_wd = reg_wdata[0]; + assign soc_control_doe_intr_en_wd = reg_wdata[1]; + assign soc_control_go_wd = reg_wdata[31]; assign soc_status_we = addr_hit[3] & reg_we & !reg_error; From 9f5c6498889f4555c36318a54d32907a0b421c35 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Thu, 21 Sep 2023 01:41:43 -0700 Subject: [PATCH 38/88] [hw,mbx,rtl] Add mbx to makefile and fix comment Signed-off-by: Robert Schilling --- hw/ip/mbx/rtl/mbx_imbx.sv | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/hw/ip/mbx/rtl/mbx_imbx.sv b/hw/ip/mbx/rtl/mbx_imbx.sv index 709938199f6a7..05b6cef99b126 100644 --- a/hw/ip/mbx/rtl/mbx_imbx.sv +++ b/hw/ip/mbx/rtl/mbx_imbx.sv @@ -115,9 +115,10 @@ module mbx_imbx #( assign imbx_set_busy = (mbx_write & sysif_control_go_set_i & ~hostif_control_error_set_i & - ~sysif_control_abort_set_i) | - sysif_control_abort_set_i | - ~hostif_range_valid_i; + ~sysif_control_abort_set_i + ) | + sysif_control_abort_set_i | + ~hostif_range_valid_i; // Clear the busy signal if // - all data has been been read from the outbound mailbox From bcecadb01bab980c22107d91020bf3c1a8c7eb37 Mon Sep 17 00:00:00 2001 From: Andreas Kurth Date: Tue, 19 Sep 2023 14:09:19 +0000 Subject: [PATCH 39/88] [mbx/rtl] Comment broken assertions out All these assertions include at least one undefined signal. We don't have time to fix them right now; this is tracked in issue lowRISC/opentitan-integrated#476. Signed-off-by: Andreas Kurth --- hw/ip/mbx/rtl/mbx_imbx.sv | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/hw/ip/mbx/rtl/mbx_imbx.sv b/hw/ip/mbx/rtl/mbx_imbx.sv index 05b6cef99b126..92ee0ee9a673b 100644 --- a/hw/ip/mbx/rtl/mbx_imbx.sv +++ b/hw/ip/mbx/rtl/mbx_imbx.sv @@ -162,7 +162,7 @@ module mbx_imbx #( ////////////////////////////////////////////////////////////////////////////// // Don't write the mailbox if it is full - `ASSERT(NeverWriteMbxIfFull_A, imbx_is_full & hostif_sram_write_req_o) + // `ASSERT(NeverWriteMbxIfFull_A, imbx_is_full & hostif_sram_write_req_o) TODO(#476) `ifdef INC_ASSERT logic[CfgSramAddrWidth-1:0] sram_write_ptr_assert_q; @@ -182,11 +182,11 @@ module mbx_imbx #( // The write pointer should not be advanced if there is not yet acked request `ASSERT_IF(WrPtrShouldNotAdvanceIfNoAck_A, ~imbx_pending_o, advance_write_ptr & imbx_pending_o) // Clear busy/abort does not clear the IRQ - `ASSERT_IF(ClearBusyAbortDoesNotClearIrq_A, sysif_status_busy_i == imbx_irq_host_o, - sysif_status_busy_i & imbx_irq_host_o) + // `ASSERT_IF(ClearBusyAbortDoesNotClearIrq_A, sysif_status_busy_i == imbx_irq_host_o, + // sysif_status_busy_i & imbx_irq_host_o) TODO(#476) // Busy and host IRQ are not set together - `ASSERT_IF(BusyIrqNotSetTogether_A, sysif_status_busy_i & imbx_irq_host_o, - sysif_control_go_set_i | sysif_control_abort_set_i) + // `ASSERT_IF(BusyIrqNotSetTogether_A, sysif_status_busy_i & imbx_irq_host_o, + // sysif_control_go_set_i | sysif_control_abort_set_i) TODO(#476) // When writing to the mailbox, DOE status busy must be low `ASSERT_NEVER(WriteToMbxBusyMustBeLow_A, hostif_sram_write_req_o & sysif_status_busy_i) From 5a4c191ebd0fb16cc18bdc2400f1565abe3a515f Mon Sep 17 00:00:00 2001 From: Andreas Kurth Date: Wed, 20 Sep 2023 12:03:28 +0000 Subject: [PATCH 40/88] [mbx] Exclude most CSRs from automated tests Many of Mailbox's CSRs have side effects or are implemented by a hardware mechanism that automated CSR tests are not aware of. For this reason, those CSRs have to be (partially) excluded from automated tests. To enable progress, at the moment probably too many exclusions are in place, though. This should be revisited, which is tracked in issue lowRISC/opentitan-integrated#477 and by the TODO comments in this commit. Signed-off-by: Andreas Kurth --- hw/ip/mbx/data/mbx.hjson | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/hw/ip/mbx/data/mbx.hjson b/hw/ip/mbx/data/mbx.hjson index 58160b4c83655..379a0396d6474 100644 --- a/hw/ip/mbx/data/mbx.hjson +++ b/hw/ip/mbx/data/mbx.hjson @@ -98,6 +98,7 @@ hwqe: "true" } ] + tags: ["excl:CsrAllTests:CsrExclAll"] // alias of another register; no automated CSR tests applicable } { name: "STATUS" desc: "DOE mailbox status register visible to OpenTitan" @@ -125,6 +126,7 @@ hwaccess: "hwo" } ] + tags: ["excl:CsrAllTests:CsrExclAll"] // alias of another register; no automated CSR tests applicable } { name: "ADDRESS_RANGE_REGWEN" desc: "Used to lock the inbound/outbound base/limit configuration registers." @@ -142,6 +144,7 @@ resval: true } ] + tags: ["excl:CsrNonInitTests:CsrExclAll"] // only check initial value because writing will have side effects } { name: "ADDRESS_RANGE_VALID" desc: "Used to mark the inbound/outbound base/limit configuration registers to have a valid configuration." @@ -154,6 +157,7 @@ resval: "0" } ] + tags: ["excl:CsrAllTests:CsrExclAll"] // TODO(#477) } { name: "INBOUND_BASE_ADDRESS" desc: '''Base address of SRAM region, which is used to back up the inbound mailbox data. @@ -169,6 +173,7 @@ resval: "0x0" } ] + tags: ["excl:CsrAllTests:CsrExclAll"] // TODO(#477) } { name: "INBOUND_LIMIT_ADDRESS" desc: '''Limit Address to mark the end of the inbound mailbox memory range in the private SRAM.. @@ -199,6 +204,7 @@ hwaccess: "hwo" } ] + tags: ["excl:CsrAllTests:CsrExclAll"] // TODO(#477) } { name: "OUTBOUND_BASE_ADDRESS" desc: '''Base address of SRAM region, which is used to buffer the outbound mailbox data. @@ -214,6 +220,7 @@ resval: "0x0" } ] + tags: ["excl:CsrAllTests:CsrExclAll"] // TODO(#477) } { name: "OUTBOUND_LIMIT_ADDRESS" desc: '''Limit Address to mark the end of the outbound mailbox memory range in the private SRAM. @@ -229,6 +236,7 @@ resval: "0x0" } ] + tags: ["excl:CsrAllTests:CsrExclAll"] // TODO(#477) } { name: "OUTBOUND_READ_PTR" desc: '''Read pointer for the next outbound data read. @@ -244,6 +252,7 @@ hwaccess: "hwo" } ] + tags: ["excl:CsrAllTests:CsrExclAll"] // TODO(#477) } { name: "OUTBOUND_OBJECT_SIZE" desc: '''Indicates the size of the data object to be transferred out. @@ -260,6 +269,7 @@ hwqe: "true" } ] + tags: ["excl:CsrAllTests:CsrExclAll"] // TODO(#477) } { name: "DOE_INTR_MSG_ADDR" desc: ''' @@ -276,6 +286,7 @@ resval: "0x0" } ] + tags: ["excl:CsrAllTests:CsrExclAll"] // TODO(#477) } { name: "DOE_INTR_MSG_DATA" desc: ''' @@ -292,6 +303,7 @@ resval: "0x0" } ] + tags: ["excl:CsrAllTests:CsrExclAll"] // TODO(#477) } ] soc: [ @@ -356,6 +368,7 @@ swaccess: "wo" } ] + tags: ["excl:CsrNonInitTests:CsrExclAll"] // only check initial value because writing will have side effects } { name: "SOC_STATUS" desc: "DOE mailbox status register" @@ -397,6 +410,7 @@ hwaccess: "hwo" } ] + tags: ["excl:CsrAllTests:CsrExclAll"] // TODO(#477) } { window: { name: "WDATA" From 997f00f51b0ccb06a9dc0a4a7533cf41a7f8195c Mon Sep 17 00:00:00 2001 From: Andreas Kurth Date: Tue, 19 Sep 2023 13:43:37 +0000 Subject: [PATCH 41/88] [sw/mbx] Add scaffold of DIF Signed-off-by: Andreas Kurth --- hw/ip/mbx/data/BUILD | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/hw/ip/mbx/data/BUILD b/hw/ip/mbx/data/BUILD index 730e284d2d896..acf012522e046 100644 --- a/hw/ip/mbx/data/BUILD +++ b/hw/ip/mbx/data/BUILD @@ -6,6 +6,13 @@ package(default_visibility = ["//visibility:public"]) load("//rules:autogen.bzl", "autogen_hjson_header") +autogen_hjson_header( + name = "mbx_regs", + srcs = [ + "mbx.hjson", + ], +) + filegroup( name = "all_files", srcs = glob(["**"]), From c0ea37f08b0ff0d3318d590ab83aff8f751e6440 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Tue, 3 Oct 2023 02:41:24 -0700 Subject: [PATCH 42/88] [hw,mbx,rtl] Fix undriven signals and busy clear This PR fixes two issues: * It connects drives sysif_status_ready_i * It clears the busy signal if the memory range becomes valid Signed-off-by: Robert Schilling --- hw/ip/mbx/data/mbx.hjson | 1 + hw/ip/mbx/rtl/mbx.sv | 49 ++++++++++++++++--------------- hw/ip/mbx/rtl/mbx_core_reg_top.sv | 14 ++++++++- hw/ip/mbx/rtl/mbx_hostif.sv | 4 ++- hw/ip/mbx/rtl/mbx_imbx.sv | 6 +++- hw/ip/mbx/rtl/mbx_ombx.sv | 4 +-- hw/ip/mbx/rtl/mbx_reg_pkg.sv | 13 ++++---- 7 files changed, 57 insertions(+), 34 deletions(-) diff --git a/hw/ip/mbx/data/mbx.hjson b/hw/ip/mbx/data/mbx.hjson index 379a0396d6474..9c69e7a41b94d 100644 --- a/hw/ip/mbx/data/mbx.hjson +++ b/hw/ip/mbx/data/mbx.hjson @@ -150,6 +150,7 @@ desc: "Used to mark the inbound/outbound base/limit configuration registers to have a valid configuration." swaccess: "rw" hwaccess: "hro" + hwqe: "true" fields: [ { name: "range_valid" desc: "Once set the mailbox inbound/outbound base/limit registers are valid." diff --git a/hw/ip/mbx/rtl/mbx.sv b/hw/ip/mbx/rtl/mbx.sv index 7f5ea4da2b778..863b97f78f93c 100644 --- a/hw/ip/mbx/rtl/mbx.sv +++ b/hw/ip/mbx/rtl/mbx.sv @@ -54,7 +54,7 @@ module mbx ////////////////////////////////////////////////////////////////////////////// logic hostif_event_intr_ready, hostif_event_intr_abort; - logic hostif_address_range_valid; + logic hostif_address_range_valid, hostif_address_range_valid_write; logic sysif_control_abort_set; // Status signal inputs from the sysif to the hostif @@ -115,6 +115,7 @@ module mbx .hostif_imbx_write_ptr_i ( imbx_sram_write_ptr ), .hostif_ombx_read_ptr_i ( ombx_sram_read_ptr ), // Access to the memory region registers + .hostif_address_range_valid_write_o ( hostif_address_range_valid_write ), .hostif_address_range_valid_o ( hostif_address_range_valid ), .hostif_imbx_base_o ( hostif_imbx_base ), .hostif_imbx_limit_o ( hostif_imbx_limit ), @@ -210,31 +211,32 @@ module mbx .CfgSramAddrWidth( CfgSramAddrWidth ), .CfgSramDataWidth( CfgSramDataWidth ) ) u_imbx ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), // Interface to the host port - .imbx_state_error_o ( imbx_state_error ), - .imbx_pending_o ( imbx_pending ), - .imbx_irq_ready_o ( hostif_event_intr_ready ), - .imbx_irq_abort_o ( hostif_event_intr_abort ), - .imbx_status_busy_update_o ( imbx_status_busy_valid ), - .imbx_status_busy_o ( imbx_status_busy ), - .hostif_control_abort_clear_i( hostif_control_abort_clear ), - .hostif_control_error_set_i ( hostif_control_error_set ), - .sys_read_all_i ( sys_read_all ), + .imbx_state_error_o ( imbx_state_error ), + .imbx_pending_o ( imbx_pending ), + .imbx_irq_ready_o ( hostif_event_intr_ready ), + .imbx_irq_abort_o ( hostif_event_intr_abort ), + .imbx_status_busy_update_o ( imbx_status_busy_valid ), + .imbx_status_busy_o ( imbx_status_busy ), + .hostif_control_abort_clear_i( hostif_control_abort_clear ), + .hostif_control_error_set_i ( hostif_control_error_set ), + .sys_read_all_i ( sys_read_all ), // SRAM range configuration - .hostif_range_valid_i ( hostif_address_range_valid ), - .hostif_base_i ( hostif_imbx_base ), - .hostif_limit_i ( hostif_imbx_limit ), + .hostif_range_valid_write_i ( hostif_address_range_valid_write ), + .hostif_range_valid_i ( hostif_address_range_valid ), + .hostif_base_i ( hostif_imbx_base ), + .hostif_limit_i ( hostif_imbx_limit ), // Interface to the system port - .sysif_status_busy_i ( sysif_status_busy ), - .sysif_control_go_set_i ( sysif_control_go_set ), - .sysif_control_abort_set_i ( sysif_control_abort_set ), - .sysif_data_write_valid_i ( sysif_write_data_write_valid ), + .sysif_status_busy_i ( sysif_status_busy ), + .sysif_control_go_set_i ( sysif_control_go_set ), + .sysif_control_abort_set_i ( sysif_control_abort_set ), + .sysif_data_write_valid_i ( sysif_write_data_write_valid ), // Host interface to access private SRAM - .hostif_sram_write_req_o ( imbx_sram_write_req ), - .hostif_sram_write_gnt_i ( imbx_sram_write_gnt ), - .hostif_sram_write_ptr_o ( imbx_sram_write_ptr ) + .hostif_sram_write_req_o ( imbx_sram_write_req ), + .hostif_sram_write_gnt_i ( imbx_sram_write_gnt ), + .hostif_sram_write_ptr_o ( imbx_sram_write_ptr ) ); @@ -256,7 +258,8 @@ module mbx .hostif_base_i ( hostif_ombx_base ), .hostif_limit_i ( hostif_ombx_limit ), .sys_read_all_o ( sys_read_all ), - // Control signals from the host and system interface + // Control and signals from the host and system interface + .sysif_status_ready_i ( ombx_status_ready ), // Writing a 1 to control.abort register clears the abort condition .hostif_control_abort_clear_i ( hostif_control_abort_clear ), .hostif_control_error_set_i ( hostif_control_error_set ), diff --git a/hw/ip/mbx/rtl/mbx_core_reg_top.sv b/hw/ip/mbx/rtl/mbx_core_reg_top.sv index 290220f8437f3..568653c2d51c0 100644 --- a/hw/ip/mbx/rtl/mbx_core_reg_top.sv +++ b/hw/ip/mbx/rtl/mbx_core_reg_top.sv @@ -477,6 +477,17 @@ module mbx_core_reg_top ( // R[address_range_valid]: V(False) + logic address_range_valid_qe; + logic [0:0] address_range_valid_flds_we; + prim_flop #( + .Width(1), + .ResetValue(0) + ) u_address_range_valid0_qe ( + .clk_i(clk_i), + .rst_ni(rst_ni), + .d_i(&address_range_valid_flds_we), + .q_o(address_range_valid_qe) + ); prim_subreg #( .DW (1), .SwAccess(prim_subreg_pkg::SwAccessRW), @@ -495,13 +506,14 @@ module mbx_core_reg_top ( .d ('0), // to internal hardware - .qe (), + .qe (address_range_valid_flds_we[0]), .q (reg2hw.address_range_valid.q), .ds (), // to register interface (read) .qs (address_range_valid_qs) ); + assign reg2hw.address_range_valid.qe = address_range_valid_qe; // R[inbound_base_address]: V(False) diff --git a/hw/ip/mbx/rtl/mbx_hostif.sv b/hw/ip/mbx/rtl/mbx_hostif.sv index 7902f56523ddc..c58b3a518d3b5 100644 --- a/hw/ip/mbx/rtl/mbx_hostif.sv +++ b/hw/ip/mbx/rtl/mbx_hostif.sv @@ -39,6 +39,7 @@ module mbx_hostif input logic [CfgSramAddrWidth-1:0] hostif_imbx_write_ptr_i, input logic [CfgSramAddrWidth-1:0] hostif_ombx_read_ptr_i, // Base/Limit for in/outbound mailbox + output logic hostif_address_range_valid_write_o, output logic hostif_address_range_valid_o, output logic [CfgSramAddrWidth-1:0] hostif_imbx_base_o, output logic [CfgSramAddrWidth-1:0] hostif_imbx_limit_o, @@ -169,7 +170,8 @@ module mbx_hostif assign hw2reg.status.sys_intr_state.d = hostif_status_sys_intr_state_i; // Address config valid - assign hostif_address_range_valid_o = reg2hw.address_range_valid.q; + assign hostif_address_range_valid_write_o = reg2hw.address_range_valid.qe; + assign hostif_address_range_valid_o = reg2hw.address_range_valid.q; // Inbound Mailbox Base/Limit Register assign hostif_imbx_base_o = { reg2hw.inbound_base_address.q, {2{1'b0}} }; diff --git a/hw/ip/mbx/rtl/mbx_imbx.sv b/hw/ip/mbx/rtl/mbx_imbx.sv index 92ee0ee9a673b..e3d2da974f519 100644 --- a/hw/ip/mbx/rtl/mbx_imbx.sv +++ b/hw/ip/mbx/rtl/mbx_imbx.sv @@ -21,6 +21,7 @@ module mbx_imbx #( input logic hostif_control_abort_clear_i, input logic hostif_control_error_set_i, // Range configuration for the private SRAM + input logic hostif_range_valid_write_i, input logic hostif_range_valid_i, input logic [CfgSramAddrWidth-1:0] hostif_base_i, input logic [CfgSramAddrWidth-1:0] hostif_limit_i, @@ -121,9 +122,12 @@ module mbx_imbx #( ~hostif_range_valid_i; // Clear the busy signal if + // - the private SRAM range becomes valid // - all data has been been read from the outbound mailbox // - the host acknowledges an abort request from the sys - assign imbx_clear_busy = sys_read_all_i | hostif_control_abort_clear_i; + assign imbx_clear_busy = (hostif_range_valid_write_i & hostif_range_valid_i) | + sys_read_all_i | + hostif_control_abort_clear_i; // External busy update interface assign imbx_status_busy_update_o = imbx_set_busy | imbx_clear_busy; diff --git a/hw/ip/mbx/rtl/mbx_ombx.sv b/hw/ip/mbx/rtl/mbx_ombx.sv index d36af6ab6e3c0..2f79c4e60ff04 100644 --- a/hw/ip/mbx/rtl/mbx_ombx.sv +++ b/hw/ip/mbx/rtl/mbx_ombx.sv @@ -20,11 +20,11 @@ module mbx_ombx #( input logic [CfgSramAddrWidth-1:0] hostif_base_i, input logic [CfgSramAddrWidth-1:0] hostif_limit_i, output logic sys_read_all_o, - // Control signals from the host and system interface + // Control and status signals from the host and system interface // Writing a 1 to control.abort register clears the abort condition + input logic sysif_status_ready_i, input logic hostif_control_abort_clear_i, input logic hostif_control_error_set_i, - input logic sysif_status_ready_i, input logic sysif_control_abort_set_i, input logic sysif_read_data_read_valid_i, input logic sysif_read_data_write_valid_i, diff --git a/hw/ip/mbx/rtl/mbx_reg_pkg.sv b/hw/ip/mbx/rtl/mbx_reg_pkg.sv index 588de5c54a537..84d78de36b33f 100644 --- a/hw/ip/mbx/rtl/mbx_reg_pkg.sv +++ b/hw/ip/mbx/rtl/mbx_reg_pkg.sv @@ -70,6 +70,7 @@ package mbx_reg_pkg; typedef struct packed { logic q; + logic qe; } mbx_reg2hw_address_range_valid_reg_t; typedef struct packed { @@ -148,12 +149,12 @@ package mbx_reg_pkg; // Register -> HW type for core interface typedef struct packed { - mbx_reg2hw_intr_state_reg_t intr_state; // [148:147] - mbx_reg2hw_intr_enable_reg_t intr_enable; // [146:145] - mbx_reg2hw_intr_test_reg_t intr_test; // [144:141] - mbx_reg2hw_alert_test_reg_t alert_test; // [140:137] - mbx_reg2hw_control_reg_t control; // [136:133] - mbx_reg2hw_address_range_valid_reg_t address_range_valid; // [132:132] + mbx_reg2hw_intr_state_reg_t intr_state; // [149:148] + mbx_reg2hw_intr_enable_reg_t intr_enable; // [147:146] + mbx_reg2hw_intr_test_reg_t intr_test; // [145:142] + mbx_reg2hw_alert_test_reg_t alert_test; // [141:138] + mbx_reg2hw_control_reg_t control; // [137:134] + mbx_reg2hw_address_range_valid_reg_t address_range_valid; // [133:132] mbx_reg2hw_inbound_base_address_reg_t inbound_base_address; // [131:102] mbx_reg2hw_inbound_limit_address_reg_t inbound_limit_address; // [101:72] mbx_reg2hw_outbound_base_address_reg_t outbound_base_address; // [71:42] From 2858ef948de4b541ef8102e7243887aa81c5d04f Mon Sep 17 00:00:00 2001 From: Adrian Lees Date: Tue, 3 Oct 2023 16:09:11 +0100 Subject: [PATCH 43/88] [mbx] Advance pointer on initial write Ensure that write pointer advances on initial word of a request message even when bus access is granted immediately, to prevent overwriting of the first message word. Signed-off-by: Adrian Lees --- hw/ip/mbx/rtl/mbx_imbx.sv | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/hw/ip/mbx/rtl/mbx_imbx.sv b/hw/ip/mbx/rtl/mbx_imbx.sv index e3d2da974f519..b8784a572c69c 100644 --- a/hw/ip/mbx/rtl/mbx_imbx.sv +++ b/hw/ip/mbx/rtl/mbx_imbx.sv @@ -69,10 +69,13 @@ module mbx_imbx #( assign sys_clear_abort = hostif_control_abort_clear_i & mbx_sys_abort; // Rewind the write pointer to the base - assign load_write_ptr = mbx_empty | sys_clear_abort | (mbx_read & sys_read_all_i); + // Note: `mbx_empty` and `advance_write_ptr` can both be asserted if bus access is granted + // immediately on the initial word write of a message, and we must advance the write pointer. + assign load_write_ptr = (mbx_empty & ~advance_write_ptr) | sys_clear_abort | + (mbx_read & sys_read_all_i); - // Advance the write pointer when the valid write command is granted by the tlul_adaptor_host - assign advance_write_ptr = hostif_sram_write_req_o & hostif_sram_write_gnt_i; + // Advance the write pointer when the valid write command is granted by the tlul_adapter_host + assign advance_write_ptr = hostif_sram_write_req_o & hostif_sram_write_gnt_i; always_comb begin sram_write_ptr_d = sram_write_ptr_q; From 87b557dbc56411129d79f1e85b3d3043b0d727f8 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Fri, 29 Sep 2023 09:59:22 -0700 Subject: [PATCH 44/88] [hw,mbx,rtl] Fix linting errors on mailbox Signed-off-by: Robert Schilling --- hw/ip/mbx/rtl/mbx_fsm.sv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/ip/mbx/rtl/mbx_fsm.sv b/hw/ip/mbx/rtl/mbx_fsm.sv index 6ec460ed1d8b8..b1138bba6a4e7 100644 --- a/hw/ip/mbx/rtl/mbx_fsm.sv +++ b/hw/ip/mbx/rtl/mbx_fsm.sv @@ -41,7 +41,7 @@ module mbx_fsm #( prim_flop #( .Width($bits(mbx_ctrl_state_e)), - .ResetValue(MbxIdle) + .ResetValue({MbxIdle}) ) aff_ctrl_state_q ( .clk_i ( clk_i ), .rst_ni( rst_ni ), From a5759024bb6e3cfa04984f3a6a30f2499e80158b Mon Sep 17 00:00:00 2001 From: Michael Schaffner Date: Tue, 17 Oct 2023 17:46:12 -0700 Subject: [PATCH 45/88] [mbox/lint] Fix a concatenation error This should be a replication and not a concatenation operation. Signed-off-by: Michael Schaffner --- hw/ip/mbx/rtl/mbx_sramrwarb.sv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/ip/mbx/rtl/mbx_sramrwarb.sv b/hw/ip/mbx/rtl/mbx_sramrwarb.sv index 091e1d448d6eb..4a6215d076192 100644 --- a/hw/ip/mbx/rtl/mbx_sramrwarb.sv +++ b/hw/ip/mbx/rtl/mbx_sramrwarb.sv @@ -90,7 +90,7 @@ module mbx_sramrwarb .we_i ( arb_write_winner ), .wdata_i ( imbx_write_data_i ), .wdata_intg_i ( TL_A_USER_DEFAULT.data_intg ), - .be_i ( {{top_pkg::TL_DBW}{1'b1}} ), + .be_i ( {top_pkg::TL_DBW{1'b1}} ), .instr_type_i ( prim_mubi_pkg::MuBi4False ), .user_rsvd_i ( '0 ), // Response channel From b7e48a068847c7ba30164ac663688a55853f8d3a Mon Sep 17 00:00:00 2001 From: Michael Schaffner Date: Tue, 17 Oct 2023 18:34:59 -0700 Subject: [PATCH 46/88] [mbx/lint] Update waiver Signed-off-by: Michael Schaffner --- hw/ip/mbx/lint/mbx.waiver | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hw/ip/mbx/lint/mbx.waiver b/hw/ip/mbx/lint/mbx.waiver index b22813b2134cf..3a20320111e42 100644 --- a/hw/ip/mbx/lint/mbx.waiver +++ b/hw/ip/mbx/lint/mbx.waiver @@ -4,6 +4,9 @@ # # waiver file for mbx +waive -rules SAME_NAME_TYPE -location {mbx.sv} -regexp {'mbx' is used as a module here, and as a} \ + -comment "The module has a very short name and it is hence possible that other scopes use the same name for a signal." + waive -rules INPUT_NOT_READ -location {mbx_imbx.sv} -regexp {Input port 'sysif_status_busy_i' is not read from} \ -comment "Signal only used for assertions" waive -rules HIER_BRANCH_NOT_READ: -location {mbx_imbx.sv} -regexp {Net 'sysif_status_busy_i' is not read from} \ From 8f9b9f508321368306eea73977d7aab56dae939d Mon Sep 17 00:00:00 2001 From: Adrian Lees Date: Fri, 6 Oct 2023 14:43:40 +0100 Subject: [PATCH 47/88] [mbx] Stable Ready bit required in ombx assertion Outbox assertion requires the current state of Ready bit at all times, not just the transition to Ready. Signed-off-by: Adrian Lees --- hw/ip/mbx/data/mbx.hjson | 2 +- hw/ip/mbx/rtl/mbx.sv | 4 +++- hw/ip/mbx/rtl/mbx_ombx.sv | 2 +- hw/ip/mbx/rtl/mbx_reg_pkg.sv | 11 +++++++---- hw/ip/mbx/rtl/mbx_soc_reg_top.sv | 2 +- hw/ip/mbx/rtl/mbx_sysif.sv | 3 +++ 6 files changed, 16 insertions(+), 8 deletions(-) diff --git a/hw/ip/mbx/data/mbx.hjson b/hw/ip/mbx/data/mbx.hjson index 9c69e7a41b94d..4c92773ed2fba 100644 --- a/hw/ip/mbx/data/mbx.hjson +++ b/hw/ip/mbx/data/mbx.hjson @@ -408,7 +408,7 @@ bits: "31" resval: "0x0" swaccess: "ro" - hwaccess: "hwo" + hwaccess: "hrw" } ] tags: ["excl:CsrAllTests:CsrExclAll"] // TODO(#477) diff --git a/hw/ip/mbx/rtl/mbx.sv b/hw/ip/mbx/rtl/mbx.sv index 863b97f78f93c..6fa4c6bd75fe4 100644 --- a/hw/ip/mbx/rtl/mbx.sv +++ b/hw/ip/mbx/rtl/mbx.sv @@ -158,6 +158,7 @@ module mbx ////////////////////////////////////////////////////////////////////////////// logic ombx_pending; logic ombx_status_ready_valid, ombx_status_ready; + logic sysif_status_ready; logic ombx_doe_intr_state_set; // Interface signals for SRAM host access to read the memory and serve it to the outbox @@ -192,6 +193,7 @@ module mbx .sysif_status_error_o ( sysif_status_error ), .sysif_status_ready_valid_i ( ombx_status_ready_valid ), .sysif_status_ready_i ( ombx_status_ready ), + .sysif_status_ready_o ( sysif_status_ready ), // Alias of the interrupt address and data registers to the host interface .sysif_intr_msg_addr_o ( sysif_intr_msg_addr ), .sysif_intr_msg_data_o ( sysif_intr_msg_data ), @@ -259,7 +261,7 @@ module mbx .hostif_limit_i ( hostif_ombx_limit ), .sys_read_all_o ( sys_read_all ), // Control and signals from the host and system interface - .sysif_status_ready_i ( ombx_status_ready ), + .sysif_status_ready_i ( sysif_status_ready ), // Writing a 1 to control.abort register clears the abort condition .hostif_control_abort_clear_i ( hostif_control_abort_clear ), .hostif_control_error_set_i ( hostif_control_error_set ), diff --git a/hw/ip/mbx/rtl/mbx_ombx.sv b/hw/ip/mbx/rtl/mbx_ombx.sv index 2f79c4e60ff04..c4eee7580bb5f 100644 --- a/hw/ip/mbx/rtl/mbx_ombx.sv +++ b/hw/ip/mbx/rtl/mbx_ombx.sv @@ -280,7 +280,7 @@ module mbx_ombx #( .d_i ( sram_read_ptr_d ), .q_o ( sram_read_ptr_assert_q ) ); - // A granted write by the host adapter must advance the write pointer + // A granted read by the host adapter must advance the read pointer `ASSERT_IF(GntMustAdvanceReadPtr_A, sram_read_ptr_assert_q == sram_read_ptr_q, ombx_sram_read_gnt_i) `endif diff --git a/hw/ip/mbx/rtl/mbx_reg_pkg.sv b/hw/ip/mbx/rtl/mbx_reg_pkg.sv index 84d78de36b33f..5c990e2e82585 100644 --- a/hw/ip/mbx/rtl/mbx_reg_pkg.sv +++ b/hw/ip/mbx/rtl/mbx_reg_pkg.sv @@ -286,6 +286,9 @@ package mbx_reg_pkg; } mbx_reg2hw_soc_control_reg_t; typedef struct packed { + struct packed { + logic q; + } ready; struct packed { logic q; } error; @@ -330,10 +333,10 @@ package mbx_reg_pkg; // Register -> HW type for soc interface typedef struct packed { - mbx_reg2hw_soc_doe_intr_msg_addr_reg_t soc_doe_intr_msg_addr; // [72:41] - mbx_reg2hw_soc_doe_intr_msg_data_reg_t soc_doe_intr_msg_data; // [40:9] - mbx_reg2hw_soc_control_reg_t soc_control; // [8:3] - mbx_reg2hw_soc_status_reg_t soc_status; // [2:0] + mbx_reg2hw_soc_doe_intr_msg_addr_reg_t soc_doe_intr_msg_addr; // [73:42] + mbx_reg2hw_soc_doe_intr_msg_data_reg_t soc_doe_intr_msg_data; // [41:10] + mbx_reg2hw_soc_control_reg_t soc_control; // [9:4] + mbx_reg2hw_soc_status_reg_t soc_status; // [3:0] } mbx_soc_reg2hw_t; // HW -> register type for soc interface diff --git a/hw/ip/mbx/rtl/mbx_soc_reg_top.sv b/hw/ip/mbx/rtl/mbx_soc_reg_top.sv index 83ea87657d931..57774099edd50 100644 --- a/hw/ip/mbx/rtl/mbx_soc_reg_top.sv +++ b/hw/ip/mbx/rtl/mbx_soc_reg_top.sv @@ -404,7 +404,7 @@ module mbx_soc_reg_top ( // to internal hardware .qe (), - .q (), + .q (reg2hw.soc_status.ready.q), .ds (), // to register interface (read) diff --git a/hw/ip/mbx/rtl/mbx_sysif.sv b/hw/ip/mbx/rtl/mbx_sysif.sv index 74340d178b462..c7e82c5391367 100644 --- a/hw/ip/mbx/rtl/mbx_sysif.sv +++ b/hw/ip/mbx/rtl/mbx_sysif.sv @@ -32,6 +32,7 @@ module mbx_sysif output logic sysif_status_error_o, input logic sysif_status_ready_valid_i, input logic sysif_status_ready_i, + output logic sysif_status_ready_o, // Alias of the interrupt address and data registers to the host interface output logic [CfgSramAddrWidth-1:0] sysif_intr_msg_addr_o, output logic [CfgSramDataWidth-1:0] sysif_intr_msg_data_o, @@ -123,6 +124,8 @@ module mbx_sysif // Cleared by SoC firmware (w1c) assign hw2reg.soc_status.ready.de = sysif_status_ready_valid_i; assign hw2reg.soc_status.ready.d = sysif_status_ready_i; + // Ready bit indication into hardware + assign sysif_status_ready_o = reg2hw.soc_status.ready.q; // Dedicated TLUL adapter for implementing the write data mailbox register via a register window. // We use the register window to access the internal bus signals, allowing the mailbox to halt From d3ef3bd6d0868f4cffd8288113ac8fa1d3475aad Mon Sep 17 00:00:00 2001 From: Adrian Lees Date: Thu, 19 Oct 2023 15:23:46 +0100 Subject: [PATCH 48/88] [mbx] Assertion improvements Correct a couple of incorrect assertions to allow smoke test to pass. Ensure that the read/write ptr assertions validate increment. Introduce a new assertion to catch Ready IRQ overtaking write traffic (disabled for now, tracking in lowRISC/opentitan-integrated#476). Minor whitespace tweaks. Signed-off-by: Adrian Lees --- hw/ip/mbx/rtl/mbx_imbx.sv | 30 ++++++++++++++++++------------ hw/ip/mbx/rtl/mbx_ombx.sv | 21 ++++++++++++--------- 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/hw/ip/mbx/rtl/mbx_imbx.sv b/hw/ip/mbx/rtl/mbx_imbx.sv index b8784a572c69c..e16ec734985cd 100644 --- a/hw/ip/mbx/rtl/mbx_imbx.sv +++ b/hw/ip/mbx/rtl/mbx_imbx.sv @@ -169,7 +169,8 @@ module mbx_imbx #( ////////////////////////////////////////////////////////////////////////////// // Don't write the mailbox if it is full - // `ASSERT(NeverWriteMbxIfFull_A, imbx_is_full & hostif_sram_write_req_o) TODO(#476) + `ASSERT_NEVER(NeverWriteMbxIfFull_A, hostif_sram_write_req_o & + (sram_write_ptr_q > hostif_limit_i)) `ifdef INC_ASSERT logic[CfgSramAddrWidth-1:0] sram_write_ptr_assert_q; @@ -182,19 +183,24 @@ module mbx_imbx #( .q_o ( sram_write_ptr_assert_q ) ); // A granted write by the host adapter must advance the write pointer - `ASSERT_IF(GntMustAdvanceWritePtr_A, sram_write_ptr_assert_q == sram_write_ptr_q, + `ASSERT_IF(GntMustAdvanceWritePtr_A, advance_write_ptr & + (sram_write_ptr_d == sram_write_ptr_assert_q + LCFG_SRM_ADDRINC), hostif_sram_write_gnt_i) `endif - // The write pointer should not be advanced if there is not yet acked request - `ASSERT_IF(WrPtrShouldNotAdvanceIfNoAck_A, ~imbx_pending_o, advance_write_ptr & imbx_pending_o) - // Clear busy/abort does not clear the IRQ - // `ASSERT_IF(ClearBusyAbortDoesNotClearIrq_A, sysif_status_busy_i == imbx_irq_host_o, - // sysif_status_busy_i & imbx_irq_host_o) TODO(#476) - // Busy and host IRQ are not set together - // `ASSERT_IF(BusyIrqNotSetTogether_A, sysif_status_busy_i & imbx_irq_host_o, - // sysif_control_go_set_i | sysif_control_abort_set_i) TODO(#476) - // When writing to the mailbox, DOE status busy must be low - `ASSERT_NEVER(WriteToMbxBusyMustBeLow_A, hostif_sram_write_req_o & sysif_status_busy_i) + // Ready IRQ to core should not be asserted whilst there is still pending write traffic + // TODO: this should wait until the write receives a response and not just a grent, and + // presently it should be expected to fire because assertion of ibmx_irq_ready_o is not + // even deferred until the final word write has been granted. (#476) + //`ASSERT_NEVER(WrEverythingBeforeReadyIRQ, imbx_irq_ready_o & + // hostif_sram_write_req_o & ~hostif_sram_write_gnt_i) + + // The write pointer should not be advanced if the request has not yet been granted. + `ASSERT_IF(WrPtrShouldNotAdvanceIfNoAck_A, hostif_sram_write_gnt_i, + advance_write_ptr & imbx_pending_o) + + // When writing to the mailbox, DOE status busy must be low; it shall be set after the request + // writing is complete, and no further requests shall be received until it has been cleared. + `ASSERT_NEVER(WriteToMbxBusyMustBeLow_A, sysif_data_write_valid_i & sysif_status_busy_i) endmodule diff --git a/hw/ip/mbx/rtl/mbx_ombx.sv b/hw/ip/mbx/rtl/mbx_ombx.sv index c4eee7580bb5f..2edf55b40b53a 100644 --- a/hw/ip/mbx/rtl/mbx_ombx.sv +++ b/hw/ip/mbx/rtl/mbx_ombx.sv @@ -101,9 +101,9 @@ module mbx_ombx #( assign writer_close_mbx = mbx_empty & ombx_sram_read_resp_valid_i; // Terminate mbx_read state (Ready = 1 -> 0) if ombx is already drained (sram_read is not issued) - assign sys_read_all_o = mbx_read & - sysif_read_data_write_valid_i & - (sram_read_ptr_q == sram_read_ptr_limit_q); + assign sys_read_all_o = mbx_read & + sysif_read_data_write_valid_i & + (sram_read_ptr_q == sram_read_ptr_limit_q); logic host_clear_abort; assign host_clear_abort = hostif_control_abort_clear_i & mbx_sys_abort; @@ -115,7 +115,7 @@ module mbx_ombx #( assign load_read_ptr = set_first_req | sys_read_all_o | host_clear_abort; // Advance the read pointer when one request went through - assign advance_read_ptr = ombx_sram_read_req_o & ombx_sram_read_gnt_i; + assign advance_read_ptr = ombx_sram_read_req_o & ombx_sram_read_gnt_i; always_comb begin sram_read_ptr_d = sram_read_ptr_q; @@ -264,13 +264,14 @@ module mbx_ombx #( (sysif_read_data_read_valid_i | sysif_read_data_write_valid_i)) // Never read the SRAM if it is empty logic ombx_is_empty; - assign ombx_is_empty = (sram_read_ptr_q == sram_read_ptr_limit_q); + assign ombx_is_empty = (sram_read_ptr_q == sram_read_ptr_limit_q); `ASSERT_NEVER(NeverReadWhenEmpty_A, ombx_sram_read_req_o & ombx_is_empty) - // Never let the read pointer run out of the limit - `ASSERT_NEVER(NeverRunOutOfLimit_A, sram_read_ptr_q > sram_read_ptr_limit_q) + // Never let the read pointer run out of the limit, but allow the range to be redefined whilst + // the mailbox is not active + `ASSERT_NEVER(NeverRunOutOfLimit_A, |{set_first_req, first_req_q, mbx_read} & + (sram_read_ptr_q > sram_read_ptr_limit_q)) `ifdef INC_ASSERT - logic[CfgSramAddrWidth-1:0] sram_read_ptr_assert_q; prim_flop #( .Width(CfgSramAddrWidth) @@ -280,8 +281,10 @@ module mbx_ombx #( .d_i ( sram_read_ptr_d ), .q_o ( sram_read_ptr_assert_q ) ); + // A granted read by the host adapter must advance the read pointer - `ASSERT_IF(GntMustAdvanceReadPtr_A, sram_read_ptr_assert_q == sram_read_ptr_q, + `ASSERT_IF(GntMustAdvanceWritePtr_A, advance_read_ptr & + (sram_read_ptr_d == sram_read_ptr_assert_q + LCFG_SRM_ADDRINC), ombx_sram_read_gnt_i) `endif endmodule From aacc0bfbfedc740620582a5d0bf680335d58a65d Mon Sep 17 00:00:00 2001 From: Kevin Virgen Date: Thu, 28 Sep 2023 09:54:44 -0700 Subject: [PATCH 49/88] [mbx, dv] - First pass mbx ip dv enviorment and smoke test Includes mbx tb along with env, seq_lib and mbx_sim_cfg.hjson First pass smoke test with Mailbox data exchance Basic Self-checking enabled Pending, abort and interrup content. Signed-off-by: Kevin Virgen Signed-off-by: Harry Callahan --- hw/ip/mbx/dv/env/mbx_env.core | 39 ++ hw/ip/mbx/dv/env/mbx_env.sv | 24 + hw/ip/mbx/dv/env/mbx_env_cfg.sv | 54 ++ hw/ip/mbx/dv/env/mbx_env_cov.sv | 32 ++ hw/ip/mbx/dv/env/mbx_env_pkg.sv | 53 ++ hw/ip/mbx/dv/env/mbx_mem_ral_pkg.sv | 66 +++ hw/ip/mbx/dv/env/mbx_scoreboard.sv | 537 ++++++++++++++++++ hw/ip/mbx/dv/env/mbx_virtual_sequencer.sv | 13 + .../mbx/dv/env/seq_lib/mbx_async_msg_vseq.sv | 143 +++++ hw/ip/mbx/dv/env/seq_lib/mbx_base_vseq.sv | 134 +++++ .../dv/env/seq_lib/mbx_reg_reset_val_vseq.sv | 90 +++ hw/ip/mbx/dv/env/seq_lib/mbx_smoke_vseq.sv | 165 ++++++ hw/ip/mbx/dv/env/seq_lib/mbx_tl_device_seq.sv | 20 + hw/ip/mbx/dv/env/seq_lib/mbx_tl_reg_seq.sv | 26 + hw/ip/mbx/dv/env/seq_lib/mbx_vseq_list.sv | 8 + hw/ip/mbx/dv/mbx_sim.core | 29 + hw/ip/mbx/dv/mbx_sim_cfg.hjson | 93 +++ hw/ip/mbx/dv/sva/mbx_bind.sv | 42 ++ hw/ip/mbx/dv/sva/mbx_sva.core | 39 ++ hw/ip/mbx/dv/tb.sv | 107 ++++ hw/ip/mbx/dv/tests/mbx_base_test.sv | 20 + hw/ip/mbx/dv/tests/mbx_test.core | 19 + hw/ip/mbx/dv/tests/mbx_test_pkg.sv | 22 + 23 files changed, 1775 insertions(+) create mode 100644 hw/ip/mbx/dv/env/mbx_env.core create mode 100644 hw/ip/mbx/dv/env/mbx_env.sv create mode 100644 hw/ip/mbx/dv/env/mbx_env_cfg.sv create mode 100644 hw/ip/mbx/dv/env/mbx_env_cov.sv create mode 100644 hw/ip/mbx/dv/env/mbx_env_pkg.sv create mode 100644 hw/ip/mbx/dv/env/mbx_mem_ral_pkg.sv create mode 100644 hw/ip/mbx/dv/env/mbx_scoreboard.sv create mode 100644 hw/ip/mbx/dv/env/mbx_virtual_sequencer.sv create mode 100644 hw/ip/mbx/dv/env/seq_lib/mbx_async_msg_vseq.sv create mode 100644 hw/ip/mbx/dv/env/seq_lib/mbx_base_vseq.sv create mode 100644 hw/ip/mbx/dv/env/seq_lib/mbx_reg_reset_val_vseq.sv create mode 100644 hw/ip/mbx/dv/env/seq_lib/mbx_smoke_vseq.sv create mode 100644 hw/ip/mbx/dv/env/seq_lib/mbx_tl_device_seq.sv create mode 100644 hw/ip/mbx/dv/env/seq_lib/mbx_tl_reg_seq.sv create mode 100644 hw/ip/mbx/dv/env/seq_lib/mbx_vseq_list.sv create mode 100644 hw/ip/mbx/dv/mbx_sim.core create mode 100644 hw/ip/mbx/dv/mbx_sim_cfg.hjson create mode 100644 hw/ip/mbx/dv/sva/mbx_bind.sv create mode 100644 hw/ip/mbx/dv/sva/mbx_sva.core create mode 100644 hw/ip/mbx/dv/tb.sv create mode 100644 hw/ip/mbx/dv/tests/mbx_base_test.sv create mode 100644 hw/ip/mbx/dv/tests/mbx_test.core create mode 100644 hw/ip/mbx/dv/tests/mbx_test_pkg.sv diff --git a/hw/ip/mbx/dv/env/mbx_env.core b/hw/ip/mbx/dv/env/mbx_env.core new file mode 100644 index 0000000000000..d52781c2550aa --- /dev/null +++ b/hw/ip/mbx/dv/env/mbx_env.core @@ -0,0 +1,39 @@ +CAPI=2: +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: "lowrisc:dv:mbx_env:0.1" +description: "MBX DV UVM environment" +filesets: + files_dv: + depend: + - lowrisc:dv:ralgen + - lowrisc:dv:cip_lib + files: + - mbx_mem_ral_pkg.sv + - mbx_env_pkg.sv + - mbx_env_cfg.sv: {is_include_file: true} + - mbx_env_cov.sv: {is_include_file: true} + - mbx_virtual_sequencer.sv: {is_include_file: true} + - mbx_scoreboard.sv: {is_include_file: true} + - mbx_env.sv: {is_include_file: true} + - seq_lib/mbx_tl_reg_seq.sv: {is_include_file: true} + - seq_lib/mbx_tl_device_seq.sv: {is_include_file: true} + - seq_lib/mbx_base_vseq.sv: {is_include_file: true} + - seq_lib/mbx_smoke_vseq.sv: {is_include_file: true} + - seq_lib/mbx_vseq_list.sv: {is_include_file: true} + file_type: systemVerilogSource + +generate: + ral: + generator: ralgen + parameters: + name: mbx + ip_hjson: ../../data/mbx.hjson + +targets: + default: + filesets: + - files_dv + generate: + - ral diff --git a/hw/ip/mbx/dv/env/mbx_env.sv b/hw/ip/mbx/dv/env/mbx_env.sv new file mode 100644 index 0000000000000..20a02e0365ab2 --- /dev/null +++ b/hw/ip/mbx/dv/env/mbx_env.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 + +class mbx_env extends cip_base_env #( + .CFG_T (mbx_env_cfg), + .COV_T (mbx_env_cov), + .VIRTUAL_SEQUENCER_T(mbx_virtual_sequencer), + .SCOREBOARD_T (mbx_scoreboard) + ); + + `uvm_component_utils(mbx_env) + + `uvm_component_new + + function void build_phase(uvm_phase phase); + super.build_phase(phase); + endfunction: build_phase + + function void connect_phase(uvm_phase phase); + super.connect_phase(phase); + endfunction: connect_phase + +endclass: mbx_env diff --git a/hw/ip/mbx/dv/env/mbx_env_cfg.sv b/hw/ip/mbx/dv/env/mbx_env_cfg.sv new file mode 100644 index 0000000000000..8946345030aef --- /dev/null +++ b/hw/ip/mbx/dv/env/mbx_env_cfg.sv @@ -0,0 +1,54 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +class mbx_env_cfg extends cip_base_env_cfg #( + .RAL_T(mbx_core_reg_block) +); + + string mbx_mem_ral_name = "mbx_mem_reg_block"; + string mbx_soc_ral_name = "mbx_soc_reg_block"; + + `uvm_object_utils(mbx_env_cfg) + + function new(string name = ""); + super.new(name); + has_devmode = 0; + endfunction: new + + virtual function void initialize(bit [31:0] csr_base_addr = '1); + list_of_alerts = mbx_env_pkg::LIST_OF_ALERTS; + // RAL model for the memory TL interface + ral_model_names.push_back(mbx_mem_ral_name); + ral_model_names.push_back(mbx_soc_ral_name); + + super.initialize(csr_base_addr); + + // TODO: Revisit the configuration parameters for tl_agent_cfg + // scxb_mbx_core_cfg + m_tl_agent_cfgs[mbx_soc_ral_name].max_outstanding_req = 16; + m_tl_agent_cfgs[mbx_soc_ral_name].if_mode = dv_utils_pkg::Host; + + // agxb_mbx_core_cfg + m_tl_agent_cfgs[RAL_T::type_name].max_outstanding_req = 16; + m_tl_agent_cfgs[RAL_T::type_name].if_mode = dv_utils_pkg::Host; + + // mbx_agxb TL I/F + m_tl_agent_cfgs[mbx_mem_ral_name].max_outstanding_req = 16; + m_tl_agent_cfgs[mbx_mem_ral_name].if_mode = dv_utils_pkg::Device; + + endfunction: initialize + + virtual function dv_base_reg_block create_ral_by_name(string name); + if (name == RAL_T::type_name) begin + return super.create_ral_by_name(name); + end else if (name == mbx_mem_ral_name) begin + return mbx_mem_reg_block::type_id::create(mbx_mem_ral_name); + end else if (name == mbx_soc_ral_name) begin + return mbx_soc_reg_block::type_id::create(mbx_soc_ral_name); + end else begin + `uvm_error(`gfn, $sformatf("%0s is an illegal RAL model name", name)) + end + endfunction: create_ral_by_name + +endclass: mbx_env_cfg diff --git a/hw/ip/mbx/dv/env/mbx_env_cov.sv b/hw/ip/mbx/dv/env/mbx_env_cov.sv new file mode 100644 index 0000000000000..d1c40d899ea63 --- /dev/null +++ b/hw/ip/mbx/dv/env/mbx_env_cov.sv @@ -0,0 +1,32 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +/** + * Covergoups that are dependent on run-time parameters that may be available + * only in build_phase can be defined here + * Covergroups may also be wrapped inside helper classes if needed. + */ + +class mbx_env_cov extends cip_base_env_cov #(.CFG_T(mbx_env_cfg)); + `uvm_component_utils(mbx_env_cov) + + // the base class provides the following handles for use: + // mbx_env_cfg: cfg + + // covergroups + // [add covergroups here] + + function new(string name, uvm_component parent); + super.new(name, parent); + // [instantiate covergroups here] + endfunction : new + + virtual function void build_phase(uvm_phase phase); + super.build_phase(phase); + // [or instantiate covergroups here] + // Please instantiate sticky_intr_cov array of objects for all interrupts that are sticky + // See cip_base_env_cov for details + endfunction + +endclass diff --git a/hw/ip/mbx/dv/env/mbx_env_pkg.sv b/hw/ip/mbx/dv/env/mbx_env_pkg.sv new file mode 100644 index 0000000000000..faaf30c583a24 --- /dev/null +++ b/hw/ip/mbx/dv/env/mbx_env_pkg.sv @@ -0,0 +1,53 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +package mbx_env_pkg; + // dep packages + import uvm_pkg::*; + import top_pkg::*; + import dv_utils_pkg::*; + import dv_lib_pkg::*; + import dv_base_reg_pkg::*; + import mbx_core_ral_pkg::*; + import mbx_soc_ral_pkg::*; + import mbx_mem_ral_pkg::*; + import tl_agent_pkg::*; + import cip_base_pkg::*; + import dv_base_reg_pkg::*; + import csr_utils_pkg::*; + import mem_model_pkg::*; + + // macro includes + `include "uvm_macros.svh" + `include "dv_macros.svh" + + // parameters + parameter int unsigned NUM_ALERTS = 2; + parameter string LIST_OF_ALERTS[] = {"fatal_fault", "recov_fault"}; + + parameter int unsigned MBX_DV_DW_SIZE_BYTES = 4; + parameter int unsigned MBX_DV_MAX_DW = 1023; + + // types + typedef int unsigned uint_t; + typedef enum bit { + READ = 0, + WRITE = 1 + } reg_op_e; + typedef enum { + MbxCoreReady, + MbxCoreAbort + } mbx_core_intr_e; + + // functions + + // package sources + `include "mbx_env_cfg.sv" + `include "mbx_env_cov.sv" + `include "mbx_virtual_sequencer.sv" + `include "mbx_scoreboard.sv" + `include "mbx_env.sv" + `include "mbx_vseq_list.sv" + +endpackage: mbx_env_pkg diff --git a/hw/ip/mbx/dv/env/mbx_mem_ral_pkg.sv b/hw/ip/mbx/dv/env/mbx_mem_ral_pkg.sv new file mode 100644 index 0000000000000..9084b9387b3f9 --- /dev/null +++ b/hw/ip/mbx/dv/env/mbx_mem_ral_pkg.sv @@ -0,0 +1,66 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +package mbx_mem_ral_pkg; + + import uvm_pkg::*; + import dv_base_reg_pkg::*; + + `include "uvm_macros.svh" + + typedef int unsigned uint; + typedef class mbx_mem; + typedef class mbx_mem_reg_block; + + class mbx_mem #(parameter int unsigned MemDepth = 32) extends dv_base_mem; + + `uvm_object_param_utils(mbx_mem#(MemDepth)) + + function new(string name = "mbx_mem", + longint unsigned size = MemDepth, + int unsigned n_bits = 32, + string access = "RW", + int has_coverage = UVM_NO_COVERAGE); + super.new(name, size, n_bits, access, has_coverage); + endfunction : new + + endclass : mbx_mem + + + class mbx_mem_reg_block extends dv_base_reg_block; + // memories + // TODO: The dv_reg_base_block uses int to calculate max_offset in max2 function. + // To map the complete range, 30 bits are required but int type supports at max only 31 bits. + rand mbx_mem #(uint'(2 ** 29)) m_mem; + + `uvm_object_param_utils(mbx_mem_reg_block) + + function new(string name = "mbx_mem_reg_block", + int has_coverage = UVM_NO_COVERAGE); + super.new(name, has_coverage); + endfunction : new + + virtual function void build(uvm_reg_addr_t base_addr, + csr_excl_item csr_excl = null); + // create default map + this.default_map = create_map(.name("default_map"), + .base_addr(base_addr), + .n_bytes(4), + .endian(UVM_LITTLE_ENDIAN)); + if (csr_excl == null) begin + csr_excl = csr_excl_item::type_id::create("csr_excl"); + this.csr_excl = csr_excl; + end + + // create memories + m_mem = mbx_mem#(uint'(2 ** 29))::type_id::create("m_mem"); + m_mem.configure(.parent(this)); + default_map.add_mem(.mem(m_mem), + .offset(32'h0), + .rights("RW")); + + endfunction : build + endclass : mbx_mem_reg_block + +endpackage diff --git a/hw/ip/mbx/dv/env/mbx_scoreboard.sv b/hw/ip/mbx/dv/env/mbx_scoreboard.sv new file mode 100644 index 0000000000000..16fac7e2d0f3b --- /dev/null +++ b/hw/ip/mbx/dv/env/mbx_scoreboard.sv @@ -0,0 +1,537 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +class mbx_scoreboard extends cip_base_scoreboard #( + .CFG_T(mbx_env_cfg), + .RAL_T(mbx_core_reg_block), + .COV_T(mbx_env_cov) + ); + `uvm_component_utils(mbx_scoreboard) + + // local variables + bit [top_pkg::TL_AW-1:0] m_ibmbx_ptr; + bit [top_pkg::TL_AW-1:0] m_obmbx_ptr_q[$]; + bit [top_pkg::TL_AW-1:0] m_obmbx_ptr; + bit [9:0] m_obdwcnt; + bit mbxsts_core_wr_in_progress; + bit mbxsts_system_rd_in_progress; + bit mbxsts_core_rd_in_progress; + bit mbxsts_system_wr_in_progress; + + bit skip_read_check; + bit exp_mbx_core_irq; + bit exp_mbx_core_irq_q[$]; + + // TLM agent fifos + + // local queues to hold incoming packets pending comparison + bit [top_pkg::TL_DW-1:0] m_ib_q[$]; + bit [top_pkg::TL_DW-1:0] m_ob_q[$]; + + // System RAL model + mbx_soc_reg_block m_mbx_soc_ral; + + `uvm_component_new + + function void build_phase(uvm_phase phase); + super.build_phase(phase); + endfunction + + function void connect_phase(uvm_phase phase); + super.connect_phase(phase); + endfunction + + virtual task monitor_core_interrupt(); + `uvm_info(`gfn, "monitor_core_interrupt -- Start", UVM_DEBUG) + // `DV_CHECK_CASE_EQ(exp_mbx_core_irq, cfg.intr_vif.pins, "Default state of interrupt pin is 0") + forever begin + @(cfg.intr_vif.pins); + //Adjusting the clk delay before running the check + //TLUL Write completion is taking 5-6 cyles + cfg.clk_rst_vif.wait_n_clks(12); + `uvm_info(`gfn, $sformatf("Change in interrupt pin('b%b)", cfg.intr_vif.pins), UVM_LOW) + `DV_CHECK_CASE_EQ(exp_mbx_core_irq, cfg.intr_vif.pins[MbxCoreReady], + "Exp. interrupt doesn't match actual") + end + `uvm_info(`gfn, "monitor_core_interrupt -- End", UVM_DEBUG) + endtask: monitor_core_interrupt + + virtual task monitor_exp_core_interrupts(); + `uvm_info(`gfn, "monitor_exp_core_interrupts -- Start", UVM_DEBUG) + fork + forever begin + bit exp_irq; + + wait(exp_mbx_core_irq_q.size() != 0); + exp_irq = exp_mbx_core_irq_q.pop_front(); + if(exp_irq == 1) begin + cfg.clk_rst_vif.wait_n_clks(2); + `DV_CHECK_EQ(exp_irq, cfg.intr_vif.pins[MbxCoreReady], + "Expecting interrupt pin to go high") + end + if(exp_irq == 0) begin + // TODO: Earlier it was set to '1', updating it to larger value for the RTL change + // to go, reduce it once the RTL is fixed. + cfg.clk_rst_vif.wait_n_clks(5); + `DV_CHECK_EQ(exp_irq, cfg.intr_vif.pins[MbxCoreReady], "Expecting interrupt pin to go low") + end + end + join_none + wait fork; + `uvm_info(`gfn, "monitor_exp_core_interrupts -- End", UVM_DEBUG) + endtask: monitor_exp_core_interrupts + + task run_phase(uvm_phase phase); + super.run_phase(phase); + `downcast(m_mbx_soc_ral, cfg.ral_models[cfg.mbx_soc_ral_name]) + fork + monitor_core_interrupt(); + monitor_exp_core_interrupts(); + join_none + endtask + + virtual task process_tl_access(tl_seq_item item, tl_channels_e channel, string ral_name); + uvm_reg csr; + bit do_read_check = 1'b1; + bit write = item.is_write(); + uvm_reg_addr_t csr_addr = cfg.ral_models[ral_name].get_word_aligned_addr(item.a_addr); + bit [31:0] mask = 'hffff_ffff; + + bit addr_phase_read = (!write && channel == AddrChannel); + bit addr_phase_write = (write && channel == AddrChannel); + bit data_phase_read = (!write && channel == DataChannel); + bit data_phase_write = (write && channel == DataChannel); + + // if access was to a valid csr, get the csr handle + if (ral_name != cfg.mbx_mem_ral_name) begin + if (csr_addr inside {cfg.ral_models[ral_name].csr_addrs}) begin + csr = cfg.ral_models[ral_name].default_map.get_reg_by_offset(csr_addr); + `DV_CHECK_NE_FATAL(csr, null) + end + else begin + // `uvm_fatal(`gfn, $sformatf("Access unexpected addr 0x%0h", csr_addr)) +return; + end + + // if incoming access is a write to a valid csr, then make updates right away + if(addr_phase_write) begin + void'(csr.predict(.value(item.a_data), .kind(UVM_PREDICT_WRITE), .be(item.a_mask))); + end + end + + if((ral_name == RAL_T::type_name) + && (csr.get_name() == "status") + && addr_phase_write) begin + mbxsts_core_wr_in_progress = 1'b1; + end + if((ral_name == RAL_T::type_name) + && (csr.get_name() == "status") + && data_phase_write) begin + mbxsts_core_wr_in_progress = 1'b0; + end + + if((ral_name == RAL_T::type_name) + && (csr.get_name() == "status") + && addr_phase_read) begin + mbxsts_core_rd_in_progress = 1'b1; + end + if((ral_name == RAL_T::type_name) + && (csr.get_name() == "status") + && data_phase_read) begin + mbxsts_core_rd_in_progress = 1'b0; + end + + if((ral_name == cfg.mbx_soc_ral_name) + && (csr.get_name() == "soc_status") + && addr_phase_read) begin + mbxsts_system_rd_in_progress = 1'b1; + end + if((ral_name == cfg.mbx_soc_ral_name) + && (csr.get_name() == "soc_status") + && data_phase_read) begin + mbxsts_system_rd_in_progress = 1'b0; + end + + if((ral_name == cfg.mbx_soc_ral_name) + && (csr.get_name() == "control") + && addr_phase_write) begin + mbxsts_system_wr_in_progress = 1'b1; + end + if((ral_name == cfg.mbx_soc_ral_name) + && (csr.get_name() == "control") + && data_phase_write) begin + mbxsts_system_wr_in_progress = 1'b0; + end + + + if((mbxsts_core_wr_in_progress + && ((ral_name == cfg.mbx_soc_ral_name) + && (csr.get_name() == "soc_status") + && data_phase_read)) + || ((ral_name == RAL_T::type_name) + && (csr.get_name() == "status") + && data_phase_read) + && (mbxsts_system_wr_in_progress)) begin + skip_read_check = 1'b1; + end + + if(((ral_name == cfg.mbx_soc_ral_name) + ||(ral_name == RAL_T::type_name)) + && ((csr.get_name() == "soc_status") + || (csr.get_name() == "status"))) begin + do_read_check = ~skip_read_check; + if(do_read_check == 1'b0) begin + `uvm_info(`gfn, + "Skipping read for status from system/core as core/system is updating it", + UVM_LOW) + end + end + +// TODO: AML +return; + + // process the csr req + // for write, update local variable and fifo at address phase + // for read, update predication at address phase and compare at data phase + case (ral_name) + RAL_T::type_name : begin + process_tl_mbx_core_access(item, channel); + end + cfg.mbx_soc_ral_name : begin + process_tl_mbx_soc_access(item, channel); + end + cfg.mbx_mem_ral_name : begin + process_tl_mbx_mem_access(item, channel); + return; + end + default: begin + `uvm_fatal(`gfn, $sformatf("invalid ral: %0s", ral_name)) + end + endcase + + // On reads, if do_read_check, is set, then check mirrored_value against item.d_data + if (data_phase_read) begin + if(csr.get_name() == "status") begin + // TODO: Remove this, once mbx doe ready bit issue is resolved + mask = 'h7fff_ffff; + end + if (do_read_check) begin + void'(csr.predict(.value(item.d_data), .kind(UVM_PREDICT_READ))); + end + + end + if(((ral_name == cfg.mbx_soc_ral_name) + || (ral_name == RAL_T::type_name)) + && (csr.get_name() == "status") + && data_phase_read) begin + skip_read_check = 1'b0; + end + endtask + + virtual function void process_tl_mbx_core_access(tl_seq_item item, tl_channels_e channel); + uvm_reg csr; + bit do_read_check = 1'b1; + bit write = item.is_write(); + uvm_reg_addr_t csr_addr = cfg.ral_models[RAL_T::type_name].get_word_aligned_addr( + item.a_addr); + + bit addr_phase_read = (!write && channel == AddrChannel); + bit addr_phase_write = (write && channel == AddrChannel); + bit data_phase_read = (!write && channel == DataChannel); + bit data_phase_write = (write && channel == DataChannel); + + `uvm_info(`gfn, "process_tl_mbx_core_access -- Start", UVM_DEBUG) + csr = cfg.ral_models[RAL_T::type_name].default_map.get_reg_by_offset(csr_addr); + + case(csr.get_name()) + default:; // Do nothing + "inbound_write_ptr" : begin + if(addr_phase_write) begin + m_ibmbx_ptr = item.a_data; + end + if(addr_phase_read) begin + void'(ral.inbound_write_ptr.predict( + .value(ral.inbound_base_address.get() + m_ibmbx_ptr), + .kind(UVM_PREDICT_READ))); + end + end + "outbound_read_ptr" : begin + if(addr_phase_write) begin + m_obmbx_ptr_q[0] = item.a_data; + m_obmbx_ptr = item.a_data; + end + if(addr_phase_read) begin + void'(ral.outbound_read_ptr.predict( + .value(ral.outbound_base_address.get() + (m_obmbx_ptr_q[0])), + .kind(UVM_PREDICT_READ))); + end + end + "inbound_base_address" : begin + // Do nothing + end + "inbound_limit_address" : begin + // Do nothing + end + "outbound_base_address" : begin + // Do nothing + end + "outbound_limit_address" : begin + // Do nothing + end + "outbound_object_size" : begin + if(addr_phase_write) begin + m_obdwcnt = item.a_data; + `uvm_info(`gfn, $sformatf("Updating m_obdwcnt to %0d", m_obdwcnt), UVM_LOW) + end + if(addr_phase_read) begin + void'(ral.outbound_object_size.predict(.value(m_obdwcnt), .kind(UVM_PREDICT_READ))); + end + end + "control" : begin + if(addr_phase_write) begin + if(ral.control.abort.get_mirrored_value() == 0) begin + exp_mbx_core_irq = 0; + exp_mbx_core_irq_q.push_back(0); + end + if(ral.control.error.get_mirrored_value() == 1) begin + // TODO: Check if busy bit is expected to be cleared - RVSCS-491 + void'(ral.status.busy.predict(.value(0), .kind(UVM_PREDICT_READ))); + end + end + end + "status" : begin + if(addr_phase_read) begin + //TODO: Review ready field + //void'(ral.status.ready.predict(.value(m_obdwcnt != 0), .kind(UVM_PREDICT_READ))); + end + // TODO: Add the support for async message sts + if(addr_phase_write) begin + if(ral.status.busy.get_mirrored_value() == 0) begin + exp_mbx_core_irq = 0; + exp_mbx_core_irq_q.push_back(0); + end + end + end + // TODO: Add interrupt registers + endcase + `uvm_info(`gfn, "process_tl_mbx_core_access -- End", UVM_DEBUG) + endfunction: process_tl_mbx_core_access + + virtual function void process_tl_mbx_soc_access(tl_seq_item item, tl_channels_e channel); + uvm_reg csr; + bit do_read_check = 1'b1; + bit write = item.is_write(); + uvm_reg_addr_t csr_addr = + cfg.ral_models[cfg.mbx_soc_ral_name].get_word_aligned_addr(item.a_addr); + + bit addr_phase_read = (!write && channel == AddrChannel); + bit addr_phase_write = (write && channel == AddrChannel); + bit data_phase_read = (!write && channel == DataChannel); + bit data_phase_write = (write && channel == DataChannel); + + `uvm_info(`gfn, "process_tl_mbx_soc_access -- Start", UVM_DEBUG) + csr = cfg.ral_models[cfg.mbx_soc_ral_name].default_map.get_reg_by_offset(csr_addr); + case(csr.get_name()) + default:; // Do nothing + "soc_control" : begin + mbx_soc_reg_soc_control ctl_reg_h; + + `DV_CHECK_FATAL($cast(ctl_reg_h, csr), "Unable to cast csr handle to MBX control type") + if(data_phase_write) begin + if(ctl_reg_h.abort.get() == 1) begin + exp_mbx_core_irq = 1; + exp_mbx_core_irq_q.push_back(1); + // TODO: Check if busy bit also needs to be set + void'(ral.control.abort.predict(.value(1), .kind(UVM_PREDICT_WRITE))); + void'(ral.status.busy.predict(.value(1), .kind(UVM_PREDICT_WRITE))); + if((ral.status.busy.get() == 1) || (ral.control.error.get() == 1) || + (m_obdwcnt != 0)) begin + void'(ral.status.busy.predict(.value(1), .kind(UVM_PREDICT_WRITE))); + end + end else if((item.a_data[31] & item.a_mask[3]) == 1) begin + // if (ctl_reg_h.abort.get() == 1) + if((ral.status.busy.get() == 0) && (ral.control.error.get() == 0) && + (ral.control.abort.get() == 0)) begin + void'(ral.status.busy.predict(.value(1), .kind(UVM_PREDICT_WRITE))); + void'(m_mbx_soc_ral.soc_status.busy.predict(.value(1), .kind(UVM_PREDICT_READ))); + + exp_mbx_core_irq = 1; + exp_mbx_core_irq_q.push_back(1); + end + end + void'(ral.status.sys_intr_enable.predict( + .value(ctl_reg_h.doe_intr_en.get()), + .kind(UVM_PREDICT_WRITE))); + // TODO: Add async logic + end + if(addr_phase_read) begin + void'(ctl_reg_h.abort.predict( + .value(0), + .kind(UVM_PREDICT_READ))); + void'(ctl_reg_h.doe_intr_en.predict( + .value(ral.status.sys_intr_enable.get()), + .kind(UVM_PREDICT_READ))); + void'(ctl_reg_h.go.predict( + .value(0), + .kind(UVM_PREDICT_READ))); + // TODO Add async logic + end + end + "soc_status" : begin + mbx_soc_reg_soc_status soc_sts_reg_h; + mbx_core_reg_status hst_sts_reg_h; + mbx_core_reg_control hst_ctl_reg_h; + + `DV_CHECK_FATAL($cast(soc_sts_reg_h, csr), + "Unable to cast csr handle to soc_status type") + hst_sts_reg_h = ral.status; + hst_ctl_reg_h = ral.control; + if(addr_phase_read) begin + void'(soc_sts_reg_h.busy.predict( + .value(hst_sts_reg_h.busy.get()), + .kind(UVM_PREDICT_READ))); + void'(soc_sts_reg_h.doe_intr_status.predict( + .value(hst_sts_reg_h.sys_intr_state.get()), + .kind(UVM_PREDICT_READ))); + void'(soc_sts_reg_h.error.predict( + .value(hst_ctl_reg_h.error.get()), + .kind(UVM_PREDICT_READ))); + //TODO: Review new ready field + void'(soc_sts_reg_h.ready.predict( + .value(m_obdwcnt != 0), + .kind(UVM_PREDICT_READ))); + end + if(addr_phase_write) begin + if((item.a_data[1] & item.a_mask[0]) == 1) begin + void'(hst_sts_reg_h.sys_intr_state.predict(.value(0))); + end + end + end + "wdata" : begin + if(addr_phase_write) begin + m_ib_q.push_back(item.a_data); + end + if(addr_phase_read) begin + void'(csr.predict(.value(0), .kind(UVM_PREDICT_READ))); + end + end + "rdata" : begin + if(addr_phase_read) begin + if(m_obdwcnt == 0) begin + void'(csr.predict(.value(0), .kind(UVM_PREDICT_READ))); + end else begin + void'(csr.predict(.value(m_ob_q[0]), .kind(UVM_PREDICT_READ))); + end + end + if(addr_phase_write) begin + int tmp_ptr=0; + if(m_obmbx_ptr_q.size() == 0) + tmp_ptr = m_obmbx_ptr+4; + else + tmp_ptr = m_obmbx_ptr_q[$]+4; + m_obmbx_ptr_q.push_back(tmp_ptr); + m_obmbx_ptr = tmp_ptr; + m_obdwcnt--; + void'(m_ob_q.pop_front()); + end + end + endcase + `uvm_info(`gfn, "process_tl_mbx_soc_access -- End", UVM_DEBUG) + endfunction: process_tl_mbx_soc_access + + virtual function void process_tl_mbx_mem_access(tl_seq_item item, tl_channels_e channel); + bit write = item.is_write(); + bit addr_phase_read = (!write && channel == AddrChannel); + bit addr_phase_write = (write && channel == AddrChannel); + bit data_phase_read = (!write && channel == DataChannel); + bit data_phase_write = (write && channel == DataChannel); + + `uvm_info(`gfn, "process_tl_mbx_mem_access -- Start", UVM_DEBUG) + if(addr_phase_read || addr_phase_write) begin + // Check for integrity error on Address + void'(item.is_a_chan_intg_ok(.throw_error(1))); + + // Check the transaction is full 4B access + `DV_CHECK_EQ(((item.a_size == 2) && (item.a_mask == '1)), 1, + $sformatf("Incorrect a_size(%0d) or a_mask('b%0b)", item.a_size, item.a_mask)) + + // Check the addresses are generated between the configured limits only + if(addr_phase_write) begin + bit is_addr_match; + + // Check if address is within IB Mailbox SRAM range + if((item.a_addr >= ral.inbound_base_address.get()) && + (item.a_addr < ral.inbound_limit_address.get())) begin + is_addr_match = 1'b1; + end + `DV_CHECK_EQ(is_addr_match, 1, + $sformatf("Address('h%0h) doesn't match any of inbound mailbox address ranges", + item.a_addr)) + + // Check if the SRAM write is expected or not + `DV_CHECK_NE(m_ib_q.size(), 0, "No write data in mbxwrdat register") + + // Check if the SRAM write address is correct. + `DV_CHECK_EQ(item.a_addr, (ral.inbound_base_address.get() + m_ibmbx_ptr), + "Incorrect address seen on the write to SRAM") + m_ibmbx_ptr += 4; + + // Check if the data written matches with the data written to wrdat register + `DV_CHECK_EQ(item.a_data, m_ib_q[0], + "Bus data doesn't match with data written to wdat") + void'(m_ib_q.pop_front()); + end + end + if(data_phase_read) begin + bit is_addr_match; + + // Check if address is within OB Mailbox SRAM range + if((item.a_addr >= ral.outbound_base_address.get()) && + (item.a_addr < ral.outbound_limit_address.get())) begin + is_addr_match = 1'b1; + end + `DV_CHECK_EQ(is_addr_match, 1, + $sformatf("Address('h%0h) out of outbound mailbox address ranges", item.a_addr)) + + // No read should occur when obdwcnt is '0' + `DV_CHECK_NE(m_obdwcnt, 0, "Illegal read from memory when obdwcnt is 0") + + m_obmbx_ptr = m_obmbx_ptr_q[0]; + // Check if the SRAM read address is correct. + `DV_CHECK_EQ(item.a_addr, (ral.outbound_base_address.get() + m_obmbx_ptr_q[0]), + "Incorrect address seen on the read to SRAM") + `uvm_info(`gfn, $sformatf("Added data 'h%0h to m_ob_q", item.d_data), UVM_LOW) + m_ob_q.push_back(item.d_data); + void'(m_obmbx_ptr_q.pop_front()); + + end + `uvm_info(`gfn, "process_tl_mbx_mem_access -- End", UVM_DEBUG) + endfunction: process_tl_mbx_mem_access + + virtual function void reset(string kind = "HARD"); + super.reset(kind); + // reset local fifos queues and variables + m_ib_q.delete(); + m_ob_q.delete(); + m_ibmbx_ptr = 0; + m_obmbx_ptr = 0; + m_obdwcnt = 0; + exp_mbx_core_irq = 0; + endfunction + + function void check_phase(uvm_phase phase); + super.check_phase(phase); + // post test checks - ensure that all local fifos and queues are empty + if(m_ib_q.size() > 0) begin + `uvm_error(`gfn, $sformatf("m_ib_q is not empty(%0d)", m_ib_q.size())) + end + if(m_ob_q.size() > 0) begin + `uvm_error(`gfn, $sformatf("m_ob_q is not empty(%0d)", m_ob_q.size())) + end + if(exp_mbx_core_irq_q.size() > 0) begin + `uvm_error(`gfn, $sformatf("exp_mbx_core_irq_q is not empty(%0d)", exp_mbx_core_irq_q.size())) + end + endfunction + +endclass diff --git a/hw/ip/mbx/dv/env/mbx_virtual_sequencer.sv b/hw/ip/mbx/dv/env/mbx_virtual_sequencer.sv new file mode 100644 index 0000000000000..ff4fb2f2e1598 --- /dev/null +++ b/hw/ip/mbx/dv/env/mbx_virtual_sequencer.sv @@ -0,0 +1,13 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +class mbx_virtual_sequencer extends cip_base_virtual_sequencer #( + .CFG_T(mbx_env_cfg), + .COV_T(mbx_env_cov) + ); + + `uvm_component_utils(mbx_virtual_sequencer) + + `uvm_component_new + +endclass: mbx_virtual_sequencer diff --git a/hw/ip/mbx/dv/env/seq_lib/mbx_async_msg_vseq.sv b/hw/ip/mbx/dv/env/seq_lib/mbx_async_msg_vseq.sv new file mode 100644 index 0000000000000..4d7ddf0efa47b --- /dev/null +++ b/hw/ip/mbx/dv/env/seq_lib/mbx_async_msg_vseq.sv @@ -0,0 +1,143 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +class mbx_async_msg_vseq extends mbx_base_vseq; + + rand uint_t m_req_dw_sz; + rand uint_t m_rsp_dw_sz; + rand uint_t m_num_msg; + rand uint_t m_num_of_iterations; + rand uint_t m_mbx_num; + + `uvm_object_utils(mbx_async_msg_vseq) + + constraint mbx_num_c { m_mbx_num == 0; } + + constraint req_dw_sz_c { m_req_dw_sz inside {[1 : 5]}; } + + constraint rsp_dw_sz_c { m_rsp_dw_sz inside {[1 : 5]}; } + + constraint num_msg_c { m_num_msg inside {[1 : 2]}; } + + constraint num_of_iterations_c { m_num_of_iterations inside {[1 : 3]}; } + + `uvm_object_new + + virtual task system_thread(uint_t num_msg); + uint_t msg_rcvd; + + `uvm_info(`gfn, + $sformatf("system_thread(num_msg=%0d) -- Start", num_msg), + UVM_DEBUG) + // Wait for the async msg sts to be set + csr_spinwait( + .ptr(m_mbx_soc_ral.m_mbxsoc_reg_block.mbxsts.asyncmsgsts), + .exp_data(1) + ); + forever begin + bit [31:0] rd_data; + + msg_rcvd++; + + // Wait for busy bit to be '0' + csr_spinwait( + .ptr(m_mbx_soc_ral.m_mbxsoc_reg_block.mbxsts.mbxbusy), + .exp_data(0) + ); + + // Generate request + for(uint_t dw = 0; dw < m_req_dw_sz; dw++) begin + csr_wr(m_mbx_soc_ral.m_mbxsoc_reg_block.mbxwrdat, $urandom); + end + csr_wr(m_mbx_soc_ral.m_mbxsoc_reg_block.mbxctl.mbxgo, 1); + + // Wait for response + for(uint_t dw = 0; dw < m_rsp_dw_sz; dw++) begin + csr_spinwait( + .ptr(m_mbx_soc_ral.m_mbxsoc_reg_block.mbxsts.mbxready), + .exp_data(1) + ); + + csr_rd(m_mbx_soc_ral.m_mbxsoc_reg_block.mbxrddat, rd_data); + csr_wr(m_mbx_soc_ral.m_mbxsoc_reg_block.mbxrddat, $urandom); + end + // MBXREADY should be '0', once all the data has been read + csr_rd_check(.ptr(m_mbx_soc_ral.m_mbxsoc_reg_block.mbxsts.mbxready), .compare_value(0)); + + // Check if asyncmsgsts is still set + csr_rd(m_mbx_soc_ral.m_mbxsoc_reg_block.mbxsts.asyncmsgsts, rd_data); + + if(rd_data == 0) begin + `uvm_info(`gfn, "No more async messages to be sent by core", UVM_LOW) + break; + end + `DV_CHECK_RANDOMIZE_FATAL(this) + end + `DV_CHECK_EQ(num_msg, msg_rcvd, "Expected async messages doesn't receive actual") + `uvm_info(`gfn, + $sformatf("system_thread(num_msg=%0d) -- End", num_msg), + UVM_DEBUG) + endtask: system_thread + + virtual task core_thread(uint_t num_msg); + `uvm_info(`gfn, + $sformatf("core_thread(num_msg=%0d) -- Start", num_msg), + UVM_DEBUG) + // Set the asyncmsgsts bit + csr_wr(ral.m_mbxhst_reg_block.mbxsts.asyncmsgsts, 1); + + for(uint_t msg = 0; msg < num_msg; msg++) begin + byte q[$]; + + // Wait for request packet to be written + wait_for_core_interrupt(); + + // Check num of DW sent is same as received + csr_rd_check(.ptr(ral.m_mbxhst_reg_block.mbxibwrptr), + .compare_value(m_req_dw_sz * 4 + ral.m_mbxhst_reg_block.mbxibbase.get())); + + // Set MBXIBWRPTR back to MBXIBBASE + csr_wr(ral.m_mbxhst_reg_block.mbxibwrptr, 0); + // Clear busy + csr_wr(ral.m_mbxhst_reg_block.mbxsts.mbxbusy, 0); + + // Create response + for(uint_t dw = 0; dw < m_rsp_dw_sz; dw++) begin + for(uint_t byte_cnt = 0; byte_cnt < MBX_DV_DW_SIZE_BYTES; byte_cnt++) begin + q.push_back($urandom); + end + end + write_mem(obmbx_base_addr, q); + csr_wr(ral.m_mbxhst_reg_block.mbxobrdptr, 0); + csr_wr(ral.m_mbxhst_reg_block.mbxobdwcnt, m_rsp_dw_sz); + end + + // Set asyncmsgsts bit to '0' + csr_wr(ral.m_mbxhst_reg_block.mbxsts.asyncmsgsts, 0); + `uvm_info(`gfn, + $sformatf("core_thread(num_msg=%0d) -- End", num_msg), + UVM_DEBUG) + endtask: core_thread + + virtual task body(); + `uvm_info(`gfn, "body -- Start", UVM_DEBUG) + super.body(); + ibmbx_base_addr.rand_mode(0); + ibmbx_limit_addr.rand_mode(0); + obmbx_base_addr.rand_mode(0); + obmbx_limit_addr.rand_mode(0); + m_num_of_iterations.rand_mode(0); + for(uint_t iter = 0; iter < m_num_of_iterations; iter++) begin + m_num_msg.rand_mode(0); + fork + system_thread(m_num_msg); + core_thread(m_num_msg); + join + m_num_msg.rand_mode(1); + `DV_CHECK_RANDOMIZE_FATAL(this) + end + `uvm_info(`gfn, "body -- End", UVM_DEBUG) + endtask: body + +endclass: mbx_async_msg_vseq diff --git a/hw/ip/mbx/dv/env/seq_lib/mbx_base_vseq.sv b/hw/ip/mbx/dv/env/seq_lib/mbx_base_vseq.sv new file mode 100644 index 0000000000000..35b49affb324d --- /dev/null +++ b/hw/ip/mbx/dv/env/seq_lib/mbx_base_vseq.sv @@ -0,0 +1,134 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +class mbx_base_vseq extends cip_base_vseq #( + .RAL_T (mbx_core_reg_block), + .CFG_T (mbx_env_cfg), + .COV_T (mbx_env_cov), + .VIRTUAL_SEQUENCER_T (mbx_virtual_sequencer) + ); + + bit do_mbx_init = 1'b1; + mem_model seq_mem_model; + rand bit [top_pkg::TL_AW-1:0] ibmbx_base_addr; + rand bit [top_pkg::TL_AW-1:0] ibmbx_limit_addr; + rand bit [top_pkg::TL_AW-1:0] obmbx_base_addr; + rand bit [top_pkg::TL_AW-1:0] obmbx_limit_addr; + + mbx_mem_reg_block m_mbx_mem_ral; + mbx_soc_reg_block m_mbx_soc_ral; + + `uvm_object_utils(mbx_base_vseq) + + constraint ib_ob_addr_range_c { + (ibmbx_base_addr inside + {[m_mbx_mem_ral.mem_ranges[0].start_addr : m_mbx_mem_ral.mem_ranges[0].end_addr]}); + (ibmbx_limit_addr inside + {[m_mbx_mem_ral.mem_ranges[0].start_addr : m_mbx_mem_ral.mem_ranges[0].end_addr]}); + (obmbx_base_addr inside + {[m_mbx_mem_ral.mem_ranges[0].start_addr : m_mbx_mem_ral.mem_ranges[0].end_addr]}); + (obmbx_limit_addr inside + {[m_mbx_mem_ral.mem_ranges[0].start_addr : m_mbx_mem_ral.mem_ranges[0].end_addr]}); + } + + constraint legal_addr_range_c { + (ibmbx_limit_addr > ibmbx_base_addr); + ((obmbx_limit_addr - obmbx_base_addr) == (MBX_DV_DW_SIZE_BYTES * MBX_DV_MAX_DW)); + } + + constraint legal_non_overlapping_region_c { + unique {ibmbx_base_addr, ibmbx_limit_addr, obmbx_base_addr, obmbx_limit_addr}; + } + + constraint legal_addr_alignment_c { + (ibmbx_base_addr[1:0] == 0); + (ibmbx_limit_addr[1:0] == 0); + (obmbx_base_addr[1:0] == 0); + (obmbx_limit_addr[1:0] == 0); + } + + function new(string name = ""); + super.new(); + seq_mem_model = mem_model#()::type_id::create("seq_mem_model"); + seq_mem_model.init(); + endfunction: new + + function void pre_randomize(); + super.pre_randomize(); + `downcast(m_mbx_soc_ral, cfg.ral_models[cfg.mbx_soc_ral_name]) + `downcast(m_mbx_mem_ral, cfg.ral_models[cfg.mbx_mem_ral_name]) + endfunction: pre_randomize + + virtual task dut_init(string reset_kind = "HARD"); + super.dut_init(); + if (do_mbx_init == 1'b1) begin + mbx_init(); + end + endtask: dut_init + + virtual task start_device_seq(); + mbx_tl_device_seq seq_h; + + seq_h = mbx_tl_device_seq::type_id::create("seq_h"); + seq_h.mem = seq_mem_model; + fork + seq_h.start(p_sequencer.tl_sequencer_hs[cfg.mbx_mem_ral_name]); + join_none + endtask: start_device_seq + + virtual task write_mem(int start_addr, byte q[$]); + `uvm_info(get_full_name(), + $sformatf("write_mem(start_addr='h%0h, q=%p) -- Start", start_addr, q), + UVM_DEBUG); + foreach(q[ii]) begin + seq_mem_model.write_byte((start_addr + ii), q[ii]); + end + `uvm_info(get_full_name(), + $sformatf("write_mem(start_addr='h%0h, q=%p) -- End", start_addr, q), + UVM_DEBUG); + endtask: write_mem + + virtual task read_mem(int start_addr, int sz, ref byte q[$]); + `uvm_info(get_full_name(), + $sformatf("read_mem(start_addr='h%0h, sz=%0d) -- Start", start_addr, sz), + UVM_DEBUG) + q = {}; + for(int ii = 0; ii < sz; ii++) begin + q[ii] = seq_mem_model.read_byte(start_addr + ii); + end + `uvm_info(get_full_name(), + $sformatf("read_mem(start_addr='h%0h', sz=%0d, q=%p) -- Start", start_addr, sz, q), + UVM_DEBUG) + endtask: read_mem + + virtual task mbx_init(); + uvm_status_e status; + + `uvm_info(get_full_name(), + $sformatf("mbx_init -- Start"), + UVM_DEBUG) + csr_wr(ral.inbound_base_address, ibmbx_base_addr); + csr_wr(ral.inbound_limit_address, ibmbx_limit_addr); + csr_wr(ral.outbound_base_address, obmbx_base_addr); + csr_wr(ral.outbound_limit_address, obmbx_limit_addr); + csr_wr(ral.outbound_object_size, 0); + csr_wr(ral.control, 0); + `uvm_info(get_full_name(), + $sformatf("mbx_init -- End"), + UVM_DEBUG) + endtask: mbx_init + + virtual task wait_for_core_interrupt(); + `uvm_info(`gfn, $sformatf("wait_for_core_interrupt -- Start"), UVM_DEBUG) + `DV_WAIT(cfg.intr_vif.pins == 1'b1) + `uvm_info(`gfn, $sformatf("wait_for_core_interrupt -- End"), UVM_DEBUG) + endtask: wait_for_core_interrupt + + virtual task body(); + `uvm_info(get_full_name(), "body -- Start", UVM_DEBUG) + start_device_seq(); + `uvm_info(get_full_name(), "body -- End", UVM_DEBUG) + endtask: body + +endclass: mbx_base_vseq diff --git a/hw/ip/mbx/dv/env/seq_lib/mbx_reg_reset_val_vseq.sv b/hw/ip/mbx/dv/env/seq_lib/mbx_reg_reset_val_vseq.sv new file mode 100644 index 0000000000000..933fca3b1de4f --- /dev/null +++ b/hw/ip/mbx/dv/env/seq_lib/mbx_reg_reset_val_vseq.sv @@ -0,0 +1,90 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +class mbx_reg_reset_val_vseq extends mbx_base_vseq; + + rand int unsigned m_mbx_num; + + `uvm_object_utils(mbx_reg_reset_val_vseq) + + constraint mbx_num_c { m_mbx_num == 0; } + + function new(string name = ""); + super.new(); + do_mbx_init = 1'b0; + endfunction: new + + task soc_reg_reset_val_check(); + bit [31:0] rd_data; + + `uvm_info(get_full_name(), "soc_reg_reset_val_check -- Start", UVM_DEBUG) + + // DOE Control Register + csr_rd(m_mbx_soc_ral.m_mbxsoc_reg_block[m_mbx_num].mbxctl, rd_data); + `DV_CHECK_EQ(rd_data, 0, "Reset value mismatch for mbxctl") + + // DOE Status Register + csr_rd(m_mbx_soc_ral.m_mbxsoc_reg_block[m_mbx_num].mbxsts, rd_data); + `DV_CHECK_EQ(rd_data, 1, "Reset value mismatch for mbxsts") + + // DOE Write Data Register + csr_rd(m_mbx_soc_ral.m_mbxsoc_reg_block[m_mbx_num].mbxwrdat, rd_data); + `DV_CHECK_EQ(rd_data, 0, "Reset value mismatch for mbxwrdat") + + // DOE Read Data Register + csr_rd(m_mbx_soc_ral.m_mbxsoc_reg_block[m_mbx_num].mbxrddat, rd_data); + `DV_CHECK_EQ(rd_data, 0, "Reset value mismatch for mbxrddat") + + `uvm_info(get_full_name(), "soc_reg_reset_val_check -- End", UVM_DEBUG) + endtask: soc_reg_reset_val_check + + task core_reg_reset_val_check(); + bit [31:0] rd_data; + + `uvm_info(get_full_name(), "core_reg_reset_val_check -- Start", UVM_DEBUG) + // DOE Control Register + csr_rd(ral.m_mbxhst_reg_block[m_mbx_num].mbxctl, rd_data); + `DV_CHECK_EQ(rd_data, 0, "Reset value mismatch for uarch mbxctl") + + // DOE Status Register + csr_rd(ral.m_mbxhst_reg_block[m_mbx_num].mbxsts, rd_data); + `DV_CHECK_EQ(rd_data, 1, "Reset value mismatch for uarch mbxsts") + + // DOE IBBASE Register + csr_rd(ral.m_mbxhst_reg_block[m_mbx_num].mbxibbase, rd_data); + `DV_CHECK_EQ(rd_data, 0, "Reset value mismatch for uarch mbxibbase") + + // DOE IBLIMIT Register + csr_rd(ral.m_mbxhst_reg_block[m_mbx_num].mbxiblmit, rd_data); + `DV_CHECK_EQ(rd_data, 0, "Reset value mismatch for uarch mbxiblmit") + + // DOE OBBASE Register + csr_rd(ral.m_mbxhst_reg_block[m_mbx_num].mbxobbase, rd_data); + `DV_CHECK_EQ(rd_data, 0, "Reset value mismatch for uarch mbxobbase") + + // DOE OBLIMIT Register + csr_rd(ral.m_mbxhst_reg_block[m_mbx_num].mbxoblmit, rd_data); + `DV_CHECK_EQ(rd_data, 0, "Reset value mismatch for uarch mbxoblmit") + + // DOE OBDWCNT Register + csr_rd(ral.m_mbxhst_reg_block[m_mbx_num].mbxobdwcnt, rd_data); + `DV_CHECK_EQ(rd_data, 0, "Reset value mismatch for uarch mbxobdwcnt") + + `uvm_info(get_full_name(), "core_reg_reset_val_check -- End", UVM_DEBUG) + endtask: core_reg_reset_val_check + + task body(); + `uvm_info(get_full_name(), "body -- Start", UVM_DEBUG) + super.body(); + + // System Side + soc_reg_reset_val_check(); + + // Host Side + core_reg_reset_val_check(); + + `uvm_info(get_full_name(), "body -- End", UVM_DEBUG) + endtask: body + +endclass: mbx_reg_reset_val_vseq diff --git a/hw/ip/mbx/dv/env/seq_lib/mbx_smoke_vseq.sv b/hw/ip/mbx/dv/env/seq_lib/mbx_smoke_vseq.sv new file mode 100644 index 0000000000000..eea95caeb95ea --- /dev/null +++ b/hw/ip/mbx/dv/env/seq_lib/mbx_smoke_vseq.sv @@ -0,0 +1,165 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +class mbx_smoke_vseq extends mbx_base_vseq; + + `uvm_object_utils(mbx_smoke_vseq) + + function new(string name = "mbx_smoke_vseq"); + super.new(name); + endfunction: new + + virtual task body(); + // TODO: move to package if we decide to keep this. + typedef bit [31:0] mbx_dword_t; + + bit [top_pkg::TL_AW-1:0] rd_data; + bit [top_pkg::TL_AW-1:0] wr_data; + int unsigned req_size_limit; + int unsigned rsp_size_limit; + int unsigned req_size; + int unsigned rsp_size; + bit [31:0] req[$]; + bit [31:0] rsp[$]; + mbx_dword_t qd; + // TODO: perhaps we should change read_mem/write_mem to avoid issues. The mailbox operates only + // on DWORD quantities. + // mbx_dword_t q[$]; + byte q[$]; + + // TODO: move to appropriate location; package? + int unsigned MBX_SOC_WDATA_BASE = 'h10; + int unsigned MBX_SOC_RDATA_BASE = 'h14; + + // TODO: gross change to prevent explosions on accessing RDATA, since it does not behave like + // a regular memory + cfg.en_scb_mem_chk = 1'b0; + + `uvm_info(get_full_name(), "body -- Start", UVM_DEBUG) + super.body(); + + // Ensure that we have a valid memory range + csr_wr(ral.address_range_valid, 1'b1); + + // Data from R-code to ROT + + // Without PR#321 there was an issue in the RTL that the Busy bit is not deasserted when the + // address range becomes valid. + if (1'b1) begin + // Check for Busy bit being clear before we can write to WDATA. + rd_data = '0; + rd_data[0] = 1'b1; + while(rd_data[0] == 1'b1) begin + csr_rd(m_mbx_soc_ral.soc_status, rd_data); + `uvm_info(`gfn, + $sformatf("checking for busy bit, rd_data for soc_status is :'h%0h", rd_data), UVM_DEBUG) + end + end + + // Request and response sizes, in DWORDs + // Note: limit addresses are inclusive, and we want each message to be at least one DWORD long. + req_size_limit = (ibmbx_limit_addr - ibmbx_base_addr) >> 2; + rsp_size_limit = (obmbx_limit_addr - obmbx_base_addr) >> 2; + // TODO: Could perhaps do this with the base/limit constraints; after all the physical memory + // is going to be limited. + // TODO: Are there penalties involved in having a memory model with a ridiculous address range, + // or is it sparse? + if (req_size_limit >= 'h400) + req_size_limit = 'h400; + if (rsp_size_limit >= 'h400) + rsp_size_limit = 'h400; + // There's a further constraint on the number of DWORDs in the Response Object + if (rsp_size_limit > MBX_DV_MAX_DW) + rsp_size_limit = MBX_DV_MAX_DW; + + req_size = 1 + ($urandom % (1 + req_size_limit)); + rsp_size = 1 + ($urandom % (1 + rsp_size_limit)); + + `uvm_info(`gfn, + $sformatf("Request size %x DWORD(s), Response size %x DWORD(s)", req_size, rsp_size), UVM_LOW) + `uvm_info(`gfn, + $sformatf("Inbox should use [%x,%x)", ibmbx_base_addr, ibmbx_base_addr + req_size * 4), + UVM_LOW) + `uvm_info(`gfn, + $sformatf("Outbox should use [%x,%x)", obmbx_base_addr, obmbx_base_addr + rsp_size * 4), + UVM_LOW) + + for(int unsigned ii = 0; ii < req_size; ii++) begin + wr_data = $urandom(); + req.push_back(wr_data); + tl_access(.addr(m_mbx_soc_ral.get_addr_from_offset(MBX_SOC_WDATA_BASE)), + .write(1'b1), .data(wr_data), .mask(4'hF), .blocking(1), + .tl_sequencer_h(p_sequencer.tl_sequencer_hs[cfg.mbx_soc_ral_name])); + end + + // Note: we need only set bit 31 (Go) here, no need to read. + // csr_rd(m_mbx_soc_ral.soc_control, rd_data); + // rd_data[31] = 1'b1; + rd_data = 32'h8000_0000; + csr_wr(m_mbx_soc_ral.soc_control, rd_data); + + // TODO: should wait until the Ready interrupt is signaled to the ROT + cfg.clk_rst_vif.wait_clks(1024); + + // Collect the request message from the OT mailbox memory + read_mem(ibmbx_base_addr, req_size << 2, q); + + for(int unsigned ii = 0; ii < req_size; ii++) begin + qd = {q[ii*4+3],q[ii*4+2],q[ii*4+1],q[ii*4]}; + `uvm_info(`gfn, $sformatf("Expected %0h got %0h", req[ii], qd), UVM_LOW) + if (qd !== req[ii]) begin + `uvm_error(`gfn, $sformatf("q[%0d]('h%0h) != req[%0d]('h%0h)", ii, qd, ii, req[ii])) + end + end + + // Data from ROT to R-code + q.delete(); + for(int unsigned ii = 0 ; ii < rsp_size*4; ii++) begin + q.push_back($urandom); + end + write_mem(obmbx_base_addr, q); + csr_wr(ral.outbound_object_size, rsp_size); + do begin + csr_rd(m_mbx_soc_ral.soc_status, rd_data); + `uvm_info(get_full_name(), + $sformatf("rd_data for soc_status is :'h%0h", rd_data), + UVM_DEBUG) + end while (rd_data[31] != 1'b1); + + // Collect the entire message before checking it. + // Note: this may not be the best approach unless we can time out in the event of a lock up + // in the provision of new RDATA values. + for(int unsigned ii = 0; ii < rsp_size; ii++) begin + // Read from RDATA to collect the next message word + tl_access(.addr(cfg.ral.get_addr_from_offset(MBX_SOC_RDATA_BASE)), + .write(1'b0), .data(rd_data), .mask(4'hF), .compare_mask(0), .blocking(1), + .tl_sequencer_h(p_sequencer.tl_sequencer_hs[cfg.mbx_soc_ral_name])); + + `uvm_info(get_full_name(), $sformatf("Mailbox read data is : 'h%0h", rd_data), UVM_LOW) + + rsp.push_back(rd_data); + + // Write anything to RDATA to advance to the next word. + wr_data = $urandom; + tl_access(.addr(cfg.ral.get_addr_from_offset(MBX_SOC_RDATA_BASE)), + .write(1'b1), .data(wr_data), .mask(4'hF), .blocking(1), + .tl_sequencer_h(p_sequencer.tl_sequencer_hs[cfg.mbx_soc_ral_name])); + end + + for(int unsigned ii = 0; ii < rsp_size; ii++) begin + qd = {q[ii*4+3],q[ii*4+2],q[ii*4+1],q[ii*4]}; + `uvm_info(`gfn, $sformatf("Expected %0h got %0h", qd, rsp[ii]), UVM_LOW) + if (qd !== rsp[ii]) begin + `uvm_error(get_full_name(), + $sformatf(" q[%0d]('h%0h) != rsp[%0d]('h%0h)", ii, qd, ii, rsp[ii])) + end + end + + csr_rd(m_mbx_soc_ral.soc_status, rd_data); + `DV_CHECK_EQ(rd_data[31], 1'b0, "Ready bit still set") + + `uvm_info(get_full_name(), "body -- End", UVM_DEBUG) + endtask: body + +endclass: mbx_smoke_vseq diff --git a/hw/ip/mbx/dv/env/seq_lib/mbx_tl_device_seq.sv b/hw/ip/mbx/dv/env/seq_lib/mbx_tl_device_seq.sv new file mode 100644 index 0000000000000..233c26ccf6816 --- /dev/null +++ b/hw/ip/mbx/dv/env/seq_lib/mbx_tl_device_seq.sv @@ -0,0 +1,20 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +class mbx_tl_device_seq extends cip_tl_device_seq; + + `uvm_object_utils(mbx_tl_device_seq) + + `uvm_object_new + + virtual function void update_mem(REQ rsp); + super.update_mem(rsp); + rsp.d_user = rsp.compute_d_user(); + if (inject_d_chan_intg_err) begin + rsp.tl_intg_err_type = tl_intg_err_type; + rsp.inject_d_chan_intg_err(); + end + endfunction: update_mem + +endclass: mbx_tl_device_seq diff --git a/hw/ip/mbx/dv/env/seq_lib/mbx_tl_reg_seq.sv b/hw/ip/mbx/dv/env/seq_lib/mbx_tl_reg_seq.sv new file mode 100644 index 0000000000000..b706aac484f1b --- /dev/null +++ b/hw/ip/mbx/dv/env/seq_lib/mbx_tl_reg_seq.sv @@ -0,0 +1,26 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +class mbx_tl_reg_seq extends cip_tl_host_single_seq; + + rand tlul_pkg::tl_a_user_t auser; + + `uvm_object_utils(mbx_tl_reg_seq) + + constraint size_c { size == 2; } + constraint mask_c { mask == 'hf; } + constraint auser_c { auser.instr_type == prim_mubi_pkg::MuBi4False; } + + function new (string name = ""); + super.new(name); + endfunction: new + + virtual function void randomize_req(REQ req, int idx); + control_rand_size = 1; + control_rand_opcode = 1; + super.randomize_req(req, idx); + req.a_user = auser; + endfunction + +endclass: mbx_tl_reg_seq diff --git a/hw/ip/mbx/dv/env/seq_lib/mbx_vseq_list.sv b/hw/ip/mbx/dv/env/seq_lib/mbx_vseq_list.sv new file mode 100644 index 0000000000000..827616f1c0294 --- /dev/null +++ b/hw/ip/mbx/dv/env/seq_lib/mbx_vseq_list.sv @@ -0,0 +1,8 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +`include "mbx_tl_reg_seq.sv" +`include "mbx_tl_device_seq.sv" +`include "mbx_base_vseq.sv" +`include "mbx_smoke_vseq.sv" diff --git a/hw/ip/mbx/dv/mbx_sim.core b/hw/ip/mbx/dv/mbx_sim.core new file mode 100644 index 0000000000000..05b8d7535addb --- /dev/null +++ b/hw/ip/mbx/dv/mbx_sim.core @@ -0,0 +1,29 @@ +CAPI=2: +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: "lowrisc:dv:mbx_sim:0.1" +description: "MBX DV sim target" +filesets: + files_rtl: + depend: + - lowrisc:ip:mbx + + files_dv: + depend: + - lowrisc:dv:mbx_test + - lowrisc:dv:mbx_sva + files: + - tb.sv + file_type: systemVerilogSource + +targets: + sim: &sim_target + toplevel: tb + filesets: + - files_rtl + - files_dv + default_tool: vcs + + lint: + <<: *sim_target diff --git a/hw/ip/mbx/dv/mbx_sim_cfg.hjson b/hw/ip/mbx/dv/mbx_sim_cfg.hjson new file mode 100644 index 0000000000000..f88b421562de5 --- /dev/null +++ b/hw/ip/mbx/dv/mbx_sim_cfg.hjson @@ -0,0 +1,93 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +{ + // Name of the sim cfg - typically same as the name of the DUT. + name: mbx + + // Top level dut name (sv module). + dut: mbx + + // Top level testbench name (sv module). + tb: tb + + // Simulator used to sign off this block + tool: xcelium + + // Fusesoc core file used for building the file list. + fusesoc_core: lowrisc:dv:mbx_sim:0.1 + + // Testplan hjson file. + testplan: "{proj_root}/hw/ip/mbx/data/mbx_testplan.hjson" + + // RAL spec - used to generate the RAL model. + ral_spec: "{proj_root}/hw/ip/mbx/data/mbx.hjson" + + // Import additional common sim cfg files. + import_cfgs: [// Project wide common sim cfg file + "{proj_root}/hw/dv/tools/dvsim/common_sim_cfg.hjson", + "{proj_root}/hw/dv/tools/dvsim/tests/csr_tests.hjson", + "{proj_root}/hw/dv/tools/dvsim/tests/alert_test.hjson", + "{proj_root}/hw/dv/tools/dvsim/tests/tl_access_tests.hjson", + "{proj_root}/hw/dv/tools/dvsim/tests/sec_cm_tests.hjson", + "{proj_root}/hw/dv/tools/dvsim/tests/stress_tests.hjson"] + + // Add additional tops for simulation. +// sim_tops: ["mbx_bind", "mbx_cov_bind"] + + // Default iterations for all tests - each test entry can override this. + reseed: 2 + +// overrides: [ +// // +// // Override coverage config files to add our elaboration time coverage exclusions etc. +// // +// { +// name: default_vcs_cov_cfg_file +// value: "-cm_hier {dv_root}/tools/vcs/cover.cfg+{dv_root}/tools/vcs/common_cov_excl.cfg+{proj_root}/hw/ip/mbx/dv/cov/mbx_cover.cfg" +// } +// // The jtag agent requires the data and bytenable widths to be increased. +// { +// name: tl_dw +// value: 64 +// } +// { +// name: tl_dbw +// value: 8 +// } +// ] + +// // Add MBX specific exclusion files. +// vcs_cov_excl_files: ["{proj_root}/hw/ip/mbx/dv/cov/mbx_cov_unr_excl.el", +// "{proj_root}/hw/ip/mbx/dv/cov/mbx_terminal_st_excl.el"] + + // Default UVM test and seq class name. + uvm_test: mbx_base_test + uvm_test_seq: mbx_base_vseq + + run_opts: ["+cdc_instrumentation_enabled=1"] + + // List of test specifications. + tests: [ + { + name: mbx_smoke + uvm_test_seq: mbx_smoke_vseq + } + + ] + + // List of regressions. + regressions: [ + { + name: smoke + tests: ["mbx_smoke"] + } +// { +// name: stress +// tests : [ "mbx_sw_access", +// "mbx_sw_smoke", +// "mbx_sw_alert_test" +// ] +// } + ] +} diff --git a/hw/ip/mbx/dv/sva/mbx_bind.sv b/hw/ip/mbx/dv/sva/mbx_bind.sv new file mode 100644 index 0000000000000..3a0ed9c2cce98 --- /dev/null +++ b/hw/ip/mbx/dv/sva/mbx_bind.sv @@ -0,0 +1,42 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +module mbx_bind; + + bind mbx tlul_assert #( + .EndpointType("Host") + ) mbx_agx_tlul_assert_core ( + .clk_i(hstRegAccL3), + .rst_ni(hstRegReset), + .h2d (mbx_agx_tlReQH2d), + .d2h (agx_mbx_tlRsPD2h) + ); + + bind mbx tlul_assert #( + .EndpointType("Device") + ) agx_mbx_tlul_assert_device ( + .clk_i(hstRegAccL3), + .rst_ni(hstRegReset), + .h2d (agx_mbx_tlReQH2d), + .d2h (mbx_agx_tlRsPD2h) + ); + + bind mbx tlul_assert #( + .EndpointType("Device") + ) scx_mbx_tlul_assert_device( + .clk_i(sysRegAccL3), + .rst_ni(sysRegReset), + .h2d (scx_mbx_tlReQH2d), + .d2h (mbx_scx_tlRsPD2h) + ); + + // TODO: Revisit this + // bind mbx mbx_regs_csr_assert_fpv mbx_regs_csr_assert ( + // .clk_i, + // .rst_ni, + // .h2d (regs_tl_i), + // .d2h (regs_tl_o) + // ); + +endmodule diff --git a/hw/ip/mbx/dv/sva/mbx_sva.core b/hw/ip/mbx/dv/sva/mbx_sva.core new file mode 100644 index 0000000000000..de86e7ce250c3 --- /dev/null +++ b/hw/ip/mbx/dv/sva/mbx_sva.core @@ -0,0 +1,39 @@ +CAPI=2: +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: "lowrisc:dv:mbx_sva:0.1" +description: "MBX assertion modules and bind file." +filesets: + files_dv: + depend: + - lowrisc:tlul:headers + # TODO: Revisit this + # - lowrisc:fpv:csr_assert_gen + files: + - mbx_bind.sv + file_type: systemVerilogSource + + files_formal: + depend: + - lowrisc:ip:mbx + +generate: + csr_assert_gen: + generator: csr_assert_gen + parameters: + spec: ../../data/mbx.hjson + +targets: + default: &default_target + filesets: + - files_dv + # TODO: Revisit this + # generate: + # - csr_assert_gen + formal: + <<: *default_target + filesets: + - files_formal + - files_dv + toplevel: mbx diff --git a/hw/ip/mbx/dv/tb.sv b/hw/ip/mbx/dv/tb.sv new file mode 100644 index 0000000000000..954187899b027 --- /dev/null +++ b/hw/ip/mbx/dv/tb.sv @@ -0,0 +1,107 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +module tb; + // dep packages + import uvm_pkg::*; + import dv_utils_pkg::*; + import mbx_env_pkg::*; + import mbx_test_pkg::*; + + // macro includes + `include "uvm_macros.svh" + `include "dv_macros.svh" + `include "cip_macros.svh" + + wire clk, rst_n; + wire [NUM_MAX_INTERRUPTS-1:0] interrupts; + wire intr_ready; + wire intr_abort; + + clk_rst_if i_clk_rst_if(.clk(clk), .rst_n(rst_n)); + tl_if i_tl_scxb_mbx_core_if(.clk(clk), .rst_n(rst_n)); + tl_if i_tl_agxb_mbx_core_if(.clk(clk), .rst_n(rst_n)); + tl_if i_tl_mbx_agxb_device_if(.clk(clk), .rst_n(rst_n)); + pins_if #(NUM_MAX_INTERRUPTS) i_intr_if(interrupts); + + `DV_ALERT_IF_CONNECT() + + // dut + mbx #() dut + ( + .clk_i(clk), + .rst_ni(rst_n), + .doe_intr_support_o(), + .doe_intr_en_o(), + .doe_intr_o(), + // various tlul interfaces + .core_tl_d_o(i_tl_agxb_mbx_core_if.d2h), + .core_tl_d_i(i_tl_agxb_mbx_core_if.h2d), + .soc_tl_d_o(i_tl_scxb_mbx_core_if.d2h), + .soc_tl_d_i(i_tl_scxb_mbx_core_if.h2d), + .sram_tl_h_o(i_tl_mbx_agxb_device_if.h2d), + .sram_tl_h_i(i_tl_mbx_agxb_device_if.d2h), + // alerts and interrupts + .intr_mbx_ready_o(intr_ready), + .intr_mbx_abort_o(intr_abort), + .alert_rx_i(alert_rx), + .alert_tx_o(alert_tx) + ); + + // Connect the interrupts + assign interrupts[MbxCoreReady] = intr_ready; + assign interrupts[MbxCoreAbort] = intr_abort; + + initial begin + // drive clk and rst_n from clk_if + i_clk_rst_if.set_active(); + uvm_config_db#(virtual clk_rst_if)::set( + null, "*.env", "clk_rst_vif", i_clk_rst_if); + uvm_config_db#(virtual clk_rst_if)::set( + null, "*.env", "clk_rst_vif_mbx_mem_reg_block", i_clk_rst_if); + uvm_config_db#(virtual clk_rst_if)::set( + null, "*.env", "clk_rst_vif_mbx_soc_reg_block", i_clk_rst_if); + uvm_config_db#(virtual clk_rst_if)::set( + null, "*.env", "clk_rst_vif_mbx_reg_block", i_clk_rst_if); + uvm_config_db#(virtual clk_rst_if)::set( + null, "*.env", "clk_rst_vif_mbx_core_reg_block", i_clk_rst_if); + uvm_config_db#(virtual clk_rst_if)::set( + null, "*.env", "clk_rst_vif_mbx_soc_reg_block", i_clk_rst_if); + uvm_config_db#(virtual tl_if)::set( + null, "*.env.m_tl_agent_mbx_core_reg_block*", "vif", + i_tl_agxb_mbx_core_if); + uvm_config_db#(virtual tl_if)::set( + null, "*.env.m_tl_agent_mbx_soc_reg_block*", "vif", + i_tl_scxb_mbx_core_if); + uvm_config_db#(virtual tl_if)::set( + null, "*.env.m_tl_agent_mbxuarch_reg_block*", "vif", + i_tl_agxb_mbx_core_if); + uvm_config_db#(virtual tl_if)::set( + null, "*.env.m_tl_agent_mbx_reg_block*", "vif", + i_tl_scxb_mbx_core_if); + uvm_config_db#(virtual tl_if)::set( + null, "*.env.m_tl_agent_mbx_mem_reg_block*", "vif", + i_tl_mbx_agxb_device_if); + uvm_config_db#(intr_vif)::set( + null, "*.env", "intr_vif", i_intr_if); + $timeformat(-12, 0, " ps", 12); + run_test(); + end + + //FIXME: Previous reg_intf + //mbx_reg_intf i_mbx_reg_intf( + // .clk(clk), + // .rst_n(rst_n), + // .req(i_tl_scxb_mbx_core_if.h2d), + // .rsp(i_tl_scxb_mbx_core_if.d2h) + //); + + //mbxuarch_reg_intf i_mbxuarch_reg_intf( + // .clk(clk), + // .rst_n(rst_n), + // .req(i_tl_agxb_mbx_core_if.h2d), + // .rsp(i_tl_agxb_mbx_core_if.d2h) + //); + +endmodule diff --git a/hw/ip/mbx/dv/tests/mbx_base_test.sv b/hw/ip/mbx/dv/tests/mbx_base_test.sv new file mode 100644 index 0000000000000..a5bcdff4197c8 --- /dev/null +++ b/hw/ip/mbx/dv/tests/mbx_base_test.sv @@ -0,0 +1,20 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +class mbx_base_test extends cip_base_test #( + .CFG_T(mbx_env_cfg), + .ENV_T(mbx_env) + ); + + `uvm_component_utils(mbx_base_test) + `uvm_component_new + + // the base class dv_base_test creates the following instances: + // mbx_env_cfg: cfg + // mbx_env: env + + // the base class also looks up UVM_TEST_SEQ plusarg to create and run that seq in + // the run_phase; as such, nothing more needs to be done + +endclass : mbx_base_test diff --git a/hw/ip/mbx/dv/tests/mbx_test.core b/hw/ip/mbx/dv/tests/mbx_test.core new file mode 100644 index 0000000000000..e2400a6ad0719 --- /dev/null +++ b/hw/ip/mbx/dv/tests/mbx_test.core @@ -0,0 +1,19 @@ +CAPI=2: +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: "lowrisc:dv:mbx_test:0.1" +description: "MBX DV UVM test" +filesets: + files_dv: + depend: + - lowrisc:dv:mbx_env + files: + - mbx_test_pkg.sv + - mbx_base_test.sv: {is_include_file: true} + file_type: systemVerilogSource + +targets: + default: + filesets: + - files_dv diff --git a/hw/ip/mbx/dv/tests/mbx_test_pkg.sv b/hw/ip/mbx/dv/tests/mbx_test_pkg.sv new file mode 100644 index 0000000000000..0b5279a39d188 --- /dev/null +++ b/hw/ip/mbx/dv/tests/mbx_test_pkg.sv @@ -0,0 +1,22 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +package mbx_test_pkg; + // dep packages + import uvm_pkg::*; + import cip_base_pkg::*; + import mbx_env_pkg::*; + + // macro includes + `include "uvm_macros.svh" + `include "dv_macros.svh" + + // local types + + // functions + + // package sources + `include "mbx_base_test.sv" + +endpackage: mbx_test_pkg From 199c111c24b9301e2c1ff22cb38e5a1d895a9f77 Mon Sep 17 00:00:00 2001 From: Adrian Lees Date: Mon, 30 Oct 2023 16:20:00 +0000 Subject: [PATCH 50/88] [dv,darjeeling] Include DMA and MBX smoke tests in CI DMA and MBX smoke tests are passing; incorporate them into Darjeeling DV smoke runs. Introduce `mbx_common_vseq` required for common tests. Signed-off-by: Adrian Lees --- hw/ip/mbx/dv/env/mbx_env.core | 1 + hw/ip/mbx/dv/env/seq_lib/mbx_common_vseq.sv | 17 +++++++++++++++++ hw/ip/mbx/dv/env/seq_lib/mbx_vseq_list.sv | 1 + 3 files changed, 19 insertions(+) create mode 100644 hw/ip/mbx/dv/env/seq_lib/mbx_common_vseq.sv diff --git a/hw/ip/mbx/dv/env/mbx_env.core b/hw/ip/mbx/dv/env/mbx_env.core index d52781c2550aa..c430c74d7eccf 100644 --- a/hw/ip/mbx/dv/env/mbx_env.core +++ b/hw/ip/mbx/dv/env/mbx_env.core @@ -20,6 +20,7 @@ filesets: - seq_lib/mbx_tl_reg_seq.sv: {is_include_file: true} - seq_lib/mbx_tl_device_seq.sv: {is_include_file: true} - seq_lib/mbx_base_vseq.sv: {is_include_file: true} + - seq_lib/mbx_common_vseq.sv: {is_include_file: true} - seq_lib/mbx_smoke_vseq.sv: {is_include_file: true} - seq_lib/mbx_vseq_list.sv: {is_include_file: true} file_type: systemVerilogSource diff --git a/hw/ip/mbx/dv/env/seq_lib/mbx_common_vseq.sv b/hw/ip/mbx/dv/env/seq_lib/mbx_common_vseq.sv new file mode 100644 index 0000000000000..23347ea916de4 --- /dev/null +++ b/hw/ip/mbx/dv/env/seq_lib/mbx_common_vseq.sv @@ -0,0 +1,17 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +class mbx_common_vseq extends mbx_base_vseq; + `uvm_object_utils(mbx_common_vseq) + + constraint num_trans_c { + num_trans inside {[1:2]}; + } + `uvm_object_new + + virtual task body(); + run_common_vseq_wrapper(num_trans); + endtask : body + +endclass diff --git a/hw/ip/mbx/dv/env/seq_lib/mbx_vseq_list.sv b/hw/ip/mbx/dv/env/seq_lib/mbx_vseq_list.sv index 827616f1c0294..0c29e12387b6c 100644 --- a/hw/ip/mbx/dv/env/seq_lib/mbx_vseq_list.sv +++ b/hw/ip/mbx/dv/env/seq_lib/mbx_vseq_list.sv @@ -5,4 +5,5 @@ `include "mbx_tl_reg_seq.sv" `include "mbx_tl_device_seq.sv" `include "mbx_base_vseq.sv" +`include "mbx_common_vseq.sv" `include "mbx_smoke_vseq.sv" From a3b15fbfe9357594d00c00edda466f32cc355a71 Mon Sep 17 00:00:00 2001 From: Harry Callahan Date: Tue, 31 Oct 2023 13:46:22 +0000 Subject: [PATCH 51/88] [mbx,dv] Dv tweaks to get csr tests running in the smoke regression Signed-off-by: Harry Callahan --- hw/ip/mbx/data/mbx.hjson | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/ip/mbx/data/mbx.hjson b/hw/ip/mbx/data/mbx.hjson index 4c92773ed2fba..e3195b48f8c99 100644 --- a/hw/ip/mbx/data/mbx.hjson +++ b/hw/ip/mbx/data/mbx.hjson @@ -190,6 +190,7 @@ resval: "0x0" } ] + tags: ["excl:CsrAllTests:CsrExclAll"] // TODO(#477) } { name: "INBOUND_WRITE_PTR" desc: '''Write pointer for the next inbound data write. From d80e65a0f1f30c905cca87678328392fb29aa8c6 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Thu, 2 Nov 2023 03:17:54 -0700 Subject: [PATCH 52/88] [hw,mbx,rtl] Defer IRQ generation until write response received Signed-off-by: Robert Schilling --- hw/ip/mbx/rtl/mbx.sv | 5 +++-- hw/ip/mbx/rtl/mbx_fsm.sv | 32 +++++++++++++++++++++++++------- hw/ip/mbx/rtl/mbx_imbx.sv | 9 ++++----- hw/ip/mbx/rtl/mbx_ombx.sv | 1 + hw/ip/mbx/rtl/mbx_sramrwarb.sv | 9 +++++---- 5 files changed, 38 insertions(+), 18 deletions(-) diff --git a/hw/ip/mbx/rtl/mbx.sv b/hw/ip/mbx/rtl/mbx.sv index 6fa4c6bd75fe4..033a1f61ec2b5 100644 --- a/hw/ip/mbx/rtl/mbx.sv +++ b/hw/ip/mbx/rtl/mbx.sv @@ -149,7 +149,7 @@ module mbx // Interface signals for SRAM host access to write the incoming data to memory logic imbx_sram_write_req, imbx_sram_write_gnt; - logic imbx_sram_write_resp_vld; + logic imbx_sram_all_vld_rcvd; logic [CfgSramDataWidth-1:0] sysif_write_data; logic sysif_write_data_write_valid; @@ -238,6 +238,7 @@ module mbx // Host interface to access private SRAM .hostif_sram_write_req_o ( imbx_sram_write_req ), .hostif_sram_write_gnt_i ( imbx_sram_write_gnt ), + .hostif_sram_all_vld_rcvd_i ( imbx_sram_all_vld_rcvd ), .hostif_sram_write_ptr_o ( imbx_sram_write_ptr ) ); @@ -299,7 +300,7 @@ module mbx .imbx_sram_write_req_i ( imbx_sram_write_req ), .imbx_sram_write_gnt_o ( imbx_sram_write_gnt ), .imbx_sram_write_ptr_i ( imbx_sram_write_ptr ), - .imbx_sram_write_resp_vld_o( imbx_sram_write_resp_vld ), + .imbx_sram_all_vld_rcvd_o ( imbx_sram_all_vld_rcvd ), .imbx_write_data_i ( sysif_write_data ), // Interface to the outbound mailbox .ombx_sram_read_req_i ( ombx_sram_read_req ), diff --git a/hw/ip/mbx/rtl/mbx_fsm.sv b/hw/ip/mbx/rtl/mbx_fsm.sv index b1138bba6a4e7..bf011d33e76c0 100644 --- a/hw/ip/mbx/rtl/mbx_fsm.sv +++ b/hw/ip/mbx/rtl/mbx_fsm.sv @@ -15,8 +15,9 @@ module mbx_fsm #( input logic hostif_control_error_set_i, input logic sysif_control_abort_set_i, input logic sys_read_all_i, - input logic writer_write_valid_i, input logic writer_close_mbx_i, + input logic writer_last_word_written_i, + input logic writer_write_valid_i, // Status signals output logic mbx_empty_o, output logic mbx_write_o, @@ -26,11 +27,12 @@ module mbx_fsm #( output logic mbx_ready_o, output logic mbx_state_error_o ); - typedef enum logic [1:0] { - MbxIdle = 2'b00, - MbxWrite = 2'b01, - MbxRead = 2'b10, - MbxSysAbortHost = 2'b11 + typedef enum logic [2:0] { + MbxIdle = 3'b000, + MbxWrite = 3'b001, + MbxWaitFinalWord = 3'b010, + MbxRead = 3'b011, + MbxSysAbortHost = 3'b100 } mbx_ctrl_state_e; mbx_ctrl_state_e ctrl_state_q, ctrl_state_d; @@ -104,7 +106,23 @@ module mbx_fsm #( end else if (sysif_control_abort_set_i) begin // System wants to abort ctrl_state_d = MbxSysAbortHost; end else if (writer_close_mbx_i) begin // Writer decided to close the mailbox - ctrl_state_d = MbxRead; + if (writer_last_word_written_i) begin + ctrl_state_d = MbxRead; + end else begin + ctrl_state_d = MbxWaitFinalWord; + end + end + end + + // Inbound mailbox being written by the system = writer + // Outbound mailbox: not applicable + MbxWaitFinalWord: begin + if (hostif_control_error_set_i) begin // Host asserts an error + ctrl_state_d = MbxIdle; + end else if (sysif_control_abort_set_i) begin // System wants to abort + ctrl_state_d = MbxSysAbortHost; + end else if (writer_last_word_written_i) begin + ctrl_state_d = MbxRead; end end diff --git a/hw/ip/mbx/rtl/mbx_imbx.sv b/hw/ip/mbx/rtl/mbx_imbx.sv index e16ec734985cd..248df1b32a2c4 100644 --- a/hw/ip/mbx/rtl/mbx_imbx.sv +++ b/hw/ip/mbx/rtl/mbx_imbx.sv @@ -34,6 +34,7 @@ module mbx_imbx #( // Host interface to the private SRAM output logic hostif_sram_write_req_o, input logic hostif_sram_write_gnt_i, + input logic hostif_sram_all_vld_rcvd_i, output logic [CfgSramAddrWidth-1:0] hostif_sram_write_ptr_o ); localparam int unsigned LCFG_SRM_ADDRINC = CfgSramDataWidth / 8; @@ -153,6 +154,7 @@ module mbx_imbx #( .sysif_control_abort_set_i ( sysif_control_abort_set_i ), .sys_read_all_i ( sys_read_all_i ), .writer_close_mbx_i ( sysif_control_go_set_i ), + .writer_last_word_written_i( hostif_sram_all_vld_rcvd_i ), .writer_write_valid_i ( sysif_data_write_valid_i ), // Status signals .mbx_empty_o ( mbx_empty ), @@ -189,11 +191,8 @@ module mbx_imbx #( `endif // Ready IRQ to core should not be asserted whilst there is still pending write traffic - // TODO: this should wait until the write receives a response and not just a grent, and - // presently it should be expected to fire because assertion of ibmx_irq_ready_o is not - // even deferred until the final word write has been granted. (#476) - //`ASSERT_NEVER(WrEverythingBeforeReadyIRQ, imbx_irq_ready_o & - // hostif_sram_write_req_o & ~hostif_sram_write_gnt_i) + `ASSERT_NEVER(WrEverythingBeforeReadyIRQ, imbx_irq_ready_o & + hostif_sram_write_req_o & ~hostif_sram_write_gnt_i) // The write pointer should not be advanced if the request has not yet been granted. `ASSERT_IF(WrPtrShouldNotAdvanceIfNoAck_A, hostif_sram_write_gnt_i, diff --git a/hw/ip/mbx/rtl/mbx_ombx.sv b/hw/ip/mbx/rtl/mbx_ombx.sv index 2edf55b40b53a..262a8655cc0da 100644 --- a/hw/ip/mbx/rtl/mbx_ombx.sv +++ b/hw/ip/mbx/rtl/mbx_ombx.sv @@ -240,6 +240,7 @@ module mbx_ombx #( .sysif_control_abort_set_i ( sysif_control_abort_set_i ), .sys_read_all_i ( sys_read_all_o ), .writer_close_mbx_i ( writer_close_mbx ), + .writer_last_word_written_i( 1'b0 ), .writer_write_valid_i ( 1'b0 ), // Status signals .mbx_empty_o ( mbx_empty ), diff --git a/hw/ip/mbx/rtl/mbx_sramrwarb.sv b/hw/ip/mbx/rtl/mbx_sramrwarb.sv index 4a6215d076192..84d8e40ca283d 100644 --- a/hw/ip/mbx/rtl/mbx_sramrwarb.sv +++ b/hw/ip/mbx/rtl/mbx_sramrwarb.sv @@ -20,8 +20,8 @@ module mbx_sramrwarb input logic imbx_sram_write_req_i, output logic imbx_sram_write_gnt_o, input logic [CfgSramAddrWidth-1:0] imbx_sram_write_ptr_i, - output logic imbx_sram_write_resp_vld_o, input logic [CfgSramDataWidth-1:0] imbx_write_data_i, + output logic imbx_sram_all_vld_rcvd_o, // Interface to the outpbound mailbox input logic ombx_sram_read_req_i, output logic ombx_sram_read_gnt_o, @@ -74,7 +74,9 @@ module mbx_sramrwarb .q_o ( outstanding_req_count_q ) ); // Block SRAM requests if we reached the maximum outstanding number - assign max_outstanding_reqs_reached = (outstanding_req_count_q == LCFG_MAX_REQS); + assign max_outstanding_reqs_reached = (outstanding_req_count_q == LCFG_MAX_REQS); + // All outstanding requests responded, thus all transfers are written or read + assign imbx_sram_all_vld_rcvd_o = (outstanding_req_count_q == '0); tlul_adapter_host #( .MAX_REQS ( LCFG_MAX_REQS ), @@ -108,9 +110,8 @@ module mbx_sramrwarb // We cannot differentiate on directly on the response signal of the TLUL adapter. We need // to look if the response was a response with data or not. It it's with data, it was a read // request and we serve ombx_sram_read_resp_vld_o. If it was a response without data - // it was a write request, so we serve imbx_sram_write_resp_vld_o + // it was a write request. assign ombx_sram_read_resp_vld_o = sram_valid & (tl_host_i.d_opcode == tlul_pkg::AccessAckData); - assign imbx_sram_write_resp_vld_o = sram_valid & (tl_host_i.d_opcode == tlul_pkg::AccessAck); // Functional Coverage `COVER(MaxOutstandingRequetsReached_C, sram_req & max_outstanding_reqs_reached) From 7ee1f2f65805c654133a87d77cff28a6aad32ddd Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Thu, 2 Nov 2023 10:02:14 -0700 Subject: [PATCH 53/88] [hw,mbx] Make lint clean for unused signal Signed-off-by: Robert Schilling --- hw/ip/mbx/rtl/mbx_imbx.sv | 2 +- hw/ip/mbx/rtl/mbx_ombx.sv | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/hw/ip/mbx/rtl/mbx_imbx.sv b/hw/ip/mbx/rtl/mbx_imbx.sv index 248df1b32a2c4..8581da9981d26 100644 --- a/hw/ip/mbx/rtl/mbx_imbx.sv +++ b/hw/ip/mbx/rtl/mbx_imbx.sv @@ -192,7 +192,7 @@ module mbx_imbx #( // Ready IRQ to core should not be asserted whilst there is still pending write traffic `ASSERT_NEVER(WrEverythingBeforeReadyIRQ, imbx_irq_ready_o & - hostif_sram_write_req_o & ~hostif_sram_write_gnt_i) + hostif_sram_write_req_o & ~hostif_sram_write_gnt_i) // The write pointer should not be advanced if the request has not yet been granted. `ASSERT_IF(WrPtrShouldNotAdvanceIfNoAck_A, hostif_sram_write_gnt_i, diff --git a/hw/ip/mbx/rtl/mbx_ombx.sv b/hw/ip/mbx/rtl/mbx_ombx.sv index 262a8655cc0da..2609a765ffd25 100644 --- a/hw/ip/mbx/rtl/mbx_ombx.sv +++ b/hw/ip/mbx/rtl/mbx_ombx.sv @@ -252,6 +252,12 @@ module mbx_ombx #( .mbx_state_error_o ( ombx_state_error_o ) ); + ////////////////////////////////////////////////////////////////////////////// + // Unused signals + ////////////////////////////////////////////////////////////////////////////// + logic unused_signals; + assign unused_signals = sysif_status_ready_i; + ////////////////////////////////////////////////////////////////////////////// // Assertions ////////////////////////////////////////////////////////////////////////////// From 809f508166114b4ec42d266007a4e557ed8bcf00 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Tue, 7 Nov 2023 13:06:28 -0800 Subject: [PATCH 54/88] [hw,mbx,rtl] Gate all valid received with current request This allows the hardware to capture the current in flight request, which is not yett counted Signed-off-by: Robert Schilling --- hw/ip/mbx/rtl/mbx_sramrwarb.sv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/ip/mbx/rtl/mbx_sramrwarb.sv b/hw/ip/mbx/rtl/mbx_sramrwarb.sv index 84d8e40ca283d..50877d917b6bb 100644 --- a/hw/ip/mbx/rtl/mbx_sramrwarb.sv +++ b/hw/ip/mbx/rtl/mbx_sramrwarb.sv @@ -76,7 +76,7 @@ module mbx_sramrwarb // Block SRAM requests if we reached the maximum outstanding number assign max_outstanding_reqs_reached = (outstanding_req_count_q == LCFG_MAX_REQS); // All outstanding requests responded, thus all transfers are written or read - assign imbx_sram_all_vld_rcvd_o = (outstanding_req_count_q == '0); + assign imbx_sram_all_vld_rcvd_o = (outstanding_req_count_q == '0) & ~sram_req; tlul_adapter_host #( .MAX_REQS ( LCFG_MAX_REQS ), From c0916e7367ece0f4d64d104dfb7841be770e55a6 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Fri, 27 Oct 2023 06:56:11 -0700 Subject: [PATCH 55/88] [hw,mbx,rtl] Use the transition to Read or to Abort state to generate IRQ The state transition generates a single event that is used byt the IRQ primitive to generate a leveled interrupt, that can be cleared by software. Closes lowRISC/opentitan-integrated#647 Signed-off-by: Robert Schilling --- hw/ip/mbx/rtl/mbx_fsm.sv | 16 +++++++++++----- hw/ip/mbx/rtl/mbx_imbx.sv | 8 ++------ hw/ip/mbx/rtl/mbx_ombx.sv | 2 ++ 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/hw/ip/mbx/rtl/mbx_fsm.sv b/hw/ip/mbx/rtl/mbx_fsm.sv index bf011d33e76c0..835ecb79514f6 100644 --- a/hw/ip/mbx/rtl/mbx_fsm.sv +++ b/hw/ip/mbx/rtl/mbx_fsm.sv @@ -25,6 +25,8 @@ module mbx_fsm #( output logic mbx_sys_abort_o, output logic mbx_ready_update_o, output logic mbx_ready_o, + output logic mbx_irq_ready_o, + output logic mbx_irq_abort_o, output logic mbx_state_error_o ); typedef enum logic [2:0] { @@ -53,11 +55,15 @@ module mbx_fsm #( // Control signals for external usage logic mbx_idle; - assign mbx_idle = (ctrl_state_q == MbxIdle); - assign mbx_empty_o = mbx_idle & mbx_range_valid_i; - assign mbx_write_o = (ctrl_state_q == MbxWrite); - assign mbx_read_o = (ctrl_state_q == MbxRead); - assign mbx_sys_abort_o = (ctrl_state_q == MbxSysAbortHost); + assign mbx_idle = (ctrl_state_q == MbxIdle); + assign mbx_empty_o = mbx_idle & mbx_range_valid_i; + assign mbx_write_o = (ctrl_state_q == MbxWrite); + assign mbx_read_o = (ctrl_state_q == MbxRead); + assign mbx_sys_abort_o = (ctrl_state_q == MbxSysAbortHost); + // The transition to the abort state marks the abort interrupt generation + assign mbx_irq_abort_o = (ctrl_state_d == MbxSysAbortHost); + // The transition to the read state marks the ready interrupt generation + assign mbx_irq_ready_o = (ctrl_state_d == MbxRead); logic ombx_set_ready, ombx_clear_ready; // Outbound mailbox is ready diff --git a/hw/ip/mbx/rtl/mbx_imbx.sv b/hw/ip/mbx/rtl/mbx_imbx.sv index 8581da9981d26..748638b2e5713 100644 --- a/hw/ip/mbx/rtl/mbx_imbx.sv +++ b/hw/ip/mbx/rtl/mbx_imbx.sv @@ -137,12 +137,6 @@ module mbx_imbx #( assign imbx_status_busy_update_o = imbx_set_busy | imbx_clear_busy; assign imbx_status_busy_o = imbx_set_busy; - // Generate host interrupt - // on sys_write go, when host enters state to process the received objects - // on abort - assign imbx_irq_ready_o = mbx_read; - assign imbx_irq_abort_o = mbx_sys_abort; - mbx_fsm #( .CfgOmbx ( 0 ) ) u_mbxfsm( @@ -163,6 +157,8 @@ module mbx_imbx #( .mbx_sys_abort_o ( mbx_sys_abort ), .mbx_ready_update_o ( ), .mbx_ready_o ( ), + .mbx_irq_ready_o ( imbx_irq_ready_o ), + .mbx_irq_abort_o ( imbx_irq_abort_o ), .mbx_state_error_o ( imbx_state_error_o ) ); diff --git a/hw/ip/mbx/rtl/mbx_ombx.sv b/hw/ip/mbx/rtl/mbx_ombx.sv index 2609a765ffd25..02b1914a5cc12 100644 --- a/hw/ip/mbx/rtl/mbx_ombx.sv +++ b/hw/ip/mbx/rtl/mbx_ombx.sv @@ -249,6 +249,8 @@ module mbx_ombx #( .mbx_sys_abort_o ( mbx_sys_abort ), .mbx_ready_update_o ( ombx_status_ready_update_o ), .mbx_ready_o ( ombx_status_ready_o ), + .mbx_irq_ready_o ( ), + .mbx_irq_abort_o ( ), .mbx_state_error_o ( ombx_state_error_o ) ); From 0e3161b17be6fc04af7add998ed027e1c03f53ac Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Thu, 9 Nov 2023 07:04:38 -0800 Subject: [PATCH 56/88] [hw,mbx,rtl] Initialize the outbound read ptr when range becomes valid Signed-off-by: Robert Schilling --- hw/ip/mbx/rtl/mbx.sv | 55 ++++++++++++++++++++------------------- hw/ip/mbx/rtl/mbx_ombx.sv | 17 +++++++----- 2 files changed, 39 insertions(+), 33 deletions(-) diff --git a/hw/ip/mbx/rtl/mbx.sv b/hw/ip/mbx/rtl/mbx.sv index 033a1f61ec2b5..5a929fe8dcc32 100644 --- a/hw/ip/mbx/rtl/mbx.sv +++ b/hw/ip/mbx/rtl/mbx.sv @@ -248,40 +248,41 @@ module mbx .CfgSramDataWidth ( CfgSramDataWidth ), .CfgObjectSizeWidth ( CfgObjectSizeWidth ) ) u_ombx ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .ombx_doe_intr_state_set_o ( ombx_doe_intr_state_set ), + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .ombx_doe_intr_state_set_o ( ombx_doe_intr_state_set ), // Interface to the host port - .ombx_state_error_o ( ombx_state_error ), - .ombx_pending_o ( ombx_pending ), - .ombx_status_ready_update_o ( ombx_status_ready_valid ), - .ombx_status_ready_o ( ombx_status_ready ), + .ombx_state_error_o ( ombx_state_error ), + .ombx_pending_o ( ombx_pending ), + .ombx_status_ready_update_o ( ombx_status_ready_valid ), + .ombx_status_ready_o ( ombx_status_ready ), // SRAM range configuration - .hostif_range_valid_i ( hostif_address_range_valid ), - .hostif_base_i ( hostif_ombx_base ), - .hostif_limit_i ( hostif_ombx_limit ), - .sys_read_all_o ( sys_read_all ), + .hostif_range_valid_write_i ( hostif_address_range_valid_write ), + .hostif_range_valid_i ( hostif_address_range_valid ), + .hostif_base_i ( hostif_ombx_base ), + .hostif_limit_i ( hostif_ombx_limit ), + .sys_read_all_o ( sys_read_all ), // Control and signals from the host and system interface - .sysif_status_ready_i ( sysif_status_ready ), + .sysif_status_ready_i ( sysif_status_ready ), // Writing a 1 to control.abort register clears the abort condition - .hostif_control_abort_clear_i ( hostif_control_abort_clear ), - .hostif_control_error_set_i ( hostif_control_error_set ), - .sysif_control_abort_set_i ( sysif_control_abort_set ), - .sysif_read_data_read_valid_i ( sysif_read_data_read_valid ), - .sysif_read_data_write_valid_i ( sysif_read_data_write_valid ), + .hostif_control_abort_clear_i ( hostif_control_abort_clear ), + .hostif_control_error_set_i ( hostif_control_error_set ), + .sysif_control_abort_set_i ( sysif_control_abort_set ), + .sysif_read_data_read_valid_i ( sysif_read_data_read_valid ), + .sysif_read_data_write_valid_i ( sysif_read_data_write_valid ), // Interface for the object size register - .hostif_ombx_object_size_write_i ( hostif_ombx_object_size_write ), - .hostif_ombx_object_size_i ( hostif_ombx_object_size_wdata ), - .hostif_ombx_object_size_update_o( hostif_ombx_object_size_update ), - .hostif_ombx_object_size_o ( hostif_ombx_object_size_rdata ), + .hostif_ombx_object_size_write_i ( hostif_ombx_object_size_write ), + .hostif_ombx_object_size_i ( hostif_ombx_object_size_wdata ), + .hostif_ombx_object_size_update_o( hostif_ombx_object_size_update ), + .hostif_ombx_object_size_o ( hostif_ombx_object_size_rdata ), // DOE data coming from the SRAM - .ombx_read_data_o ( sysif_read_data ), + .ombx_read_data_o ( sysif_read_data ), // Host interface to access private SRAM - .ombx_sram_read_req_o ( ombx_sram_read_req ), - .ombx_sram_read_gnt_i ( ombx_sram_read_gnt ), - .ombx_sram_read_ptr_o ( ombx_sram_read_ptr ), - .ombx_sram_read_resp_valid_i ( ombx_sram_read_resp_vld ), - .ombx_sram_read_resp_i ( ombx_sram_read_data ) + .ombx_sram_read_req_o ( ombx_sram_read_req ), + .ombx_sram_read_gnt_i ( ombx_sram_read_gnt ), + .ombx_sram_read_ptr_o ( ombx_sram_read_ptr ), + .ombx_sram_read_resp_valid_i ( ombx_sram_read_resp_vld ), + .ombx_sram_read_resp_i ( ombx_sram_read_data ) ); // Host port connection to access the private SRAM. diff --git a/hw/ip/mbx/rtl/mbx_ombx.sv b/hw/ip/mbx/rtl/mbx_ombx.sv index 02b1914a5cc12..68fe81063dcce 100644 --- a/hw/ip/mbx/rtl/mbx_ombx.sv +++ b/hw/ip/mbx/rtl/mbx_ombx.sv @@ -16,6 +16,7 @@ module mbx_ombx #( output logic ombx_pending_o, output logic ombx_status_ready_update_o, output logic ombx_status_ready_o, + input logic hostif_range_valid_write_i, input logic hostif_range_valid_i, input logic [CfgSramAddrWidth-1:0] hostif_base_i, input logic [CfgSramAddrWidth-1:0] hostif_limit_i, @@ -111,8 +112,12 @@ module mbx_ombx #( // SRAM read pointer management logic load_read_ptr, advance_read_ptr; + // Determine when the range is set to valid + logic range_valid_set; + assign range_valid_set = hostif_range_valid_write_i & hostif_range_valid_i; + // Rewind the read pointer to the base - assign load_read_ptr = set_first_req | sys_read_all_o | host_clear_abort; + assign load_read_ptr = range_valid_set | set_first_req | sys_read_all_o | host_clear_abort; // Advance the read pointer when one request went through assign advance_read_ptr = ombx_sram_read_req_o & ombx_sram_read_gnt_i; @@ -200,12 +205,12 @@ module mbx_ombx #( prim_generic_flop_en #( .Width(CfgSramAddrWidth) ) u_sram_read_ptr_limit ( - .clk_i ( clk_i ), - .rst_ni( rst_ni ), + .clk_i ( clk_i ), + .rst_ni( rst_ni ), // Factor in ~mbx_read because HW update can trigger host_write_object_size_q - .en_i ( host_write_object_size_q & ~mbx_read ), - .d_i ( sram_read_ptr_limit_d ), - .q_o ( sram_read_ptr_limit_q ) + .en_i ( (host_write_object_size_q & ~mbx_read) | range_valid_set ), + .d_i ( sram_read_ptr_limit_d ), + .q_o ( sram_read_ptr_limit_q ) ); // Logic to initiate the first read (mbx_empty) from the SRAM to the requester From c1a105ed5e3bd1ebc81ec4546cd3a1ca83495eab Mon Sep 17 00:00:00 2001 From: Adrian Lees Date: Thu, 9 Nov 2023 19:01:29 +0000 Subject: [PATCH 57/88] [mbx] Correct assertion and updating of OUTBOUND_OBJECT_SIZE Decrement object size on every valid TL-UL transaction, not just those which are immediately accepted. Modify assertion to check SRAM read address only when it has been loaded and is about to be used. Signed-off-by: Adrian Lees --- hw/ip/mbx/rtl/mbx_ombx.sv | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/ip/mbx/rtl/mbx_ombx.sv b/hw/ip/mbx/rtl/mbx_ombx.sv index 68fe81063dcce..7bbadc99b7de7 100644 --- a/hw/ip/mbx/rtl/mbx_ombx.sv +++ b/hw/ip/mbx/rtl/mbx_ombx.sv @@ -168,21 +168,21 @@ module mbx_ombx #( // The following flop creates an indicator that hostif.object_size has been written such that // in the next cycle, the read pointer limit can be updated and the first transfer from the - // SRAM to the internal data flop can be initiated. Only update the object size when not a - // transfer was successful. + // SRAM to the internal data flop can be initiated. prim_flop #( .Width(1) ) u_host_write_object_size ( .clk_i ( clk_i ), .rst_ni( rst_ni ), + // Ignore hardware-initiated changes to the OUTBOUND_OBJECT_SIZE register. .d_i ( hostif_ombx_object_size_write_i & ~ombx_object_size_update_valid_q ), .q_o ( host_write_object_size_q ) ); logic [CfgObjectSizeWidth-1:0] hostif_ob_object_size_minus_one; // Update the hostif.object_size register on every transaction or when aborting the transaction - assign hostif_ombx_object_size_update_o = (read_req & ombx_sram_read_gnt_i) | + assign hostif_ombx_object_size_update_o = (ombx_sram_read_req_o & ombx_sram_read_gnt_i) | sysif_control_abort_set_i; // The updated value is the decremented by 1 size or zero-ed out if the transaction is aborted assign hostif_ob_object_size_minus_one = hostif_ombx_object_size_i - 1; @@ -282,7 +282,7 @@ module mbx_ombx #( `ASSERT_NEVER(NeverReadWhenEmpty_A, ombx_sram_read_req_o & ombx_is_empty) // Never let the read pointer run out of the limit, but allow the range to be redefined whilst // the mailbox is not active - `ASSERT_NEVER(NeverRunOutOfLimit_A, |{set_first_req, first_req_q, mbx_read} & + `ASSERT_NEVER(NeverRunOutOfLimit_A, |{first_req_q, mbx_read} & (sram_read_ptr_q > sram_read_ptr_limit_q)) `ifdef INC_ASSERT From 8db41f073d1b7251ac5957a17a87d8d72a58c4ce Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Mon, 30 Oct 2023 10:32:38 -0700 Subject: [PATCH 58/88] [hw,mbx,rtl] Add CSR registers for asynchronous message support Signed-off-by: Robert Schilling --- hw/ip/mbx/data/mbx.hjson | 26 +++++++++++++++ hw/ip/mbx/rtl/mbx.sv | 4 ++- hw/ip/mbx/rtl/mbx_core_reg_top.sv | 17 ++++++++++ hw/ip/mbx/rtl/mbx_hostif.sv | 4 ++- hw/ip/mbx/rtl/mbx_reg_pkg.sv | 34 +++++++++++++------ hw/ip/mbx/rtl/mbx_soc_reg_top.sv | 54 +++++++++++++++++++++++++++++-- hw/ip/mbx/rtl/mbx_sysif.sv | 1 + 7 files changed, 127 insertions(+), 13 deletions(-) diff --git a/hw/ip/mbx/data/mbx.hjson b/hw/ip/mbx/data/mbx.hjson index e3195b48f8c99..6210f71761635 100644 --- a/hw/ip/mbx/data/mbx.hjson +++ b/hw/ip/mbx/data/mbx.hjson @@ -125,6 +125,13 @@ swaccess: "ro" hwaccess: "hwo" } + { name: "sys_async_en" + desc: "Alias of the DoE mailbox async message support enable bit" + bits: "3" + resval: "0x0" + swaccess: "ro" + hwaccess: "hwo" + } ] tags: ["excl:CsrAllTests:CsrExclAll"] // alias of another register; no automated CSR tests applicable } @@ -361,6 +368,15 @@ resval: "0x0" swaccess: "rw" } + { name: "doe_async_en" + desc: ''' + If DOE Async Message Support is Set, this bit, when Set, enables the use of the DOE Async Message mechanism. + When this bit is set, it allows the DOE instance to raise the SOC_STATUS.doe_async_msg_status, indicating an asnchronous message request. + ''' + bits: "3" + resval: "0x0" + swaccess: "rw" + } { name: "go" desc: ''' A write of 1 to this bit indicates to the DOE instance that it can start consuming the data object transferred through the DOE Write Data Mailbox register. @@ -401,6 +417,16 @@ swaccess: "ro" hwaccess: "hrw" } + { name: "doe_async_msg_status" + desc: ''' + This bit, when Set, indicates the DOE instance has one or more asynchronous messages to transfer. + The transition of this bit from Clear to Set is an interrupt triggering event.This bit is set when an interrupt event occurs. + ''' + bits: "3" + resval: "0x0" + swaccess: "ro" + hwaccess: "hwo" + } { name: "ready" desc: ''' When Set, this bit indicates the DOE instance has a data object available to be read by SoC firmware/software. diff --git a/hw/ip/mbx/rtl/mbx.sv b/hw/ip/mbx/rtl/mbx.sv index 5a929fe8dcc32..4ee8119b5f7e3 100644 --- a/hw/ip/mbx/rtl/mbx.sv +++ b/hw/ip/mbx/rtl/mbx.sv @@ -58,7 +58,7 @@ module mbx logic sysif_control_abort_set; // Status signal inputs from the sysif to the hostif - logic sysif_status_busy, sysif_status_error; + logic sysif_status_busy, sysif_status_error, sysif_async_en; // Setter signals from the hostif to the sysif logic hostif_control_abort_clear, hostif_control_error_set; @@ -110,6 +110,7 @@ module mbx // Access to the status register .hostif_status_busy_i ( sysif_status_busy ), .hostif_status_sys_intr_en_i ( doe_intr_en_o ), + .hostif_status_sys_async_en_i ( sysif_async_en ), .hostif_status_sys_intr_state_i ( doe_intr_o ), // Access to the IB/OB RD/WR Pointers .hostif_imbx_write_ptr_i ( imbx_sram_write_ptr ), @@ -188,6 +189,7 @@ module mbx .sysif_status_busy_valid_i ( imbx_status_busy_valid ), .sysif_status_busy_i ( imbx_status_busy ), .sysif_status_busy_o ( sysif_status_busy ), + .sysif_status_async_en_o ( sysif_async_en ), .sysif_status_doe_intr_state_set_i ( ombx_doe_intr_state_set ), .sysif_status_error_set_i ( hostif_control_error_set ), .sysif_status_error_o ( sysif_status_error ), diff --git a/hw/ip/mbx/rtl/mbx_core_reg_top.sv b/hw/ip/mbx/rtl/mbx_core_reg_top.sv index 568653c2d51c0..f1bf61fe698d7 100644 --- a/hw/ip/mbx/rtl/mbx_core_reg_top.sv +++ b/hw/ip/mbx/rtl/mbx_core_reg_top.sv @@ -147,6 +147,7 @@ module mbx_core_reg_top ( logic status_busy_qs; logic status_sys_intr_state_qs; logic status_sys_intr_enable_qs; + logic status_sys_async_en_qs; logic address_range_regwen_we; logic [3:0] address_range_regwen_qs; logic [3:0] address_range_regwen_wd; @@ -447,6 +448,21 @@ module mbx_core_reg_top ( .qs (status_sys_intr_enable_qs) ); + // F[sys_async_en]: 3:3 + prim_subreg_ext #( + .DW (1) + ) u_status_sys_async_en ( + .re (status_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status.sys_async_en.d), + .qre (), + .qe (), + .q (), + .ds (), + .qs (status_sys_async_en_qs) + ); + // R[address_range_regwen]: V(False) prim_subreg #( @@ -908,6 +924,7 @@ module mbx_core_reg_top ( reg_rdata_next[0] = status_busy_qs; reg_rdata_next[1] = status_sys_intr_state_qs; reg_rdata_next[2] = status_sys_intr_enable_qs; + reg_rdata_next[3] = status_sys_async_en_qs; end addr_hit[6]: begin diff --git a/hw/ip/mbx/rtl/mbx_hostif.sv b/hw/ip/mbx/rtl/mbx_hostif.sv index c58b3a518d3b5..2657c64d83718 100644 --- a/hw/ip/mbx/rtl/mbx_hostif.sv +++ b/hw/ip/mbx/rtl/mbx_hostif.sv @@ -34,6 +34,7 @@ module mbx_hostif // Access to the status register input logic hostif_status_busy_i, input logic hostif_status_sys_intr_en_i, + input logic hostif_status_sys_async_en_i, input logic hostif_status_sys_intr_state_i, // Access to the IB/OB RD/WR pointers input logic [CfgSramAddrWidth-1:0] hostif_imbx_write_ptr_i, @@ -166,8 +167,9 @@ module mbx_hostif // External read logic assign hw2reg.status.busy.d = hostif_status_busy_i; - assign hw2reg.status.sys_intr_enable.d = hostif_status_sys_intr_en_i; assign hw2reg.status.sys_intr_state.d = hostif_status_sys_intr_state_i; + assign hw2reg.status.sys_intr_enable.d = hostif_status_sys_intr_en_i; + assign hw2reg.status.sys_async_en.d = hostif_status_sys_async_en_i; // Address config valid assign hostif_address_range_valid_write_o = reg2hw.address_range_valid.qe; diff --git a/hw/ip/mbx/rtl/mbx_reg_pkg.sv b/hw/ip/mbx/rtl/mbx_reg_pkg.sv index 5c990e2e82585..19af32c878da7 100644 --- a/hw/ip/mbx/rtl/mbx_reg_pkg.sv +++ b/hw/ip/mbx/rtl/mbx_reg_pkg.sv @@ -124,6 +124,9 @@ package mbx_reg_pkg; struct packed { logic d; } sys_intr_enable; + struct packed { + logic d; + } sys_async_en; } mbx_hw2reg_status_reg_t; typedef struct packed { @@ -164,9 +167,9 @@ package mbx_reg_pkg; // HW -> register type for core interface typedef struct packed { - mbx_hw2reg_intr_state_reg_t intr_state; // [144:141] - mbx_hw2reg_control_reg_t control; // [140:139] - mbx_hw2reg_status_reg_t status; // [138:136] + mbx_hw2reg_intr_state_reg_t intr_state; // [145:142] + mbx_hw2reg_control_reg_t control; // [141:140] + mbx_hw2reg_status_reg_t status; // [139:136] mbx_hw2reg_inbound_write_ptr_reg_t inbound_write_ptr; // [135:106] mbx_hw2reg_outbound_read_ptr_reg_t outbound_read_ptr; // [105:76] mbx_hw2reg_outbound_object_size_reg_t outbound_object_size; // [75:64] @@ -203,10 +206,11 @@ package mbx_reg_pkg; parameter logic [1:0] MBX_CONTROL_RESVAL = 2'h 0; parameter logic [0:0] MBX_CONTROL_ABORT_RESVAL = 1'h 0; parameter logic [0:0] MBX_CONTROL_ERROR_RESVAL = 1'h 0; - parameter logic [2:0] MBX_STATUS_RESVAL = 3'h 1; + parameter logic [3:0] MBX_STATUS_RESVAL = 4'h 1; parameter logic [0:0] MBX_STATUS_BUSY_RESVAL = 1'h 1; parameter logic [0:0] MBX_STATUS_SYS_INTR_STATE_RESVAL = 1'h 0; parameter logic [0:0] MBX_STATUS_SYS_INTR_ENABLE_RESVAL = 1'h 0; + parameter logic [0:0] MBX_STATUS_SYS_ASYNC_EN_RESVAL = 1'h 0; parameter logic [31:0] MBX_INBOUND_WRITE_PTR_RESVAL = 32'h 0; parameter logic [29:0] MBX_INBOUND_WRITE_PTR_INBOUND_READ_PTR_RESVAL = 30'h 0; parameter logic [31:0] MBX_OUTBOUND_READ_PTR_RESVAL = 32'h 0; @@ -275,6 +279,10 @@ package mbx_reg_pkg; logic q; logic qe; } go; + struct packed { + logic q; + logic qe; + } doe_async_en; struct packed { logic q; logic qe; @@ -307,6 +315,9 @@ package mbx_reg_pkg; struct packed { logic d; } doe_intr_en; + struct packed { + logic d; + } doe_async_en; struct packed { logic d; } go; @@ -325,6 +336,10 @@ package mbx_reg_pkg; logic d; logic de; } error; + struct packed { + logic d; + logic de; + } doe_async_msg_status; struct packed { logic d; logic de; @@ -333,16 +348,16 @@ package mbx_reg_pkg; // Register -> HW type for soc interface typedef struct packed { - mbx_reg2hw_soc_doe_intr_msg_addr_reg_t soc_doe_intr_msg_addr; // [73:42] - mbx_reg2hw_soc_doe_intr_msg_data_reg_t soc_doe_intr_msg_data; // [41:10] - mbx_reg2hw_soc_control_reg_t soc_control; // [9:4] + mbx_reg2hw_soc_doe_intr_msg_addr_reg_t soc_doe_intr_msg_addr; // [75:44] + mbx_reg2hw_soc_doe_intr_msg_data_reg_t soc_doe_intr_msg_data; // [43:12] + mbx_reg2hw_soc_control_reg_t soc_control; // [11:4] mbx_reg2hw_soc_status_reg_t soc_status; // [3:0] } mbx_soc_reg2hw_t; // HW -> register type for soc interface typedef struct packed { - mbx_hw2reg_soc_control_reg_t soc_control; // [10:8] - mbx_hw2reg_soc_status_reg_t soc_status; // [7:0] + mbx_hw2reg_soc_control_reg_t soc_control; // [13:10] + mbx_hw2reg_soc_status_reg_t soc_status; // [9:0] } mbx_soc_hw2reg_t; // Register offsets for soc interface @@ -355,6 +370,7 @@ package mbx_reg_pkg; parameter logic [31:0] MBX_SOC_CONTROL_RESVAL = 32'h 0; parameter logic [0:0] MBX_SOC_CONTROL_ABORT_RESVAL = 1'h 0; parameter logic [0:0] MBX_SOC_CONTROL_DOE_INTR_EN_RESVAL = 1'h 0; + parameter logic [0:0] MBX_SOC_CONTROL_DOE_ASYNC_EN_RESVAL = 1'h 0; parameter logic [0:0] MBX_SOC_CONTROL_GO_RESVAL = 1'h 0; // Window parameters for soc interface diff --git a/hw/ip/mbx/rtl/mbx_soc_reg_top.sv b/hw/ip/mbx/rtl/mbx_soc_reg_top.sv index 57774099edd50..966ca146aa55b 100644 --- a/hw/ip/mbx/rtl/mbx_soc_reg_top.sv +++ b/hw/ip/mbx/rtl/mbx_soc_reg_top.sv @@ -184,12 +184,15 @@ module mbx_soc_reg_top ( logic soc_control_abort_wd; logic soc_control_doe_intr_en_qs; logic soc_control_doe_intr_en_wd; + logic soc_control_doe_async_en_qs; + logic soc_control_doe_async_en_wd; logic soc_control_go_wd; logic soc_status_we; logic soc_status_busy_qs; logic soc_status_doe_intr_status_qs; logic soc_status_doe_intr_status_wd; logic soc_status_error_qs; + logic soc_status_doe_async_msg_status_qs; logic soc_status_ready_qs; // Register instances @@ -251,7 +254,7 @@ module mbx_soc_reg_top ( // R[soc_control]: V(True) logic soc_control_qe; - logic [2:0] soc_control_flds_we; + logic [3:0] soc_control_flds_we; assign soc_control_qe = &soc_control_flds_we; // F[abort]: 0:0 prim_subreg_ext #( @@ -285,6 +288,22 @@ module mbx_soc_reg_top ( ); assign reg2hw.soc_control.doe_intr_en.qe = soc_control_qe; + // F[doe_async_en]: 3:3 + prim_subreg_ext #( + .DW (1) + ) u_soc_control_doe_async_en ( + .re (soc_control_re), + .we (soc_control_we), + .wd (soc_control_doe_async_en_wd), + .d (hw2reg.soc_control.doe_async_en.d), + .qre (), + .qe (soc_control_flds_we[2]), + .q (reg2hw.soc_control.doe_async_en.q), + .ds (), + .qs (soc_control_doe_async_en_qs) + ); + assign reg2hw.soc_control.doe_async_en.qe = soc_control_qe; + // F[go]: 31:31 prim_subreg_ext #( .DW (1) @@ -294,7 +313,7 @@ module mbx_soc_reg_top ( .wd (soc_control_go_wd), .d (hw2reg.soc_control.go.d), .qre (), - .qe (soc_control_flds_we[2]), + .qe (soc_control_flds_we[3]), .q (reg2hw.soc_control.go.q), .ds (), .qs () @@ -384,6 +403,33 @@ module mbx_soc_reg_top ( .qs (soc_status_error_qs) ); + // F[doe_async_msg_status]: 3:3 + prim_subreg #( + .DW (1), + .SwAccess(prim_subreg_pkg::SwAccessRO), + .RESVAL (1'h0), + .Mubi (1'b0) + ) u_soc_status_doe_async_msg_status ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (1'b0), + .wd ('0), + + // from internal hardware + .de (hw2reg.soc_status.doe_async_msg_status.de), + .d (hw2reg.soc_status.doe_async_msg_status.d), + + // to internal hardware + .qe (), + .q (), + .ds (), + + // to register interface (read) + .qs (soc_status_doe_async_msg_status_qs) + ); + // F[ready]: 31:31 prim_subreg #( .DW (1), @@ -447,6 +493,8 @@ module mbx_soc_reg_top ( assign soc_control_doe_intr_en_wd = reg_wdata[1]; + assign soc_control_doe_async_en_wd = reg_wdata[3]; + assign soc_control_go_wd = reg_wdata[31]; assign soc_status_we = addr_hit[3] & reg_we & !reg_error; @@ -476,6 +524,7 @@ module mbx_soc_reg_top ( addr_hit[2]: begin reg_rdata_next[0] = '0; reg_rdata_next[1] = soc_control_doe_intr_en_qs; + reg_rdata_next[3] = soc_control_doe_async_en_qs; reg_rdata_next[31] = '0; end @@ -483,6 +532,7 @@ module mbx_soc_reg_top ( reg_rdata_next[0] = soc_status_busy_qs; reg_rdata_next[1] = soc_status_doe_intr_status_qs; reg_rdata_next[2] = soc_status_error_qs; + reg_rdata_next[3] = soc_status_doe_async_msg_status_qs; reg_rdata_next[31] = soc_status_ready_qs; end diff --git a/hw/ip/mbx/rtl/mbx_sysif.sv b/hw/ip/mbx/rtl/mbx_sysif.sv index c7e82c5391367..de198588e2713 100644 --- a/hw/ip/mbx/rtl/mbx_sysif.sv +++ b/hw/ip/mbx/rtl/mbx_sysif.sv @@ -27,6 +27,7 @@ module mbx_sysif input logic sysif_status_busy_valid_i, input logic sysif_status_busy_i, output logic sysif_status_busy_o, + output logic sysif_async_en_o, input logic sysif_status_doe_intr_state_set_i, input logic sysif_status_error_set_i, output logic sysif_status_error_o, From bb9f64e01694ccb3a18ac1770ab749e83674872d Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Tue, 7 Nov 2023 00:39:39 -0800 Subject: [PATCH 59/88] [hw,mbx,rtl] Add top-level strap for async message support Needed for the external cap header implementation Signed-off-by: Robert Schilling --- hw/ip/mbx/data/mbx.hjson | 19 ++++++- hw/ip/mbx/rtl/mbx.sv | 35 ++++++++----- hw/ip/mbx/rtl/mbx_core_reg_top.sv | 34 ++++++++++--- hw/ip/mbx/rtl/mbx_hostif.sv | 15 ++++-- hw/ip/mbx/rtl/mbx_ombx.sv | 8 ++- hw/ip/mbx/rtl/mbx_reg_pkg.sv | 27 ++++++---- hw/ip/mbx/rtl/mbx_soc_reg_top.sv | 22 ++++---- hw/ip/mbx/rtl/mbx_sysif.sv | 84 ++++++++++++++++++++++++------- 8 files changed, 174 insertions(+), 70 deletions(-) diff --git a/hw/ip/mbx/data/mbx.hjson b/hw/ip/mbx/data/mbx.hjson index 6210f71761635..58425859fc899 100644 --- a/hw/ip/mbx/data/mbx.hjson +++ b/hw/ip/mbx/data/mbx.hjson @@ -45,6 +45,13 @@ package: "", default: "1'b0" } + { struct: "logic", + type: "uni", + name: "doe_async_msg_support", + act: "req", + package: "", + default: "1'b0" + } ] interrupt_list: [ { name: "mbx_ready" @@ -97,6 +104,14 @@ hwaccess: "hrw" hwqe: "true" } + { name: "sys_async_msg" + desc: "Indicates an async message request" + bits: "3" + resval: "0x0" + swaccess: "wo" + hwaccess: "hro" + hwqe: "true" + } ] tags: ["excl:CsrAllTests:CsrExclAll"] // alias of another register; no automated CSR tests applicable } @@ -125,7 +140,7 @@ swaccess: "ro" hwaccess: "hwo" } - { name: "sys_async_en" + { name: "sys_async_enable" desc: "Alias of the DoE mailbox async message support enable bit" bits: "3" resval: "0x0" @@ -368,7 +383,7 @@ resval: "0x0" swaccess: "rw" } - { name: "doe_async_en" + { name: "doe_async_msg_en" desc: ''' If DOE Async Message Support is Set, this bit, when Set, enables the use of the DOE Async Message mechanism. When this bit is set, it allows the DOE instance to raise the SOC_STATUS.doe_async_msg_status, indicating an asnchronous message request. diff --git a/hw/ip/mbx/rtl/mbx.sv b/hw/ip/mbx/rtl/mbx.sv index 4ee8119b5f7e3..ab88c4023cd1b 100644 --- a/hw/ip/mbx/rtl/mbx.sv +++ b/hw/ip/mbx/rtl/mbx.sv @@ -12,17 +12,19 @@ module mbx parameter int unsigned CfgSramAddrWidth = 32, parameter int unsigned CfgSramDataWidth = 32, parameter int unsigned CfgObjectSizeWidth = 11, - parameter bit DoeIrqSupport = 1'b1 + parameter bit DoeIrqSupport = 1'b1, + parameter bit DoeAsyncMsgSupport = 1'b1 ) ( input logic clk_i, input logic rst_ni, // Comportable interrupt to the OT output logic intr_mbx_ready_o, output logic intr_mbx_abort_o, - // Custom interrupt to the system requester + // Custom straps for capability register implementation output logic doe_intr_support_o, output logic doe_intr_en_o, output logic doe_intr_o, + output logic doe_async_msg_support_o, // Alerts input prim_alert_pkg::alert_rx_t [NumAlerts-1:0] alert_rx_i, output prim_alert_pkg::alert_tx_t [NumAlerts-1:0] alert_tx_o, @@ -56,9 +58,11 @@ module mbx logic hostif_event_intr_ready, hostif_event_intr_abort; logic hostif_address_range_valid, hostif_address_range_valid_write; logic sysif_control_abort_set; + logic doe_async_msg_en; // Status signal inputs from the sysif to the hostif - logic sysif_status_busy, sysif_status_error, sysif_async_en; + logic sysif_status_busy, sysif_status_error; + logic doe_async_msg_set, doe_async_msg_clear; // Setter signals from the hostif to the sysif logic hostif_control_abort_clear, hostif_control_error_set; @@ -107,10 +111,12 @@ module mbx .hostif_control_abort_clear_o ( hostif_control_abort_clear ), .hostif_control_error_set_o ( hostif_control_error_set ), .hostif_control_error_i ( sysif_status_error ), + .hostif_control_async_msg_set_o ( doe_async_msg_set ), + .hostif_control_async_msg_clear_o ( doe_async_msg_clear ), // Access to the status register .hostif_status_busy_i ( sysif_status_busy ), .hostif_status_sys_intr_en_i ( doe_intr_en_o ), - .hostif_status_sys_async_en_i ( sysif_async_en ), + .hostif_status_sys_async_en_i ( doe_async_msg_en ), .hostif_status_sys_intr_state_i ( doe_intr_o ), // Access to the IB/OB RD/WR Pointers .hostif_imbx_write_ptr_i ( imbx_sram_write_ptr ), @@ -160,7 +166,7 @@ module mbx logic ombx_pending; logic ombx_status_ready_valid, ombx_status_ready; logic sysif_status_ready; - logic ombx_doe_intr_state_set; + logic ombx_doe_intr_ready_set; // Interface signals for SRAM host access to read the memory and serve it to the outbox logic ombx_sram_read_req, ombx_sram_read_gnt; @@ -169,19 +175,25 @@ module mbx logic sysif_read_data_read_valid, sysif_read_data_write_valid; mbx_sysif #( - .CfgSramAddrWidth ( CfgSramAddrWidth ), - .CfgSramDataWidth ( CfgSramDataWidth ), - .DoeIrqSupport ( DoeIrqSupport ) + .CfgSramAddrWidth ( CfgSramAddrWidth ), + .CfgSramDataWidth ( CfgSramDataWidth ), + .DoeIrqSupport ( DoeIrqSupport ), + .DoeAsyncMsgSupport ( DoeAsyncMsgSupport ) ) u_sysif ( .clk_i ( clk_i ), .rst_ni ( rst_ni ), .tl_sys_i ( soc_tl_d_i ), .tl_sys_o ( soc_tl_d_o ), .intg_err_o ( sysif_intg_err ), - // System interrupt support + // Custom interrupt to the system requester .doe_intr_support_o ( doe_intr_support_o ), .doe_intr_en_o ( doe_intr_en_o ), .doe_intr_o ( doe_intr_o ), + // Asynchronous message to the requester + .doe_async_msg_support_o ( doe_async_msg_support_o ), + .doe_async_msg_en_o ( doe_async_msg_en ), + .doe_async_msg_set_i ( doe_async_msg_set ), + .doe_async_msg_clear_i ( doe_async_msg_clear ), // Access to the control register .sysif_control_abort_set_o ( sysif_control_abort_set ), .sysif_control_go_set_o ( sysif_control_go_set ), @@ -189,8 +201,7 @@ module mbx .sysif_status_busy_valid_i ( imbx_status_busy_valid ), .sysif_status_busy_i ( imbx_status_busy ), .sysif_status_busy_o ( sysif_status_busy ), - .sysif_status_async_en_o ( sysif_async_en ), - .sysif_status_doe_intr_state_set_i ( ombx_doe_intr_state_set ), + .sysif_status_doe_intr_ready_set_i ( ombx_doe_intr_ready_set ), .sysif_status_error_set_i ( hostif_control_error_set ), .sysif_status_error_o ( sysif_status_error ), .sysif_status_ready_valid_i ( ombx_status_ready_valid ), @@ -252,7 +263,7 @@ module mbx ) u_ombx ( .clk_i ( clk_i ), .rst_ni ( rst_ni ), - .ombx_doe_intr_state_set_o ( ombx_doe_intr_state_set ), + .ombx_doe_intr_ready_set_o ( ombx_doe_intr_ready_set ), // Interface to the host port .ombx_state_error_o ( ombx_state_error ), .ombx_pending_o ( ombx_pending ), diff --git a/hw/ip/mbx/rtl/mbx_core_reg_top.sv b/hw/ip/mbx/rtl/mbx_core_reg_top.sv index f1bf61fe698d7..785dc3d4d7238 100644 --- a/hw/ip/mbx/rtl/mbx_core_reg_top.sv +++ b/hw/ip/mbx/rtl/mbx_core_reg_top.sv @@ -143,11 +143,12 @@ module mbx_core_reg_top ( logic control_abort_wd; logic control_error_qs; logic control_error_wd; + logic control_sys_async_msg_wd; logic status_re; logic status_busy_qs; logic status_sys_intr_state_qs; logic status_sys_intr_enable_qs; - logic status_sys_async_en_qs; + logic status_sys_async_enable_qs; logic address_range_regwen_we; logic [3:0] address_range_regwen_qs; logic [3:0] address_range_regwen_wd; @@ -367,7 +368,7 @@ module mbx_core_reg_top ( // R[control]: V(True) logic control_qe; - logic [1:0] control_flds_we; + logic [2:0] control_flds_we; assign control_qe = &control_flds_we; // F[abort]: 0:0 prim_subreg_ext #( @@ -401,6 +402,22 @@ module mbx_core_reg_top ( ); assign reg2hw.control.error.qe = control_qe; + // F[sys_async_msg]: 3:3 + prim_subreg_ext #( + .DW (1) + ) u_control_sys_async_msg ( + .re (1'b0), + .we (control_we), + .wd (control_sys_async_msg_wd), + .d ('0), + .qre (), + .qe (control_flds_we[2]), + .q (reg2hw.control.sys_async_msg.q), + .ds (), + .qs () + ); + assign reg2hw.control.sys_async_msg.qe = control_qe; + // R[status]: V(True) // F[busy]: 0:0 @@ -448,19 +465,19 @@ module mbx_core_reg_top ( .qs (status_sys_intr_enable_qs) ); - // F[sys_async_en]: 3:3 + // F[sys_async_enable]: 3:3 prim_subreg_ext #( .DW (1) - ) u_status_sys_async_en ( + ) u_status_sys_async_enable ( .re (status_re), .we (1'b0), .wd ('0), - .d (hw2reg.status.sys_async_en.d), + .d (hw2reg.status.sys_async_enable.d), .qre (), .qe (), .q (), .ds (), - .qs (status_sys_async_en_qs) + .qs (status_sys_async_enable_qs) ); @@ -842,6 +859,8 @@ module mbx_core_reg_top ( assign control_abort_wd = reg_wdata[0]; assign control_error_wd = reg_wdata[1]; + + assign control_sys_async_msg_wd = reg_wdata[3]; assign status_re = addr_hit[5] & reg_re & !reg_error; assign address_range_regwen_we = addr_hit[6] & reg_we & !reg_error; @@ -918,13 +937,14 @@ module mbx_core_reg_top ( addr_hit[4]: begin reg_rdata_next[0] = control_abort_qs; reg_rdata_next[1] = control_error_qs; + reg_rdata_next[3] = '0; end addr_hit[5]: begin reg_rdata_next[0] = status_busy_qs; reg_rdata_next[1] = status_sys_intr_state_qs; reg_rdata_next[2] = status_sys_intr_enable_qs; - reg_rdata_next[3] = status_sys_async_en_qs; + reg_rdata_next[3] = status_sys_async_enable_qs; end addr_hit[6]: begin diff --git a/hw/ip/mbx/rtl/mbx_hostif.sv b/hw/ip/mbx/rtl/mbx_hostif.sv index 2657c64d83718..149e077d38721 100644 --- a/hw/ip/mbx/rtl/mbx_hostif.sv +++ b/hw/ip/mbx/rtl/mbx_hostif.sv @@ -31,6 +31,8 @@ module mbx_hostif output logic hostif_control_abort_clear_o, output logic hostif_control_error_set_o, input logic hostif_control_error_i, + output logic hostif_control_async_msg_set_o, + output logic hostif_control_async_msg_clear_o, // Access to the status register input logic hostif_status_busy_i, input logic hostif_status_sys_intr_en_i, @@ -161,15 +163,20 @@ module mbx_hostif assign hostif_control_error_set_o = reg2hw.control.error.qe & reg2hw.control.error.q; assign hw2reg.control.error.d = hostif_control_error_i; + assign hostif_control_async_msg_set_o = reg2hw.control.sys_async_msg.qe & + reg2hw.control.sys_async_msg.q; + assign hostif_control_async_msg_clear_o = reg2hw.control.sys_async_msg.qe & + ~reg2hw.control.sys_async_msg.q; + // Status Register // It is implemented as hwext and implemented in a different hierarchy and only providing an // alias. Thus manually assigning the external signals // External read logic - assign hw2reg.status.busy.d = hostif_status_busy_i; - assign hw2reg.status.sys_intr_state.d = hostif_status_sys_intr_state_i; - assign hw2reg.status.sys_intr_enable.d = hostif_status_sys_intr_en_i; - assign hw2reg.status.sys_async_en.d = hostif_status_sys_async_en_i; + assign hw2reg.status.busy.d = hostif_status_busy_i; + assign hw2reg.status.sys_intr_state.d = hostif_status_sys_intr_state_i; + assign hw2reg.status.sys_intr_enable.d = hostif_status_sys_intr_en_i; + assign hw2reg.status.sys_async_enable.d = hostif_status_sys_async_en_i; // Address config valid assign hostif_address_range_valid_write_o = reg2hw.address_range_valid.qe; diff --git a/hw/ip/mbx/rtl/mbx_ombx.sv b/hw/ip/mbx/rtl/mbx_ombx.sv index 7bbadc99b7de7..90d91e69ebaa1 100644 --- a/hw/ip/mbx/rtl/mbx_ombx.sv +++ b/hw/ip/mbx/rtl/mbx_ombx.sv @@ -12,7 +12,7 @@ module mbx_ombx #( input logic clk_i, input logic rst_ni, output logic ombx_state_error_o, - output logic ombx_doe_intr_state_set_o, + output logic ombx_doe_intr_ready_set_o, output logic ombx_pending_o, output logic ombx_status_ready_update_o, output logic ombx_status_ready_o, @@ -229,10 +229,8 @@ module mbx_ombx #( .q_o ( first_req_q ) ); - // Create a DOE interrupt request when the obmx FSM turns into the ready state or when an error - // is raised - assign ombx_doe_intr_state_set_o = (ombx_status_ready_o & ombx_status_ready_update_o) | - hostif_control_error_set_i; + // Create a DOE interrupt request when the obmx FSM turns into the ready state + assign ombx_doe_intr_ready_set_o = (ombx_status_ready_o & ombx_status_ready_update_o); mbx_fsm #( .CfgOmbx ( 1 ) diff --git a/hw/ip/mbx/rtl/mbx_reg_pkg.sv b/hw/ip/mbx/rtl/mbx_reg_pkg.sv index 19af32c878da7..a2bd568c2d732 100644 --- a/hw/ip/mbx/rtl/mbx_reg_pkg.sv +++ b/hw/ip/mbx/rtl/mbx_reg_pkg.sv @@ -58,6 +58,10 @@ package mbx_reg_pkg; } mbx_reg2hw_alert_test_reg_t; typedef struct packed { + struct packed { + logic q; + logic qe; + } sys_async_msg; struct packed { logic q; logic qe; @@ -126,7 +130,7 @@ package mbx_reg_pkg; } sys_intr_enable; struct packed { logic d; - } sys_async_en; + } sys_async_enable; } mbx_hw2reg_status_reg_t; typedef struct packed { @@ -152,11 +156,11 @@ package mbx_reg_pkg; // Register -> HW type for core interface typedef struct packed { - mbx_reg2hw_intr_state_reg_t intr_state; // [149:148] - mbx_reg2hw_intr_enable_reg_t intr_enable; // [147:146] - mbx_reg2hw_intr_test_reg_t intr_test; // [145:142] - mbx_reg2hw_alert_test_reg_t alert_test; // [141:138] - mbx_reg2hw_control_reg_t control; // [137:134] + mbx_reg2hw_intr_state_reg_t intr_state; // [151:150] + mbx_reg2hw_intr_enable_reg_t intr_enable; // [149:148] + mbx_reg2hw_intr_test_reg_t intr_test; // [147:144] + mbx_reg2hw_alert_test_reg_t alert_test; // [143:140] + mbx_reg2hw_control_reg_t control; // [139:134] mbx_reg2hw_address_range_valid_reg_t address_range_valid; // [133:132] mbx_reg2hw_inbound_base_address_reg_t inbound_base_address; // [131:102] mbx_reg2hw_inbound_limit_address_reg_t inbound_limit_address; // [101:72] @@ -203,14 +207,15 @@ package mbx_reg_pkg; parameter logic [1:0] MBX_ALERT_TEST_RESVAL = 2'h 0; parameter logic [0:0] MBX_ALERT_TEST_FATAL_FAULT_RESVAL = 1'h 0; parameter logic [0:0] MBX_ALERT_TEST_RECOV_FAULT_RESVAL = 1'h 0; - parameter logic [1:0] MBX_CONTROL_RESVAL = 2'h 0; + parameter logic [3:0] MBX_CONTROL_RESVAL = 4'h 0; parameter logic [0:0] MBX_CONTROL_ABORT_RESVAL = 1'h 0; parameter logic [0:0] MBX_CONTROL_ERROR_RESVAL = 1'h 0; + parameter logic [0:0] MBX_CONTROL_SYS_ASYNC_MSG_RESVAL = 1'h 0; parameter logic [3:0] MBX_STATUS_RESVAL = 4'h 1; parameter logic [0:0] MBX_STATUS_BUSY_RESVAL = 1'h 1; parameter logic [0:0] MBX_STATUS_SYS_INTR_STATE_RESVAL = 1'h 0; parameter logic [0:0] MBX_STATUS_SYS_INTR_ENABLE_RESVAL = 1'h 0; - parameter logic [0:0] MBX_STATUS_SYS_ASYNC_EN_RESVAL = 1'h 0; + parameter logic [0:0] MBX_STATUS_SYS_ASYNC_ENABLE_RESVAL = 1'h 0; parameter logic [31:0] MBX_INBOUND_WRITE_PTR_RESVAL = 32'h 0; parameter logic [29:0] MBX_INBOUND_WRITE_PTR_INBOUND_READ_PTR_RESVAL = 30'h 0; parameter logic [31:0] MBX_OUTBOUND_READ_PTR_RESVAL = 32'h 0; @@ -282,7 +287,7 @@ package mbx_reg_pkg; struct packed { logic q; logic qe; - } doe_async_en; + } doe_async_msg_en; struct packed { logic q; logic qe; @@ -317,7 +322,7 @@ package mbx_reg_pkg; } doe_intr_en; struct packed { logic d; - } doe_async_en; + } doe_async_msg_en; struct packed { logic d; } go; @@ -370,7 +375,7 @@ package mbx_reg_pkg; parameter logic [31:0] MBX_SOC_CONTROL_RESVAL = 32'h 0; parameter logic [0:0] MBX_SOC_CONTROL_ABORT_RESVAL = 1'h 0; parameter logic [0:0] MBX_SOC_CONTROL_DOE_INTR_EN_RESVAL = 1'h 0; - parameter logic [0:0] MBX_SOC_CONTROL_DOE_ASYNC_EN_RESVAL = 1'h 0; + parameter logic [0:0] MBX_SOC_CONTROL_DOE_ASYNC_MSG_EN_RESVAL = 1'h 0; parameter logic [0:0] MBX_SOC_CONTROL_GO_RESVAL = 1'h 0; // Window parameters for soc interface diff --git a/hw/ip/mbx/rtl/mbx_soc_reg_top.sv b/hw/ip/mbx/rtl/mbx_soc_reg_top.sv index 966ca146aa55b..2fa1100d8581d 100644 --- a/hw/ip/mbx/rtl/mbx_soc_reg_top.sv +++ b/hw/ip/mbx/rtl/mbx_soc_reg_top.sv @@ -184,8 +184,8 @@ module mbx_soc_reg_top ( logic soc_control_abort_wd; logic soc_control_doe_intr_en_qs; logic soc_control_doe_intr_en_wd; - logic soc_control_doe_async_en_qs; - logic soc_control_doe_async_en_wd; + logic soc_control_doe_async_msg_en_qs; + logic soc_control_doe_async_msg_en_wd; logic soc_control_go_wd; logic soc_status_we; logic soc_status_busy_qs; @@ -288,21 +288,21 @@ module mbx_soc_reg_top ( ); assign reg2hw.soc_control.doe_intr_en.qe = soc_control_qe; - // F[doe_async_en]: 3:3 + // F[doe_async_msg_en]: 3:3 prim_subreg_ext #( .DW (1) - ) u_soc_control_doe_async_en ( + ) u_soc_control_doe_async_msg_en ( .re (soc_control_re), .we (soc_control_we), - .wd (soc_control_doe_async_en_wd), - .d (hw2reg.soc_control.doe_async_en.d), + .wd (soc_control_doe_async_msg_en_wd), + .d (hw2reg.soc_control.doe_async_msg_en.d), .qre (), .qe (soc_control_flds_we[2]), - .q (reg2hw.soc_control.doe_async_en.q), + .q (reg2hw.soc_control.doe_async_msg_en.q), .ds (), - .qs (soc_control_doe_async_en_qs) + .qs (soc_control_doe_async_msg_en_qs) ); - assign reg2hw.soc_control.doe_async_en.qe = soc_control_qe; + assign reg2hw.soc_control.doe_async_msg_en.qe = soc_control_qe; // F[go]: 31:31 prim_subreg_ext #( @@ -493,7 +493,7 @@ module mbx_soc_reg_top ( assign soc_control_doe_intr_en_wd = reg_wdata[1]; - assign soc_control_doe_async_en_wd = reg_wdata[3]; + assign soc_control_doe_async_msg_en_wd = reg_wdata[3]; assign soc_control_go_wd = reg_wdata[31]; assign soc_status_we = addr_hit[3] & reg_we & !reg_error; @@ -524,7 +524,7 @@ module mbx_soc_reg_top ( addr_hit[2]: begin reg_rdata_next[0] = '0; reg_rdata_next[1] = soc_control_doe_intr_en_qs; - reg_rdata_next[3] = soc_control_doe_async_en_qs; + reg_rdata_next[3] = soc_control_doe_async_msg_en_qs; reg_rdata_next[31] = '0; end diff --git a/hw/ip/mbx/rtl/mbx_sysif.sv b/hw/ip/mbx/rtl/mbx_sysif.sv index de198588e2713..c1977de40d798 100644 --- a/hw/ip/mbx/rtl/mbx_sysif.sv +++ b/hw/ip/mbx/rtl/mbx_sysif.sv @@ -8,7 +8,8 @@ module mbx_sysif parameter int unsigned CfgSramAddrWidth = 32, parameter int unsigned CfgSramDataWidth = 32, // PCIe capabilities - parameter bit DoeIrqSupport = 1'b1 + parameter bit DoeIrqSupport = 1'b1, + parameter bit DoeAsyncMsgSupport = 1'b1 ) ( input logic clk_i, input logic rst_ni, @@ -20,6 +21,11 @@ module mbx_sysif output logic doe_intr_support_o, output logic doe_intr_en_o, output logic doe_intr_o, + // Asynchronous message to the requester + output logic doe_async_msg_support_o, + output logic doe_async_msg_en_o, + input logic doe_async_msg_set_i, + input logic doe_async_msg_clear_i, // Access to the control register output logic sysif_control_abort_set_o, output logic sysif_control_go_set_o, @@ -27,8 +33,7 @@ module mbx_sysif input logic sysif_status_busy_valid_i, input logic sysif_status_busy_i, output logic sysif_status_busy_o, - output logic sysif_async_en_o, - input logic sysif_status_doe_intr_state_set_i, + input logic sysif_status_doe_intr_ready_set_i, input logic sysif_status_error_set_i, output logic sysif_status_error_o, input logic sysif_status_ready_valid_i, @@ -70,17 +75,25 @@ module mbx_sysif .devmode_i ( 1'b1 ) ); - assign doe_intr_support_o = DoeIrqSupport; - assign doe_intr_o = reg2hw.soc_status.doe_intr_status.q; + // Straps for the external capability header registers + assign doe_intr_support_o = DoeIrqSupport; + assign doe_async_msg_support_o = DoeAsyncMsgSupport; + // DOE IRQ is generated when: + // - the host wrote a complete message to the outbound mailbox + // - there is an error + // - there is an asynchronous message + // request + assign doe_intr_o = DoeIrqSupport & reg2hw.soc_status.doe_intr_status.q; - // Control register - assign sysif_control_abort_set_o = reg2hw.soc_control.abort.qe & reg2hw.soc_control.abort.q; - assign hw2reg.soc_control.abort.d = 1'b0; + // Fiddle rising edge of writing the abort and go bit + assign sysif_control_abort_set_o = reg2hw.soc_control.abort.qe & reg2hw.soc_control.abort.q; + assign hw2reg.soc_control.abort.d = 1'b0; - assign sysif_control_go_set_o = reg2hw.soc_control.go.qe & reg2hw.soc_control.go.q; - assign hw2reg.soc_control.go.d = 1'b0; + assign sysif_control_go_set_o = reg2hw.soc_control.go.qe & reg2hw.soc_control.go.q; + assign hw2reg.soc_control.go.d = 1'b0; // Manual implementation of the doe_intr_en bit + // Gate the data input with the feature flag // SWAccess: RW // HWAccess: RO prim_subreg #( @@ -92,7 +105,7 @@ module mbx_sysif .rst_ni (rst_ni), // from register interface .we (reg2hw.soc_control.doe_intr_en.qe), - .wd (reg2hw.soc_control.doe_intr_en.q), + .wd (reg2hw.soc_control.doe_intr_en.q & DoeIrqSupport), // HWAccess: hro .de (1'b0), .d (1'b0), @@ -103,6 +116,30 @@ module mbx_sysif .qs () ); + // Manual implementation of the doe_async_msg_en bit + // Gate the data input with the feature flag + // SWAccess: RW + // HWAccess: RO + prim_subreg #( + .DW (1), + .SwAccess(prim_subreg_pkg::SwAccessRW), + .RESVAL (1'h0) + ) u_soc_control_doe_async_msg_en ( + .clk_i (clk_i), + .rst_ni (rst_ni), + // from register interface + .we (reg2hw.soc_control.doe_async_msg_en.qe), + .wd (reg2hw.soc_control.doe_async_msg_en.q & DoeAsyncMsgSupport), + // HWAccess: hro + .de (1'b0), + .d (1'b0), + // to internal hardware + .qe (), + .q (doe_async_msg_en_o), + .ds (hw2reg.soc_control.doe_async_msg_en.d), + .qs () + ); + // Fiddle out status register bits for external write logic assign sysif_status_busy_o = reg2hw.soc_status.busy.q; assign sysif_status_error_o = reg2hw.soc_status.error.q; @@ -111,11 +148,22 @@ module mbx_sysif assign hw2reg.soc_status.busy.de = sysif_status_busy_valid_i; assign hw2reg.soc_status.busy.d = sysif_status_busy_i; - // Set by the outbound handler if the DOE interrupt is enabled. Setting this bit creates a DOE - // interrupt to the system side. - // Cleared by SoC firmware (w1c) - assign hw2reg.soc_status.doe_intr_status.de = sysif_status_doe_intr_state_set_i & doe_intr_en_o; - assign hw2reg.soc_status.doe_intr_status.d = sysif_status_doe_intr_state_set_i; + // Interrupt is triggered by the outbound handler if the message has been written to + // the memory and can be read by the system, an error is raised, or if there is an asynchronous + // message request coming from the host. + // The interrupt is cleared by the SOC firmware via the RW1C behavior + assign hw2reg.soc_status.doe_intr_status.de = DoeIrqSupport & + (sysif_status_doe_intr_ready_set_i | + sysif_status_error_set_i | + doe_async_msg_set_i); + assign hw2reg.soc_status.doe_intr_status.d = sysif_status_doe_intr_ready_set_i | + sysif_status_error_set_i | + doe_async_msg_set_i; + + // Async message status is updated by the host interface + assign hw2reg.soc_status.doe_async_msg_status.de = DoeAsyncMsgSupport & + (doe_async_msg_set_i | doe_async_msg_clear_i); + assign hw2reg.soc_status.doe_async_msg_status.d = doe_async_msg_set_i; // Error is cleared when writing the abort bit assign hw2reg.soc_status.error.de = sysif_status_error_set_i | sysif_control_abort_set_o; @@ -123,8 +171,8 @@ module mbx_sysif // Set by OT firmware (w1s) // Cleared by SoC firmware (w1c) - assign hw2reg.soc_status.ready.de = sysif_status_ready_valid_i; - assign hw2reg.soc_status.ready.d = sysif_status_ready_i; + assign hw2reg.soc_status.ready.de = sysif_status_ready_valid_i; + assign hw2reg.soc_status.ready.d = sysif_status_ready_i; // Ready bit indication into hardware assign sysif_status_ready_o = reg2hw.soc_status.ready.q; From 524be58e377026c58d53e3a4c0d7f2f66a5b9909 Mon Sep 17 00:00:00 2001 From: Greg Chadwick Date: Tue, 14 Nov 2023 20:56:14 +0000 Subject: [PATCH 60/88] [mbx, dv] Refactor tb interrupt functionality - Provides virtual interfaces for both core side and soc side interrupts - `wait_for_core_interrupt` now only looks at the core_ready interrupt and includes a clock based timeout and sensible error messages - Added `wait_for_soc_interrupt` to wait for soc side interrupt Signed-off-by: Greg Chadwick --- hw/ip/mbx/dv/env/mbx_env.sv | 5 ++++ hw/ip/mbx/dv/env/mbx_env_cfg.sv | 2 ++ hw/ip/mbx/dv/env/seq_lib/mbx_base_vseq.sv | 34 +++++++++++++++++++++-- hw/ip/mbx/dv/tb.sv | 10 +++++-- 4 files changed, 46 insertions(+), 5 deletions(-) diff --git a/hw/ip/mbx/dv/env/mbx_env.sv b/hw/ip/mbx/dv/env/mbx_env.sv index 20a02e0365ab2..b44ad285281fb 100644 --- a/hw/ip/mbx/dv/env/mbx_env.sv +++ b/hw/ip/mbx/dv/env/mbx_env.sv @@ -15,6 +15,11 @@ class mbx_env extends cip_base_env #( function void build_phase(uvm_phase phase); super.build_phase(phase); + + if (!uvm_config_db#(intr_vif)::get(this, "", "intr_soc_vif", cfg.intr_soc_vif) && + cfg.num_interrupts > 0) begin + `uvm_fatal(get_full_name(), "failed to get intr_soc_vif from uvm_config_db") + end endfunction: build_phase function void connect_phase(uvm_phase phase); diff --git a/hw/ip/mbx/dv/env/mbx_env_cfg.sv b/hw/ip/mbx/dv/env/mbx_env_cfg.sv index 8946345030aef..5a89887de4316 100644 --- a/hw/ip/mbx/dv/env/mbx_env_cfg.sv +++ b/hw/ip/mbx/dv/env/mbx_env_cfg.sv @@ -9,6 +9,8 @@ class mbx_env_cfg extends cip_base_env_cfg #( string mbx_mem_ral_name = "mbx_mem_reg_block"; string mbx_soc_ral_name = "mbx_soc_reg_block"; + intr_vif intr_soc_vif; + `uvm_object_utils(mbx_env_cfg) function new(string name = ""); diff --git a/hw/ip/mbx/dv/env/seq_lib/mbx_base_vseq.sv b/hw/ip/mbx/dv/env/seq_lib/mbx_base_vseq.sv index 35b49affb324d..d8cb7ef43b5b1 100644 --- a/hw/ip/mbx/dv/env/seq_lib/mbx_base_vseq.sv +++ b/hw/ip/mbx/dv/env/seq_lib/mbx_base_vseq.sv @@ -119,12 +119,42 @@ class mbx_base_vseq extends cip_base_vseq #( UVM_DEBUG) endtask: mbx_init - virtual task wait_for_core_interrupt(); + virtual task wait_for_core_interrupt(int clks_timeout=1024); `uvm_info(`gfn, $sformatf("wait_for_core_interrupt -- Start"), UVM_DEBUG) - `DV_WAIT(cfg.intr_vif.pins == 1'b1) + fork begin : isolation_fork + fork + begin + `DV_WAIT(cfg.intr_vif.pins[MbxCoreReady] == 1'b1, "core interrupt wait timeout") + end + begin + cfg.clk_rst_vif.wait_clks(clks_timeout); + `dv_fatal($sformatf("Timed out after %d clocks waiting for a core interrupt", + clks_timeout), `gfn) + end + join_any; + disable fork; + end join `uvm_info(`gfn, $sformatf("wait_for_core_interrupt -- End"), UVM_DEBUG) endtask: wait_for_core_interrupt + virtual task wait_for_soc_interrupt(int clks_timeout=1024); + `uvm_info(`gfn, $sformatf("wait_for_soc_interrupt -- Start"), UVM_DEBUG) + fork begin : isolation_fork + fork + begin + `DV_WAIT(cfg.intr_soc_vif.pins[0] == 1'b1, "soc interrupt wait timeout") + end + begin + cfg.clk_rst_vif.wait_clks(clks_timeout); + `dv_fatal($sformatf("Timed out after %d clocks waiting for a soc interrupt", + clks_timeout), `gfn) + end + join_any; + disable fork; + end join + `uvm_info(`gfn, $sformatf("wait_for_soc_interrupt -- End"), UVM_DEBUG) + endtask: wait_for_core_interrupt + virtual task body(); `uvm_info(get_full_name(), "body -- Start", UVM_DEBUG) start_device_seq(); diff --git a/hw/ip/mbx/dv/tb.sv b/hw/ip/mbx/dv/tb.sv index 954187899b027..77f75d3cc5c25 100644 --- a/hw/ip/mbx/dv/tb.sv +++ b/hw/ip/mbx/dv/tb.sv @@ -16,6 +16,7 @@ module tb; wire clk, rst_n; wire [NUM_MAX_INTERRUPTS-1:0] interrupts; + wire intr_doe; wire intr_ready; wire intr_abort; @@ -23,7 +24,8 @@ module tb; tl_if i_tl_scxb_mbx_core_if(.clk(clk), .rst_n(rst_n)); tl_if i_tl_agxb_mbx_core_if(.clk(clk), .rst_n(rst_n)); tl_if i_tl_mbx_agxb_device_if(.clk(clk), .rst_n(rst_n)); - pins_if #(NUM_MAX_INTERRUPTS) i_intr_if(interrupts); + pins_if #(NUM_MAX_INTERRUPTS) i_intr_core_if(interrupts); + pins_if #(NUM_MAX_INTERRUPTS) i_intr_soc_if({intr_doe}); `DV_ALERT_IF_CONNECT() @@ -34,7 +36,7 @@ module tb; .rst_ni(rst_n), .doe_intr_support_o(), .doe_intr_en_o(), - .doe_intr_o(), + .doe_intr_o(intr_doe), // various tlul interfaces .core_tl_d_o(i_tl_agxb_mbx_core_if.d2h), .core_tl_d_i(i_tl_agxb_mbx_core_if.h2d), @@ -84,7 +86,9 @@ module tb; null, "*.env.m_tl_agent_mbx_mem_reg_block*", "vif", i_tl_mbx_agxb_device_if); uvm_config_db#(intr_vif)::set( - null, "*.env", "intr_vif", i_intr_if); + null, "*.env", "intr_vif", i_intr_core_if); + uvm_config_db#(intr_vif)::set( + null, "*.env", "intr_soc_vif", i_intr_soc_if); $timeformat(-12, 0, " ps", 12); run_test(); end From d148dba2d1c6c5bbe1b722c07ba1aa789dfda9aa Mon Sep 17 00:00:00 2001 From: Greg Chadwick Date: Tue, 14 Nov 2023 23:08:19 +0000 Subject: [PATCH 61/88] [mbx,dv] Add IRQ usage to mailbox smoke This also disables interrupt checks in the scoreboard as they currently do not function correctly. Signed-off-by: Greg Chadwick --- hw/ip/mbx/dv/env/mbx_scoreboard.sv | 9 +++++---- hw/ip/mbx/dv/env/seq_lib/mbx_smoke_vseq.sv | 23 ++++++++++++---------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/hw/ip/mbx/dv/env/mbx_scoreboard.sv b/hw/ip/mbx/dv/env/mbx_scoreboard.sv index 16fac7e2d0f3b..7dae373c49a8e 100644 --- a/hw/ip/mbx/dv/env/mbx_scoreboard.sv +++ b/hw/ip/mbx/dv/env/mbx_scoreboard.sv @@ -85,10 +85,11 @@ class mbx_scoreboard extends cip_base_scoreboard #( task run_phase(uvm_phase phase); super.run_phase(phase); `downcast(m_mbx_soc_ral, cfg.ral_models[cfg.mbx_soc_ral_name]) - fork - monitor_core_interrupt(); - monitor_exp_core_interrupts(); - join_none + // TODO: Renable interrupt checking once scoreboard is fully functional + //fork + // monitor_core_interrupt(); + // monitor_exp_core_interrupts(); + //join_none endtask virtual task process_tl_access(tl_seq_item item, tl_channels_e channel, string ral_name); diff --git a/hw/ip/mbx/dv/env/seq_lib/mbx_smoke_vseq.sv b/hw/ip/mbx/dv/env/seq_lib/mbx_smoke_vseq.sv index eea95caeb95ea..a82dd6c969123 100644 --- a/hw/ip/mbx/dv/env/seq_lib/mbx_smoke_vseq.sv +++ b/hw/ip/mbx/dv/env/seq_lib/mbx_smoke_vseq.sv @@ -41,6 +41,8 @@ class mbx_smoke_vseq extends mbx_base_vseq; // Ensure that we have a valid memory range csr_wr(ral.address_range_valid, 1'b1); + // Enable core ready interrupt + cfg_interrupts(1 << MbxCoreReady); // Data from R-code to ROT @@ -93,14 +95,16 @@ class mbx_smoke_vseq extends mbx_base_vseq; .tl_sequencer_h(p_sequencer.tl_sequencer_hs[cfg.mbx_soc_ral_name])); end - // Note: we need only set bit 31 (Go) here, no need to read. + // Note: we need only set bits 31 and 1 (Go, dot_intr_en) here, no need to read. // csr_rd(m_mbx_soc_ral.soc_control, rd_data); // rd_data[31] = 1'b1; - rd_data = 32'h8000_0000; + rd_data = 32'h8000_0002; + `uvm_info(`gfn, "Doing soc_control csr wr", UVM_LOW) + clear_all_interrupts(); csr_wr(m_mbx_soc_ral.soc_control, rd_data); - // TODO: should wait until the Ready interrupt is signaled to the ROT - cfg.clk_rst_vif.wait_clks(1024); + wait_for_core_interrupt(); + clear_all_interrupts(); // Collect the request message from the OT mailbox memory read_mem(ibmbx_base_addr, req_size << 2, q); @@ -120,12 +124,11 @@ class mbx_smoke_vseq extends mbx_base_vseq; end write_mem(obmbx_base_addr, q); csr_wr(ral.outbound_object_size, rsp_size); - do begin - csr_rd(m_mbx_soc_ral.soc_status, rd_data); - `uvm_info(get_full_name(), - $sformatf("rd_data for soc_status is :'h%0h", rd_data), - UVM_DEBUG) - end while (rd_data[31] != 1'b1); + + wait_for_soc_interrupt(); + csr_rd(m_mbx_soc_ral.soc_status, rd_data); + `DV_CHECK_EQ(rd_data[31], 1'b1, "soc_status ready bit not set after soc interrupt seen") + clear_all_interrupts(); // Collect the entire message before checking it. // Note: this may not be the best approach unless we can time out in the event of a lock up From dc983ad01f6532cf85c58daf9a0853b73de5bd13 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Thu, 16 Nov 2023 03:56:55 -0800 Subject: [PATCH 62/88] [hw,mbx,rtl] Trigger an error for out-of-bounds imbx write Signed-off-by: Robert Schilling --- hw/ip/mbx/rtl/mbx.sv | 12 +++++++++--- hw/ip/mbx/rtl/mbx_fsm.sv | 34 ++++++++++++++++++++++------------ hw/ip/mbx/rtl/mbx_imbx.sv | 32 +++++++++++++++++++------------- hw/ip/mbx/rtl/mbx_ombx.sv | 7 ++++--- 4 files changed, 54 insertions(+), 31 deletions(-) diff --git a/hw/ip/mbx/rtl/mbx.sv b/hw/ip/mbx/rtl/mbx.sv index ab88c4023cd1b..d638b22f0e88b 100644 --- a/hw/ip/mbx/rtl/mbx.sv +++ b/hw/ip/mbx/rtl/mbx.sv @@ -174,6 +174,11 @@ module mbx logic [CfgSramDataWidth-1:0] ombx_sram_read_data, sysif_read_data; logic sysif_read_data_read_valid, sysif_read_data_write_valid; + // Combine error outputs of all modules and distribute back error to them to bring all + // modules to the error state if needed + logic mbx_error_set, imbx_overflow_error_set; + assign mbx_error_set = hostif_control_error_set | imbx_overflow_error_set; + mbx_sysif #( .CfgSramAddrWidth ( CfgSramAddrWidth ), .CfgSramDataWidth ( CfgSramDataWidth ), @@ -202,7 +207,7 @@ module mbx .sysif_status_busy_i ( imbx_status_busy ), .sysif_status_busy_o ( sysif_status_busy ), .sysif_status_doe_intr_ready_set_i ( ombx_doe_intr_ready_set ), - .sysif_status_error_set_i ( hostif_control_error_set ), + .sysif_status_error_set_i ( mbx_error_set ), .sysif_status_error_o ( sysif_status_error ), .sysif_status_ready_valid_i ( ombx_status_ready_valid ), .sysif_status_ready_i ( ombx_status_ready ), @@ -234,9 +239,10 @@ module mbx .imbx_irq_ready_o ( hostif_event_intr_ready ), .imbx_irq_abort_o ( hostif_event_intr_abort ), .imbx_status_busy_update_o ( imbx_status_busy_valid ), + .imbx_overflow_error_set_o ( imbx_overflow_error_set ), .imbx_status_busy_o ( imbx_status_busy ), .hostif_control_abort_clear_i( hostif_control_abort_clear ), - .hostif_control_error_set_i ( hostif_control_error_set ), + .mbx_error_set_i ( mbx_error_set ), .sys_read_all_i ( sys_read_all ), // SRAM range configuration .hostif_range_valid_write_i ( hostif_address_range_valid_write ), @@ -279,7 +285,7 @@ module mbx .sysif_status_ready_i ( sysif_status_ready ), // Writing a 1 to control.abort register clears the abort condition .hostif_control_abort_clear_i ( hostif_control_abort_clear ), - .hostif_control_error_set_i ( hostif_control_error_set ), + .mbx_error_set_i ( mbx_error_set ), .sysif_control_abort_set_i ( sysif_control_abort_set ), .sysif_read_data_read_valid_i ( sysif_read_data_read_valid ), .sysif_read_data_write_valid_i ( sysif_read_data_write_valid ), diff --git a/hw/ip/mbx/rtl/mbx_fsm.sv b/hw/ip/mbx/rtl/mbx_fsm.sv index 835ecb79514f6..1e51dfd21cb70 100644 --- a/hw/ip/mbx/rtl/mbx_fsm.sv +++ b/hw/ip/mbx/rtl/mbx_fsm.sv @@ -12,7 +12,7 @@ module mbx_fsm #( // Control input signals input logic mbx_range_valid_i, input logic hostif_abort_ack_i, - input logic hostif_control_error_set_i, + input logic mbx_error_set_i, input logic sysif_control_abort_set_i, input logic sys_read_all_i, input logic writer_close_mbx_i, @@ -34,7 +34,8 @@ module mbx_fsm #( MbxWrite = 3'b001, MbxWaitFinalWord = 3'b010, MbxRead = 3'b011, - MbxSysAbortHost = 3'b100 + MbxError = 3'b100, + MbxSysAbortHost = 3'b101 } mbx_ctrl_state_e; mbx_ctrl_state_e ctrl_state_q, ctrl_state_d; @@ -75,7 +76,7 @@ module mbx_fsm #( // MbxRead is a common state for imbx and ombx // Exit of MbxRead is used to clear imbx.Busy and ombx.Ready - assign ombx_clear_ready = CfgOmbx & (hostif_control_error_set_i | + assign ombx_clear_ready = CfgOmbx & (mbx_error_set_i | sysif_control_abort_set_i | mbx_read_o & sys_read_all_i); @@ -98,8 +99,10 @@ module mbx_fsm #( end end - // If system wants to abort, it has the highest priority - if (sysif_control_abort_set_i) begin + // If system wants to error or abort, it has the highest priority + if (mbx_error_set_i) begin + ctrl_state_d = MbxError; + end else if (sysif_control_abort_set_i) begin ctrl_state_d = MbxSysAbortHost; end end @@ -107,9 +110,9 @@ module mbx_fsm #( // Inbound mailbox being written by the system = writer // Outbound mailbox: not applicable MbxWrite: begin - if (hostif_control_error_set_i) begin // Host asserts an error - ctrl_state_d = MbxIdle; - end else if (sysif_control_abort_set_i) begin // System wants to abort + if (mbx_error_set_i) begin // Host asserts an error + ctrl_state_d = MbxError; + end else if (sysif_control_abort_set_i) begin // System wants to abort ctrl_state_d = MbxSysAbortHost; end else if (writer_close_mbx_i) begin // Writer decided to close the mailbox if (writer_last_word_written_i) begin @@ -123,8 +126,8 @@ module mbx_fsm #( // Inbound mailbox being written by the system = writer // Outbound mailbox: not applicable MbxWaitFinalWord: begin - if (hostif_control_error_set_i) begin // Host asserts an error - ctrl_state_d = MbxIdle; + if (mbx_error_set_i) begin // Host asserts an error + ctrl_state_d = MbxError; end else if (sysif_control_abort_set_i) begin // System wants to abort ctrl_state_d = MbxSysAbortHost; end else if (writer_last_word_written_i) begin @@ -135,8 +138,8 @@ module mbx_fsm #( // Inbound mailbox being read by the reader = host // Outbound mailbox being read by the reader = system MbxRead: begin - if (hostif_control_error_set_i) begin // Host asserts an error - ctrl_state_d = MbxIdle; + if (mbx_error_set_i) begin // Host asserts an error + ctrl_state_d = MbxError; end else if (sysif_control_abort_set_i) begin // System wants to abort ctrl_state_d = MbxSysAbortHost; end else if (sys_read_all_i) begin @@ -146,6 +149,13 @@ module mbx_fsm #( end end + // Wait for the abort request to occur + MbxError: begin + if (sysif_control_abort_set_i) begin + ctrl_state_d = MbxSysAbortHost; + end + end + MbxSysAbortHost: begin // Wait for the host to acknowledge the abort if (hostif_abort_ack_i) begin diff --git a/hw/ip/mbx/rtl/mbx_imbx.sv b/hw/ip/mbx/rtl/mbx_imbx.sv index 748638b2e5713..e54e62689763c 100644 --- a/hw/ip/mbx/rtl/mbx_imbx.sv +++ b/hw/ip/mbx/rtl/mbx_imbx.sv @@ -16,10 +16,11 @@ module mbx_imbx #( output logic imbx_irq_abort_o, output logic imbx_status_busy_update_o, output logic imbx_status_busy_o, + output logic imbx_overflow_error_set_o, // Access to the control and status registers of host interface // Writing a 1 to control.abort register clears the abort condition input logic hostif_control_abort_clear_i, - input logic hostif_control_error_set_i, + input logic mbx_error_set_i, // Range configuration for the private SRAM input logic hostif_range_valid_write_i, input logic hostif_range_valid_i, @@ -51,6 +52,10 @@ module mbx_imbx #( assign write_req = (mbx_empty & sysif_data_write_valid_i) | (mbx_write & sysif_data_write_valid_i & (sram_write_ptr_q <= hostif_limit_i)); + // Raise an error if the requester tries to write out of the limits + assign imbx_overflow_error_set_o = mbx_write & sysif_data_write_valid_i & + (sram_write_ptr_q > hostif_limit_i); + // Create a sticky TLUL write request until its granted logic req_q; assign hostif_sram_write_req_o = write_req | req_q; @@ -64,15 +69,16 @@ module mbx_imbx #( .q_o ( req_q ) ); - logic sys_clear_abort; - logic load_write_ptr, advance_write_ptr; + // The abort requested was handled by the host. This re-initialzes the write pointer + logic host_clear_abort; + assign host_clear_abort = hostif_control_abort_clear_i & mbx_sys_abort; - assign sys_clear_abort = hostif_control_abort_clear_i & mbx_sys_abort; + logic load_write_ptr, advance_write_ptr; // Rewind the write pointer to the base // Note: `mbx_empty` and `advance_write_ptr` can both be asserted if bus access is granted // immediately on the initial word write of a message, and we must advance the write pointer. - assign load_write_ptr = (mbx_empty & ~advance_write_ptr) | sys_clear_abort | + assign load_write_ptr = (mbx_empty & ~advance_write_ptr) | host_clear_abort | (mbx_read & sys_read_all_i); // Advance the write pointer when the valid write command is granted by the tlul_adapter_host @@ -117,13 +123,13 @@ module mbx_imbx #( // Busy logic logic imbx_set_busy, imbx_clear_busy; - assign imbx_set_busy = (mbx_write & - sysif_control_go_set_i & - ~hostif_control_error_set_i & - ~sysif_control_abort_set_i - ) | - sysif_control_abort_set_i | - ~hostif_range_valid_i; + // Busy is set when the requester asserts the go bit and we are not at the same time + // getting an abort or error request. Busy also gets set when there is an abort + // request, as this needs to be handled, and initially when the mailbox memory ranges + // are not yet configured + assign imbx_set_busy = + (mbx_write & sysif_control_go_set_i & ~mbx_error_set_i & ~sysif_control_abort_set_i) | + sysif_control_abort_set_i | ~hostif_range_valid_i; // Clear the busy signal if // - the private SRAM range becomes valid @@ -144,7 +150,7 @@ module mbx_imbx #( .rst_ni ( rst_ni ), .mbx_range_valid_i ( hostif_range_valid_i ), .hostif_abort_ack_i ( hostif_control_abort_clear_i ), - .hostif_control_error_set_i( hostif_control_error_set_i ), + .mbx_error_set_i ( mbx_error_set_i ), .sysif_control_abort_set_i ( sysif_control_abort_set_i ), .sys_read_all_i ( sys_read_all_i ), .writer_close_mbx_i ( sysif_control_go_set_i ), diff --git a/hw/ip/mbx/rtl/mbx_ombx.sv b/hw/ip/mbx/rtl/mbx_ombx.sv index 90d91e69ebaa1..8e56245abe6c7 100644 --- a/hw/ip/mbx/rtl/mbx_ombx.sv +++ b/hw/ip/mbx/rtl/mbx_ombx.sv @@ -25,7 +25,7 @@ module mbx_ombx #( // Writing a 1 to control.abort register clears the abort condition input logic sysif_status_ready_i, input logic hostif_control_abort_clear_i, - input logic hostif_control_error_set_i, + input logic mbx_error_set_i, input logic sysif_control_abort_set_i, input logic sysif_read_data_read_valid_i, input logic sysif_read_data_write_valid_i, @@ -106,6 +106,7 @@ module mbx_ombx #( sysif_read_data_write_valid_i & (sram_read_ptr_q == sram_read_ptr_limit_q); + // The abort requestet was handled by the host. This re-initialzes the read pointer logic host_clear_abort; assign host_clear_abort = hostif_control_abort_clear_i & mbx_sys_abort; @@ -147,7 +148,7 @@ module mbx_ombx #( // or the requester aborts the transaction logic clear_read_data; assign clear_read_data = sys_read_all_o | - hostif_control_error_set_i | + mbx_error_set_i | sysif_control_abort_set_i; // Advance the SRAM read response to read data prim_generic_flop_en #( @@ -239,7 +240,7 @@ module mbx_ombx #( .rst_ni ( rst_ni ), .mbx_range_valid_i ( hostif_range_valid_i ), .hostif_abort_ack_i ( hostif_control_abort_clear_i ), - .hostif_control_error_set_i( hostif_control_error_set_i ), + .mbx_error_set_i ( mbx_error_set_i ), .sysif_control_abort_set_i ( sysif_control_abort_set_i ), .sys_read_all_i ( sys_read_all_o ), .writer_close_mbx_i ( writer_close_mbx ), From 272244719d793a98ba94fab09b4ba3855d40cc71 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Thu, 16 Nov 2023 04:13:33 -0800 Subject: [PATCH 63/88] [hw,mbx,rtl] Add an error IRQ to notify host Signed-off-by: Robert Schilling --- hw/ip/mbx/data/mbx.hjson | 3 ++ hw/ip/mbx/rtl/mbx.sv | 6 ++- hw/ip/mbx/rtl/mbx_core_reg_top.sv | 86 ++++++++++++++++++++++++++++++- hw/ip/mbx/rtl/mbx_hostif.sv | 15 ++++++ hw/ip/mbx/rtl/mbx_reg_pkg.sv | 25 +++++++-- 5 files changed, 128 insertions(+), 7 deletions(-) diff --git a/hw/ip/mbx/data/mbx.hjson b/hw/ip/mbx/data/mbx.hjson index 58425859fc899..7618f75404a4a 100644 --- a/hw/ip/mbx/data/mbx.hjson +++ b/hw/ip/mbx/data/mbx.hjson @@ -60,6 +60,9 @@ { name: "mbx_abort" desc: "An abort request was received from the requester." } + { name: "mbx_error" + desc: "The mailbox instance generated an error." + } ] alert_list: [ { name: "fatal_fault" diff --git a/hw/ip/mbx/rtl/mbx.sv b/hw/ip/mbx/rtl/mbx.sv index d638b22f0e88b..3f478aa473f7e 100644 --- a/hw/ip/mbx/rtl/mbx.sv +++ b/hw/ip/mbx/rtl/mbx.sv @@ -20,6 +20,7 @@ module mbx // Comportable interrupt to the OT output logic intr_mbx_ready_o, output logic intr_mbx_abort_o, + output logic intr_mbx_error_o, // Custom straps for capability register implementation output logic doe_intr_support_o, output logic doe_intr_en_o, @@ -59,6 +60,7 @@ module mbx logic hostif_address_range_valid, hostif_address_range_valid_write; logic sysif_control_abort_set; logic doe_async_msg_en; + logic imbx_overflow_error_set; // Status signal inputs from the sysif to the hostif logic sysif_status_busy, sysif_status_error; @@ -101,8 +103,10 @@ module mbx .tl_host_o ( core_tl_d_o ), .event_intr_ready_i ( hostif_event_intr_ready ), .event_intr_abort_i ( hostif_event_intr_abort ), + .event_intr_error_i ( imbx_overflow_error_set ), .intr_ready_o ( intr_mbx_ready_o ), .intr_abort_o ( intr_mbx_abort_o ), + .intr_error_o ( intr_mbx_error_o ), .intg_err_i ( alert_signal ), .sram_err_i ( sram_err ), .alert_rx_i ( alert_rx_i ), @@ -176,7 +180,7 @@ module mbx // Combine error outputs of all modules and distribute back error to them to bring all // modules to the error state if needed - logic mbx_error_set, imbx_overflow_error_set; + logic mbx_error_set; assign mbx_error_set = hostif_control_error_set | imbx_overflow_error_set; mbx_sysif #( diff --git a/hw/ip/mbx/rtl/mbx_core_reg_top.sv b/hw/ip/mbx/rtl/mbx_core_reg_top.sv index 785dc3d4d7238..f3ac101447a2c 100644 --- a/hw/ip/mbx/rtl/mbx_core_reg_top.sv +++ b/hw/ip/mbx/rtl/mbx_core_reg_top.sv @@ -126,14 +126,19 @@ module mbx_core_reg_top ( logic intr_state_mbx_ready_wd; logic intr_state_mbx_abort_qs; logic intr_state_mbx_abort_wd; + logic intr_state_mbx_error_qs; + logic intr_state_mbx_error_wd; logic intr_enable_we; logic intr_enable_mbx_ready_qs; logic intr_enable_mbx_ready_wd; logic intr_enable_mbx_abort_qs; logic intr_enable_mbx_abort_wd; + logic intr_enable_mbx_error_qs; + logic intr_enable_mbx_error_wd; logic intr_test_we; logic intr_test_mbx_ready_wd; logic intr_test_mbx_abort_wd; + logic intr_test_mbx_error_wd; logic alert_test_we; logic alert_test_fatal_fault_wd; logic alert_test_recov_fault_wd; @@ -235,6 +240,33 @@ module mbx_core_reg_top ( .qs (intr_state_mbx_abort_qs) ); + // F[mbx_error]: 2:2 + prim_subreg #( + .DW (1), + .SwAccess(prim_subreg_pkg::SwAccessW1C), + .RESVAL (1'h0), + .Mubi (1'b0) + ) u_intr_state_mbx_error ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (intr_state_we), + .wd (intr_state_mbx_error_wd), + + // from internal hardware + .de (hw2reg.intr_state.mbx_error.de), + .d (hw2reg.intr_state.mbx_error.d), + + // to internal hardware + .qe (), + .q (reg2hw.intr_state.mbx_error.q), + .ds (), + + // to register interface (read) + .qs (intr_state_mbx_error_qs) + ); + // R[intr_enable]: V(False) // F[mbx_ready]: 0:0 @@ -291,10 +323,37 @@ module mbx_core_reg_top ( .qs (intr_enable_mbx_abort_qs) ); + // F[mbx_error]: 2:2 + prim_subreg #( + .DW (1), + .SwAccess(prim_subreg_pkg::SwAccessRW), + .RESVAL (1'h0), + .Mubi (1'b0) + ) u_intr_enable_mbx_error ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (intr_enable_we), + .wd (intr_enable_mbx_error_wd), + + // from internal hardware + .de (1'b0), + .d ('0), + + // to internal hardware + .qe (), + .q (reg2hw.intr_enable.mbx_error.q), + .ds (), + + // to register interface (read) + .qs (intr_enable_mbx_error_qs) + ); + // R[intr_test]: V(True) logic intr_test_qe; - logic [1:0] intr_test_flds_we; + logic [2:0] intr_test_flds_we; assign intr_test_qe = &intr_test_flds_we; // F[mbx_ready]: 0:0 prim_subreg_ext #( @@ -328,6 +387,22 @@ module mbx_core_reg_top ( ); assign reg2hw.intr_test.mbx_abort.qe = intr_test_qe; + // F[mbx_error]: 2:2 + prim_subreg_ext #( + .DW (1) + ) u_intr_test_mbx_error ( + .re (1'b0), + .we (intr_test_we), + .wd (intr_test_mbx_error_wd), + .d ('0), + .qre (), + .qe (intr_test_flds_we[2]), + .q (reg2hw.intr_test.mbx_error.q), + .ds (), + .qs () + ); + assign reg2hw.intr_test.mbx_error.qe = intr_test_qe; + // R[alert_test]: V(True) logic alert_test_qe; @@ -838,16 +913,22 @@ module mbx_core_reg_top ( assign intr_state_mbx_ready_wd = reg_wdata[0]; assign intr_state_mbx_abort_wd = reg_wdata[1]; + + assign intr_state_mbx_error_wd = reg_wdata[2]; assign intr_enable_we = addr_hit[1] & reg_we & !reg_error; assign intr_enable_mbx_ready_wd = reg_wdata[0]; assign intr_enable_mbx_abort_wd = reg_wdata[1]; + + assign intr_enable_mbx_error_wd = reg_wdata[2]; assign intr_test_we = addr_hit[2] & reg_we & !reg_error; assign intr_test_mbx_ready_wd = reg_wdata[0]; assign intr_test_mbx_abort_wd = reg_wdata[1]; + + assign intr_test_mbx_error_wd = reg_wdata[2]; assign alert_test_we = addr_hit[3] & reg_we & !reg_error; assign alert_test_fatal_fault_wd = reg_wdata[0]; @@ -917,16 +998,19 @@ module mbx_core_reg_top ( addr_hit[0]: begin reg_rdata_next[0] = intr_state_mbx_ready_qs; reg_rdata_next[1] = intr_state_mbx_abort_qs; + reg_rdata_next[2] = intr_state_mbx_error_qs; end addr_hit[1]: begin reg_rdata_next[0] = intr_enable_mbx_ready_qs; reg_rdata_next[1] = intr_enable_mbx_abort_qs; + reg_rdata_next[2] = intr_enable_mbx_error_qs; end addr_hit[2]: begin reg_rdata_next[0] = '0; reg_rdata_next[1] = '0; + reg_rdata_next[2] = '0; end addr_hit[3]: begin diff --git a/hw/ip/mbx/rtl/mbx_hostif.sv b/hw/ip/mbx/rtl/mbx_hostif.sv index 149e077d38721..fcd25bd2d9bf6 100644 --- a/hw/ip/mbx/rtl/mbx_hostif.sv +++ b/hw/ip/mbx/rtl/mbx_hostif.sv @@ -18,8 +18,10 @@ module mbx_hostif // Generated interrupt event input logic event_intr_ready_i, input logic event_intr_abort_i, + input logic event_intr_error_i, output logic intr_ready_o, output logic intr_abort_o, + output logic intr_error_o, // External errors input logic intg_err_i, input logic sram_err_i, @@ -133,6 +135,19 @@ module mbx_hostif .intr_o ( intr_abort_o ) ); + prim_intr_hw #(.Width(1)) u_intr_error ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .event_intr_i ( event_intr_error_i ), + .reg2hw_intr_enable_q_i ( reg2hw.intr_enable.mbx_error.q ), + .reg2hw_intr_test_q_i ( reg2hw.intr_test.mbx_error.q ), + .reg2hw_intr_test_qe_i ( reg2hw.intr_test.mbx_error.qe ), + .reg2hw_intr_state_q_i ( reg2hw.intr_state.mbx_error.q ), + .hw2reg_intr_state_de_o ( hw2reg.intr_state.mbx_error.de ), + .hw2reg_intr_state_d_o ( hw2reg.intr_state.mbx_error.d ), + .intr_o ( intr_error_o ) + ); + // Control Register logic abort_d, abort_q; diff --git a/hw/ip/mbx/rtl/mbx_reg_pkg.sv b/hw/ip/mbx/rtl/mbx_reg_pkg.sv index a2bd568c2d732..8b635fd227533 100644 --- a/hw/ip/mbx/rtl/mbx_reg_pkg.sv +++ b/hw/ip/mbx/rtl/mbx_reg_pkg.sv @@ -18,6 +18,9 @@ package mbx_reg_pkg; /////////////////////////////////////////////// typedef struct packed { + struct packed { + logic q; + } mbx_error; struct packed { logic q; } mbx_abort; @@ -27,6 +30,9 @@ package mbx_reg_pkg; } mbx_reg2hw_intr_state_reg_t; typedef struct packed { + struct packed { + logic q; + } mbx_error; struct packed { logic q; } mbx_abort; @@ -36,6 +42,10 @@ package mbx_reg_pkg; } mbx_reg2hw_intr_enable_reg_t; typedef struct packed { + struct packed { + logic q; + logic qe; + } mbx_error; struct packed { logic q; logic qe; @@ -107,6 +117,10 @@ package mbx_reg_pkg; logic d; logic de; } mbx_abort; + struct packed { + logic d; + logic de; + } mbx_error; } mbx_hw2reg_intr_state_reg_t; typedef struct packed { @@ -156,9 +170,9 @@ package mbx_reg_pkg; // Register -> HW type for core interface typedef struct packed { - mbx_reg2hw_intr_state_reg_t intr_state; // [151:150] - mbx_reg2hw_intr_enable_reg_t intr_enable; // [149:148] - mbx_reg2hw_intr_test_reg_t intr_test; // [147:144] + mbx_reg2hw_intr_state_reg_t intr_state; // [155:153] + mbx_reg2hw_intr_enable_reg_t intr_enable; // [152:150] + mbx_reg2hw_intr_test_reg_t intr_test; // [149:144] mbx_reg2hw_alert_test_reg_t alert_test; // [143:140] mbx_reg2hw_control_reg_t control; // [139:134] mbx_reg2hw_address_range_valid_reg_t address_range_valid; // [133:132] @@ -171,7 +185,7 @@ package mbx_reg_pkg; // HW -> register type for core interface typedef struct packed { - mbx_hw2reg_intr_state_reg_t intr_state; // [145:142] + mbx_hw2reg_intr_state_reg_t intr_state; // [147:142] mbx_hw2reg_control_reg_t control; // [141:140] mbx_hw2reg_status_reg_t status; // [139:136] mbx_hw2reg_inbound_write_ptr_reg_t inbound_write_ptr; // [135:106] @@ -201,9 +215,10 @@ package mbx_reg_pkg; parameter logic [CoreAw-1:0] MBX_DOE_INTR_MSG_DATA_OFFSET = 7'h 40; // Reset values for hwext registers and their fields for core interface - parameter logic [1:0] MBX_INTR_TEST_RESVAL = 2'h 0; + parameter logic [2:0] MBX_INTR_TEST_RESVAL = 3'h 0; parameter logic [0:0] MBX_INTR_TEST_MBX_READY_RESVAL = 1'h 0; parameter logic [0:0] MBX_INTR_TEST_MBX_ABORT_RESVAL = 1'h 0; + parameter logic [0:0] MBX_INTR_TEST_MBX_ERROR_RESVAL = 1'h 0; parameter logic [1:0] MBX_ALERT_TEST_RESVAL = 2'h 0; parameter logic [0:0] MBX_ALERT_TEST_FATAL_FAULT_RESVAL = 1'h 0; parameter logic [0:0] MBX_ALERT_TEST_RECOV_FAULT_RESVAL = 1'h 0; From eb77d02c3ab2cfc6daee695d7d0d78d8e2169d5f Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Mon, 20 Nov 2023 08:31:15 -0800 Subject: [PATCH 64/88] [hw,mbx,dv] Add new interrupt to the DV environment Signed-off-by: Robert Schilling --- hw/ip/mbx/dv/env/mbx_env_pkg.sv | 3 ++- hw/ip/mbx/dv/tb.sv | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/hw/ip/mbx/dv/env/mbx_env_pkg.sv b/hw/ip/mbx/dv/env/mbx_env_pkg.sv index faaf30c583a24..e220fa0f79d95 100644 --- a/hw/ip/mbx/dv/env/mbx_env_pkg.sv +++ b/hw/ip/mbx/dv/env/mbx_env_pkg.sv @@ -37,7 +37,8 @@ package mbx_env_pkg; } reg_op_e; typedef enum { MbxCoreReady, - MbxCoreAbort + MbxCoreAbort, + MbxCoreError } mbx_core_intr_e; // functions diff --git a/hw/ip/mbx/dv/tb.sv b/hw/ip/mbx/dv/tb.sv index 77f75d3cc5c25..224c7671d6dbb 100644 --- a/hw/ip/mbx/dv/tb.sv +++ b/hw/ip/mbx/dv/tb.sv @@ -19,6 +19,7 @@ module tb; wire intr_doe; wire intr_ready; wire intr_abort; + wire intr_error; clk_rst_if i_clk_rst_if(.clk(clk), .rst_n(rst_n)); tl_if i_tl_scxb_mbx_core_if(.clk(clk), .rst_n(rst_n)); @@ -37,6 +38,7 @@ module tb; .doe_intr_support_o(), .doe_intr_en_o(), .doe_intr_o(intr_doe), + .doe_async_msg_support_o(), // various tlul interfaces .core_tl_d_o(i_tl_agxb_mbx_core_if.d2h), .core_tl_d_i(i_tl_agxb_mbx_core_if.h2d), @@ -47,6 +49,7 @@ module tb; // alerts and interrupts .intr_mbx_ready_o(intr_ready), .intr_mbx_abort_o(intr_abort), + .intr_mbx_error_o(intr_error), .alert_rx_i(alert_rx), .alert_tx_o(alert_tx) ); @@ -54,6 +57,7 @@ module tb; // Connect the interrupts assign interrupts[MbxCoreReady] = intr_ready; assign interrupts[MbxCoreAbort] = intr_abort; + assign interrupts[MbxCoreError] = intr_error; initial begin // drive clk and rst_n from clk_if From 9953efbd4a81a1a856683d163e734c202d4ede64 Mon Sep 17 00:00:00 2001 From: Adrian Lees Date: Wed, 22 Nov 2023 20:14:55 +0000 Subject: [PATCH 65/88] [dv,mbx] Changes for vcs support Minor fixes to support use of vcs as an alternative. Signed-off-by: Adrian Lees --- hw/ip/mbx/dv/env/mbx_env_cfg.sv | 3 ++- hw/ip/mbx/dv/env/mbx_env_pkg.sv | 3 +++ hw/ip/mbx/dv/env/seq_lib/mbx_base_vseq.sv | 2 +- hw/ip/mbx/dv/tb.sv | 20 ++++++-------------- 4 files changed, 12 insertions(+), 16 deletions(-) diff --git a/hw/ip/mbx/dv/env/mbx_env_cfg.sv b/hw/ip/mbx/dv/env/mbx_env_cfg.sv index 5a89887de4316..22713c48f3d87 100644 --- a/hw/ip/mbx/dv/env/mbx_env_cfg.sv +++ b/hw/ip/mbx/dv/env/mbx_env_cfg.sv @@ -5,11 +5,12 @@ class mbx_env_cfg extends cip_base_env_cfg #( .RAL_T(mbx_core_reg_block) ); + import dv_utils_pkg::*; string mbx_mem_ral_name = "mbx_mem_reg_block"; string mbx_soc_ral_name = "mbx_soc_reg_block"; - intr_vif intr_soc_vif; + virtual pins_if #(NUM_MAX_INTERRUPTS) intr_soc_vif; `uvm_object_utils(mbx_env_cfg) diff --git a/hw/ip/mbx/dv/env/mbx_env_pkg.sv b/hw/ip/mbx/dv/env/mbx_env_pkg.sv index e220fa0f79d95..21caf6ef4eef2 100644 --- a/hw/ip/mbx/dv/env/mbx_env_pkg.sv +++ b/hw/ip/mbx/dv/env/mbx_env_pkg.sv @@ -40,6 +40,9 @@ package mbx_env_pkg; MbxCoreAbort, MbxCoreError } mbx_core_intr_e; + typedef enum { + MbxSocDOE + } mbx_soc_intr_e; // functions diff --git a/hw/ip/mbx/dv/env/seq_lib/mbx_base_vseq.sv b/hw/ip/mbx/dv/env/seq_lib/mbx_base_vseq.sv index d8cb7ef43b5b1..3e7a0ff2d035c 100644 --- a/hw/ip/mbx/dv/env/seq_lib/mbx_base_vseq.sv +++ b/hw/ip/mbx/dv/env/seq_lib/mbx_base_vseq.sv @@ -153,7 +153,7 @@ class mbx_base_vseq extends cip_base_vseq #( disable fork; end join `uvm_info(`gfn, $sformatf("wait_for_soc_interrupt -- End"), UVM_DEBUG) - endtask: wait_for_core_interrupt + endtask: wait_for_soc_interrupt virtual task body(); `uvm_info(get_full_name(), "body -- Start", UVM_DEBUG) diff --git a/hw/ip/mbx/dv/tb.sv b/hw/ip/mbx/dv/tb.sv index 224c7671d6dbb..0e65d7fd7f28d 100644 --- a/hw/ip/mbx/dv/tb.sv +++ b/hw/ip/mbx/dv/tb.sv @@ -16,17 +16,14 @@ module tb; wire clk, rst_n; wire [NUM_MAX_INTERRUPTS-1:0] interrupts; - wire intr_doe; - wire intr_ready; - wire intr_abort; - wire intr_error; + wire [NUM_MAX_INTERRUPTS-1:0] interrupts_soc; clk_rst_if i_clk_rst_if(.clk(clk), .rst_n(rst_n)); tl_if i_tl_scxb_mbx_core_if(.clk(clk), .rst_n(rst_n)); tl_if i_tl_agxb_mbx_core_if(.clk(clk), .rst_n(rst_n)); tl_if i_tl_mbx_agxb_device_if(.clk(clk), .rst_n(rst_n)); pins_if #(NUM_MAX_INTERRUPTS) i_intr_core_if(interrupts); - pins_if #(NUM_MAX_INTERRUPTS) i_intr_soc_if({intr_doe}); + pins_if #(NUM_MAX_INTERRUPTS) i_intr_soc_if(interrupts_soc); `DV_ALERT_IF_CONNECT() @@ -37,7 +34,7 @@ module tb; .rst_ni(rst_n), .doe_intr_support_o(), .doe_intr_en_o(), - .doe_intr_o(intr_doe), + .doe_intr_o(interrupts_soc[MbxSocDOE]), .doe_async_msg_support_o(), // various tlul interfaces .core_tl_d_o(i_tl_agxb_mbx_core_if.d2h), @@ -47,18 +44,13 @@ module tb; .sram_tl_h_o(i_tl_mbx_agxb_device_if.h2d), .sram_tl_h_i(i_tl_mbx_agxb_device_if.d2h), // alerts and interrupts - .intr_mbx_ready_o(intr_ready), - .intr_mbx_abort_o(intr_abort), - .intr_mbx_error_o(intr_error), + .intr_mbx_ready_o(interrupts[MbxCoreReady]), + .intr_mbx_abort_o(interrupts[MbxCoreAbort]), + .intr_mbx_error_o(interrupts[MbxCoreError]), .alert_rx_i(alert_rx), .alert_tx_o(alert_tx) ); - // Connect the interrupts - assign interrupts[MbxCoreReady] = intr_ready; - assign interrupts[MbxCoreAbort] = intr_abort; - assign interrupts[MbxCoreError] = intr_error; - initial begin // drive clk and rst_n from clk_if i_clk_rst_if.set_active(); From d23f500997b5030f4380cfcc03a0d84c7208477b Mon Sep 17 00:00:00 2001 From: Adrian Lees Date: Wed, 22 Nov 2023 13:46:18 +0000 Subject: [PATCH 66/88] [mbx] Fault recovery via Abort mechanism Clearing of Abort condition resets both inbound and outbound traffic, clears down the count of outstanding requests and suppresses any subsequent core-side TL-UL read responses. Since the Abort request clears Ready, keep the Read Data register zeroed until the abort is acknowledged. Signed-off-by: Adrian Lees --- hw/ip/mbx/rtl/mbx.sv | 34 +++++++++++++++-------------- hw/ip/mbx/rtl/mbx_fsm.sv | 12 ++++++----- hw/ip/mbx/rtl/mbx_imbx.sv | 25 ++++++++++++++-------- hw/ip/mbx/rtl/mbx_ombx.sv | 39 ++++++++++++++++++++++------------ hw/ip/mbx/rtl/mbx_sramrwarb.sv | 26 ++++++++++++++++++----- 5 files changed, 88 insertions(+), 48 deletions(-) diff --git a/hw/ip/mbx/rtl/mbx.sv b/hw/ip/mbx/rtl/mbx.sv index 3f478aa473f7e..2402b3459e933 100644 --- a/hw/ip/mbx/rtl/mbx.sv +++ b/hw/ip/mbx/rtl/mbx.sv @@ -314,24 +314,26 @@ module mbx .CfgSramAddrWidth( CfgSramAddrWidth ), .CfgSramDataWidth( CfgSramDataWidth ) ) u_sramrwarb ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .tl_host_o ( sram_tl_h_o ), - .tl_host_i ( sram_tl_h_i ), - .intg_err_o ( tl_sram_intg_err ), - .sram_err_o ( sram_err ), + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .tl_host_o ( sram_tl_h_o ), + .tl_host_i ( sram_tl_h_i ), + .intg_err_o ( tl_sram_intg_err ), + .sram_err_o ( sram_err ), + // Host-side acknowledgement of an Abort operation + .hostif_control_abort_clear_i ( hostif_control_abort_clear ), // Interface to the inbound mailbox - .imbx_sram_write_req_i ( imbx_sram_write_req ), - .imbx_sram_write_gnt_o ( imbx_sram_write_gnt ), - .imbx_sram_write_ptr_i ( imbx_sram_write_ptr ), - .imbx_sram_all_vld_rcvd_o ( imbx_sram_all_vld_rcvd ), - .imbx_write_data_i ( sysif_write_data ), + .imbx_sram_write_req_i ( imbx_sram_write_req ), + .imbx_sram_write_gnt_o ( imbx_sram_write_gnt ), + .imbx_sram_write_ptr_i ( imbx_sram_write_ptr ), + .imbx_sram_all_vld_rcvd_o ( imbx_sram_all_vld_rcvd ), + .imbx_write_data_i ( sysif_write_data ), // Interface to the outbound mailbox - .ombx_sram_read_req_i ( ombx_sram_read_req ), - .ombx_sram_read_gnt_o ( ombx_sram_read_gnt ), - .ombx_sram_read_ptr_i ( ombx_sram_read_ptr ), - .ombx_sram_read_resp_vld_o ( ombx_sram_read_resp_vld ), - .ombx_sram_read_resp_o ( ombx_sram_read_data ) + .ombx_sram_read_req_i ( ombx_sram_read_req ), + .ombx_sram_read_gnt_o ( ombx_sram_read_gnt ), + .ombx_sram_read_ptr_i ( ombx_sram_read_ptr ), + .ombx_sram_read_resp_vld_o ( ombx_sram_read_resp_vld ), + .ombx_sram_read_resp_o ( ombx_sram_read_data ) ); // Assertions diff --git a/hw/ip/mbx/rtl/mbx_fsm.sv b/hw/ip/mbx/rtl/mbx_fsm.sv index 1e51dfd21cb70..22fc156ab5db3 100644 --- a/hw/ip/mbx/rtl/mbx_fsm.sv +++ b/hw/ip/mbx/rtl/mbx_fsm.sv @@ -67,21 +67,23 @@ module mbx_fsm #( assign mbx_irq_ready_o = (ctrl_state_d == MbxRead); logic ombx_set_ready, ombx_clear_ready; - // Outbound mailbox is ready + // Outbound mailbox is Ready, but only if not simultaneous with the exceptional conditions that + // demand clearing of the Ready status bit. assign ombx_set_ready = CfgOmbx & mbx_idle & mbx_range_valid_i - & writer_close_mbx_i - & ~sysif_control_abort_set_i; + & writer_close_mbx_i; // MbxRead is a common state for imbx and ombx - // Exit of MbxRead is used to clear imbx.Busy and ombx.Ready + // Exit of MbxRead is used to clear imbx.Busy and ombx.Ready. + // This must also happen when an Error, Abort or FW-initiated reset occurs. assign ombx_clear_ready = CfgOmbx & (mbx_error_set_i | sysif_control_abort_set_i | + hostif_abort_ack_i | mbx_read_o & sys_read_all_i); assign mbx_ready_update_o = CfgOmbx & (ombx_set_ready | ombx_clear_ready); // MUTEX(set,clr) - assign mbx_ready_o = ombx_set_ready; + assign mbx_ready_o = !ombx_clear_ready; // Clearing overrules setting. always_comb begin ctrl_state_d = ctrl_state_q; diff --git a/hw/ip/mbx/rtl/mbx_imbx.sv b/hw/ip/mbx/rtl/mbx_imbx.sv index e54e62689763c..5424d6ae3d61d 100644 --- a/hw/ip/mbx/rtl/mbx_imbx.sv +++ b/hw/ip/mbx/rtl/mbx_imbx.sv @@ -48,9 +48,15 @@ module mbx_imbx #( // hostif_sram_write_req_o is actually sticky because the sys-side TLUL_adapter_reg is // NOT ack'ed until the command is granted by the host-side TLUL_adapter_host // RW2A = sticky from DEC/RW-stage to (srm command) ACK - logic write_req; - assign write_req = (mbx_empty & sysif_data_write_valid_i) | - (mbx_write & sysif_data_write_valid_i & (sram_write_ptr_q <= hostif_limit_i)); + logic write_req; + assign write_req = (mbx_empty & sysif_data_write_valid_i) | + (mbx_write & sysif_data_write_valid_i & (sram_write_ptr_q <= hostif_limit_i)); + + // Waiting for a write request to be accepted onto the TL-UL bus; reset state if the host side + // is acknowledging an Abort request from the SoC side. + logic awaiting_gnt; + assign awaiting_gnt = hostif_sram_write_req_o & ~hostif_sram_write_gnt_i & + ~hostif_control_abort_clear_i; // Raise an error if the requester tries to write out of the limits assign imbx_overflow_error_set_o = mbx_write & sysif_data_write_valid_i & @@ -63,10 +69,10 @@ module mbx_imbx #( prim_flop #( .Width(1) ) u_req_state ( - .clk_i ( clk_i ), - .rst_ni( rst_ni ), - .d_i ( hostif_sram_write_req_o & ~hostif_sram_write_gnt_i ), - .q_o ( req_q ) + .clk_i ( clk_i ), + .rst_ni( rst_ni ), + .d_i ( awaiting_gnt ), + .q_o ( req_q ) ); // The abort requested was handled by the host. This re-initialzes the write pointer @@ -108,9 +114,10 @@ module mbx_imbx #( // Backpressure the next write data until the current write data is granted by the TLUL adapter logic set_pending, clear_pending; - // Block the request from TLUL until the SRAM write is complete + // Block the request from TLUL until the SRAM write is complete. + // Reset state if the host side is acknowledging an Abort request. assign set_pending = write_req; - assign clear_pending = hostif_sram_write_gnt_i; + assign clear_pending = hostif_sram_write_gnt_i | hostif_control_abort_clear_i; prim_flop #( .Width(1) diff --git a/hw/ip/mbx/rtl/mbx_ombx.sv b/hw/ip/mbx/rtl/mbx_ombx.sv index 8e56245abe6c7..d45d07681a74b 100644 --- a/hw/ip/mbx/rtl/mbx_ombx.sv +++ b/hw/ip/mbx/rtl/mbx_ombx.sv @@ -63,6 +63,12 @@ module mbx_ombx #( (sram_read_ptr_q <= hostif_limit_i) & (sram_read_ptr_q < sram_read_ptr_limit_q)); + // Waiting for a read request to be accepted onto the TL-UL bus; reset state if the host side + // is acknowledging an Abort request from the SoC side. + logic awaiting_gnt; + assign awaiting_gnt = ombx_sram_read_req_o & ~ombx_sram_read_gnt_i & + ~hostif_control_abort_clear_i; + // Create a sticky TLUL read request until its granted logic req_q; assign ombx_sram_read_req_o = read_req | req_q; @@ -70,10 +76,10 @@ module mbx_ombx #( prim_flop #( .Width(1) ) u_req_state ( - .clk_i ( clk_i ), - .rst_ni( rst_ni ), - .d_i ( ombx_sram_read_req_o & ~ombx_sram_read_gnt_i ), - .q_o ( req_q ) + .clk_i ( clk_i ), + .rst_ni( rst_ni ), + .d_i ( awaiting_gnt ), + .q_o ( req_q ) ); // Backpressure the next read data until the current write data brings back the data from SRAM @@ -86,14 +92,15 @@ module mbx_ombx #( assign set_pending = mbx_read & sysif_read_data_write_valid_i & (sram_read_ptr_q <= hostif_limit_i) & (sram_read_ptr_q < sram_read_ptr_limit_q); - assign clear_pending = ombx_sram_read_resp_valid_i; + // Reset state if the host side is acknowledging an Abort request. + assign clear_pending = ombx_sram_read_resp_valid_i | hostif_control_abort_clear_i; prim_flop #( .Width(1) ) u_pending ( .clk_i ( clk_i ), .rst_ni( rst_ni ), - .d_i ( set_pending | (ombx_pending_o & ~clear_pending) ), + .d_i ( ~clear_pending & (set_pending | ombx_pending_o) ), .q_o ( ombx_pending_o ) ); @@ -144,12 +151,18 @@ module mbx_ombx #( ); assign ombx_sram_read_ptr_o = sram_read_ptr_q; - // Clear ombx read data register in case of all data is read, an error happens, - // or the requester aborts the transaction + // Abort has been requested by the SoC but not yet acknowledged on the host side. + logic aborting; + assign aborting = sysif_control_abort_set_i | mbx_sys_abort; + + // Clear ombx read data register in case of all data is read, an error happens, or an Abort or + // FW-initiated reset occurs. logic clear_read_data; - assign clear_read_data = sys_read_all_o | - mbx_error_set_i | - sysif_control_abort_set_i; + assign clear_read_data = sys_read_all_o | // Normal completion of Response + mbx_error_set_i | // Error raised by host side + aborting | // Abort requested by SoC side + hostif_control_abort_clear_i; // Abort ack or FW reset from host side + // Advance the SRAM read response to read data prim_generic_flop_en #( .Width(CfgSramDataWidth) @@ -184,10 +197,10 @@ module mbx_ombx #( logic [CfgObjectSizeWidth-1:0] hostif_ob_object_size_minus_one; // Update the hostif.object_size register on every transaction or when aborting the transaction assign hostif_ombx_object_size_update_o = (ombx_sram_read_req_o & ombx_sram_read_gnt_i) | - sysif_control_abort_set_i; + hostif_control_abort_clear_i; // The updated value is the decremented by 1 size or zero-ed out if the transaction is aborted assign hostif_ob_object_size_minus_one = hostif_ombx_object_size_i - 1; - assign hostif_ombx_object_size_o = {CfgObjectSizeWidth{~sysif_control_abort_set_i}} & + assign hostif_ombx_object_size_o = {CfgObjectSizeWidth{~hostif_control_abort_clear_i}} & hostif_ob_object_size_minus_one; prim_flop #( diff --git a/hw/ip/mbx/rtl/mbx_sramrwarb.sv b/hw/ip/mbx/rtl/mbx_sramrwarb.sv index 50877d917b6bb..2d116b25d93ef 100644 --- a/hw/ip/mbx/rtl/mbx_sramrwarb.sv +++ b/hw/ip/mbx/rtl/mbx_sramrwarb.sv @@ -16,6 +16,9 @@ module mbx_sramrwarb output logic intg_err_o, output logic sram_err_o, + // Host-side acknowledgement of an Abort operation + input logic hostif_control_abort_clear_i, + // Interface to the inbound mailbox input logic imbx_sram_write_req_i, output logic imbx_sram_write_gnt_o, @@ -60,9 +63,20 @@ module mbx_sramrwarb // FIFO Counting logic for maximum outstanding requests logic [LCFG_MAX_REQS_LOG2-1:0] outstanding_req_count_d, outstanding_req_count_q; logic inc_cnt, dec_cnt; - assign inc_cnt = sram_req & ~max_outstanding_reqs_reached & sram_gnt; - assign dec_cnt = sram_valid; - assign outstanding_req_count_d = outstanding_req_count_q + inc_cnt - dec_cnt; + + // Do we have knowledge of any outstanding requests, including one currently being accepted? + // Note: a device may respond in the same cycle as accepting the request. + logic any_outstanding_reqs; + assign any_outstanding_reqs = inc_cnt || (outstanding_req_count_q != '0); + + // Increment the count of outstanding requests when a new request is accepted onto the bus, + // being sure not to drive out more requests than we can track. + assign inc_cnt = sram_req & ~max_outstanding_reqs_reached & sram_gnt; + // Decrement the count when a reply is received, being sure not to underflow if we have had to + // process an Abort operation whilst one or more requests was still outstanding. + assign dec_cnt = sram_valid & any_outstanding_reqs; + assign outstanding_req_count_d = hostif_control_abort_clear_i ? '0 : + (outstanding_req_count_q + inc_cnt - dec_cnt); prim_generic_flop_en #( .Width(LCFG_MAX_REQS_LOG2) @@ -111,8 +125,10 @@ module mbx_sramrwarb // to look if the response was a response with data or not. It it's with data, it was a read // request and we serve ombx_sram_read_resp_vld_o. If it was a response without data // it was a write request. - assign ombx_sram_read_resp_vld_o = sram_valid & (tl_host_i.d_opcode == tlul_pkg::AccessAckData); + // We also ensure that any responses are not propagated after an Abort operation. + assign ombx_sram_read_resp_vld_o = sram_valid & any_outstanding_reqs & + (tl_host_i.d_opcode == tlul_pkg::AccessAckData); // Functional Coverage - `COVER(MaxOutstandingRequetsReached_C, sram_req & max_outstanding_reqs_reached) + `COVER(MaxOutstandingRequestsReached_C, sram_req & max_outstanding_reqs_reached) endmodule From a9cb33699a730ac7ab044903e12a85ba07e82833 Mon Sep 17 00:00:00 2001 From: Adrian Lees Date: Wed, 22 Nov 2023 13:59:53 +0000 Subject: [PATCH 67/88] [mbx] Abort acknowledgement always resets FSMs. Abort acknowledgement is of the highest priority, permitting its use as a FW-driven reset mechanism even if there was no explicit SoC-side Abort request. Signed-off-by: Adrian Lees --- hw/ip/mbx/rtl/mbx_fsm.sv | 140 ++++++++++++++++++++------------------- 1 file changed, 71 insertions(+), 69 deletions(-) diff --git a/hw/ip/mbx/rtl/mbx_fsm.sv b/hw/ip/mbx/rtl/mbx_fsm.sv index 22fc156ab5db3..53de33fa5cb6e 100644 --- a/hw/ip/mbx/rtl/mbx_fsm.sv +++ b/hw/ip/mbx/rtl/mbx_fsm.sv @@ -89,87 +89,89 @@ module mbx_fsm #( ctrl_state_d = ctrl_state_q; mbx_state_error_o = 1'b0; - unique case (ctrl_state_q) - MbxIdle: begin - if (CfgOmbx) begin - if (mbx_range_valid_i & writer_close_mbx_i) begin - ctrl_state_d = MbxRead; + // Acknowledgement of an Abort request may occur at any time, with the FSM in any state. + if (hostif_abort_ack_i) begin + ctrl_state_d = MbxIdle; + end else begin + unique case (ctrl_state_q) + MbxIdle: begin + if (CfgOmbx) begin + if (mbx_range_valid_i & writer_close_mbx_i) begin + ctrl_state_d = MbxRead; + end + end else begin + if (mbx_range_valid_i & writer_write_valid_i) begin + ctrl_state_d = MbxWrite; + end end - end else begin - if (mbx_range_valid_i & writer_write_valid_i) begin - ctrl_state_d = MbxWrite; + + // If system wants to error or abort, it has the highest priority + if (mbx_error_set_i) begin + ctrl_state_d = MbxError; + end else if (sysif_control_abort_set_i) begin + ctrl_state_d = MbxSysAbortHost; end end - // If system wants to error or abort, it has the highest priority - if (mbx_error_set_i) begin - ctrl_state_d = MbxError; - end else if (sysif_control_abort_set_i) begin - ctrl_state_d = MbxSysAbortHost; + // Inbound mailbox being written by the system = writer + // Outbound mailbox: not applicable + MbxWrite: begin + if (mbx_error_set_i) begin // Host asserts an error + ctrl_state_d = MbxError; + end else if (sysif_control_abort_set_i) begin // System wants to abort + ctrl_state_d = MbxSysAbortHost; + end else if (writer_close_mbx_i) begin // Writer decided to close the mailbox + if (writer_last_word_written_i) begin + ctrl_state_d = MbxRead; + end else begin + ctrl_state_d = MbxWaitFinalWord; + end + end end - end - - // Inbound mailbox being written by the system = writer - // Outbound mailbox: not applicable - MbxWrite: begin - if (mbx_error_set_i) begin // Host asserts an error - ctrl_state_d = MbxError; - end else if (sysif_control_abort_set_i) begin // System wants to abort - ctrl_state_d = MbxSysAbortHost; - end else if (writer_close_mbx_i) begin // Writer decided to close the mailbox - if (writer_last_word_written_i) begin - ctrl_state_d = MbxRead; - end else begin - ctrl_state_d = MbxWaitFinalWord; + + // Inbound mailbox being written by the system = writer + // Outbound mailbox: not applicable + MbxWaitFinalWord: begin + if (mbx_error_set_i) begin // Host asserts an error + ctrl_state_d = MbxError; + end else if (sysif_control_abort_set_i) begin // System wants to abort + ctrl_state_d = MbxSysAbortHost; + end else if (writer_last_word_written_i) begin + ctrl_state_d = MbxRead; end end - end - - // Inbound mailbox being written by the system = writer - // Outbound mailbox: not applicable - MbxWaitFinalWord: begin - if (mbx_error_set_i) begin // Host asserts an error - ctrl_state_d = MbxError; - end else if (sysif_control_abort_set_i) begin // System wants to abort - ctrl_state_d = MbxSysAbortHost; - end else if (writer_last_word_written_i) begin - ctrl_state_d = MbxRead; + + // Inbound mailbox being read by the reader = host + // Outbound mailbox being read by the reader = system + MbxRead: begin + if (mbx_error_set_i) begin // Host asserts an error + ctrl_state_d = MbxError; + end else if (sysif_control_abort_set_i) begin // System wants to abort + ctrl_state_d = MbxSysAbortHost; + end else if (sys_read_all_i) begin + // Inbound and outbound mailbox go back to idle after all data has + // been read by the sys requester + ctrl_state_d = MbxIdle; + end end - end - - // Inbound mailbox being read by the reader = host - // Outbound mailbox being read by the reader = system - MbxRead: begin - if (mbx_error_set_i) begin // Host asserts an error - ctrl_state_d = MbxError; - end else if (sysif_control_abort_set_i) begin // System wants to abort - ctrl_state_d = MbxSysAbortHost; - end else if (sys_read_all_i) begin - // Inbound and outbound mailbox go back to idle after all data has - // been read by the sys requester - ctrl_state_d = MbxIdle; + + // Wait for the abort request to occur + MbxError: begin + if (sysif_control_abort_set_i) begin + ctrl_state_d = MbxSysAbortHost; + end end - end - // Wait for the abort request to occur - MbxError: begin - if (sysif_control_abort_set_i) begin - ctrl_state_d = MbxSysAbortHost; + MbxSysAbortHost: begin + // Wait for the host to acknowledge the abort; handled above. end - end - MbxSysAbortHost: begin - // Wait for the host to acknowledge the abort - if (hostif_abort_ack_i) begin - ctrl_state_d = MbxIdle; + default: begin + // Should not reach this + ctrl_state_d = MbxIdle; + mbx_state_error_o = 1'b1; end - end - - default: begin - // Should not reach this - ctrl_state_d = MbxIdle; - mbx_state_error_o = 1'b1; - end - endcase + endcase + end end endmodule From f6c2ef2d31bf619b4ea3c8391f45079471f26e94 Mon Sep 17 00:00:00 2001 From: Adrian Lees Date: Thu, 30 Nov 2023 20:57:37 +0000 Subject: [PATCH 68/88] [mbx] Reset request count when abort cleared. Abort clearing/FW-initiated reset must clear the count of outstanding requests to suppress delayed responses from propagating into the mailbox logic. Signed-off-by: Adrian Lees --- hw/ip/mbx/rtl/mbx_sramrwarb.sv | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hw/ip/mbx/rtl/mbx_sramrwarb.sv b/hw/ip/mbx/rtl/mbx_sramrwarb.sv index 2d116b25d93ef..7c94660d06cef 100644 --- a/hw/ip/mbx/rtl/mbx_sramrwarb.sv +++ b/hw/ip/mbx/rtl/mbx_sramrwarb.sv @@ -62,7 +62,7 @@ module mbx_sramrwarb // FIFO Counting logic for maximum outstanding requests logic [LCFG_MAX_REQS_LOG2-1:0] outstanding_req_count_d, outstanding_req_count_q; - logic inc_cnt, dec_cnt; + logic inc_cnt, dec_cnt, update_cnt; // Do we have knowledge of any outstanding requests, including one currently being accepted? // Note: a device may respond in the same cycle as accepting the request. @@ -77,13 +77,15 @@ module mbx_sramrwarb assign dec_cnt = sram_valid & any_outstanding_reqs; assign outstanding_req_count_d = hostif_control_abort_clear_i ? '0 : (outstanding_req_count_q + inc_cnt - dec_cnt); + // Update the count of outstanding requests. + assign update_cnt = inc_cnt | dec_cnt | hostif_control_abort_clear_i; prim_generic_flop_en #( .Width(LCFG_MAX_REQS_LOG2) ) u_outstanding_req_cnt ( .clk_i ( clk_i ), .rst_ni ( rst_ni ), - .en_i ( inc_cnt | dec_cnt ), + .en_i ( update_cnt ), .d_i ( outstanding_req_count_d ), .q_o ( outstanding_req_count_q ) ); From 1049ed1577e562e357d21e364070e7dc3dcacd87 Mon Sep 17 00:00:00 2001 From: Andreas Kurth Date: Tue, 5 Dec 2023 15:56:51 +0000 Subject: [PATCH 69/88] [mbx/dv] Create scaffold for testplan This ensures that all existing tests are mapped to a testpoint. Signed-off-by: Andreas Kurth --- hw/ip/mbx/data/mbx_testplan.hjson | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 hw/ip/mbx/data/mbx_testplan.hjson diff --git a/hw/ip/mbx/data/mbx_testplan.hjson b/hw/ip/mbx/data/mbx_testplan.hjson new file mode 100644 index 0000000000000..6062934ac078b --- /dev/null +++ b/hw/ip/mbx/data/mbx_testplan.hjson @@ -0,0 +1,30 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +{ + name: "mbx" + import_testplans: [ + hw/dv/tools/dvsim/testplans/alert_test_testplan.hjson + hw/dv/tools/dvsim/testplans/csr_testplan.hjson + hw/dv/tools/dvsim/testplans/intr_test_testplan.hjson + hw/dv/tools/dvsim/testplans/stress_all_with_reset_testplan.hjson + hw/dv/tools/dvsim/testplans/tl_device_access_types_testplan.hjson + mbx_sec_cm_testplan.hjson + ] + testpoints: [ + { name: mbx_smoke + desc: ''' + Smoke test + ''' + stage: V1 + tests: ["mbx_smoke"] + } + { name: mbx_stress + desc: ''' + Stress test + ''' + stage: V3 + tests: ["mbx_stress_all"] + } + ] +} From 168f0caa076a2d05b00eb56f4539b318d4863ca0 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Fri, 15 Dec 2023 11:12:53 +0500 Subject: [PATCH 70/88] [hw,mbx,rtl] Use the transition to the Read/Abort to generate the IRQ Instead of only using the next state signal of the FSM, we also take into account the current state, to compute the transition edge into the Read and Abort state, that generates the event for the IRQ primitive. Closes https://github.com/lowRISC/opentitan-integrated/issues/714 Signed-off-by: Robert Schilling --- hw/ip/mbx/rtl/mbx_fsm.sv | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/ip/mbx/rtl/mbx_fsm.sv b/hw/ip/mbx/rtl/mbx_fsm.sv index 53de33fa5cb6e..2d79e2ea0ada5 100644 --- a/hw/ip/mbx/rtl/mbx_fsm.sv +++ b/hw/ip/mbx/rtl/mbx_fsm.sv @@ -62,9 +62,9 @@ module mbx_fsm #( assign mbx_read_o = (ctrl_state_q == MbxRead); assign mbx_sys_abort_o = (ctrl_state_q == MbxSysAbortHost); // The transition to the abort state marks the abort interrupt generation - assign mbx_irq_abort_o = (ctrl_state_d == MbxSysAbortHost); + assign mbx_irq_abort_o = (ctrl_state_q != MbxSysAbortHost) && (ctrl_state_d == MbxSysAbortHost); // The transition to the read state marks the ready interrupt generation - assign mbx_irq_ready_o = (ctrl_state_d == MbxRead); + assign mbx_irq_ready_o = (ctrl_state_q != MbxRead) && (ctrl_state_d == MbxRead); logic ombx_set_ready, ombx_clear_ready; // Outbound mailbox is Ready, but only if not simultaneous with the exceptional conditions that From 6cd737cc2f30d4646ae2e6446f83bdd15687a7d6 Mon Sep 17 00:00:00 2001 From: Adrian Lees Date: Fri, 5 Jan 2024 17:18:36 +0000 Subject: [PATCH 71/88] [mbx] Limit addresses are inclusive Modify documentation to specify that the mailbox limit addresses are inclusive and indicate the final usable DWORD location. Update DIF address checks accordingly. Signed-off-by: Adrian Lees --- hw/ip/mbx/data/mbx.hjson | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/hw/ip/mbx/data/mbx.hjson b/hw/ip/mbx/data/mbx.hjson index 7618f75404a4a..ef63060293eb7 100644 --- a/hw/ip/mbx/data/mbx.hjson +++ b/hw/ip/mbx/data/mbx.hjson @@ -187,7 +187,7 @@ } { name: "INBOUND_BASE_ADDRESS" desc: '''Base address of SRAM region, which is used to back up the inbound mailbox data. - This address is 4-byte aligned, the lower 2-bits are ignored. + This address is 4-byte aligned, the lower 2 bits are ignored. ''' regwen: "ADDRESS_RANGE_REGWEN" swaccess: "rw" @@ -202,8 +202,9 @@ tags: ["excl:CsrAllTests:CsrExclAll"] // TODO(#477) } { name: "INBOUND_LIMIT_ADDRESS" - desc: '''Limit Address to mark the end of the inbound mailbox memory range in the private SRAM.. - This address is 4-byte aligned, the lower 2-bits are ignored. + desc: '''Inclusive end address of the inbound mailbox memory range in the private SRAM. + This address is 4-byte aligned and it specifies the start address of the final valid + DWORD location. The lower 2 bits are ignored. ''' regwen: "ADDRESS_RANGE_REGWEN" swaccess: "rw" @@ -219,7 +220,7 @@ } { name: "INBOUND_WRITE_PTR" desc: '''Write pointer for the next inbound data write. - This pointer is 4-byte aligned, the lower 2-bits are always zero. + This pointer is 4-byte aligned, the lower 2 bits are always zero. ''' hwext: "true" fields: [ @@ -235,7 +236,7 @@ } { name: "OUTBOUND_BASE_ADDRESS" desc: '''Base address of SRAM region, which is used to buffer the outbound mailbox data. - This address is 4-byte aligned, the lower 2-bits are ignored. + This address is 4-byte aligned, the lower 2 bits are ignored. ''' regwen: "ADDRESS_RANGE_REGWEN" swaccess: "rw" @@ -250,8 +251,9 @@ tags: ["excl:CsrAllTests:CsrExclAll"] // TODO(#477) } { name: "OUTBOUND_LIMIT_ADDRESS" - desc: '''Limit Address to mark the end of the outbound mailbox memory range in the private SRAM. - This address is 4-byte aligned, the lower 2-bits are ignored. + desc: '''Inclusive end address of the outbound mailbox memory range in the private SRAM. + This address is 4-byte aligned and it specifies the start address of the final valid + DWORD location. The lower 2 bits are ignored. ''' regwen: "ADDRESS_RANGE_REGWEN" swaccess: "rw" @@ -267,7 +269,7 @@ } { name: "OUTBOUND_READ_PTR" desc: '''Read pointer for the next outbound data read. - This pointer is 4-byte aligned, the lower 2-bits are always zero. + This pointer is 4-byte aligned, the lower 2 bits are always zero. ''' hwext: "true" fields: [ From 923e15cf4a1810628004588a662cca0a6653e69e Mon Sep 17 00:00:00 2001 From: Adrian Lees Date: Tue, 5 Dec 2023 14:06:46 +0000 Subject: [PATCH 72/88] [dv,mbx] Tidying, restructuring and minor fixes. Migrate code from smoke sequence into base sequence to form the basis of a test suite include stress sequences. Minor corrections. No significant impact upon current smoke sequence. Signed-off-by: Adrian Lees --- hw/ip/mbx/dv/env/mbx_env.core | 1 + hw/ip/mbx/dv/env/mbx_env_pkg.sv | 2 +- hw/ip/mbx/dv/env/mbx_scoreboard.sv | 15 +- hw/ip/mbx/dv/env/seq_lib/mbx_base_vseq.sv | 162 ++++++++++++++++++++- hw/ip/mbx/dv/env/seq_lib/mbx_smoke_vseq.sv | 159 +------------------- hw/ip/mbx/dv/tb.sv | 14 +- 6 files changed, 178 insertions(+), 175 deletions(-) diff --git a/hw/ip/mbx/dv/env/mbx_env.core b/hw/ip/mbx/dv/env/mbx_env.core index c430c74d7eccf..f723e1b6157bf 100644 --- a/hw/ip/mbx/dv/env/mbx_env.core +++ b/hw/ip/mbx/dv/env/mbx_env.core @@ -7,6 +7,7 @@ description: "MBX DV UVM environment" filesets: files_dv: depend: + - lowrisc:ip:mbx - lowrisc:dv:ralgen - lowrisc:dv:cip_lib files: diff --git a/hw/ip/mbx/dv/env/mbx_env_pkg.sv b/hw/ip/mbx/dv/env/mbx_env_pkg.sv index 21caf6ef4eef2..3ad69cb323df9 100644 --- a/hw/ip/mbx/dv/env/mbx_env_pkg.sv +++ b/hw/ip/mbx/dv/env/mbx_env_pkg.sv @@ -27,7 +27,7 @@ package mbx_env_pkg; parameter string LIST_OF_ALERTS[] = {"fatal_fault", "recov_fault"}; parameter int unsigned MBX_DV_DW_SIZE_BYTES = 4; - parameter int unsigned MBX_DV_MAX_DW = 1023; + parameter int unsigned MBX_DV_MAX_DW = 1024; // types typedef int unsigned uint_t; diff --git a/hw/ip/mbx/dv/env/mbx_scoreboard.sv b/hw/ip/mbx/dv/env/mbx_scoreboard.sv index 7dae373c49a8e..3d2abf118822e 100644 --- a/hw/ip/mbx/dv/env/mbx_scoreboard.sv +++ b/hw/ip/mbx/dv/env/mbx_scoreboard.sv @@ -47,9 +47,6 @@ class mbx_scoreboard extends cip_base_scoreboard #( // `DV_CHECK_CASE_EQ(exp_mbx_core_irq, cfg.intr_vif.pins, "Default state of interrupt pin is 0") forever begin @(cfg.intr_vif.pins); - //Adjusting the clk delay before running the check - //TLUL Write completion is taking 5-6 cyles - cfg.clk_rst_vif.wait_n_clks(12); `uvm_info(`gfn, $sformatf("Change in interrupt pin('b%b)", cfg.intr_vif.pins), UVM_LOW) `DV_CHECK_CASE_EQ(exp_mbx_core_irq, cfg.intr_vif.pins[MbxCoreReady], "Exp. interrupt doesn't match actual") @@ -85,7 +82,7 @@ class mbx_scoreboard extends cip_base_scoreboard #( task run_phase(uvm_phase phase); super.run_phase(phase); `downcast(m_mbx_soc_ral, cfg.ral_models[cfg.mbx_soc_ral_name]) - // TODO: Renable interrupt checking once scoreboard is fully functional + // TODO: Re-enable interrupt checking once scoreboard is fully functional //fork // monitor_core_interrupt(); // monitor_exp_core_interrupts(); @@ -111,8 +108,10 @@ class mbx_scoreboard extends cip_base_scoreboard #( `DV_CHECK_NE_FATAL(csr, null) end else begin - // `uvm_fatal(`gfn, $sformatf("Access unexpected addr 0x%0h", csr_addr)) -return; + // TODO: this does not yet cope with the fact that WDATA and RDATA accesses do not produce + // a hit in the above test, since they are not CSRs + // `uvm_fatal(`gfn, $sformatf("Access unexpected addr 0x%0h", csr_addr)) + return; end // if incoming access is a write to a valid csr, then make updates right away @@ -189,7 +188,7 @@ return; end end -// TODO: AML +// TODO: The scoreboard needs updating and completing. return; // process the csr req @@ -260,7 +259,7 @@ return; "outbound_read_ptr" : begin if(addr_phase_write) begin m_obmbx_ptr_q[0] = item.a_data; - m_obmbx_ptr = item.a_data; + m_obmbx_ptr = item.a_data; end if(addr_phase_read) begin void'(ral.outbound_read_ptr.predict( diff --git a/hw/ip/mbx/dv/env/seq_lib/mbx_base_vseq.sv b/hw/ip/mbx/dv/env/seq_lib/mbx_base_vseq.sv index 3e7a0ff2d035c..c8625056dc5cb 100644 --- a/hw/ip/mbx/dv/env/seq_lib/mbx_base_vseq.sv +++ b/hw/ip/mbx/dv/env/seq_lib/mbx_base_vseq.sv @@ -9,7 +9,6 @@ class mbx_base_vseq extends cip_base_vseq #( .VIRTUAL_SEQUENCER_T (mbx_virtual_sequencer) ); - bit do_mbx_init = 1'b1; mem_model seq_mem_model; rand bit [top_pkg::TL_AW-1:0] ibmbx_base_addr; rand bit [top_pkg::TL_AW-1:0] ibmbx_limit_addr; @@ -62,9 +61,6 @@ class mbx_base_vseq extends cip_base_vseq #( virtual task dut_init(string reset_kind = "HARD"); super.dut_init(); - if (do_mbx_init == 1'b1) begin - mbx_init(); - end endtask: dut_init virtual task start_device_seq(); @@ -158,7 +154,161 @@ class mbx_base_vseq extends cip_base_vseq #( virtual task body(); `uvm_info(get_full_name(), "body -- Start", UVM_DEBUG) start_device_seq(); + begin + + // TODO: move to package if we decide to keep this. + typedef bit [31:0] mbx_dword_t; + + bit [top_pkg::TL_AW-1:0] rd_data; + bit [top_pkg::TL_AW-1:0] wr_data; + int unsigned req_size_limit; + int unsigned rsp_size_limit; + int unsigned req_size; + int unsigned rsp_size; + bit [31:0] req[$]; + bit [31:0] rsp[$]; + mbx_dword_t qd; + // TODO: perhaps we should change read_mem/write_mem to avoid issues. The mailbox operates only + // on DWORD quantities. + // mbx_dword_t q[$]; + byte q[$]; + + // TODO: move to appropriate location; package? + int unsigned MBX_SOC_WDATA_BASE = 'h10; + int unsigned MBX_SOC_RDATA_BASE = 'h14; + + // TODO: gross change to prevent explosions on accessing RDATA, since it does not behave like + // a regular memory + cfg.en_scb_mem_chk = 1'b0; + + mbx_init(); + + // Ensure that we have a valid memory range + csr_wr(ral.address_range_valid, 1'b1); + // Enable core ready interrupt + cfg_interrupts(1 << MbxCoreReady); + + // Data from R-code to ROT + + // Without PR#321 there was an issue in the RTL that the Busy bit is not deasserted when the + // address range becomes valid. + if (1'b1) begin + // Check for Busy bit being clear before we can write to WDATA. + rd_data = '0; + rd_data[0] = 1'b1; + while(rd_data[0] == 1'b1) begin + csr_rd(m_mbx_soc_ral.soc_status, rd_data); + `uvm_info(`gfn, + $sformatf("checking for busy bit, rd_data for soc_status is :'h%0h", rd_data), UVM_DEBUG) + end + end + + // Request and response sizes, in DWORDs + // Note: limit addresses are inclusive, and we want each message to be at least one DWORD long. + req_size_limit = (ibmbx_limit_addr - ibmbx_base_addr) >> 2; + rsp_size_limit = (obmbx_limit_addr - obmbx_base_addr) >> 2; + // TODO: Could perhaps do this with the base/limit constraints; after all the physical memory + // is going to be limited. + // TODO: Are there penalties involved in having a memory model with a ridiculous address range, + // or is it sparse? + if (req_size_limit >= 'h400) + req_size_limit = 'h400; + if (rsp_size_limit >= 'h400) + rsp_size_limit = 'h400; + // There's a further constraint on the number of DWORDs in the Response Object + if (rsp_size_limit > MBX_DV_MAX_DW) + rsp_size_limit = MBX_DV_MAX_DW; + + req_size = 1 + ($urandom % (1 + req_size_limit)); + rsp_size = 1 + ($urandom % (1 + rsp_size_limit)); + + `uvm_info(`gfn, + $sformatf("Request size %x DWORD(s), Response size %x DWORD(s)", req_size, rsp_size), UVM_LOW) + `uvm_info(`gfn, + $sformatf("Inbox should use [%x,%x)", ibmbx_base_addr, ibmbx_base_addr + req_size * 4), + UVM_LOW) + `uvm_info(`gfn, + $sformatf("Outbox should use [%x,%x)", obmbx_base_addr, obmbx_base_addr + rsp_size * 4), + UVM_LOW) + + for(int unsigned ii = 0; ii < req_size; ii++) begin + wr_data = $urandom(); + req.push_back(wr_data); + tl_access(.addr(m_mbx_soc_ral.get_addr_from_offset(MBX_SOC_WDATA_BASE)), + .write(1'b1), .data(wr_data), .mask(4'hF), .blocking(1), + .tl_sequencer_h(p_sequencer.tl_sequencer_hs[cfg.mbx_soc_ral_name])); + end + + // Note: we need only set bits 31 and 1 (Go, dot_intr_en) here, no need to read. + // csr_rd(m_mbx_soc_ral.soc_control, rd_data); + // rd_data[31] = 1'b1; + rd_data = 32'h8000_0002; + `uvm_info(`gfn, "Doing soc_control csr wr", UVM_LOW) + clear_all_interrupts(); + csr_wr(m_mbx_soc_ral.soc_control, rd_data); + + wait_for_core_interrupt(); + clear_all_interrupts(); + + // Collect the request message from the OT mailbox memory + read_mem(ibmbx_base_addr, req_size << 2, q); + + for(int unsigned ii = 0; ii < req_size; ii++) begin + qd = {q[ii*4+3],q[ii*4+2],q[ii*4+1],q[ii*4]}; + `uvm_info(`gfn, $sformatf("Expected %0h got %0h", req[ii], qd), UVM_LOW) + if (qd !== req[ii]) begin + `uvm_error(`gfn, $sformatf("q[%0d]('h%0h) != req[%0d]('h%0h)", ii, qd, ii, req[ii])) + end + end + + // Data from ROT to R-code + q.delete(); + for(int unsigned ii = 0 ; ii < rsp_size*4; ii++) begin + q.push_back($urandom); + end + write_mem(obmbx_base_addr, q); + csr_wr(ral.outbound_object_size, rsp_size); + + wait_for_soc_interrupt(); + csr_rd(m_mbx_soc_ral.soc_status, rd_data); + `DV_CHECK_EQ(rd_data[31], 1'b1, "soc_status ready bit not set after soc interrupt seen") + clear_all_interrupts(); + + // Collect the entire message before checking it. + // Note: this may not be the best approach unless we can time out in the event of a lock up + // in the provision of new RDATA values. + for(int unsigned ii = 0; ii < rsp_size; ii++) begin + // Read from RDATA to collect the next message word + tl_access(.addr(cfg.ral.get_addr_from_offset(MBX_SOC_RDATA_BASE)), + .write(1'b0), .data(rd_data), .mask(4'hF), .compare_mask(0), .blocking(1), + .tl_sequencer_h(p_sequencer.tl_sequencer_hs[cfg.mbx_soc_ral_name])); + + `uvm_info(get_full_name(), $sformatf("Mailbox read data is : 'h%0h", rd_data), UVM_LOW) + + rsp.push_back(rd_data); + + // Write anything to RDATA to advance to the next word. + wr_data = $urandom; + tl_access(.addr(cfg.ral.get_addr_from_offset(MBX_SOC_RDATA_BASE)), + .write(1'b1), .data(wr_data), .mask(4'hF), .blocking(1), + .tl_sequencer_h(p_sequencer.tl_sequencer_hs[cfg.mbx_soc_ral_name])); + end + + for(int unsigned ii = 0; ii < rsp_size; ii++) begin + qd = {q[ii*4+3],q[ii*4+2],q[ii*4+1],q[ii*4]}; + `uvm_info(`gfn, $sformatf("Expected %0h got %0h", qd, rsp[ii]), UVM_LOW) + if (qd !== rsp[ii]) begin + `uvm_error(get_full_name(), + $sformatf(" q[%0d]('h%0h) != rsp[%0d]('h%0h)", ii, qd, ii, rsp[ii])) + end + end + + csr_rd(m_mbx_soc_ral.soc_status, rd_data); + `DV_CHECK_EQ(rd_data[31], 1'b0, "Ready bit still set") + `uvm_info(get_full_name(), "body -- End", UVM_DEBUG) - endtask: body -endclass: mbx_base_vseq + end + endtask : body + +endclass : mbx_base_vseq diff --git a/hw/ip/mbx/dv/env/seq_lib/mbx_smoke_vseq.sv b/hw/ip/mbx/dv/env/seq_lib/mbx_smoke_vseq.sv index a82dd6c969123..a9e2d59ef61a4 100644 --- a/hw/ip/mbx/dv/env/seq_lib/mbx_smoke_vseq.sv +++ b/hw/ip/mbx/dv/env/seq_lib/mbx_smoke_vseq.sv @@ -8,161 +8,12 @@ class mbx_smoke_vseq extends mbx_base_vseq; function new(string name = "mbx_smoke_vseq"); super.new(name); - endfunction: new + endfunction : new virtual task body(); - // TODO: move to package if we decide to keep this. - typedef bit [31:0] mbx_dword_t; - - bit [top_pkg::TL_AW-1:0] rd_data; - bit [top_pkg::TL_AW-1:0] wr_data; - int unsigned req_size_limit; - int unsigned rsp_size_limit; - int unsigned req_size; - int unsigned rsp_size; - bit [31:0] req[$]; - bit [31:0] rsp[$]; - mbx_dword_t qd; - // TODO: perhaps we should change read_mem/write_mem to avoid issues. The mailbox operates only - // on DWORD quantities. - // mbx_dword_t q[$]; - byte q[$]; - - // TODO: move to appropriate location; package? - int unsigned MBX_SOC_WDATA_BASE = 'h10; - int unsigned MBX_SOC_RDATA_BASE = 'h14; - - // TODO: gross change to prevent explosions on accessing RDATA, since it does not behave like - // a regular memory - cfg.en_scb_mem_chk = 1'b0; - - `uvm_info(get_full_name(), "body -- Start", UVM_DEBUG) + `uvm_info(get_full_name(), "body -- smoke test -- Start", UVM_DEBUG) super.body(); + `uvm_info(get_full_name(), "body -- smoke test -- End", UVM_DEBUG) + endtask : body - // Ensure that we have a valid memory range - csr_wr(ral.address_range_valid, 1'b1); - // Enable core ready interrupt - cfg_interrupts(1 << MbxCoreReady); - - // Data from R-code to ROT - - // Without PR#321 there was an issue in the RTL that the Busy bit is not deasserted when the - // address range becomes valid. - if (1'b1) begin - // Check for Busy bit being clear before we can write to WDATA. - rd_data = '0; - rd_data[0] = 1'b1; - while(rd_data[0] == 1'b1) begin - csr_rd(m_mbx_soc_ral.soc_status, rd_data); - `uvm_info(`gfn, - $sformatf("checking for busy bit, rd_data for soc_status is :'h%0h", rd_data), UVM_DEBUG) - end - end - - // Request and response sizes, in DWORDs - // Note: limit addresses are inclusive, and we want each message to be at least one DWORD long. - req_size_limit = (ibmbx_limit_addr - ibmbx_base_addr) >> 2; - rsp_size_limit = (obmbx_limit_addr - obmbx_base_addr) >> 2; - // TODO: Could perhaps do this with the base/limit constraints; after all the physical memory - // is going to be limited. - // TODO: Are there penalties involved in having a memory model with a ridiculous address range, - // or is it sparse? - if (req_size_limit >= 'h400) - req_size_limit = 'h400; - if (rsp_size_limit >= 'h400) - rsp_size_limit = 'h400; - // There's a further constraint on the number of DWORDs in the Response Object - if (rsp_size_limit > MBX_DV_MAX_DW) - rsp_size_limit = MBX_DV_MAX_DW; - - req_size = 1 + ($urandom % (1 + req_size_limit)); - rsp_size = 1 + ($urandom % (1 + rsp_size_limit)); - - `uvm_info(`gfn, - $sformatf("Request size %x DWORD(s), Response size %x DWORD(s)", req_size, rsp_size), UVM_LOW) - `uvm_info(`gfn, - $sformatf("Inbox should use [%x,%x)", ibmbx_base_addr, ibmbx_base_addr + req_size * 4), - UVM_LOW) - `uvm_info(`gfn, - $sformatf("Outbox should use [%x,%x)", obmbx_base_addr, obmbx_base_addr + rsp_size * 4), - UVM_LOW) - - for(int unsigned ii = 0; ii < req_size; ii++) begin - wr_data = $urandom(); - req.push_back(wr_data); - tl_access(.addr(m_mbx_soc_ral.get_addr_from_offset(MBX_SOC_WDATA_BASE)), - .write(1'b1), .data(wr_data), .mask(4'hF), .blocking(1), - .tl_sequencer_h(p_sequencer.tl_sequencer_hs[cfg.mbx_soc_ral_name])); - end - - // Note: we need only set bits 31 and 1 (Go, dot_intr_en) here, no need to read. - // csr_rd(m_mbx_soc_ral.soc_control, rd_data); - // rd_data[31] = 1'b1; - rd_data = 32'h8000_0002; - `uvm_info(`gfn, "Doing soc_control csr wr", UVM_LOW) - clear_all_interrupts(); - csr_wr(m_mbx_soc_ral.soc_control, rd_data); - - wait_for_core_interrupt(); - clear_all_interrupts(); - - // Collect the request message from the OT mailbox memory - read_mem(ibmbx_base_addr, req_size << 2, q); - - for(int unsigned ii = 0; ii < req_size; ii++) begin - qd = {q[ii*4+3],q[ii*4+2],q[ii*4+1],q[ii*4]}; - `uvm_info(`gfn, $sformatf("Expected %0h got %0h", req[ii], qd), UVM_LOW) - if (qd !== req[ii]) begin - `uvm_error(`gfn, $sformatf("q[%0d]('h%0h) != req[%0d]('h%0h)", ii, qd, ii, req[ii])) - end - end - - // Data from ROT to R-code - q.delete(); - for(int unsigned ii = 0 ; ii < rsp_size*4; ii++) begin - q.push_back($urandom); - end - write_mem(obmbx_base_addr, q); - csr_wr(ral.outbound_object_size, rsp_size); - - wait_for_soc_interrupt(); - csr_rd(m_mbx_soc_ral.soc_status, rd_data); - `DV_CHECK_EQ(rd_data[31], 1'b1, "soc_status ready bit not set after soc interrupt seen") - clear_all_interrupts(); - - // Collect the entire message before checking it. - // Note: this may not be the best approach unless we can time out in the event of a lock up - // in the provision of new RDATA values. - for(int unsigned ii = 0; ii < rsp_size; ii++) begin - // Read from RDATA to collect the next message word - tl_access(.addr(cfg.ral.get_addr_from_offset(MBX_SOC_RDATA_BASE)), - .write(1'b0), .data(rd_data), .mask(4'hF), .compare_mask(0), .blocking(1), - .tl_sequencer_h(p_sequencer.tl_sequencer_hs[cfg.mbx_soc_ral_name])); - - `uvm_info(get_full_name(), $sformatf("Mailbox read data is : 'h%0h", rd_data), UVM_LOW) - - rsp.push_back(rd_data); - - // Write anything to RDATA to advance to the next word. - wr_data = $urandom; - tl_access(.addr(cfg.ral.get_addr_from_offset(MBX_SOC_RDATA_BASE)), - .write(1'b1), .data(wr_data), .mask(4'hF), .blocking(1), - .tl_sequencer_h(p_sequencer.tl_sequencer_hs[cfg.mbx_soc_ral_name])); - end - - for(int unsigned ii = 0; ii < rsp_size; ii++) begin - qd = {q[ii*4+3],q[ii*4+2],q[ii*4+1],q[ii*4]}; - `uvm_info(`gfn, $sformatf("Expected %0h got %0h", qd, rsp[ii]), UVM_LOW) - if (qd !== rsp[ii]) begin - `uvm_error(get_full_name(), - $sformatf(" q[%0d]('h%0h) != rsp[%0d]('h%0h)", ii, qd, ii, rsp[ii])) - end - end - - csr_rd(m_mbx_soc_ral.soc_status, rd_data); - `DV_CHECK_EQ(rd_data[31], 1'b0, "Ready bit still set") - - `uvm_info(get_full_name(), "body -- End", UVM_DEBUG) - endtask: body - -endclass: mbx_smoke_vseq +endclass : mbx_smoke_vseq diff --git a/hw/ip/mbx/dv/tb.sv b/hw/ip/mbx/dv/tb.sv index 0e65d7fd7f28d..4ca890df3bfdd 100644 --- a/hw/ip/mbx/dv/tb.sv +++ b/hw/ip/mbx/dv/tb.sv @@ -72,12 +72,14 @@ module tb; uvm_config_db#(virtual tl_if)::set( null, "*.env.m_tl_agent_mbx_soc_reg_block*", "vif", i_tl_scxb_mbx_core_if); - uvm_config_db#(virtual tl_if)::set( - null, "*.env.m_tl_agent_mbxuarch_reg_block*", "vif", - i_tl_agxb_mbx_core_if); - uvm_config_db#(virtual tl_if)::set( - null, "*.env.m_tl_agent_mbx_reg_block*", "vif", - i_tl_scxb_mbx_core_if); + +// uvm_config_db#(virtual tl_if)::set( +// null, "*.env.m_tl_agent_mbxuarch_reg_block*", "vif", +// i_tl_agxb_mbx_core_if); +// uvm_config_db#(virtual tl_if)::set( +// null, "*.env.m_tl_agent_mbx_reg_block*", "vif", +// i_tl_scxb_mbx_core_if); + uvm_config_db#(virtual tl_if)::set( null, "*.env.m_tl_agent_mbx_mem_reg_block*", "vif", i_tl_mbx_agxb_device_if); From 64e663db1de3cb83a633e2a7fb4bf7206a1f2d1c Mon Sep 17 00:00:00 2001 From: Adrian Lees Date: Tue, 5 Dec 2023 14:46:54 +0000 Subject: [PATCH 73/88] [dv,mbx] Extended smoke sequence Introduce constrained, randomized sequence item that describes a request and response communication. Multiple back-to-back transactions between IP block resets. Multiple iterations, separated by IP block resets. Signed-off-by: Adrian Lees --- hw/ip/mbx/dv/env/mbx_env.core | 1 + hw/ip/mbx/dv/env/mbx_env_cfg.sv | 2 - hw/ip/mbx/dv/env/mbx_env_pkg.sv | 10 +- hw/ip/mbx/dv/env/mbx_seq_item.sv | 86 +++++ hw/ip/mbx/dv/env/seq_lib/mbx_base_vseq.sv | 412 ++++++++++++--------- hw/ip/mbx/dv/env/seq_lib/mbx_smoke_vseq.sv | 5 + 6 files changed, 334 insertions(+), 182 deletions(-) create mode 100644 hw/ip/mbx/dv/env/mbx_seq_item.sv diff --git a/hw/ip/mbx/dv/env/mbx_env.core b/hw/ip/mbx/dv/env/mbx_env.core index f723e1b6157bf..aa92349fe8ce3 100644 --- a/hw/ip/mbx/dv/env/mbx_env.core +++ b/hw/ip/mbx/dv/env/mbx_env.core @@ -16,6 +16,7 @@ filesets: - mbx_env_cfg.sv: {is_include_file: true} - mbx_env_cov.sv: {is_include_file: true} - mbx_virtual_sequencer.sv: {is_include_file: true} + - mbx_seq_item.sv: {is_include_file: true} - mbx_scoreboard.sv: {is_include_file: true} - mbx_env.sv: {is_include_file: true} - seq_lib/mbx_tl_reg_seq.sv: {is_include_file: true} diff --git a/hw/ip/mbx/dv/env/mbx_env_cfg.sv b/hw/ip/mbx/dv/env/mbx_env_cfg.sv index 22713c48f3d87..07020d2d88e44 100644 --- a/hw/ip/mbx/dv/env/mbx_env_cfg.sv +++ b/hw/ip/mbx/dv/env/mbx_env_cfg.sv @@ -5,8 +5,6 @@ class mbx_env_cfg extends cip_base_env_cfg #( .RAL_T(mbx_core_reg_block) ); - import dv_utils_pkg::*; - string mbx_mem_ral_name = "mbx_mem_reg_block"; string mbx_soc_ral_name = "mbx_soc_reg_block"; diff --git a/hw/ip/mbx/dv/env/mbx_env_pkg.sv b/hw/ip/mbx/dv/env/mbx_env_pkg.sv index 3ad69cb323df9..14d91f0a9c073 100644 --- a/hw/ip/mbx/dv/env/mbx_env_pkg.sv +++ b/hw/ip/mbx/dv/env/mbx_env_pkg.sv @@ -9,6 +9,7 @@ package mbx_env_pkg; import dv_utils_pkg::*; import dv_lib_pkg::*; import dv_base_reg_pkg::*; + import prim_mubi_pkg::*; import mbx_core_ral_pkg::*; import mbx_soc_ral_pkg::*; import mbx_mem_ral_pkg::*; @@ -29,7 +30,14 @@ package mbx_env_pkg; parameter int unsigned MBX_DV_DW_SIZE_BYTES = 4; parameter int unsigned MBX_DV_MAX_DW = 1024; - // types + // Addresses used by the mailbox DUT. + typedef bit [top_pkg::TL_AW-1:0] mbx_addr_t; + // Mailbox specification is in terms of 32-bit DWORDs. + typedef bit [31:0] mbx_dword_t; + + `include "mbx_seq_item.sv" + + typedef int unsigned uint_t; typedef enum bit { READ = 0, diff --git a/hw/ip/mbx/dv/env/mbx_seq_item.sv b/hw/ip/mbx/dv/env/mbx_seq_item.sv new file mode 100644 index 0000000000000..e584dd9e4a7d3 --- /dev/null +++ b/hw/ip/mbx/dv/env/mbx_seq_item.sv @@ -0,0 +1,86 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +class mbx_seq_item extends uvm_sequence_item; + + rand bit [top_pkg::TL_AW-1:0] ibmbx_base_addr; + rand bit [top_pkg::TL_AW-1:0] ibmbx_limit_addr; + rand bit [top_pkg::TL_AW-1:0] obmbx_base_addr; + rand bit [top_pkg::TL_AW-1:0] obmbx_limit_addr; + + rand bit address_range_valid; + rand mubi4_t address_range_regwen; + + // Sizes of Request and Response message in DWORDs + rand bit [10:0] request_dwords; + rand bit [10:0] response_dwords; + + `uvm_object_utils_begin(mbx_seq_item) + `uvm_field_int(ibmbx_base_addr, UVM_DEFAULT) + `uvm_field_int(ibmbx_limit_addr, UVM_DEFAULT) + `uvm_field_int(obmbx_base_addr, UVM_DEFAULT) + `uvm_field_int(obmbx_limit_addr, UVM_DEFAULT) + `uvm_field_int(address_range_valid, UVM_DEFAULT) + `uvm_field_enum(mubi4_t, address_range_regwen, UVM_DEFAULT) + `uvm_field_int(request_dwords, UVM_DEFAULT) + `uvm_field_int(response_dwords, UVM_DEFAULT) + `uvm_object_utils_end + + // Constructor: new + function new(string name = ""); + super.new(name); + endfunction : new + + function void set_address_range_randomization(bit enabled); + ibmbx_base_addr.rand_mode(enabled); + ibmbx_limit_addr.rand_mode(enabled); + obmbx_base_addr.rand_mode(enabled); + obmbx_limit_addr.rand_mode(enabled); + endfunction + + constraint legal_ibmbx_addr_range_c { + // TODO: Should have a full 32-bit address space! + (ibmbx_limit_addr < 32'h4000_0000); + + (ibmbx_limit_addr >= ibmbx_base_addr); + // Ensure that the allocated address range is large enough for all valid messages because + // otherwise we run the risk of making all subsequent response messages artificially small + // because the address range has been locked. + ((ibmbx_limit_addr - ibmbx_base_addr) / 4 >= MBX_DV_MAX_DW); + } + + constraint legal_obmbx_addr_range_c { + // TODO: Should have a full 32-bit address space! + (obmbx_limit_addr < 32'h4000_0000); + + (obmbx_limit_addr >= obmbx_base_addr); + } + + constraint legal_address_range_valid_c { + // TODO: presently we are concerned only with generating valid hardware configurations. + address_range_valid == 1'b1; + } + + constraint legal_request_dwords_c { + request_dwords > 0 && request_dwords < 'h400; + } + + constraint legal_response_dwords_c { + // There is an additioanl constraint upon the length of the Response because the register + // OUTBOUND_OBJECT_SIZE is limited. + response_dwords > 0 && response_dwords <= MBX_DV_MAX_DW; + } + + constraint legal_non_overlapping_region_c { + ibmbx_limit_addr < obmbx_base_addr || ibmbx_base_addr > obmbx_limit_addr; + } + + constraint legal_addr_alignment_c { + (ibmbx_base_addr[1:0] == 0); + (ibmbx_limit_addr[1:0] == 0); + (obmbx_base_addr[1:0] == 0); + (obmbx_limit_addr[1:0] == 0); + } + +endclass : mbx_seq_item diff --git a/hw/ip/mbx/dv/env/seq_lib/mbx_base_vseq.sv b/hw/ip/mbx/dv/env/seq_lib/mbx_base_vseq.sv index c8625056dc5cb..9d31cc34f264d 100644 --- a/hw/ip/mbx/dv/env/seq_lib/mbx_base_vseq.sv +++ b/hw/ip/mbx/dv/env/seq_lib/mbx_base_vseq.sv @@ -9,48 +9,33 @@ class mbx_base_vseq extends cip_base_vseq #( .VIRTUAL_SEQUENCER_T (mbx_virtual_sequencer) ); + `uvm_object_utils(mbx_base_vseq) + + string mbx_mem_ral_name = "mbx_mem_reg_block"; + string mbx_soc_ral_name = "mbx_soc_reg_block"; + + // Number of iterations + rand int unsigned num_iters; + // Number of transactions (message transfers within an iteration without an= + // intervening DUT reset) + rand int unsigned num_txns; + mem_model seq_mem_model; - rand bit [top_pkg::TL_AW-1:0] ibmbx_base_addr; - rand bit [top_pkg::TL_AW-1:0] ibmbx_limit_addr; - rand bit [top_pkg::TL_AW-1:0] obmbx_base_addr; - rand bit [top_pkg::TL_AW-1:0] obmbx_limit_addr; + + mbx_tl_device_seq seq_h; mbx_mem_reg_block m_mbx_mem_ral; mbx_soc_reg_block m_mbx_soc_ral; - `uvm_object_utils(mbx_base_vseq) + mbx_seq_item mbx_config; - constraint ib_ob_addr_range_c { - (ibmbx_base_addr inside - {[m_mbx_mem_ral.mem_ranges[0].start_addr : m_mbx_mem_ral.mem_ranges[0].end_addr]}); - (ibmbx_limit_addr inside - {[m_mbx_mem_ral.mem_ranges[0].start_addr : m_mbx_mem_ral.mem_ranges[0].end_addr]}); - (obmbx_base_addr inside - {[m_mbx_mem_ral.mem_ranges[0].start_addr : m_mbx_mem_ral.mem_ranges[0].end_addr]}); - (obmbx_limit_addr inside - {[m_mbx_mem_ral.mem_ranges[0].start_addr : m_mbx_mem_ral.mem_ranges[0].end_addr]}); - } - - constraint legal_addr_range_c { - (ibmbx_limit_addr > ibmbx_base_addr); - ((obmbx_limit_addr - obmbx_base_addr) == (MBX_DV_DW_SIZE_BYTES * MBX_DV_MAX_DW)); - } - - constraint legal_non_overlapping_region_c { - unique {ibmbx_base_addr, ibmbx_limit_addr, obmbx_base_addr, obmbx_limit_addr}; - } - - constraint legal_addr_alignment_c { - (ibmbx_base_addr[1:0] == 0); - (ibmbx_limit_addr[1:0] == 0); - (obmbx_base_addr[1:0] == 0); - (obmbx_limit_addr[1:0] == 0); - } + // Number of words of memory available to the mailbox(es) + int unsigned mbx_mem_words = 'h400; function new(string name = ""); super.new(); + mbx_config = mbx_seq_item::type_id::create("mbx_config"); seq_mem_model = mem_model#()::type_id::create("seq_mem_model"); - seq_mem_model.init(); endfunction: new function void pre_randomize(); @@ -59,13 +44,16 @@ class mbx_base_vseq extends cip_base_vseq #( `downcast(m_mbx_mem_ral, cfg.ral_models[cfg.mbx_mem_ral_name]) endfunction: pre_randomize + // Task: Simulate a clock delay + virtual task delay(int num = 1); + cfg.clk_rst_vif.wait_clks(num); + endtask : delay + virtual task dut_init(string reset_kind = "HARD"); super.dut_init(); endtask: dut_init virtual task start_device_seq(); - mbx_tl_device_seq seq_h; - seq_h = mbx_tl_device_seq::type_id::create("seq_h"); seq_h.mem = seq_mem_model; fork @@ -73,6 +61,32 @@ class mbx_base_vseq extends cip_base_vseq #( join_none endtask: start_device_seq + virtual task set_mem_range_regwen(mubi4_t regwen); + `uvm_info(`gfn, $sformatf("Setting memory range regwen to 0x%x", regwen), UVM_LOW) + + ral.address_range_regwen.regwen.set(int'(regwen)); + csr_update(ral.address_range_regwen); + endtask + + virtual task set_address_range(mbx_addr_t ibmbx_base_addr, mbx_addr_t ibmbx_limit_addr, + mbx_addr_t obmbx_base_addr, mbx_addr_t obmbx_limit_addr, + bit range_valid, mubi4_t regwen); + // Program the memory address ranges into the configuration registers + csr_wr(ral.inbound_base_address, ibmbx_base_addr); + csr_wr(ral.inbound_limit_address, ibmbx_limit_addr); + csr_wr(ral.outbound_base_address, obmbx_base_addr); + csr_wr(ral.outbound_limit_address, obmbx_limit_addr); + // Specify whether a valid range has been supplied + csr_wr(ral.address_range_valid, range_valid); + // Set the lock as requested + set_mem_range_regwen(regwen); + endtask + + virtual task clear_mem(); + `uvm_info(`gfn, "Clearing memory", UVM_DEBUG) + seq_mem_model.init(); + endtask + virtual task write_mem(int start_addr, byte q[$]); `uvm_info(get_full_name(), $sformatf("write_mem(start_addr='h%0h, q=%p) -- Start", start_addr, q), @@ -104,12 +118,9 @@ class mbx_base_vseq extends cip_base_vseq #( `uvm_info(get_full_name(), $sformatf("mbx_init -- Start"), UVM_DEBUG) - csr_wr(ral.inbound_base_address, ibmbx_base_addr); - csr_wr(ral.inbound_limit_address, ibmbx_limit_addr); - csr_wr(ral.outbound_base_address, obmbx_base_addr); - csr_wr(ral.outbound_limit_address, obmbx_limit_addr); - csr_wr(ral.outbound_object_size, 0); - csr_wr(ral.control, 0); + + `DV_CHECK_RANDOMIZE_FATAL(mbx_config) + `uvm_info(get_full_name(), $sformatf("mbx_init -- End"), UVM_DEBUG) @@ -154,161 +165,204 @@ class mbx_base_vseq extends cip_base_vseq #( virtual task body(); `uvm_info(get_full_name(), "body -- Start", UVM_DEBUG) start_device_seq(); - begin - - // TODO: move to package if we decide to keep this. - typedef bit [31:0] mbx_dword_t; - - bit [top_pkg::TL_AW-1:0] rd_data; - bit [top_pkg::TL_AW-1:0] wr_data; - int unsigned req_size_limit; - int unsigned rsp_size_limit; - int unsigned req_size; - int unsigned rsp_size; - bit [31:0] req[$]; - bit [31:0] rsp[$]; - mbx_dword_t qd; - // TODO: perhaps we should change read_mem/write_mem to avoid issues. The mailbox operates only - // on DWORD quantities. - // mbx_dword_t q[$]; - byte q[$]; - - // TODO: move to appropriate location; package? - int unsigned MBX_SOC_WDATA_BASE = 'h10; - int unsigned MBX_SOC_RDATA_BASE = 'h14; // TODO: gross change to prevent explosions on accessing RDATA, since it does not behave like // a regular memory cfg.en_scb_mem_chk = 1'b0; - mbx_init(); + for (int unsigned iter = 0; iter < num_iters; iter++) begin + `uvm_info(`gfn, $sformatf("Starting iteration %d of %d", iter + 1, num_iters), UVM_LOW) + + // Since the DUT has just been reset, we should take the opportunity to choose new memory + // addresses. + mbx_config.set_address_range_randomization(1'b1); + + // Initialize mailbox with randomized memory configuration. + mbx_init(); + + for (int unsigned txn = 0; txn < num_txns; txn++) begin + bit [top_pkg::TL_DW-1:0] rd_data; + bit [top_pkg::TL_DW-1:0] wr_data; + bit intr_driven = 1'b1; // TODO: support either CSR or interrupts. + bit check_request = 1'b0; + bit send_response = 1'b0; + int unsigned req_size_limit; + int unsigned rsp_size_limit; + int unsigned req_size; + int unsigned rsp_size; + mbx_dword_t req[$]; + mbx_dword_t rsp[$]; + mbx_dword_t qd; + bit obs_ready; + bit obs_error; + bit obs_busy; + // TODO: whether to perform RDATA write accesses as blocking operations. + bit rdata_wr_blocking = 1'b1; + + // TODO: perhaps we should change read_mem/write_mem to avoid issues. + // The mailbox operates only on DWORD quantities. + // mbx_dword_t q[$]; + byte q[$]; + + // Empty the mailbox memory model of any previous contents. + clear_mem(); + + `uvm_info(`gfn, $sformatf("Starting transaction %d of %d", txn + 1, num_txns), UVM_LOW) + + set_address_range(mbx_config.ibmbx_base_addr, mbx_config.ibmbx_limit_addr, + mbx_config.obmbx_base_addr, mbx_config.obmbx_limit_addr, + mbx_config.address_range_valid, mbx_config.address_range_regwen); + + // Enable/Disable Core interrupts. + cfg_interrupts((1 << MbxCoreError) | + (1 << MbxCoreReady) | + (1 << MbxCoreAbort), intr_driven); + `uvm_info(`gfn, $sformatf("Using interrupts? %s", intr_driven ? "Y" : "N"), UVM_MEDIUM) + + // ---------------------------------------------------------------------------------------- + // Request from SoC to RoT + // ---------------------------------------------------------------------------------------- + + // Data from R-code to ROT + req_size = mbx_config.request_dwords; + rsp_size = mbx_config.response_dwords; + + `uvm_info(`gfn, $sformatf("Request size %x DWORD(s), Response size %x DWORD(s)", + req_size, rsp_size), UVM_LOW) + `uvm_info(`gfn, + $sformatf("Inbox should use address range [%x,%x)", + mbx_config.ibmbx_base_addr, mbx_config.ibmbx_base_addr + req_size * 4), + UVM_LOW) + `uvm_info(`gfn, + $sformatf("Outbox should use address range [%x,%x)", + mbx_config.obmbx_base_addr, mbx_config.obmbx_base_addr + rsp_size * 4), + UVM_LOW) + + `uvm_info(`gfn, $sformatf("Constructing Request of 0x%0x DWORDs", req_size), UVM_LOW) + for(int unsigned ii = 0; ii < req_size; ii++) begin + wr_data = $urandom(); + `uvm_info(`gfn, $sformatf(" - Offset 0x%0x : 0x%0x", ii, wr_data), UVM_LOW) + req.push_back(wr_data); + tl_access(.addr(m_mbx_soc_ral.get_addr_from_offset(mbx_reg_pkg::MBX_WDATA_OFFSET)), + .write(1'b1), .data(wr_data), .mask(4'hF), .blocking(1'b1), + .tl_sequencer_h(p_sequencer.tl_sequencer_hs[cfg.mbx_soc_ral_name])); + end + + csr_rd(m_mbx_soc_ral.soc_status, rd_data); + // Set the GO bit to mark complete transmission of the Request to the OT FW. + m_mbx_soc_ral.soc_control.abort.set(1'b0); + m_mbx_soc_ral.soc_control.go.set(1'b1); + csr_update(m_mbx_soc_ral.soc_control); + + wait_for_core_interrupt(); + clear_all_interrupts(); + + // Collect the request message from the OT mailbox memory + read_mem(mbx_config.ibmbx_base_addr, req_size << 2, q); + + for(int unsigned ii = 0; ii < req_size; ii++) begin + qd = {q[ii*4+3],q[ii*4+2],q[ii*4+1],q[ii*4]}; + `uvm_info(`gfn, $sformatf("Expected Request DWORD %0h got %0h", req[ii], qd), UVM_HIGH) + if (qd !== req[ii]) begin + `uvm_error(`gfn, + $sformatf("Request DWORD mismatches q[%0d]('h%0h) != req[%0d]('h%0h)", + ii, qd, ii, req[ii])) + end + end + `uvm_info(`gfn, "Request data matched expectations", UVM_LOW) + + // Data from ROT to R-code + q.delete(); + `uvm_info(`gfn, $sformatf("Constructing Response of 0x%0x DWORDs", rsp_size), UVM_LOW) + for(int unsigned ii = 0 ; ii < rsp_size; ii++) begin + mbx_dword_t data = $urandom; + `uvm_info(`gfn, $sformatf(" - Offset 0x%0x : 0x%0x", ii, data), UVM_LOW) + // TODO: replace this byte queue with DWORDs + q.push_back(data[7:0]); + q.push_back(data[15:8]); + q.push_back(data[23:16]); + q.push_back(data[31:24]); + end - // Ensure that we have a valid memory range - csr_wr(ral.address_range_valid, 1'b1); - // Enable core ready interrupt - cfg_interrupts(1 << MbxCoreReady); + // -------------------------------------------------------------------------------------- + // Response from RoT to SoC + // -------------------------------------------------------------------------------------- - // Data from R-code to ROT + write_mem(mbx_config.obmbx_base_addr, q); + csr_wr(ral.outbound_object_size, rsp_size); - // Without PR#321 there was an issue in the RTL that the Busy bit is not deasserted when the - // address range becomes valid. - if (1'b1) begin - // Check for Busy bit being clear before we can write to WDATA. - rd_data = '0; - rd_data[0] = 1'b1; - while(rd_data[0] == 1'b1) begin + wait_for_soc_interrupt(); csr_rd(m_mbx_soc_ral.soc_status, rd_data); - `uvm_info(`gfn, - $sformatf("checking for busy bit, rd_data for soc_status is :'h%0h", rd_data), UVM_DEBUG) - end - end + `DV_CHECK_EQ(rd_data[31], 1'b1, "soc_status ready bit not set after soc interrupt seen") + clear_all_interrupts(); + + // Collect the entire message before checking it. + // Note: this may not be the best approach unless we can time out in the event of a + // lock up in the provision of new RDATA values. + for(int unsigned ii = 0; ii < rsp_size; ii++) begin + // Read from RDATA to collect the next message word + tl_access(.addr(cfg.ral.get_addr_from_offset(mbx_reg_pkg::MBX_RDATA_OFFSET)), + .write(1'b0), .data(rd_data), .mask(4'hF), .compare_mask(0), + .blocking(1'b1), + .tl_sequencer_h(p_sequencer.tl_sequencer_hs[cfg.mbx_soc_ral_name])); + + `uvm_info(`gfn, $sformatf("Mailbox read data is : 'h%0h", rd_data), UVM_LOW) + + rsp.push_back(rd_data); + + // Write anything to RDATA to advance to the next word. + wr_data = $urandom; + tl_access(.addr(cfg.ral.get_addr_from_offset(mbx_reg_pkg::MBX_RDATA_OFFSET)), + .write(1'b1), .data(wr_data), .mask(4'hF), .blocking(rdata_wr_blocking), + .tl_sequencer_h(p_sequencer.tl_sequencer_hs[cfg.mbx_soc_ral_name])); + end + `uvm_info(`gfn, "READ all DATA from SoC side", UVM_HIGH); + + for(int unsigned ii = 0; ii < rsp_size; ii++) begin + qd = {q[ii*4+3],q[ii*4+2],q[ii*4+1],q[ii*4]}; + `uvm_info(`gfn, + $sformatf("Expected Response DWORD %0h got %0h", qd, rsp[ii]), UVM_HIGH) + if (qd !== rsp[ii]) begin + `uvm_error(`gfn, + $sformatf("Response DWORD mismatches q[%0d]('h%0h) != rsp[%0d]('h%0h)", + ii, qd, ii, rsp[ii])) + end + end - // Request and response sizes, in DWORDs - // Note: limit addresses are inclusive, and we want each message to be at least one DWORD long. - req_size_limit = (ibmbx_limit_addr - ibmbx_base_addr) >> 2; - rsp_size_limit = (obmbx_limit_addr - obmbx_base_addr) >> 2; - // TODO: Could perhaps do this with the base/limit constraints; after all the physical memory - // is going to be limited. - // TODO: Are there penalties involved in having a memory model with a ridiculous address range, - // or is it sparse? - if (req_size_limit >= 'h400) - req_size_limit = 'h400; - if (rsp_size_limit >= 'h400) - rsp_size_limit = 'h400; - // There's a further constraint on the number of DWORDs in the Response Object - if (rsp_size_limit > MBX_DV_MAX_DW) - rsp_size_limit = MBX_DV_MAX_DW; - - req_size = 1 + ($urandom % (1 + req_size_limit)); - rsp_size = 1 + ($urandom % (1 + rsp_size_limit)); - - `uvm_info(`gfn, - $sformatf("Request size %x DWORD(s), Response size %x DWORD(s)", req_size, rsp_size), UVM_LOW) - `uvm_info(`gfn, - $sformatf("Inbox should use [%x,%x)", ibmbx_base_addr, ibmbx_base_addr + req_size * 4), - UVM_LOW) - `uvm_info(`gfn, - $sformatf("Outbox should use [%x,%x)", obmbx_base_addr, obmbx_base_addr + rsp_size * 4), - UVM_LOW) - - for(int unsigned ii = 0; ii < req_size; ii++) begin - wr_data = $urandom(); - req.push_back(wr_data); - tl_access(.addr(m_mbx_soc_ral.get_addr_from_offset(MBX_SOC_WDATA_BASE)), - .write(1'b1), .data(wr_data), .mask(4'hF), .blocking(1), - .tl_sequencer_h(p_sequencer.tl_sequencer_hs[cfg.mbx_soc_ral_name])); - end + csr_rd(m_mbx_soc_ral.soc_status, rd_data); + `uvm_info(`gfn, $sformatf("Transaction complete; SOC_STATUS 0x%0x", rd_data), UVM_MEDIUM) + + `DV_CHECK_EQ(rd_data[31], 1'b0, "Ready bit still set") + + `uvm_info(`gfn, $sformatf("Completing transaction %d of %d", txn + 1, num_txns), UVM_LOW) + + // Ensure that we clear any asserted interrupts because otherwise they could interfere + // with subsequent CSR-driven tests, in particular. + csr_wr(ral.intr_state, (1 << MbxCoreError) | + (1 << MbxCoreReady) | + (1 << MbxCoreAbort)); + // Similarly control bits + csr_wr(ral.control, 0); + // SoC side interrupt + m_mbx_soc_ral.soc_status.doe_intr_status.set(1'b1); + csr_update(m_mbx_soc_ral.soc_status); + + // Can the memory range still be changed on subsequent transactions? + if (mbx_config.address_range_regwen != MuBi4True) begin + // Further changes are not expected to work until an IP reset, and the DV values must + // remain in step with those used by the DUT. + mbx_config.set_address_range_randomization(1'b0); + end - // Note: we need only set bits 31 and 1 (Go, dot_intr_en) here, no need to read. - // csr_rd(m_mbx_soc_ral.soc_control, rd_data); - // rd_data[31] = 1'b1; - rd_data = 32'h8000_0002; - `uvm_info(`gfn, "Doing soc_control csr wr", UVM_LOW) - clear_all_interrupts(); - csr_wr(m_mbx_soc_ral.soc_control, rd_data); - - wait_for_core_interrupt(); - clear_all_interrupts(); - - // Collect the request message from the OT mailbox memory - read_mem(ibmbx_base_addr, req_size << 2, q); - - for(int unsigned ii = 0; ii < req_size; ii++) begin - qd = {q[ii*4+3],q[ii*4+2],q[ii*4+1],q[ii*4]}; - `uvm_info(`gfn, $sformatf("Expected %0h got %0h", req[ii], qd), UVM_LOW) - if (qd !== req[ii]) begin - `uvm_error(`gfn, $sformatf("q[%0d]('h%0h) != req[%0d]('h%0h)", ii, qd, ii, req[ii])) + // Generate a new configuration for the next transaction, if there is one. + `DV_CHECK_RANDOMIZE_FATAL(mbx_config); end - end - - // Data from ROT to R-code - q.delete(); - for(int unsigned ii = 0 ; ii < rsp_size*4; ii++) begin - q.push_back($urandom); - end - write_mem(obmbx_base_addr, q); - csr_wr(ral.outbound_object_size, rsp_size); - - wait_for_soc_interrupt(); - csr_rd(m_mbx_soc_ral.soc_status, rd_data); - `DV_CHECK_EQ(rd_data[31], 1'b1, "soc_status ready bit not set after soc interrupt seen") - clear_all_interrupts(); - - // Collect the entire message before checking it. - // Note: this may not be the best approach unless we can time out in the event of a lock up - // in the provision of new RDATA values. - for(int unsigned ii = 0; ii < rsp_size; ii++) begin - // Read from RDATA to collect the next message word - tl_access(.addr(cfg.ral.get_addr_from_offset(MBX_SOC_RDATA_BASE)), - .write(1'b0), .data(rd_data), .mask(4'hF), .compare_mask(0), .blocking(1), - .tl_sequencer_h(p_sequencer.tl_sequencer_hs[cfg.mbx_soc_ral_name])); - - `uvm_info(get_full_name(), $sformatf("Mailbox read data is : 'h%0h", rd_data), UVM_LOW) - - rsp.push_back(rd_data); - - // Write anything to RDATA to advance to the next word. - wr_data = $urandom; - tl_access(.addr(cfg.ral.get_addr_from_offset(MBX_SOC_RDATA_BASE)), - .write(1'b1), .data(wr_data), .mask(4'hF), .blocking(1), - .tl_sequencer_h(p_sequencer.tl_sequencer_hs[cfg.mbx_soc_ral_name])); - end - for(int unsigned ii = 0; ii < rsp_size; ii++) begin - qd = {q[ii*4+3],q[ii*4+2],q[ii*4+1],q[ii*4]}; - `uvm_info(`gfn, $sformatf("Expected %0h got %0h", qd, rsp[ii]), UVM_LOW) - if (qd !== rsp[ii]) begin - `uvm_error(get_full_name(), - $sformatf(" q[%0d]('h%0h) != rsp[%0d]('h%0h)", ii, qd, ii, rsp[ii])) - end + apply_resets_concurrently(); + delay(10); end - csr_rd(m_mbx_soc_ral.soc_status, rd_data); - `DV_CHECK_EQ(rd_data[31], 1'b0, "Ready bit still set") - `uvm_info(get_full_name(), "body -- End", UVM_DEBUG) - - end endtask : body endclass : mbx_base_vseq diff --git a/hw/ip/mbx/dv/env/seq_lib/mbx_smoke_vseq.sv b/hw/ip/mbx/dv/env/seq_lib/mbx_smoke_vseq.sv index a9e2d59ef61a4..9d229d8541cd6 100644 --- a/hw/ip/mbx/dv/env/seq_lib/mbx_smoke_vseq.sv +++ b/hw/ip/mbx/dv/env/seq_lib/mbx_smoke_vseq.sv @@ -6,6 +6,11 @@ class mbx_smoke_vseq extends mbx_base_vseq; `uvm_object_utils(mbx_smoke_vseq) + // Constrain the iteration and transaction counts to produce a longer stress test and, + // importantly, perform multiple request and responses without an intervening block reset. + constraint num_iters_c { num_iters inside {[2:5]}; } + constraint num_txns_c { num_txns inside {[5:10]}; } + function new(string name = "mbx_smoke_vseq"); super.new(name); endfunction : new From ff139b59929a781f4cf6372689421c4177cd7da5 Mon Sep 17 00:00:00 2001 From: Adrian Lees Date: Tue, 5 Dec 2023 14:57:25 +0000 Subject: [PATCH 74/88] [dv,mbx] Placeholder stress sequence. Simple stress test runs more iterations of more transactions. To be extended. Signed-off-by: Adrian Lees --- hw/ip/mbx/dv/env/mbx_env.core | 1 + hw/ip/mbx/dv/env/seq_lib/mbx_stress_vseq.sv | 27 +++++++++++++++++++++ hw/ip/mbx/dv/env/seq_lib/mbx_vseq_list.sv | 1 + hw/ip/mbx/dv/mbx_sim_cfg.hjson | 16 +++++++----- 4 files changed, 39 insertions(+), 6 deletions(-) create mode 100644 hw/ip/mbx/dv/env/seq_lib/mbx_stress_vseq.sv diff --git a/hw/ip/mbx/dv/env/mbx_env.core b/hw/ip/mbx/dv/env/mbx_env.core index aa92349fe8ce3..fa66ebb5ca147 100644 --- a/hw/ip/mbx/dv/env/mbx_env.core +++ b/hw/ip/mbx/dv/env/mbx_env.core @@ -25,6 +25,7 @@ filesets: - seq_lib/mbx_common_vseq.sv: {is_include_file: true} - seq_lib/mbx_smoke_vseq.sv: {is_include_file: true} - seq_lib/mbx_vseq_list.sv: {is_include_file: true} + - seq_lib/mbx_stress_vseq.sv: {is_include_file: true} file_type: systemVerilogSource generate: diff --git a/hw/ip/mbx/dv/env/seq_lib/mbx_stress_vseq.sv b/hw/ip/mbx/dv/env/seq_lib/mbx_stress_vseq.sv new file mode 100644 index 0000000000000..c5407258ed350 --- /dev/null +++ b/hw/ip/mbx/dv/env/seq_lib/mbx_stress_vseq.sv @@ -0,0 +1,27 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +class mbx_stress_vseq extends mbx_base_vseq; + + `uvm_object_utils(mbx_stress_vseq) + + // Constrain the iteration and transaction counts to produce a longer stress test and, + // importantly, perform multiple request and responses without an intervening block reset. + constraint num_iters_c { num_iters inside {[5:10]}; } + constraint num_txns_c { num_txns inside {[2:20]}; } + + + + function new(string name = "mbx_stress_vseq"); + super.new(name); + endfunction : new + + virtual task body(); + `uvm_info(get_full_name(), "body -- stress test -- Start", UVM_DEBUG) + + super.body(); + `uvm_info(get_full_name(), "body -- stress test -- End", UVM_DEBUG) + endtask : body + +endclass : mbx_stress_vseq diff --git a/hw/ip/mbx/dv/env/seq_lib/mbx_vseq_list.sv b/hw/ip/mbx/dv/env/seq_lib/mbx_vseq_list.sv index 0c29e12387b6c..bdafc428d282c 100644 --- a/hw/ip/mbx/dv/env/seq_lib/mbx_vseq_list.sv +++ b/hw/ip/mbx/dv/env/seq_lib/mbx_vseq_list.sv @@ -7,3 +7,4 @@ `include "mbx_base_vseq.sv" `include "mbx_common_vseq.sv" `include "mbx_smoke_vseq.sv" +`include "mbx_stress_vseq.sv" diff --git a/hw/ip/mbx/dv/mbx_sim_cfg.hjson b/hw/ip/mbx/dv/mbx_sim_cfg.hjson index f88b421562de5..82ee26b0fe3d4 100644 --- a/hw/ip/mbx/dv/mbx_sim_cfg.hjson +++ b/hw/ip/mbx/dv/mbx_sim_cfg.hjson @@ -73,7 +73,10 @@ name: mbx_smoke uvm_test_seq: mbx_smoke_vseq } - + { + name: mbx_stress + uvm_test_seq: mbx_stress_vseq + } ] // List of regressions. @@ -82,12 +85,13 @@ name: smoke tests: ["mbx_smoke"] } -// { -// name: stress -// tests : [ "mbx_sw_access", + { + name: stress + tests : ["mbx_stress" +// "mbx_sw_access", // "mbx_sw_smoke", // "mbx_sw_alert_test" -// ] -// } + ] + } ] } From 768a94f57389cc26e0dcf3ce3ae40a16125f2148 Mon Sep 17 00:00:00 2001 From: Adrian Lees Date: Tue, 5 Dec 2023 15:08:28 +0000 Subject: [PATCH 75/88] [dv,mbx] Extended stress testing Generate SoC-side Aborts, Core-side Errors and Core-Side FW-initiated resets (Abort acknowledgements). Support interrupt-driven or CSR-driven operation. Signed-off-by: Adrian Lees Co-authored-by: Harry Callahan --- hw/ip/mbx/dv/env/seq_lib/mbx_base_vseq.sv | 450 +++++++++++++++----- hw/ip/mbx/dv/env/seq_lib/mbx_stress_vseq.sv | 41 ++ 2 files changed, 380 insertions(+), 111 deletions(-) diff --git a/hw/ip/mbx/dv/env/seq_lib/mbx_base_vseq.sv b/hw/ip/mbx/dv/env/seq_lib/mbx_base_vseq.sv index 9d31cc34f264d..b1fa18a2f429c 100644 --- a/hw/ip/mbx/dv/env/seq_lib/mbx_base_vseq.sv +++ b/hw/ip/mbx/dv/env/seq_lib/mbx_base_vseq.sv @@ -2,6 +2,20 @@ // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 +/* + The body of this base_vseq exercises the DUT by creating a number of 'transactions', which + nominally involve the requester posting a message, the responder receiving this message then + replying with its own message in return. Each transaction is a sequential series of operations, + with hooks which optionally may insert 'stressors' (SOC_ABORT, ERROR, ROT_ABORT) which causes + the nominal control flow to short-circuit to the end of the txn, while confirming we see the + effect of these stressors. + Each 'iteration' (num_iters) consists of a number of 'transactions' (num_txns), with a DUT reset + seperating each iteration. This allows the regwen features to be meaningfully exercised. + This is a quick, minimal effort extension of the existing 'smoke' test into something that more + thoroughly exercises the mailbox IP at block level, including exceptional traffic/conditions. + The linear-nature of stimulus->checking means it is not the basis of a proper DV stress test. +*/ + class mbx_base_vseq extends cip_base_vseq #( .RAL_T (mbx_core_reg_block), .CFG_T (mbx_env_cfg), @@ -16,8 +30,8 @@ class mbx_base_vseq extends cip_base_vseq #( // Number of iterations rand int unsigned num_iters; - // Number of transactions (message transfers within an iteration without an= - // intervening DUT reset) + // Number of transactions (per iteration) + // (sequential message transfers without an intervening DUT reset) rand int unsigned num_txns; mem_model seq_mem_model; @@ -32,6 +46,28 @@ class mbx_base_vseq extends cip_base_vseq #( // Number of words of memory available to the mailbox(es) int unsigned mbx_mem_words = 'h400; + // Raise an Abort request from the SoC side? + // Note: `aborted` shall already be clear, and be set here only when a new stimulus is applied. + virtual task do_abort(ref bit aborted); + endtask + // Raise an Error from the Core side? + // Note: `errored` shall already be clear, and be set here only when a new stimulus is applied. + virtual task do_error(ref bit errored); + endtask + // Raise a FW-initiated Reset from the Core side? + // Note: `panicked` shall already be clear, and be set here only when a new stimulus is applied. + virtual task do_panic(ref bit panicked); + endtask + + // Apply stressors to DUT? + // Note: each of `aborted`, `errored` and `panicked` shall already be clear, and be set here only + // when a new stimulus is applied. + virtual task stressors(ref bit aborted, ref bit errored, ref bit panicked); + do_abort(aborted); + do_error(errored); + do_panic(panicked); + endtask + function new(string name = ""); super.new(); mbx_config = mbx_seq_item::type_id::create("mbx_config"); @@ -53,16 +89,17 @@ class mbx_base_vseq extends cip_base_vseq #( super.dut_init(); endtask: dut_init - virtual task start_device_seq(); + // Start a sequence that creates a memory_model on the 'mem' interface. + virtual task start_mem_seq(); seq_h = mbx_tl_device_seq::type_id::create("seq_h"); seq_h.mem = seq_mem_model; fork seq_h.start(p_sequencer.tl_sequencer_hs[cfg.mbx_mem_ral_name]); join_none - endtask: start_device_seq + endtask: start_mem_seq virtual task set_mem_range_regwen(mubi4_t regwen); - `uvm_info(`gfn, $sformatf("Setting memory range regwen to 0x%x", regwen), UVM_LOW) + `uvm_info(`gfn, $sformatf("Setting memory range regwen to 0x%x", regwen), UVM_MEDIUM) ral.address_range_regwen.regwen.set(int'(regwen)); csr_update(ral.address_range_regwen); @@ -126,12 +163,25 @@ class mbx_base_vseq extends cip_base_vseq #( UVM_DEBUG) endtask: mbx_init - virtual task wait_for_core_interrupt(int clks_timeout=1024); + virtual task mbx_abort(); + `uvm_info(`gfn, "ABORTing operation", UVM_HIGH) + m_mbx_soc_ral.soc_control.go.set(1'b0); + m_mbx_soc_ral.soc_control.abort.set(1'b1); + csr_update(m_mbx_soc_ral.soc_control); + endtask + + virtual task wait_for_core_interrupt(ref bit intr_ready, ref bit intr_abort, + input int clks_timeout = 'h10000); + bit aborted = 1'b0; `uvm_info(`gfn, $sformatf("wait_for_core_interrupt -- Start"), UVM_DEBUG) - fork begin : isolation_fork + fork begin : iso_fork fork begin - `DV_WAIT(cfg.intr_vif.pins[MbxCoreReady] == 1'b1, "core interrupt wait timeout") + `DV_WAIT(cfg.intr_vif.pins[MbxCoreReady] == 1'b1, "core ready interrupt wait timeout") + end + begin + `DV_WAIT(cfg.intr_vif.pins[MbxCoreAbort] == 1'b1, "core abort interrupt wait timeout") + aborted = 1'b1; end begin cfg.clk_rst_vif.wait_clks(clks_timeout); @@ -140,13 +190,18 @@ class mbx_base_vseq extends cip_base_vseq #( end join_any; disable fork; - end join + end: iso_fork join + if (aborted) begin + intr_abort = 1'b1; + end else begin + intr_ready = 1'b1; + end `uvm_info(`gfn, $sformatf("wait_for_core_interrupt -- End"), UVM_DEBUG) - endtask: wait_for_core_interrupt + endtask : wait_for_core_interrupt - virtual task wait_for_soc_interrupt(int clks_timeout=1024); + virtual task wait_for_soc_interrupt(int clks_timeout = 'h10000); `uvm_info(`gfn, $sformatf("wait_for_soc_interrupt -- Start"), UVM_DEBUG) - fork begin : isolation_fork + fork begin : iso_fork fork begin `DV_WAIT(cfg.intr_soc_vif.pins[0] == 1'b1, "soc interrupt wait timeout") @@ -158,20 +213,78 @@ class mbx_base_vseq extends cip_base_vseq #( end join_any; disable fork; - end join + end: iso_fork join `uvm_info(`gfn, $sformatf("wait_for_soc_interrupt -- End"), UVM_DEBUG) - endtask: wait_for_soc_interrupt + endtask : wait_for_soc_interrupt + + // Wait until the Ready/Abort interrupt is received on the Core side, or alternatively rely + // upon the INTR_STATE register and polling. + // If we decide to perform a FW-initiated reset ('panic') then neither will occur. + task automatic wait_for_core_signal(output bit intr_ready, + output bit intr_abort, + output bit aborted, + output bit errored, + output bit panicked, + input bit intr_driven); + // Detected interrupt/status bits on Core side + bit got_ready = 1'b0; + bit got_abort = 1'b0; + // Generated stimuli + bit gen_abort = 1'b0; + bit gen_error = 1'b0; + bit gen_panic = 1'b0; + event e_stop; + fork begin: iso_fork + // With two processes we monitor CSR activity and interrupt signals concurrently. + fork + // CSR-driving thread generates errors and aborts as well as optionally polling the + // INTR_STATE register. + begin + do begin + // Ensure simulation time advances, even if this process has nothing to do! + delay(1); + stressors(gen_abort, gen_error, gen_panic); + if (!intr_driven) begin + bit [top_pkg::TL_DW-1:0] rd_data; + csr_rd(ral.intr_state, rd_data); + got_ready |= get_field_val(ral.intr_state.mbx_ready, rd_data); + got_abort |= get_field_val(ral.intr_state.mbx_abort, rd_data); + end + end while (!(got_ready | got_abort | gen_error | gen_panic)); + // Signal to the parallel thread that the CSR registers are no longer being accessed. + ->e_stop; + end + begin + if (intr_driven) wait_for_core_interrupt(got_ready, got_abort); + // Note: we must never kill the CSR-polling process because it may leave the RAL + // locked, so this thread must only terminate with permission of the CSR process. + wait (e_stop.triggered); + end + join_any + // Ensure that the interrupt-monitoring process terminates. + disable fork; + end: iso_fork join + // Signals from DUT + intr_ready = got_ready; + intr_abort = got_abort; + // Generated stimuli + aborted = gen_abort; + errored = gen_error; + panicked = gen_panic; + endtask virtual task body(); `uvm_info(get_full_name(), "body -- Start", UVM_DEBUG) - start_device_seq(); + + // Start a sequence that creates a memory_model on the 'mem' interface. + start_mem_seq(); // TODO: gross change to prevent explosions on accessing RDATA, since it does not behave like // a regular memory cfg.en_scb_mem_chk = 1'b0; - for (int unsigned iter = 0; iter < num_iters; iter++) begin - `uvm_info(`gfn, $sformatf("Starting iteration %d of %d", iter + 1, num_iters), UVM_LOW) + for (int unsigned iter = 0; iter < num_iters; iter++) begin: b_num_iters + `uvm_info(`gfn, $sformatf("Starting iteration %0d of %0d", iter + 1, num_iters), UVM_LOW) // Since the DUT has just been reset, we should take the opportunity to choose new memory // addresses. @@ -183,13 +296,16 @@ class mbx_base_vseq extends cip_base_vseq #( for (int unsigned txn = 0; txn < num_txns; txn++) begin bit [top_pkg::TL_DW-1:0] rd_data; bit [top_pkg::TL_DW-1:0] wr_data; - bit intr_driven = 1'b1; // TODO: support either CSR or interrupts. + bit intr_driven = $urandom & 1; bit check_request = 1'b0; bit send_response = 1'b0; int unsigned req_size_limit; int unsigned rsp_size_limit; int unsigned req_size; int unsigned rsp_size; + bit panicked = 1'b0; + bit errored = 1'b0; + bit aborted = 1'b0; mbx_dword_t req[$]; mbx_dword_t rsp[$]; mbx_dword_t qd; @@ -207,7 +323,10 @@ class mbx_base_vseq extends cip_base_vseq #( // Empty the mailbox memory model of any previous contents. clear_mem(); - `uvm_info(`gfn, $sformatf("Starting transaction %d of %d", txn + 1, num_txns), UVM_LOW) + `uvm_info(`gfn, $sformatf("Starting transaction %0d of %0d", txn + 1, num_txns), UVM_LOW) + + // Generate a new configuration for the transaction. + `DV_CHECK_RANDOMIZE_FATAL(mbx_config); set_address_range(mbx_config.ibmbx_base_addr, mbx_config.ibmbx_limit_addr, mbx_config.obmbx_base_addr, mbx_config.obmbx_limit_addr, @@ -227,114 +346,226 @@ class mbx_base_vseq extends cip_base_vseq #( req_size = mbx_config.request_dwords; rsp_size = mbx_config.response_dwords; - `uvm_info(`gfn, $sformatf("Request size %x DWORD(s), Response size %x DWORD(s)", - req_size, rsp_size), UVM_LOW) + `uvm_info(`gfn, $sformatf("Request size 0x%x DWORD(s), Response size 0x%x DWORD(s)", + req_size, rsp_size), UVM_MEDIUM) `uvm_info(`gfn, - $sformatf("Inbox should use address range [%x,%x)", + $sformatf("Inbox should use address range [0x%x,0x%x]", mbx_config.ibmbx_base_addr, mbx_config.ibmbx_base_addr + req_size * 4), - UVM_LOW) + UVM_MEDIUM) `uvm_info(`gfn, - $sformatf("Outbox should use address range [%x,%x)", + $sformatf("Outbox should use address range [0x%x,0x%x]", mbx_config.obmbx_base_addr, mbx_config.obmbx_base_addr + rsp_size * 4), - UVM_LOW) + UVM_MEDIUM) - `uvm_info(`gfn, $sformatf("Constructing Request of 0x%0x DWORDs", req_size), UVM_LOW) + `uvm_info(`gfn, $sformatf("Constructing Request of 0x%0x DWORDs", req_size), UVM_MEDIUM) for(int unsigned ii = 0; ii < req_size; ii++) begin - wr_data = $urandom(); - `uvm_info(`gfn, $sformatf(" - Offset 0x%0x : 0x%0x", ii, wr_data), UVM_LOW) - req.push_back(wr_data); - tl_access(.addr(m_mbx_soc_ral.get_addr_from_offset(mbx_reg_pkg::MBX_WDATA_OFFSET)), - .write(1'b1), .data(wr_data), .mask(4'hF), .blocking(1'b1), - .tl_sequencer_h(p_sequencer.tl_sequencer_hs[cfg.mbx_soc_ral_name])); + stressors(aborted, errored, panicked); + + if (aborted | panicked) begin + if (!panicked) begin + // We know that we're not permitted to write to WDATA whilst the mailbox is BUSY, + // which should be expected if we've ABORTed the operation. + uvm_reg_data_t data; + csr_rd(m_mbx_soc_ral.soc_status, data); + `DV_CHECK_EQ(get_field_val(m_mbx_soc_ral.soc_status.busy, data), 1'b1, + "SOC_STATUS.busy not set when expected in response to Abort request") + end + // Do NOT send the remainder of the Request. + break; + end else begin + wr_data = $urandom(); + `uvm_info(`gfn, $sformatf(" - Offset 0x%0x : 0x%0x", ii, wr_data), UVM_HIGH) + req.push_back(wr_data); + tl_access(.addr(m_mbx_soc_ral.get_addr_from_offset(mbx_reg_pkg::MBX_WDATA_OFFSET)), + .write(1'b1), .data(wr_data), .mask(4'hF), .blocking(1'b1), + .tl_sequencer_h(p_sequencer.tl_sequencer_hs[cfg.mbx_soc_ral_name])); + end end csr_rd(m_mbx_soc_ral.soc_status, rd_data); - // Set the GO bit to mark complete transmission of the Request to the OT FW. - m_mbx_soc_ral.soc_control.abort.set(1'b0); - m_mbx_soc_ral.soc_control.go.set(1'b1); - csr_update(m_mbx_soc_ral.soc_control); - - wait_for_core_interrupt(); - clear_all_interrupts(); - - // Collect the request message from the OT mailbox memory - read_mem(mbx_config.ibmbx_base_addr, req_size << 2, q); + obs_error = get_field_val(m_mbx_soc_ral.soc_status.error, rd_data); + + if (!panicked & !aborted & !obs_error) begin + // No disruption in the supply of the Request, activate the RoT + bit intr_abort; + bit intr_ready; + + // As we supplied all of the data, it should all make it into the mailbox SRAM. + check_request = 1'b1; + + // Set the GO bit to mark complete transmission of the Request to the OT FW. + m_mbx_soc_ral.soc_control.abort.set(1'b0); + m_mbx_soc_ral.soc_control.go.set(1'b1); + csr_update(m_mbx_soc_ral.soc_control); + + // Wait until the Ready interrupt is received on the Core side, or alternatively rely + // upon the INTR_STATE register and polling. + // If we decide to perform a FW-initiated reset ('panic') then neither will occur. + wait_for_core_signal(intr_ready, intr_abort, // Core side signals from DUT + aborted, errored, panicked, // Stimuli generated by DV + intr_driven); // Interrupt-driven operation? + + // Are we expecting the mailbox to be operational still? + `uvm_info(`gfn, $sformatf("intr_ready %d abort %d errored %d panicked %d", + intr_ready, intr_abort, errored, panicked), UVM_HIGH); + send_response = intr_ready & !intr_abort & !aborted & !errored & !panicked; + end - for(int unsigned ii = 0; ii < req_size; ii++) begin - qd = {q[ii*4+3],q[ii*4+2],q[ii*4+1],q[ii*4]}; - `uvm_info(`gfn, $sformatf("Expected Request DWORD %0h got %0h", req[ii], qd), UVM_HIGH) - if (qd !== req[ii]) begin - `uvm_error(`gfn, - $sformatf("Request DWORD mismatches q[%0d]('h%0h) != req[%0d]('h%0h)", - ii, qd, ii, req[ii])) + if (check_request) begin + // Collect the request message from the OT mailbox memory + read_mem(mbx_config.ibmbx_base_addr, req_size << 2, q); + + for(int unsigned ii = 0; ii < req_size; ii++) begin + qd = {q[ii*4+3],q[ii*4+2],q[ii*4+1],q[ii*4]}; + `uvm_info(`gfn, $sformatf("Expected Request DWORD %0h got %0h", req[ii], qd), UVM_HIGH) + if (qd !== req[ii]) begin + `uvm_error(`gfn, + $sformatf("Request DWORD mismatches q[%0d]('h%0h) != req[%0d]('h%0h)", + ii, qd, ii, req[ii])) + end end - end - `uvm_info(`gfn, "Request data matched expectations", UVM_LOW) - - // Data from ROT to R-code - q.delete(); - `uvm_info(`gfn, $sformatf("Constructing Response of 0x%0x DWORDs", rsp_size), UVM_LOW) - for(int unsigned ii = 0 ; ii < rsp_size; ii++) begin - mbx_dword_t data = $urandom; - `uvm_info(`gfn, $sformatf(" - Offset 0x%0x : 0x%0x", ii, data), UVM_LOW) - // TODO: replace this byte queue with DWORDs - q.push_back(data[7:0]); - q.push_back(data[15:8]); - q.push_back(data[23:16]); - q.push_back(data[31:24]); + `uvm_info(`gfn, "Request data matched expectations", UVM_MEDIUM) end - // -------------------------------------------------------------------------------------- - // Response from RoT to SoC - // -------------------------------------------------------------------------------------- - - write_mem(mbx_config.obmbx_base_addr, q); - csr_wr(ral.outbound_object_size, rsp_size); + if (send_response) begin: b_send_response + // Data from ROT to R-code + q.delete(); + `uvm_info(`gfn, $sformatf("Constructing Response of 0x%0x DWORDs", rsp_size), UVM_MEDIUM) + for(int unsigned ii = 0 ; ii < rsp_size; ii++) begin + mbx_dword_t data = $urandom; + `uvm_info(`gfn, $sformatf(" - Offset 0x%0x : 0x%0x", ii, data), UVM_HIGH) + // TODO: replace this byte queue with DWORDs + q.push_back(data[7:0]); + q.push_back(data[15:8]); + q.push_back(data[23:16]); + q.push_back(data[31:24]); + end - wait_for_soc_interrupt(); - csr_rd(m_mbx_soc_ral.soc_status, rd_data); - `DV_CHECK_EQ(rd_data[31], 1'b1, "soc_status ready bit not set after soc interrupt seen") - clear_all_interrupts(); - - // Collect the entire message before checking it. - // Note: this may not be the best approach unless we can time out in the event of a - // lock up in the provision of new RDATA values. - for(int unsigned ii = 0; ii < rsp_size; ii++) begin - // Read from RDATA to collect the next message word - tl_access(.addr(cfg.ral.get_addr_from_offset(mbx_reg_pkg::MBX_RDATA_OFFSET)), - .write(1'b0), .data(rd_data), .mask(4'hF), .compare_mask(0), - .blocking(1'b1), - .tl_sequencer_h(p_sequencer.tl_sequencer_hs[cfg.mbx_soc_ral_name])); - - `uvm_info(`gfn, $sformatf("Mailbox read data is : 'h%0h", rd_data), UVM_LOW) - - rsp.push_back(rd_data); - - // Write anything to RDATA to advance to the next word. - wr_data = $urandom; - tl_access(.addr(cfg.ral.get_addr_from_offset(mbx_reg_pkg::MBX_RDATA_OFFSET)), - .write(1'b1), .data(wr_data), .mask(4'hF), .blocking(rdata_wr_blocking), - .tl_sequencer_h(p_sequencer.tl_sequencer_hs[cfg.mbx_soc_ral_name])); - end - `uvm_info(`gfn, "READ all DATA from SoC side", UVM_HIGH); - - for(int unsigned ii = 0; ii < rsp_size; ii++) begin - qd = {q[ii*4+3],q[ii*4+2],q[ii*4+1],q[ii*4]}; - `uvm_info(`gfn, - $sformatf("Expected Response DWORD %0h got %0h", qd, rsp[ii]), UVM_HIGH) - if (qd !== rsp[ii]) begin - `uvm_error(`gfn, - $sformatf("Response DWORD mismatches q[%0d]('h%0h) != rsp[%0d]('h%0h)", - ii, qd, ii, rsp[ii])) + // -------------------------------------------------------------------------------------- + // Response from RoT to SoC + // -------------------------------------------------------------------------------------- + + write_mem(mbx_config.obmbx_base_addr, q); + // Writing to 'outbound_object_size' triggers the mbx to make the response available. + csr_wr(ral.outbound_object_size, rsp_size); + + // Await assertion of READY bit or interrupt indicating that there's a Response available. + do begin + stressors(aborted, errored, panicked); + + csr_rd(m_mbx_soc_ral.soc_status, rd_data); + `uvm_info(`gfn, $sformatf("rd_data for soc_status is :'h%0h", rd_data), UVM_DEBUG) + + // TODO: wait_soc_interrupt here + // if intr_driven ... + + // We're waiting to see the READY bit, but we may also see BUSY in response to + // an ABORT or ERROR if we raised an error. + obs_error = get_field_val(m_mbx_soc_ral.soc_status.error, rd_data); + obs_ready = get_field_val(m_mbx_soc_ral.soc_status.ready, rd_data); + end while (!(aborted | panicked | obs_error | obs_ready)); + + if (obs_ready & !aborted & !errored & !panicked) begin + bit check_response = 1'b1; + + // Use an explicit termination signal for the other parallel thread, to avoid killing + // it during a CSR access since doing so could leave the RAL locked. + bit done = 1'b0; + fork + begin + // Collect the entire message before checking it. + // Note: this may not be the best approach unless we can time out in the event of a + // lock up in the provision of new RDATA values. + for(int unsigned ii = 0; ii < rsp_size && !done; ii++) begin + // Read from RDATA to collect the next message word + tl_access(.addr(cfg.ral.get_addr_from_offset(mbx_reg_pkg::MBX_RDATA_OFFSET)), + .write(1'b0), .data(rd_data), .mask(4'hF), .compare_mask(0), + .blocking(1'b1), + .tl_sequencer_h(p_sequencer.tl_sequencer_hs[cfg.mbx_soc_ral_name])); + + `uvm_info(`gfn, $sformatf("Mailbox read data is : 'h%0h", rd_data), UVM_HIGH) + + rsp.push_back(rd_data); + + // Write anything to RDATA to advance to the next word. + wr_data = $urandom; + tl_access(.addr(cfg.ral.get_addr_from_offset(mbx_reg_pkg::MBX_RDATA_OFFSET)), + .write(1'b1), .data(wr_data), .mask(4'hF), .blocking(rdata_wr_blocking), + .tl_sequencer_h(p_sequencer.tl_sequencer_hs[cfg.mbx_soc_ral_name])); + end + `uvm_info(`gfn, "READ all DATA from SoC side", UVM_HIGH); + done = 1'b1; + end + begin + while (!done) begin + // Ensure simulation time advances, even if this process has nothing to do! + delay(1); + stressors(aborted, errored, panicked); + + if (aborted | errored | panicked) begin + check_response = 1'b0; + done = 1'b1; + end + end + `uvm_info(`gfn, "Abort/Error process stopping", UVM_HIGH); + end + join + + if (check_response) begin + for(int unsigned ii = 0; ii < rsp_size; ii++) begin + qd = {q[ii*4+3],q[ii*4+2],q[ii*4+1],q[ii*4]}; + `uvm_info(`gfn, + $sformatf("Expected Response DWORD %0h got %0h", qd, rsp[ii]), UVM_HIGH) + if (qd !== rsp[ii]) begin + `uvm_error(`gfn, + $sformatf("Response DWORD mismatches q[%0d]('h%0h) != rsp[%0d]('h%0h)", + ii, qd, ii, rsp[ii])) + end + end + end end - end + end: b_send_response csr_rd(m_mbx_soc_ral.soc_status, rd_data); `uvm_info(`gfn, $sformatf("Transaction complete; SOC_STATUS 0x%0x", rd_data), UVM_MEDIUM) + // Collect SoC.STATUS bits + obs_busy = get_field_val(m_mbx_soc_ral.soc_status.busy, rd_data); + obs_error = get_field_val(m_mbx_soc_ral.soc_status.error, rd_data); + if (obs_error) begin + `DV_CHECK_EQ(errored, 1'b1, "Unsignaled ERROR occurred") + + `uvm_info(`gfn, "Clearing ERROR condition from SoC side using ABORT mechanism", UVM_HIGH) + mbx_abort(); + aborted = 1'b1; + + // Check that the BUSY bit becomes set + csr_rd(m_mbx_soc_ral.soc_status, rd_data); + obs_busy = get_field_val(m_mbx_soc_ral.soc_status.busy, rd_data); + obs_error = get_field_val(m_mbx_soc_ral.soc_status.error, rd_data); + `DV_CHECK_EQ(obs_busy, 1'b1, "BUSY bit has not become set when ABORTing") + end + + if (obs_busy) begin + `DV_CHECK_EQ(aborted, 1'b1, "BUSY asserted but not ABORTed") + + // Abort occurred, clear it from the OT FW side + `uvm_info(`gfn, "Clearing ABORT condition from OT FW side", UVM_HIGH) + ral.control.abort.set(1'b1); + ral.control.error.set(1'b0); // Don't raise another ERROR! + csr_update(ral.control); + + // Check that the BUSY bit resets + csr_rd(m_mbx_soc_ral.soc_status, rd_data); + obs_busy = get_field_val(m_mbx_soc_ral.soc_status.busy, rd_data); + obs_error = get_field_val(m_mbx_soc_ral.soc_status.error, rd_data); + `DV_CHECK_EQ(obs_busy, 1'b0, "BUSY bit cannot be cleared") + `DV_CHECK_EQ(obs_error, 1'b0, "ERROR bit cannot be cleared") + end + `DV_CHECK_EQ(rd_data[31], 1'b0, "Ready bit still set") - `uvm_info(`gfn, $sformatf("Completing transaction %d of %d", txn + 1, num_txns), UVM_LOW) + `uvm_info(`gfn, $sformatf("Completed transaction %0d of %0d", txn + 1, num_txns), UVM_LOW) // Ensure that we clear any asserted interrupts because otherwise they could interfere // with subsequent CSR-driven tests, in particular. @@ -353,14 +584,11 @@ class mbx_base_vseq extends cip_base_vseq #( // remain in step with those used by the DUT. mbx_config.set_address_range_randomization(1'b0); end - - // Generate a new configuration for the next transaction, if there is one. - `DV_CHECK_RANDOMIZE_FATAL(mbx_config); - end + end: b_num_txns apply_resets_concurrently(); delay(10); - end + end: b_num_iters `uvm_info(get_full_name(), "body -- End", UVM_DEBUG) endtask : body diff --git a/hw/ip/mbx/dv/env/seq_lib/mbx_stress_vseq.sv b/hw/ip/mbx/dv/env/seq_lib/mbx_stress_vseq.sv index c5407258ed350..c57bbf4c3a1aa 100644 --- a/hw/ip/mbx/dv/env/seq_lib/mbx_stress_vseq.sv +++ b/hw/ip/mbx/dv/env/seq_lib/mbx_stress_vseq.sv @@ -11,8 +11,44 @@ class mbx_stress_vseq extends mbx_base_vseq; constraint num_iters_c { num_iters inside {[5:10]}; } constraint num_txns_c { num_txns inside {[2:20]}; } + // Whether to produce these stimuli to stress the DUT. + bit aborts_en = 1'b1; // Aborts from the SoC side. + bit errors_en = 1'b1; // Errors from the Core side. + bit panics_en = 1'b1; // FW-initiated reset/Abort clear from the Core side. + // TODO: decide how often errors and aborts should be generated; sequences shall probably want + // to override the behavior, but we shall also want some kind of sensible default. Perhaps + // randomize the number of clock cycles until we raise an abort, rather than treating each clock + // cycle as an independent event? + // Raise an Abort request from the SoC side? + virtual task do_abort(ref bit aborted); + if (aborts_en && !($urandom() % 1024)) begin + `uvm_info(`gfn, "Setting ABORT condition", UVM_LOW) + mbx_abort(); + aborted = 1'b1; + end + endtask + + // Raise an Error from the Core side? + virtual task do_error(ref bit errored); + if (errors_en && !($urandom() % 1024)) begin + `uvm_info(`gfn, "Setting ERROR condition", UVM_LOW) + ral.control.error.set(1'b1); + csr_update(ral.control); + errored = 1'b1; + end + endtask + + // Raise a FW-initiated Reset from the Core side? + virtual task do_panic(ref bit panicked); + if (panics_en && !($urandom() % 1024)) begin + `uvm_info(`gfn, "Setting FW RESET/ABORT ACK condition", UVM_LOW) + ral.control.abort.set(1'b1); + csr_update(ral.control); + panicked = 1'b1; + end + endtask function new(string name = "mbx_stress_vseq"); super.new(name); endfunction : new @@ -20,6 +56,11 @@ class mbx_stress_vseq extends mbx_base_vseq; virtual task body(); `uvm_info(get_full_name(), "body -- stress test -- Start", UVM_DEBUG) + // Decide which stimuli to present to the DUT. + aborts_en = ($urandom_range(0,100) > 75); + errors_en = ($urandom_range(0,100) > 75); + panics_en = ($urandom_range(0,100) > 75); + super.body(); `uvm_info(get_full_name(), "body -- stress test -- End", UVM_DEBUG) endtask : body From 8e19d6c2e38950c3a35bce17cee738b9acaa324d Mon Sep 17 00:00:00 2001 From: Adrian Lees Date: Tue, 5 Dec 2023 15:19:16 +0000 Subject: [PATCH 76/88] [dv,mbx] Vary TL-UL access/response timings. Randomization of TL-UL access and response timings within stress sequence(s). Introduce 'zero delays' stress sequence for throughput testing and exercising back-pressuring logic. Signed-off-by: Adrian Lees --- hw/ip/mbx/dv/env/seq_lib/mbx_base_vseq.sv | 77 ++++++++++++++++++++- hw/ip/mbx/dv/env/seq_lib/mbx_stress_vseq.sv | 14 ++++ hw/ip/mbx/dv/mbx_sim_cfg.hjson | 8 ++- 3 files changed, 97 insertions(+), 2 deletions(-) diff --git a/hw/ip/mbx/dv/env/seq_lib/mbx_base_vseq.sv b/hw/ip/mbx/dv/env/seq_lib/mbx_base_vseq.sv index b1fa18a2f429c..29ffbd257c694 100644 --- a/hw/ip/mbx/dv/env/seq_lib/mbx_base_vseq.sv +++ b/hw/ip/mbx/dv/env/seq_lib/mbx_base_vseq.sv @@ -68,6 +68,21 @@ class mbx_base_vseq extends cip_base_vseq #( do_panic(panicked); endtask + // Decide upon the access delays for this transaction. + virtual function bit choose_access_delays(output int min_acc_delay, output int max_acc_delay); + min_acc_delay = 0; + max_acc_delay = 0; + // Do not modify them by default. + return 1'b0; + endfunction + + virtual function bit choose_response_delays(output int min_rsp_delay, output int max_rsp_delay); + min_rsp_delay = 0; + max_rsp_delay = 0; + // Do not modify them by default. + return 1'b0; + endfunction + function new(string name = ""); super.new(); mbx_config = mbx_seq_item::type_id::create("mbx_config"); @@ -85,6 +100,43 @@ class mbx_base_vseq extends cip_base_vseq #( cfg.clk_rst_vif.wait_clks(num); endtask : delay + // Set the minimum and maximum grant delays of the mailbox SRAM + // TODO: this function was introduced to guarantee the desired values during bring up; + // it may no longer be required. + function void set_access_delays(int min, int max); + cfg.m_tl_agent_cfgs[mbx_mem_ral_name].a_ready_delay_min = min; + cfg.m_tl_agent_cfgs[mbx_mem_ral_name].a_ready_delay_max = max; + + cfg.m_tl_agent_cfgs[RAL_T::type_name].a_valid_delay_min = min; + cfg.m_tl_agent_cfgs[RAL_T::type_name].a_valid_delay_max = max; + + cfg.m_tl_agent_cfgs[mbx_soc_ral_name].a_valid_delay_min = min; + cfg.m_tl_agent_cfgs[mbx_soc_ral_name].a_valid_delay_max = max; + endfunction + + // Set the minimum and maximum response delays of the mailbox SRAM + // TODO: this function was introduced to guarantee the desired values during bring up; + // it may no longer be required. + function void set_response_delays(int min, int max); + cfg.m_tl_agent_cfgs[mbx_mem_ral_name].use_seq_item_d_valid_delay = 1'b0; + cfg.m_tl_agent_cfgs[mbx_mem_ral_name].d_valid_delay_min = min; + cfg.m_tl_agent_cfgs[mbx_mem_ral_name].d_valid_delay_max = max; + + cfg.m_tl_agent_cfgs[RAL_T::type_name].d_ready_delay_min = min; + cfg.m_tl_agent_cfgs[RAL_T::type_name].d_ready_delay_max = max; + + cfg.m_tl_agent_cfgs[mbx_soc_ral_name].d_ready_delay_min = min; + cfg.m_tl_agent_cfgs[mbx_soc_ral_name].d_ready_delay_max = max; + + seq_h.min_rsp_delay = min; + seq_h.max_rsp_delay = max; + endfunction + + // Enable/disable errors on TL-UL buses with the given percentage probability/word + function void enable_bus_errors(int pct); + seq_h.d_error_pct = pct; + endfunction + virtual task dut_init(string reset_kind = "HARD"); super.dut_init(); endtask: dut_init @@ -296,6 +348,7 @@ class mbx_base_vseq extends cip_base_vseq #( for (int unsigned txn = 0; txn < num_txns; txn++) begin bit [top_pkg::TL_DW-1:0] rd_data; bit [top_pkg::TL_DW-1:0] wr_data; + int error_pct = $urandom_range(0, 200); bit intr_driven = $urandom & 1; bit check_request = 1'b0; bit send_response = 1'b0; @@ -312,8 +365,12 @@ class mbx_base_vseq extends cip_base_vseq #( bit obs_ready; bit obs_error; bit obs_busy; + int min_rsp_delay; + int max_rsp_delay; + int min_acc_delay; + int max_acc_delay; // TODO: whether to perform RDATA write accesses as blocking operations. - bit rdata_wr_blocking = 1'b1; + bit rdata_wr_blocking = 1'b0; // TODO: perhaps we should change read_mem/write_mem to avoid issues. // The mailbox operates only on DWORD quantities. @@ -338,6 +395,24 @@ class mbx_base_vseq extends cip_base_vseq #( (1 << MbxCoreAbort), intr_driven); `uvm_info(`gfn, $sformatf("Using interrupts? %s", intr_driven ? "Y" : "N"), UVM_MEDIUM) + // Generate TL-UL bus errors during the operation. + // TODO: this trips up the base scoreboard at present + // enable_bus_errors((error_pct >= 100) ? 0 : error_pct); + + // Let the derived sequence vary the timing as appropriate; because of the back-pressuring + // signals in DUT, there's a sequence that specifically sets 'zero_delays' to exercise + // low latency bus responses. + if (!cfg.zero_delays && choose_access_delays(min_acc_delay, max_acc_delay)) begin + set_access_delays(min_acc_delay, max_acc_delay); + `uvm_info(`gfn, $sformatf("Setting access delays [%d,%d]", + min_acc_delay, max_acc_delay), UVM_MEDIUM) + end + if (!cfg.zero_delays && choose_response_delays(min_rsp_delay, max_rsp_delay)) begin + set_response_delays(min_rsp_delay, max_rsp_delay); + `uvm_info(`gfn, $sformatf("Setting response delays [%d,%d]", + min_rsp_delay, max_rsp_delay), UVM_MEDIUM) + end + // ---------------------------------------------------------------------------------------- // Request from SoC to RoT // ---------------------------------------------------------------------------------------- diff --git a/hw/ip/mbx/dv/env/seq_lib/mbx_stress_vseq.sv b/hw/ip/mbx/dv/env/seq_lib/mbx_stress_vseq.sv index c57bbf4c3a1aa..199dbef929e9a 100644 --- a/hw/ip/mbx/dv/env/seq_lib/mbx_stress_vseq.sv +++ b/hw/ip/mbx/dv/env/seq_lib/mbx_stress_vseq.sv @@ -49,6 +49,20 @@ class mbx_stress_vseq extends mbx_base_vseq; panicked = 1'b1; end endtask + + // Decide upon the access delays for this transaction. + virtual function bit choose_access_delays(output int min_acc_delay, output int max_acc_delay); + min_acc_delay = $urandom_range(0, 5); + max_acc_delay = $urandom_range(min_acc_delay, 20); + return 1'b1; + endfunction + + virtual function bit choose_response_delays(output int min_rsp_delay, output int max_rsp_delay); + min_rsp_delay = $urandom_range(0, 5); + max_rsp_delay = $urandom_range(min_rsp_delay, 20); + return 1'b1; + endfunction + function new(string name = "mbx_stress_vseq"); super.new(name); endfunction : new diff --git a/hw/ip/mbx/dv/mbx_sim_cfg.hjson b/hw/ip/mbx/dv/mbx_sim_cfg.hjson index 82ee26b0fe3d4..f7cd7996cad2c 100644 --- a/hw/ip/mbx/dv/mbx_sim_cfg.hjson +++ b/hw/ip/mbx/dv/mbx_sim_cfg.hjson @@ -77,6 +77,11 @@ name: mbx_stress uvm_test_seq: mbx_stress_vseq } + { + name: mbx_stress_zero_delays + uvm_test_seq: mbx_stress_vseq + run_opts: ["+zero_delays=1"] + } ] // List of regressions. @@ -87,7 +92,8 @@ } { name: stress - tests : ["mbx_stress" + tests : ["mbx_stress", + "mbx_stress_zero_delays" // "mbx_sw_access", // "mbx_sw_smoke", // "mbx_sw_alert_test" From 4d87e284c3db73db96a3a02f3b55c90ba144295e Mon Sep 17 00:00:00 2001 From: Harry Callahan Date: Wed, 17 Jan 2024 18:08:06 +0000 Subject: [PATCH 77/88] [dv,mbx] Reduce num_iters/num_txns for mbx_stress to avoid timeouts Signed-off-by: Harry Callahan --- hw/ip/mbx/dv/env/seq_lib/mbx_stress_vseq.sv | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/ip/mbx/dv/env/seq_lib/mbx_stress_vseq.sv b/hw/ip/mbx/dv/env/seq_lib/mbx_stress_vseq.sv index 199dbef929e9a..3668b10090703 100644 --- a/hw/ip/mbx/dv/env/seq_lib/mbx_stress_vseq.sv +++ b/hw/ip/mbx/dv/env/seq_lib/mbx_stress_vseq.sv @@ -8,8 +8,8 @@ class mbx_stress_vseq extends mbx_base_vseq; // Constrain the iteration and transaction counts to produce a longer stress test and, // importantly, perform multiple request and responses without an intervening block reset. - constraint num_iters_c { num_iters inside {[5:10]}; } - constraint num_txns_c { num_txns inside {[2:20]}; } + constraint num_iters_c { num_iters inside {[5:8]}; } + constraint num_txns_c { num_txns inside {[2:12]}; } // Whether to produce these stimuli to stress the DUT. bit aborts_en = 1'b1; // Aborts from the SoC side. From 1ca90d814be0a2ec6fb99dd9e1f4d69909ac7bc2 Mon Sep 17 00:00:00 2001 From: Harry Callahan Date: Wed, 17 Jan 2024 23:01:20 +0000 Subject: [PATCH 78/88] [mbx,dv] Test hw mechanism for reporting imbx oob Signed-off-by: Harry Callahan --- hw/ip/mbx/dv/env/mbx_env.core | 1 + hw/ip/mbx/dv/env/mbx_seq_item.sv | 3 ++ hw/ip/mbx/dv/env/seq_lib/mbx_base_vseq.sv | 25 +++++++++++++-- hw/ip/mbx/dv/env/seq_lib/mbx_imbx_oob_vseq.sv | 31 +++++++++++++++++++ hw/ip/mbx/dv/env/seq_lib/mbx_stress_vseq.sv | 19 +++++++----- hw/ip/mbx/dv/env/seq_lib/mbx_vseq_list.sv | 1 + hw/ip/mbx/dv/mbx_sim_cfg.hjson | 4 +++ 7 files changed, 74 insertions(+), 10 deletions(-) create mode 100644 hw/ip/mbx/dv/env/seq_lib/mbx_imbx_oob_vseq.sv diff --git a/hw/ip/mbx/dv/env/mbx_env.core b/hw/ip/mbx/dv/env/mbx_env.core index fa66ebb5ca147..c3fcde078ea4d 100644 --- a/hw/ip/mbx/dv/env/mbx_env.core +++ b/hw/ip/mbx/dv/env/mbx_env.core @@ -26,6 +26,7 @@ filesets: - seq_lib/mbx_smoke_vseq.sv: {is_include_file: true} - seq_lib/mbx_vseq_list.sv: {is_include_file: true} - seq_lib/mbx_stress_vseq.sv: {is_include_file: true} + - seq_lib/mbx_imbx_oob_vseq.sv: {is_include_file: true} file_type: systemVerilogSource generate: diff --git a/hw/ip/mbx/dv/env/mbx_seq_item.sv b/hw/ip/mbx/dv/env/mbx_seq_item.sv index e584dd9e4a7d3..f51275d7cf016 100644 --- a/hw/ip/mbx/dv/env/mbx_seq_item.sv +++ b/hw/ip/mbx/dv/env/mbx_seq_item.sv @@ -44,6 +44,9 @@ class mbx_seq_item extends uvm_sequence_item; (ibmbx_limit_addr < 32'h4000_0000); (ibmbx_limit_addr >= ibmbx_base_addr); + } + + constraint imbx_addr_range_lock_limit_c { // Ensure that the allocated address range is large enough for all valid messages because // otherwise we run the risk of making all subsequent response messages artificially small // because the address range has been locked. diff --git a/hw/ip/mbx/dv/env/seq_lib/mbx_base_vseq.sv b/hw/ip/mbx/dv/env/seq_lib/mbx_base_vseq.sv index 29ffbd257c694..094b75bb875f2 100644 --- a/hw/ip/mbx/dv/env/seq_lib/mbx_base_vseq.sv +++ b/hw/ip/mbx/dv/env/seq_lib/mbx_base_vseq.sv @@ -42,6 +42,7 @@ class mbx_base_vseq extends cip_base_vseq #( mbx_soc_reg_block m_mbx_soc_ral; mbx_seq_item mbx_config; + bit p_expect_error = 1'b0; // Predictor variable // Number of words of memory available to the mailbox(es) int unsigned mbx_mem_words = 'h400; @@ -137,6 +138,12 @@ class mbx_base_vseq extends cip_base_vseq #( seq_h.d_error_pct = pct; endfunction + virtual function void randomize_mbx_config(); + `DV_CHECK_RANDOMIZE_FATAL(mbx_config) + `uvm_info(`gfn, $sformatf("MBX: Randomized a new transaction:%s", + mbx_config.convert2string()), UVM_HIGH) + endfunction + virtual task dut_init(string reset_kind = "HARD"); super.dut_init(); endtask: dut_init @@ -208,7 +215,7 @@ class mbx_base_vseq extends cip_base_vseq #( $sformatf("mbx_init -- Start"), UVM_DEBUG) - `DV_CHECK_RANDOMIZE_FATAL(mbx_config) + randomize_mbx_config(); `uvm_info(get_full_name(), $sformatf("mbx_init -- End"), @@ -385,6 +392,9 @@ class mbx_base_vseq extends cip_base_vseq #( // Generate a new configuration for the transaction. `DV_CHECK_RANDOMIZE_FATAL(mbx_config); + // Generate a new configuration for the transaction. + randomize_mbx_config(); + set_address_range(mbx_config.ibmbx_base_addr, mbx_config.ibmbx_limit_addr, mbx_config.obmbx_base_addr, mbx_config.obmbx_limit_addr, mbx_config.address_range_valid, mbx_config.address_range_regwen); @@ -607,9 +617,18 @@ class mbx_base_vseq extends cip_base_vseq #( // Collect SoC.STATUS bits obs_busy = get_field_val(m_mbx_soc_ral.soc_status.busy, rd_data); obs_error = get_field_val(m_mbx_soc_ral.soc_status.error, rd_data); - if (obs_error) begin - `DV_CHECK_EQ(errored, 1'b1, "Unsignaled ERROR occurred") + if (!p_expect_error) begin + if (obs_error) `DV_CHECK_EQ(errored, 1'b1, "ERROR occurred, but not due to stressors!") + end else if (p_expect_error && !obs_error && !(aborted || panicked)) begin + // If we aborted/panicked, then even if the stimulus should have generated an error, we + // won't see it. + `uvm_error(`gfn, "Didn't observe an error when stimulus expected to generate one!") + end + p_expect_error = 1'b0; + + // Cleanup after error + if (obs_error) begin `uvm_info(`gfn, "Clearing ERROR condition from SoC side using ABORT mechanism", UVM_HIGH) mbx_abort(); aborted = 1'b1; diff --git a/hw/ip/mbx/dv/env/seq_lib/mbx_imbx_oob_vseq.sv b/hw/ip/mbx/dv/env/seq_lib/mbx_imbx_oob_vseq.sv new file mode 100644 index 0000000000000..16d7cd89d0610 --- /dev/null +++ b/hw/ip/mbx/dv/env/seq_lib/mbx_imbx_oob_vseq.sv @@ -0,0 +1,31 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// Add extra constraints to the mbx_config to ensure we generate messages +// which exceed the size of the imbx. +// This should trigger a HW-based check when the imbx attempts to write +// outside the configured address range, raising the 'Error' condition. + +class mbx_imbx_oob_vseq extends mbx_stress_vseq; + + `uvm_object_utils(mbx_imbx_oob_vseq) + `uvm_object_new + + function void randomize_mbx_config(); + // Disabling this constraint allows the solver to randomize to an otherwise-invalid + // config of imbx size + response_dwords that elicits the out-of-bounds error. + mbx_config.imbx_addr_range_lock_limit_c.constraint_mode(0); + `DV_CHECK_RANDOMIZE_WITH_FATAL(mbx_config, + // imbx_size is inclusive of limit address, hence +1 + ((ibmbx_limit_addr - ibmbx_base_addr) / 4) + 1 < request_dwords; + ) + `uvm_info(`gfn, + $sformatf("imbx_size_dwords = %0d, request_dwords = %0d", + ((mbx_config.ibmbx_limit_addr - mbx_config.ibmbx_base_addr) / 4) + 1, + mbx_config.request_dwords), + UVM_MEDIUM) + p_expect_error = 1'b1; + endfunction + +endclass : mbx_imbx_oob_vseq diff --git a/hw/ip/mbx/dv/env/seq_lib/mbx_stress_vseq.sv b/hw/ip/mbx/dv/env/seq_lib/mbx_stress_vseq.sv index 3668b10090703..4f2a7048e8e07 100644 --- a/hw/ip/mbx/dv/env/seq_lib/mbx_stress_vseq.sv +++ b/hw/ip/mbx/dv/env/seq_lib/mbx_stress_vseq.sv @@ -12,9 +12,15 @@ class mbx_stress_vseq extends mbx_base_vseq; constraint num_txns_c { num_txns inside {[2:12]}; } // Whether to produce these stimuli to stress the DUT. - bit aborts_en = 1'b1; // Aborts from the SoC side. - bit errors_en = 1'b1; // Errors from the Core side. - bit panics_en = 1'b1; // FW-initiated reset/Abort clear from the Core side. + rand bit aborts_en; // Aborts from the SoC side. + rand bit errors_en; // Errors from the Core side. + rand bit panics_en; // FW-initiated reset/Abort clear from the Core side. + + constraint stressors_en_c { + aborts_en dist {0:/75, 1:/25}; + errors_en dist {0:/75, 1:/25}; + panics_en dist {0:/75, 1:/25}; + } // TODO: decide how often errors and aborts should be generated; sequences shall probably want // to override the behavior, but we shall also want some kind of sensible default. Perhaps @@ -70,10 +76,9 @@ class mbx_stress_vseq extends mbx_base_vseq; virtual task body(); `uvm_info(get_full_name(), "body -- stress test -- Start", UVM_DEBUG) - // Decide which stimuli to present to the DUT. - aborts_en = ($urandom_range(0,100) > 75); - errors_en = ($urandom_range(0,100) > 75); - panics_en = ($urandom_range(0,100) > 75); + `uvm_info(`gfn, $sformatf("aborts_en = %0b", aborts_en), UVM_LOW) + `uvm_info(`gfn, $sformatf("errors_en = %0b", errors_en), UVM_LOW) + `uvm_info(`gfn, $sformatf("panics_en = %0b", panics_en), UVM_LOW) super.body(); `uvm_info(get_full_name(), "body -- stress test -- End", UVM_DEBUG) diff --git a/hw/ip/mbx/dv/env/seq_lib/mbx_vseq_list.sv b/hw/ip/mbx/dv/env/seq_lib/mbx_vseq_list.sv index bdafc428d282c..3efb73fdddf61 100644 --- a/hw/ip/mbx/dv/env/seq_lib/mbx_vseq_list.sv +++ b/hw/ip/mbx/dv/env/seq_lib/mbx_vseq_list.sv @@ -8,3 +8,4 @@ `include "mbx_common_vseq.sv" `include "mbx_smoke_vseq.sv" `include "mbx_stress_vseq.sv" +`include "mbx_imbx_oob_vseq.sv" diff --git a/hw/ip/mbx/dv/mbx_sim_cfg.hjson b/hw/ip/mbx/dv/mbx_sim_cfg.hjson index f7cd7996cad2c..4319a84e82362 100644 --- a/hw/ip/mbx/dv/mbx_sim_cfg.hjson +++ b/hw/ip/mbx/dv/mbx_sim_cfg.hjson @@ -82,6 +82,10 @@ uvm_test_seq: mbx_stress_vseq run_opts: ["+zero_delays=1"] } + { + name: mbx_imbx_oob + uvm_test_seq: mbx_imbx_oob_vseq + } ] // List of regressions. From dfe9fa195dfa0d1fa8f7fc5aa73d2fc61e38bc97 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Tue, 23 Jan 2024 10:54:00 -0800 Subject: [PATCH 79/88] [hw,mbx,rtl] Gate the AsyncMsg support with feature strap and enable Signed-off-by: Robert Schilling --- hw/ip/mbx/rtl/mbx_sysif.sv | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/hw/ip/mbx/rtl/mbx_sysif.sv b/hw/ip/mbx/rtl/mbx_sysif.sv index c1977de40d798..84ba3ad8b6fc4 100644 --- a/hw/ip/mbx/rtl/mbx_sysif.sv +++ b/hw/ip/mbx/rtl/mbx_sysif.sv @@ -148,6 +148,10 @@ module mbx_sysif assign hw2reg.soc_status.busy.de = sysif_status_busy_valid_i; assign hw2reg.soc_status.busy.d = sysif_status_busy_i; + // Gate the async msg setter with the feature strap and the enable bit + logic async_msg_set_gated; + assign async_msg_set_gated = DoeAsyncMsgSupport & doe_async_msg_en_o & doe_async_msg_set_i; + // Interrupt is triggered by the outbound handler if the message has been written to // the memory and can be read by the system, an error is raised, or if there is an asynchronous // message request coming from the host. @@ -155,13 +159,13 @@ module mbx_sysif assign hw2reg.soc_status.doe_intr_status.de = DoeIrqSupport & (sysif_status_doe_intr_ready_set_i | sysif_status_error_set_i | - doe_async_msg_set_i); + async_msg_set_gated); assign hw2reg.soc_status.doe_intr_status.d = sysif_status_doe_intr_ready_set_i | sysif_status_error_set_i | - doe_async_msg_set_i; + async_msg_set_gated; // Async message status is updated by the host interface - assign hw2reg.soc_status.doe_async_msg_status.de = DoeAsyncMsgSupport & + assign hw2reg.soc_status.doe_async_msg_status.de = DoeAsyncMsgSupport & doe_async_msg_en_o & (doe_async_msg_set_i | doe_async_msg_clear_i); assign hw2reg.soc_status.doe_async_msg_status.d = doe_async_msg_set_i; From 8e71c9a0beb7aa70f28aad2e302d2e35a20d0f47 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Thu, 1 Feb 2024 22:23:27 -0800 Subject: [PATCH 80/88] [hw,mbx,rtl] No direct prim_generic_flop instances Signed-off-by: Robert Schilling --- hw/ip/mbx/rtl/mbx_imbx.sv | 2 +- hw/ip/mbx/rtl/mbx_ombx.sv | 6 +++--- hw/ip/mbx/rtl/mbx_sramrwarb.sv | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/hw/ip/mbx/rtl/mbx_imbx.sv b/hw/ip/mbx/rtl/mbx_imbx.sv index 5424d6ae3d61d..7eaca88f8b94c 100644 --- a/hw/ip/mbx/rtl/mbx_imbx.sv +++ b/hw/ip/mbx/rtl/mbx_imbx.sv @@ -100,7 +100,7 @@ module mbx_imbx #( end end - prim_generic_flop_en #( + prim_flop_en #( .Width(CfgSramAddrWidth) ) u_sram_write_ptr ( .clk_i ( clk_i ), diff --git a/hw/ip/mbx/rtl/mbx_ombx.sv b/hw/ip/mbx/rtl/mbx_ombx.sv index d45d07681a74b..ae8988da8c167 100644 --- a/hw/ip/mbx/rtl/mbx_ombx.sv +++ b/hw/ip/mbx/rtl/mbx_ombx.sv @@ -140,7 +140,7 @@ module mbx_ombx #( end end - prim_generic_flop_en #( + prim_flop_en #( .Width(CfgSramAddrWidth) ) u_sram_read_ptr ( .clk_i ( clk_i ), @@ -164,7 +164,7 @@ module mbx_ombx #( hostif_control_abort_clear_i; // Abort ack or FW reset from host side // Advance the SRAM read response to read data - prim_generic_flop_en #( + prim_flop_en #( .Width(CfgSramDataWidth) ) u_sram_read_data ( .clk_i ( clk_i ), @@ -216,7 +216,7 @@ module mbx_ombx #( assign sram_read_ptr_limit_d = hostif_base_i + CfgSramAddrWidth'({hostif_ombx_object_size_i, 2'b0}); - prim_generic_flop_en #( + prim_flop_en #( .Width(CfgSramAddrWidth) ) u_sram_read_ptr_limit ( .clk_i ( clk_i ), diff --git a/hw/ip/mbx/rtl/mbx_sramrwarb.sv b/hw/ip/mbx/rtl/mbx_sramrwarb.sv index 7c94660d06cef..b3466f93e9341 100644 --- a/hw/ip/mbx/rtl/mbx_sramrwarb.sv +++ b/hw/ip/mbx/rtl/mbx_sramrwarb.sv @@ -80,7 +80,7 @@ module mbx_sramrwarb // Update the count of outstanding requests. assign update_cnt = inc_cnt | dec_cnt | hostif_control_abort_clear_i; - prim_generic_flop_en #( + prim_flop_en #( .Width(LCFG_MAX_REQS_LOG2) ) u_outstanding_req_cnt ( .clk_i ( clk_i ), From c9efb359bd679d346242efa3eab45df6b9a2ef5d Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Fri, 19 Jan 2024 03:03:32 -0800 Subject: [PATCH 81/88] [hw,mbx,rtl] Clear interrupts when acknowledging an abort Signed-off-by: Robert Schilling --- hw/ip/mbx/rtl/mbx.sv | 2 ++ hw/ip/mbx/rtl/mbx_hostif.sv | 32 ++++++++++++++++++++++---------- hw/ip/mbx/rtl/mbx_sysif.sv | 29 ++++++++++++++++++++--------- 3 files changed, 44 insertions(+), 19 deletions(-) diff --git a/hw/ip/mbx/rtl/mbx.sv b/hw/ip/mbx/rtl/mbx.sv index 2402b3459e933..947896de2d7b9 100644 --- a/hw/ip/mbx/rtl/mbx.sv +++ b/hw/ip/mbx/rtl/mbx.sv @@ -203,6 +203,8 @@ module mbx .doe_async_msg_en_o ( doe_async_msg_en ), .doe_async_msg_set_i ( doe_async_msg_set ), .doe_async_msg_clear_i ( doe_async_msg_clear ), + // Abort clearing from the host + .sysif_abort_ack_i ( hostif_control_abort_clear ), // Access to the control register .sysif_control_abort_set_o ( sysif_control_abort_set ), .sysif_control_go_set_o ( sysif_control_go_set ), diff --git a/hw/ip/mbx/rtl/mbx_hostif.sv b/hw/ip/mbx/rtl/mbx_hostif.sv index fcd25bd2d9bf6..f351e937ccd72 100644 --- a/hw/ip/mbx/rtl/mbx_hostif.sv +++ b/hw/ip/mbx/rtl/mbx_hostif.sv @@ -108,7 +108,10 @@ module mbx_hostif .devmode_i ( 1'b1 ) ); - // Instantiate interrupt hardware primitives for ready and abort IRQ + logic intr_ready_de, intr_abort_de, intr_error_de; + logic intr_ready_d, intr_abort_d, intr_error_d; + + // Instantiate interrupt hardware primitives for ready, abort, and error IRQ prim_intr_hw #(.Width(1)) u_intr_ready ( .clk_i ( clk_i ), .rst_ni ( rst_ni ), @@ -117,8 +120,8 @@ module mbx_hostif .reg2hw_intr_test_q_i ( reg2hw.intr_test.mbx_ready.q ), .reg2hw_intr_test_qe_i ( reg2hw.intr_test.mbx_ready.qe ), .reg2hw_intr_state_q_i ( reg2hw.intr_state.mbx_ready.q ), - .hw2reg_intr_state_de_o ( hw2reg.intr_state.mbx_ready.de ), - .hw2reg_intr_state_d_o ( hw2reg.intr_state.mbx_ready.d ), + .hw2reg_intr_state_de_o ( intr_ready_de ), + .hw2reg_intr_state_d_o ( intr_ready_d ), .intr_o ( intr_ready_o ) ); @@ -130,8 +133,8 @@ module mbx_hostif .reg2hw_intr_test_q_i ( reg2hw.intr_test.mbx_abort.q ), .reg2hw_intr_test_qe_i ( reg2hw.intr_test.mbx_abort.qe ), .reg2hw_intr_state_q_i ( reg2hw.intr_state.mbx_abort.q ), - .hw2reg_intr_state_de_o ( hw2reg.intr_state.mbx_abort.de ), - .hw2reg_intr_state_d_o ( hw2reg.intr_state.mbx_abort.d ), + .hw2reg_intr_state_de_o ( intr_abort_de ), + .hw2reg_intr_state_d_o ( intr_abort_d ), .intr_o ( intr_abort_o ) ); @@ -143,11 +146,20 @@ module mbx_hostif .reg2hw_intr_test_q_i ( reg2hw.intr_test.mbx_error.q ), .reg2hw_intr_test_qe_i ( reg2hw.intr_test.mbx_error.qe ), .reg2hw_intr_state_q_i ( reg2hw.intr_state.mbx_error.q ), - .hw2reg_intr_state_de_o ( hw2reg.intr_state.mbx_error.de ), - .hw2reg_intr_state_d_o ( hw2reg.intr_state.mbx_error.d ), + .hw2reg_intr_state_de_o ( intr_error_de ), + .hw2reg_intr_state_d_o ( intr_error_d ), .intr_o ( intr_error_o ) ); + // Let acknowledging the abort from the host clear all pending interrupts + assign hw2reg.intr_state.mbx_ready.de = intr_ready_de | hostif_control_abort_clear_o; + assign hw2reg.intr_state.mbx_abort.de = intr_abort_de | hostif_control_abort_clear_o; + assign hw2reg.intr_state.mbx_error.de = intr_error_de | hostif_control_abort_clear_o; + + assign hw2reg.intr_state.mbx_ready.d = hostif_control_abort_clear_o ? 1'b0 : intr_ready_d; + assign hw2reg.intr_state.mbx_abort.d = hostif_control_abort_clear_o ? 1'b0 : intr_abort_d; + assign hw2reg.intr_state.mbx_error.d = hostif_control_abort_clear_o ? 1'b0 : intr_error_d; + // Control Register logic abort_d, abort_q; @@ -155,10 +167,10 @@ module mbx_hostif always_comb begin abort_d = abort_q; - if (sysif_control_abort_set_i) begin - abort_d = 1'b1; - end else if (hostif_control_abort_clear_o) begin + if (hostif_control_abort_clear_o) begin abort_d = 1'b0; + end else if (sysif_control_abort_set_i) begin + abort_d = 1'b1; end end diff --git a/hw/ip/mbx/rtl/mbx_sysif.sv b/hw/ip/mbx/rtl/mbx_sysif.sv index 84ba3ad8b6fc4..19351fdb3703d 100644 --- a/hw/ip/mbx/rtl/mbx_sysif.sv +++ b/hw/ip/mbx/rtl/mbx_sysif.sv @@ -26,6 +26,8 @@ module mbx_sysif output logic doe_async_msg_en_o, input logic doe_async_msg_set_i, input logic doe_async_msg_clear_i, + // Abort clearing from the host + input logic sysif_abort_ack_i, // Access to the control register output logic sysif_control_abort_set_o, output logic sysif_control_go_set_o, @@ -155,22 +157,31 @@ module mbx_sysif // Interrupt is triggered by the outbound handler if the message has been written to // the memory and can be read by the system, an error is raised, or if there is an asynchronous // message request coming from the host. - // The interrupt is cleared by the SOC firmware via the RW1C behavior + // The interrupt is cleared by the SOC firmware via the RW1C behavior or when an abort is + // acknowledged by the host assign hw2reg.soc_status.doe_intr_status.de = DoeIrqSupport & (sysif_status_doe_intr_ready_set_i | + sysif_abort_ack_i | sysif_status_error_set_i | async_msg_set_gated); - assign hw2reg.soc_status.doe_intr_status.d = sysif_status_doe_intr_ready_set_i | - sysif_status_error_set_i | - async_msg_set_gated; + assign hw2reg.soc_status.doe_intr_status.d = (sysif_status_doe_intr_ready_set_i | + sysif_status_error_set_i | + async_msg_set_gated) & + ~sysif_abort_ack_i; - // Async message status is updated by the host interface - assign hw2reg.soc_status.doe_async_msg_status.de = DoeAsyncMsgSupport & doe_async_msg_en_o & - (doe_async_msg_set_i | doe_async_msg_clear_i); + // Async message status is updated by the host interface when enabled + // and cleared in all cases on an abort and abort ack/FW reset + assign hw2reg.soc_status.doe_async_msg_status.de = (DoeAsyncMsgSupport & doe_async_msg_en_o & + (doe_async_msg_set_i | + doe_async_msg_clear_i)) | + sysif_control_abort_set_o | + sysif_abort_ack_i; assign hw2reg.soc_status.doe_async_msg_status.d = doe_async_msg_set_i; - // Error is cleared when writing the abort bit - assign hw2reg.soc_status.error.de = sysif_status_error_set_i | sysif_control_abort_set_o; + // Error is cleared when writing the abort bit or on a FW-based reset + assign hw2reg.soc_status.error.de = sysif_status_error_set_i | + sysif_control_abort_set_o | + sysif_abort_ack_i; assign hw2reg.soc_status.error.d = sysif_status_error_set_i; // Set by OT firmware (w1s) From 79f6bb06db58710dd54b42558c751556e3eed6f3 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Mon, 12 Feb 2024 00:37:17 -0800 Subject: [PATCH 82/88] [hw,mbx,dv] Disable not implemented stress tests Signed-off-by: Robert Schilling --- hw/ip/mbx/dv/mbx_sim_cfg.hjson | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/hw/ip/mbx/dv/mbx_sim_cfg.hjson b/hw/ip/mbx/dv/mbx_sim_cfg.hjson index 4319a84e82362..4ff984b46a8e9 100644 --- a/hw/ip/mbx/dv/mbx_sim_cfg.hjson +++ b/hw/ip/mbx/dv/mbx_sim_cfg.hjson @@ -30,7 +30,10 @@ "{proj_root}/hw/dv/tools/dvsim/tests/alert_test.hjson", "{proj_root}/hw/dv/tools/dvsim/tests/tl_access_tests.hjson", "{proj_root}/hw/dv/tools/dvsim/tests/sec_cm_tests.hjson", - "{proj_root}/hw/dv/tools/dvsim/tests/stress_tests.hjson"] + // Disable stress_all and stress_all_with_rand_reset tests as they are not + // implemented yet #21298 + // "{proj_root}/hw/dv/tools/dvsim/tests/stress_tests.hjson" + ] // Add additional tops for simulation. // sim_tops: ["mbx_bind", "mbx_cov_bind"] From beedd484958d6bf1a177d0fc89ae35f5f0229ade Mon Sep 17 00:00:00 2001 From: Andreas Kurth Date: Tue, 13 Feb 2024 13:05:37 +0000 Subject: [PATCH 83/88] [mbx/dv] Separate `mbx_stress` from `mbx_stress_all` in testplan The former is a test specifically written for Mailbox (and it already exists) while the latter is a generic test that combines tests specifically written for Mailbox. Both should be part of V2 (in contrast to the generic `stress_all_with_rand_reset`, which is part of V3). Signed-off-by: Andreas Kurth --- hw/ip/mbx/data/mbx_testplan.hjson | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/hw/ip/mbx/data/mbx_testplan.hjson b/hw/ip/mbx/data/mbx_testplan.hjson index 6062934ac078b..dbecb1f21d4aa 100644 --- a/hw/ip/mbx/data/mbx_testplan.hjson +++ b/hw/ip/mbx/data/mbx_testplan.hjson @@ -23,7 +23,14 @@ desc: ''' Stress test ''' - stage: V3 + stage: V2 + tests: ["mbx_stress"] + } + { name: mbx_stress_all + desc: ''' + Run the other tests in random order while injecting TL errors and running automated CSR tests in parallel. + ''' + stage: V2 tests: ["mbx_stress_all"] } ] From 132f38bd3c04c33903f8ec3714d6f5fe475ac6a0 Mon Sep 17 00:00:00 2001 From: Andreas Kurth Date: Tue, 13 Feb 2024 13:10:18 +0000 Subject: [PATCH 84/88] [mbx/dv] Add `mbx_stress_zero_delays` test to `mbx_stress` test point Signed-off-by: Andreas Kurth --- hw/ip/mbx/data/mbx_testplan.hjson | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/ip/mbx/data/mbx_testplan.hjson b/hw/ip/mbx/data/mbx_testplan.hjson index dbecb1f21d4aa..4b24084aa3048 100644 --- a/hw/ip/mbx/data/mbx_testplan.hjson +++ b/hw/ip/mbx/data/mbx_testplan.hjson @@ -24,7 +24,7 @@ Stress test ''' stage: V2 - tests: ["mbx_stress"] + tests: ["mbx_stress", "mbx_stress_zero_delays"] } { name: mbx_stress_all desc: ''' From ed9574f2c434880dbb74bc358df0ca2cfdf2cdcc Mon Sep 17 00:00:00 2001 From: Andreas Kurth Date: Tue, 13 Feb 2024 13:13:49 +0000 Subject: [PATCH 85/88] [mbx/dv] Add test point for out-of-bound inbound mailbox accesses Signed-off-by: Andreas Kurth --- hw/ip/mbx/data/mbx_testplan.hjson | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/hw/ip/mbx/data/mbx_testplan.hjson b/hw/ip/mbx/data/mbx_testplan.hjson index 4b24084aa3048..b5eba6c282b09 100644 --- a/hw/ip/mbx/data/mbx_testplan.hjson +++ b/hw/ip/mbx/data/mbx_testplan.hjson @@ -33,5 +33,12 @@ stage: V2 tests: ["mbx_stress_all"] } + { name: mbx_imbx_oob + desc: ''' + Test accesses that are out of bounds for the inbound mailbox. + ''' + stage: V2 + tests: ["mbx_imbx_oob"] + } ] } From 941995074dc7f9618f1ada636c54d257a2885355 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Sat, 27 Apr 2024 04:31:57 -0700 Subject: [PATCH 86/88] [hw,mbx,rtl] Move SOC_INTR_ADDR/DATA registers to the end A mailbox con either be a PCIe mailbox or a FW mailbox. In case of the PCIe setting, the SOC reagisters 0x0 and 0x4 implement the capability header functionality, but this is done outside of the mbx RTL. PCIe mailboxes do not use the SOC_INTR_DATA/ADDR registers. FW-based mailboxes on the other hand only use the SOC_INTR_DATA/ADDR registers but no capability headers. Previously, it was decided to alias both registers as they are used orthogonally. However, this deceission was revised. This PR moves the SOC_INTR_DATA/ADDR registers to the end of the SOC register interface to not alias with any capability header registers for PCIe mailboxes Signed-off-by: Robert Schilling --- hw/ip/mbx/data/mbx.hjson | 61 +++++------ hw/ip/mbx/rtl/mbx_reg_pkg.sv | 42 ++++---- hw/ip/mbx/rtl/mbx_soc_reg_top.sv | 176 +++++++++++++++---------------- 3 files changed, 140 insertions(+), 139 deletions(-) diff --git a/hw/ip/mbx/data/mbx.hjson b/hw/ip/mbx/data/mbx.hjson index ef63060293eb7..49249d2e4e110 100644 --- a/hw/ip/mbx/data/mbx.hjson +++ b/hw/ip/mbx/data/mbx.hjson @@ -336,36 +336,7 @@ } ] soc: [ - { name: "SOC_DOE_INTR_MSG_ADDR" - desc: ''' - Utilized by the mailbox responder to send an interrupt message to the requester via a write to the configured address. - Defined only for FW-to-FW mailboxes. - ''' - swaccess: "rw" - hwaccess: "hro" - fields: [ - { name: "doe_intr_msg_addr" - desc: "Utilized by the mailbox responder to send an interrupt message to the requester via a write to the configured address." - bits: "31:0" - resval: "0x0" - } - ] - } - { name: "SOC_DOE_INTR_MSG_DATA" - desc: ''' - Interrupt message data to be sent to the address configured in the DOE_INTR_MSG_ADDR register. - Defined only for FW-to-FW mailboxes. - ''' - swaccess: "rw" - hwaccess: "hro" - fields: [ - { name: "doe_intr_msg_data" - desc: "Interrupt message data to be sent to the address configured in the DOE_INTR_MSG_ADDR register." - bits: "31:0" - resval: "0x0" - } - ] - } + { skipto: "0x8" } { name: "SOC_CONTROL" desc: "DOE mailbox control register." hwaccess: "hrw" @@ -482,6 +453,36 @@ swaccess: "rw" } } + { name: "SOC_DOE_INTR_MSG_ADDR" + desc: ''' + Utilized by the mailbox responder to send an interrupt message to the requester via a write to the configured address. + Defined only for FW-to-FW mailboxes. + ''' + swaccess: "rw" + hwaccess: "hro" + fields: [ + { name: "doe_intr_msg_addr" + desc: "Utilized by the mailbox responder to send an interrupt message to the requester via a write to the configured address." + bits: "31:0" + resval: "0x0" + } + ] + } + { name: "SOC_DOE_INTR_MSG_DATA" + desc: ''' + Interrupt message data to be sent to the address configured in the DOE_INTR_MSG_ADDR register. + Defined only for FW-to-FW mailboxes. + ''' + swaccess: "rw" + hwaccess: "hro" + fields: [ + { name: "doe_intr_msg_data" + desc: "Interrupt message data to be sent to the address configured in the DOE_INTR_MSG_ADDR register." + bits: "31:0" + resval: "0x0" + } + ] + } ] } } diff --git a/hw/ip/mbx/rtl/mbx_reg_pkg.sv b/hw/ip/mbx/rtl/mbx_reg_pkg.sv index 8b635fd227533..57a48b8876a18 100644 --- a/hw/ip/mbx/rtl/mbx_reg_pkg.sv +++ b/hw/ip/mbx/rtl/mbx_reg_pkg.sv @@ -286,14 +286,6 @@ package mbx_reg_pkg; // Typedefs for registers for soc interface // ////////////////////////////////////////////// - typedef struct packed { - logic [31:0] q; - } mbx_reg2hw_soc_doe_intr_msg_addr_reg_t; - - typedef struct packed { - logic [31:0] q; - } mbx_reg2hw_soc_doe_intr_msg_data_reg_t; - typedef struct packed { struct packed { logic q; @@ -328,6 +320,14 @@ package mbx_reg_pkg; } busy; } mbx_reg2hw_soc_status_reg_t; + typedef struct packed { + logic [31:0] q; + } mbx_reg2hw_soc_doe_intr_msg_addr_reg_t; + + typedef struct packed { + logic [31:0] q; + } mbx_reg2hw_soc_doe_intr_msg_data_reg_t; + typedef struct packed { struct packed { logic d; @@ -368,10 +368,10 @@ package mbx_reg_pkg; // Register -> HW type for soc interface typedef struct packed { - mbx_reg2hw_soc_doe_intr_msg_addr_reg_t soc_doe_intr_msg_addr; // [75:44] - mbx_reg2hw_soc_doe_intr_msg_data_reg_t soc_doe_intr_msg_data; // [43:12] - mbx_reg2hw_soc_control_reg_t soc_control; // [11:4] - mbx_reg2hw_soc_status_reg_t soc_status; // [3:0] + mbx_reg2hw_soc_control_reg_t soc_control; // [75:68] + mbx_reg2hw_soc_status_reg_t soc_status; // [67:64] + mbx_reg2hw_soc_doe_intr_msg_addr_reg_t soc_doe_intr_msg_addr; // [63:32] + mbx_reg2hw_soc_doe_intr_msg_data_reg_t soc_doe_intr_msg_data; // [31:0] } mbx_soc_reg2hw_t; // HW -> register type for soc interface @@ -381,10 +381,10 @@ package mbx_reg_pkg; } mbx_soc_hw2reg_t; // Register offsets for soc interface - parameter logic [SocAw-1:0] MBX_SOC_DOE_INTR_MSG_ADDR_OFFSET = 5'h 0; - parameter logic [SocAw-1:0] MBX_SOC_DOE_INTR_MSG_DATA_OFFSET = 5'h 4; parameter logic [SocAw-1:0] MBX_SOC_CONTROL_OFFSET = 5'h 8; parameter logic [SocAw-1:0] MBX_SOC_STATUS_OFFSET = 5'h c; + parameter logic [SocAw-1:0] MBX_SOC_DOE_INTR_MSG_ADDR_OFFSET = 5'h 18; + parameter logic [SocAw-1:0] MBX_SOC_DOE_INTR_MSG_DATA_OFFSET = 5'h 1c; // Reset values for hwext registers and their fields for soc interface parameter logic [31:0] MBX_SOC_CONTROL_RESVAL = 32'h 0; @@ -403,18 +403,18 @@ package mbx_reg_pkg; // Register index for soc interface typedef enum int { - MBX_SOC_DOE_INTR_MSG_ADDR, - MBX_SOC_DOE_INTR_MSG_DATA, MBX_SOC_CONTROL, - MBX_SOC_STATUS + MBX_SOC_STATUS, + MBX_SOC_DOE_INTR_MSG_ADDR, + MBX_SOC_DOE_INTR_MSG_DATA } mbx_soc_id_e; // Register width information to check illegal writes for soc interface parameter logic [3:0] MBX_SOC_PERMIT [4] = '{ - 4'b 1111, // index[0] MBX_SOC_DOE_INTR_MSG_ADDR - 4'b 1111, // index[1] MBX_SOC_DOE_INTR_MSG_DATA - 4'b 1111, // index[2] MBX_SOC_CONTROL - 4'b 1111 // index[3] MBX_SOC_STATUS + 4'b 1111, // index[0] MBX_SOC_CONTROL + 4'b 1111, // index[1] MBX_SOC_STATUS + 4'b 1111, // index[2] MBX_SOC_DOE_INTR_MSG_ADDR + 4'b 1111 // index[3] MBX_SOC_DOE_INTR_MSG_DATA }; endpackage diff --git a/hw/ip/mbx/rtl/mbx_soc_reg_top.sv b/hw/ip/mbx/rtl/mbx_soc_reg_top.sv index 2fa1100d8581d..c66f6340ced06 100644 --- a/hw/ip/mbx/rtl/mbx_soc_reg_top.sv +++ b/hw/ip/mbx/rtl/mbx_soc_reg_top.sv @@ -173,12 +173,6 @@ module mbx_soc_reg_top ( // Define SW related signals // Format: __{wd|we|qs} // or _{wd|we|qs} if field == 1 or 0 - logic soc_doe_intr_msg_addr_we; - logic [31:0] soc_doe_intr_msg_addr_qs; - logic [31:0] soc_doe_intr_msg_addr_wd; - logic soc_doe_intr_msg_data_we; - logic [31:0] soc_doe_intr_msg_data_qs; - logic [31:0] soc_doe_intr_msg_data_wd; logic soc_control_re; logic soc_control_we; logic soc_control_abort_wd; @@ -194,64 +188,14 @@ module mbx_soc_reg_top ( logic soc_status_error_qs; logic soc_status_doe_async_msg_status_qs; logic soc_status_ready_qs; + logic soc_doe_intr_msg_addr_we; + logic [31:0] soc_doe_intr_msg_addr_qs; + logic [31:0] soc_doe_intr_msg_addr_wd; + logic soc_doe_intr_msg_data_we; + logic [31:0] soc_doe_intr_msg_data_qs; + logic [31:0] soc_doe_intr_msg_data_wd; // Register instances - // R[soc_doe_intr_msg_addr]: V(False) - prim_subreg #( - .DW (32), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (32'h0), - .Mubi (1'b0) - ) u_soc_doe_intr_msg_addr ( - .clk_i (clk_i), - .rst_ni (rst_ni), - - // from register interface - .we (soc_doe_intr_msg_addr_we), - .wd (soc_doe_intr_msg_addr_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.soc_doe_intr_msg_addr.q), - .ds (), - - // to register interface (read) - .qs (soc_doe_intr_msg_addr_qs) - ); - - - // R[soc_doe_intr_msg_data]: V(False) - prim_subreg #( - .DW (32), - .SwAccess(prim_subreg_pkg::SwAccessRW), - .RESVAL (32'h0), - .Mubi (1'b0) - ) u_soc_doe_intr_msg_data ( - .clk_i (clk_i), - .rst_ni (rst_ni), - - // from register interface - .we (soc_doe_intr_msg_data_we), - .wd (soc_doe_intr_msg_data_wd), - - // from internal hardware - .de (1'b0), - .d ('0), - - // to internal hardware - .qe (), - .q (reg2hw.soc_doe_intr_msg_data.q), - .ds (), - - // to register interface (read) - .qs (soc_doe_intr_msg_data_qs) - ); - - // R[soc_control]: V(True) logic soc_control_qe; logic [3:0] soc_control_flds_we; @@ -458,14 +402,70 @@ module mbx_soc_reg_top ( ); + // R[soc_doe_intr_msg_addr]: V(False) + prim_subreg #( + .DW (32), + .SwAccess(prim_subreg_pkg::SwAccessRW), + .RESVAL (32'h0), + .Mubi (1'b0) + ) u_soc_doe_intr_msg_addr ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (soc_doe_intr_msg_addr_we), + .wd (soc_doe_intr_msg_addr_wd), + + // from internal hardware + .de (1'b0), + .d ('0), + + // to internal hardware + .qe (), + .q (reg2hw.soc_doe_intr_msg_addr.q), + .ds (), + + // to register interface (read) + .qs (soc_doe_intr_msg_addr_qs) + ); + + + // R[soc_doe_intr_msg_data]: V(False) + prim_subreg #( + .DW (32), + .SwAccess(prim_subreg_pkg::SwAccessRW), + .RESVAL (32'h0), + .Mubi (1'b0) + ) u_soc_doe_intr_msg_data ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (soc_doe_intr_msg_data_we), + .wd (soc_doe_intr_msg_data_wd), + + // from internal hardware + .de (1'b0), + .d ('0), + + // to internal hardware + .qe (), + .q (reg2hw.soc_doe_intr_msg_data.q), + .ds (), + + // to register interface (read) + .qs (soc_doe_intr_msg_data_qs) + ); + + logic [3:0] addr_hit; always_comb begin addr_hit = '0; - addr_hit[0] = (reg_addr == MBX_SOC_DOE_INTR_MSG_ADDR_OFFSET); - addr_hit[1] = (reg_addr == MBX_SOC_DOE_INTR_MSG_DATA_OFFSET); - addr_hit[2] = (reg_addr == MBX_SOC_CONTROL_OFFSET); - addr_hit[3] = (reg_addr == MBX_SOC_STATUS_OFFSET); + addr_hit[0] = (reg_addr == MBX_SOC_CONTROL_OFFSET); + addr_hit[1] = (reg_addr == MBX_SOC_STATUS_OFFSET); + addr_hit[2] = (reg_addr == MBX_SOC_DOE_INTR_MSG_ADDR_OFFSET); + addr_hit[3] = (reg_addr == MBX_SOC_DOE_INTR_MSG_DATA_OFFSET); end assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ; @@ -480,14 +480,8 @@ module mbx_soc_reg_top ( end // Generate write-enables - assign soc_doe_intr_msg_addr_we = addr_hit[0] & reg_we & !reg_error; - - assign soc_doe_intr_msg_addr_wd = reg_wdata[31:0]; - assign soc_doe_intr_msg_data_we = addr_hit[1] & reg_we & !reg_error; - - assign soc_doe_intr_msg_data_wd = reg_wdata[31:0]; - assign soc_control_re = addr_hit[2] & reg_re & !reg_error; - assign soc_control_we = addr_hit[2] & reg_we & !reg_error; + assign soc_control_re = addr_hit[0] & reg_re & !reg_error; + assign soc_control_we = addr_hit[0] & reg_we & !reg_error; assign soc_control_abort_wd = reg_wdata[0]; @@ -496,17 +490,23 @@ module mbx_soc_reg_top ( assign soc_control_doe_async_msg_en_wd = reg_wdata[3]; assign soc_control_go_wd = reg_wdata[31]; - assign soc_status_we = addr_hit[3] & reg_we & !reg_error; + assign soc_status_we = addr_hit[1] & reg_we & !reg_error; assign soc_status_doe_intr_status_wd = reg_wdata[1]; + assign soc_doe_intr_msg_addr_we = addr_hit[2] & reg_we & !reg_error; + + assign soc_doe_intr_msg_addr_wd = reg_wdata[31:0]; + assign soc_doe_intr_msg_data_we = addr_hit[3] & reg_we & !reg_error; + + assign soc_doe_intr_msg_data_wd = reg_wdata[31:0]; // Assign write-enables to checker logic vector. always_comb begin reg_we_check = '0; - reg_we_check[0] = soc_doe_intr_msg_addr_we; - reg_we_check[1] = soc_doe_intr_msg_data_we; - reg_we_check[2] = soc_control_we; - reg_we_check[3] = soc_status_we; + reg_we_check[0] = soc_control_we; + reg_we_check[1] = soc_status_we; + reg_we_check[2] = soc_doe_intr_msg_addr_we; + reg_we_check[3] = soc_doe_intr_msg_data_we; end // Read data return @@ -514,21 +514,13 @@ module mbx_soc_reg_top ( reg_rdata_next = '0; unique case (1'b1) addr_hit[0]: begin - reg_rdata_next[31:0] = soc_doe_intr_msg_addr_qs; - end - - addr_hit[1]: begin - reg_rdata_next[31:0] = soc_doe_intr_msg_data_qs; - end - - addr_hit[2]: begin reg_rdata_next[0] = '0; reg_rdata_next[1] = soc_control_doe_intr_en_qs; reg_rdata_next[3] = soc_control_doe_async_msg_en_qs; reg_rdata_next[31] = '0; end - addr_hit[3]: begin + addr_hit[1]: begin reg_rdata_next[0] = soc_status_busy_qs; reg_rdata_next[1] = soc_status_doe_intr_status_qs; reg_rdata_next[2] = soc_status_error_qs; @@ -536,6 +528,14 @@ module mbx_soc_reg_top ( reg_rdata_next[31] = soc_status_ready_qs; end + addr_hit[2]: begin + reg_rdata_next[31:0] = soc_doe_intr_msg_addr_qs; + end + + addr_hit[3]: begin + reg_rdata_next[31:0] = soc_doe_intr_msg_data_qs; + end + default: begin reg_rdata_next = '1; end From 541dd75f208ebcce91cf6172b55875fc37f28d5f Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Thu, 29 Aug 2024 16:18:30 +0200 Subject: [PATCH 87/88] [hw,mbx] Update source files with new license header Signed-off-by: Robert Schilling --- hw/ip/mbx/data/BUILD | 2 +- hw/ip/mbx/data/mbx.hjson | 2 +- hw/ip/mbx/data/mbx_sec_cm_testplan.hjson | 2 +- hw/ip/mbx/data/mbx_testplan.hjson | 2 +- hw/ip/mbx/dv/env/mbx_env.core | 2 +- hw/ip/mbx/dv/env/mbx_env.sv | 2 +- hw/ip/mbx/dv/env/mbx_env_cfg.sv | 2 +- hw/ip/mbx/dv/env/mbx_env_cov.sv | 2 +- hw/ip/mbx/dv/env/mbx_env_pkg.sv | 2 +- hw/ip/mbx/dv/env/mbx_mem_ral_pkg.sv | 2 +- hw/ip/mbx/dv/env/mbx_scoreboard.sv | 2 +- hw/ip/mbx/dv/env/mbx_seq_item.sv | 2 +- hw/ip/mbx/dv/env/mbx_virtual_sequencer.sv | 2 +- hw/ip/mbx/dv/env/seq_lib/mbx_async_msg_vseq.sv | 2 +- hw/ip/mbx/dv/env/seq_lib/mbx_base_vseq.sv | 2 +- hw/ip/mbx/dv/env/seq_lib/mbx_common_vseq.sv | 2 +- hw/ip/mbx/dv/env/seq_lib/mbx_imbx_oob_vseq.sv | 2 +- hw/ip/mbx/dv/env/seq_lib/mbx_reg_reset_val_vseq.sv | 2 +- hw/ip/mbx/dv/env/seq_lib/mbx_smoke_vseq.sv | 2 +- hw/ip/mbx/dv/env/seq_lib/mbx_stress_vseq.sv | 2 +- hw/ip/mbx/dv/env/seq_lib/mbx_tl_device_seq.sv | 2 +- hw/ip/mbx/dv/env/seq_lib/mbx_tl_reg_seq.sv | 2 +- hw/ip/mbx/dv/env/seq_lib/mbx_vseq_list.sv | 2 +- hw/ip/mbx/dv/mbx_sim.core | 2 +- hw/ip/mbx/dv/mbx_sim_cfg.hjson | 2 +- hw/ip/mbx/dv/sva/mbx_bind.sv | 2 +- hw/ip/mbx/dv/sva/mbx_sva.core | 2 +- hw/ip/mbx/dv/tb.sv | 2 +- hw/ip/mbx/dv/tests/mbx_base_test.sv | 2 +- hw/ip/mbx/dv/tests/mbx_test.core | 2 +- hw/ip/mbx/dv/tests/mbx_test_pkg.sv | 2 +- hw/ip/mbx/lint/mbx.vlt | 2 +- hw/ip/mbx/lint/mbx.waiver | 2 +- hw/ip/mbx/mbx.core | 2 +- hw/ip/mbx/rtl/mbx.sv | 2 +- hw/ip/mbx/rtl/mbx_fsm.sv | 2 +- hw/ip/mbx/rtl/mbx_hostif.sv | 2 +- hw/ip/mbx/rtl/mbx_imbx.sv | 2 +- hw/ip/mbx/rtl/mbx_ombx.sv | 2 +- hw/ip/mbx/rtl/mbx_sramrwarb.sv | 2 +- hw/ip/mbx/rtl/mbx_sysif.sv | 2 +- 41 files changed, 41 insertions(+), 41 deletions(-) diff --git a/hw/ip/mbx/data/BUILD b/hw/ip/mbx/data/BUILD index acf012522e046..718fbf89ed168 100644 --- a/hw/ip/mbx/data/BUILD +++ b/hw/ip/mbx/data/BUILD @@ -1,4 +1,4 @@ -# Copyright lowRISC contributors. +# Copyright lowRISC contributors (OpenTitan project). # Licensed under the Apache License, Version 2.0, see LICENSE for details. # SPDX-License-Identifier: Apache-2.0 diff --git a/hw/ip/mbx/data/mbx.hjson b/hw/ip/mbx/data/mbx.hjson index 49249d2e4e110..ecad9597e9a23 100644 --- a/hw/ip/mbx/data/mbx.hjson +++ b/hw/ip/mbx/data/mbx.hjson @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 // diff --git a/hw/ip/mbx/data/mbx_sec_cm_testplan.hjson b/hw/ip/mbx/data/mbx_sec_cm_testplan.hjson index aa6a330b11526..cab79175ca590 100644 --- a/hw/ip/mbx/data/mbx_sec_cm_testplan.hjson +++ b/hw/ip/mbx/data/mbx_sec_cm_testplan.hjson @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 diff --git a/hw/ip/mbx/data/mbx_testplan.hjson b/hw/ip/mbx/data/mbx_testplan.hjson index b5eba6c282b09..21f0d82dbfb01 100644 --- a/hw/ip/mbx/data/mbx_testplan.hjson +++ b/hw/ip/mbx/data/mbx_testplan.hjson @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 { diff --git a/hw/ip/mbx/dv/env/mbx_env.core b/hw/ip/mbx/dv/env/mbx_env.core index c3fcde078ea4d..f83c6e66102d8 100644 --- a/hw/ip/mbx/dv/env/mbx_env.core +++ b/hw/ip/mbx/dv/env/mbx_env.core @@ -1,5 +1,5 @@ CAPI=2: -# Copyright lowRISC contributors. +# Copyright lowRISC contributors (OpenTitan project). # Licensed under the Apache License, Version 2.0, see LICENSE for details. # SPDX-License-Identifier: Apache-2.0 name: "lowrisc:dv:mbx_env:0.1" diff --git a/hw/ip/mbx/dv/env/mbx_env.sv b/hw/ip/mbx/dv/env/mbx_env.sv index b44ad285281fb..fe727489d1dec 100644 --- a/hw/ip/mbx/dv/env/mbx_env.sv +++ b/hw/ip/mbx/dv/env/mbx_env.sv @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 diff --git a/hw/ip/mbx/dv/env/mbx_env_cfg.sv b/hw/ip/mbx/dv/env/mbx_env_cfg.sv index 07020d2d88e44..eaa9d456b30ce 100644 --- a/hw/ip/mbx/dv/env/mbx_env_cfg.sv +++ b/hw/ip/mbx/dv/env/mbx_env_cfg.sv @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 diff --git a/hw/ip/mbx/dv/env/mbx_env_cov.sv b/hw/ip/mbx/dv/env/mbx_env_cov.sv index d1c40d899ea63..0cfff71c21f01 100644 --- a/hw/ip/mbx/dv/env/mbx_env_cov.sv +++ b/hw/ip/mbx/dv/env/mbx_env_cov.sv @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 diff --git a/hw/ip/mbx/dv/env/mbx_env_pkg.sv b/hw/ip/mbx/dv/env/mbx_env_pkg.sv index 14d91f0a9c073..21eb925bde3e6 100644 --- a/hw/ip/mbx/dv/env/mbx_env_pkg.sv +++ b/hw/ip/mbx/dv/env/mbx_env_pkg.sv @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 diff --git a/hw/ip/mbx/dv/env/mbx_mem_ral_pkg.sv b/hw/ip/mbx/dv/env/mbx_mem_ral_pkg.sv index 9084b9387b3f9..6b5258ba8bd9d 100644 --- a/hw/ip/mbx/dv/env/mbx_mem_ral_pkg.sv +++ b/hw/ip/mbx/dv/env/mbx_mem_ral_pkg.sv @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 diff --git a/hw/ip/mbx/dv/env/mbx_scoreboard.sv b/hw/ip/mbx/dv/env/mbx_scoreboard.sv index 3d2abf118822e..afbc5e17fdfdc 100644 --- a/hw/ip/mbx/dv/env/mbx_scoreboard.sv +++ b/hw/ip/mbx/dv/env/mbx_scoreboard.sv @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 diff --git a/hw/ip/mbx/dv/env/mbx_seq_item.sv b/hw/ip/mbx/dv/env/mbx_seq_item.sv index f51275d7cf016..25a40ee1cb765 100644 --- a/hw/ip/mbx/dv/env/mbx_seq_item.sv +++ b/hw/ip/mbx/dv/env/mbx_seq_item.sv @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 diff --git a/hw/ip/mbx/dv/env/mbx_virtual_sequencer.sv b/hw/ip/mbx/dv/env/mbx_virtual_sequencer.sv index ff4fb2f2e1598..d29bfca9bcad9 100644 --- a/hw/ip/mbx/dv/env/mbx_virtual_sequencer.sv +++ b/hw/ip/mbx/dv/env/mbx_virtual_sequencer.sv @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 class mbx_virtual_sequencer extends cip_base_virtual_sequencer #( diff --git a/hw/ip/mbx/dv/env/seq_lib/mbx_async_msg_vseq.sv b/hw/ip/mbx/dv/env/seq_lib/mbx_async_msg_vseq.sv index 4d7ddf0efa47b..28f95a3ca8aea 100644 --- a/hw/ip/mbx/dv/env/seq_lib/mbx_async_msg_vseq.sv +++ b/hw/ip/mbx/dv/env/seq_lib/mbx_async_msg_vseq.sv @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 diff --git a/hw/ip/mbx/dv/env/seq_lib/mbx_base_vseq.sv b/hw/ip/mbx/dv/env/seq_lib/mbx_base_vseq.sv index 094b75bb875f2..de3dee2421ef9 100644 --- a/hw/ip/mbx/dv/env/seq_lib/mbx_base_vseq.sv +++ b/hw/ip/mbx/dv/env/seq_lib/mbx_base_vseq.sv @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 diff --git a/hw/ip/mbx/dv/env/seq_lib/mbx_common_vseq.sv b/hw/ip/mbx/dv/env/seq_lib/mbx_common_vseq.sv index 23347ea916de4..91690ed990e11 100644 --- a/hw/ip/mbx/dv/env/seq_lib/mbx_common_vseq.sv +++ b/hw/ip/mbx/dv/env/seq_lib/mbx_common_vseq.sv @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 diff --git a/hw/ip/mbx/dv/env/seq_lib/mbx_imbx_oob_vseq.sv b/hw/ip/mbx/dv/env/seq_lib/mbx_imbx_oob_vseq.sv index 16d7cd89d0610..f51f3546f7fbd 100644 --- a/hw/ip/mbx/dv/env/seq_lib/mbx_imbx_oob_vseq.sv +++ b/hw/ip/mbx/dv/env/seq_lib/mbx_imbx_oob_vseq.sv @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 diff --git a/hw/ip/mbx/dv/env/seq_lib/mbx_reg_reset_val_vseq.sv b/hw/ip/mbx/dv/env/seq_lib/mbx_reg_reset_val_vseq.sv index 933fca3b1de4f..2ae00081d71ee 100644 --- a/hw/ip/mbx/dv/env/seq_lib/mbx_reg_reset_val_vseq.sv +++ b/hw/ip/mbx/dv/env/seq_lib/mbx_reg_reset_val_vseq.sv @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 diff --git a/hw/ip/mbx/dv/env/seq_lib/mbx_smoke_vseq.sv b/hw/ip/mbx/dv/env/seq_lib/mbx_smoke_vseq.sv index 9d229d8541cd6..14521b42f2f28 100644 --- a/hw/ip/mbx/dv/env/seq_lib/mbx_smoke_vseq.sv +++ b/hw/ip/mbx/dv/env/seq_lib/mbx_smoke_vseq.sv @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 diff --git a/hw/ip/mbx/dv/env/seq_lib/mbx_stress_vseq.sv b/hw/ip/mbx/dv/env/seq_lib/mbx_stress_vseq.sv index 4f2a7048e8e07..81a9127b43e23 100644 --- a/hw/ip/mbx/dv/env/seq_lib/mbx_stress_vseq.sv +++ b/hw/ip/mbx/dv/env/seq_lib/mbx_stress_vseq.sv @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 diff --git a/hw/ip/mbx/dv/env/seq_lib/mbx_tl_device_seq.sv b/hw/ip/mbx/dv/env/seq_lib/mbx_tl_device_seq.sv index 233c26ccf6816..88faae49889dc 100644 --- a/hw/ip/mbx/dv/env/seq_lib/mbx_tl_device_seq.sv +++ b/hw/ip/mbx/dv/env/seq_lib/mbx_tl_device_seq.sv @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 diff --git a/hw/ip/mbx/dv/env/seq_lib/mbx_tl_reg_seq.sv b/hw/ip/mbx/dv/env/seq_lib/mbx_tl_reg_seq.sv index b706aac484f1b..a385a4694b27a 100644 --- a/hw/ip/mbx/dv/env/seq_lib/mbx_tl_reg_seq.sv +++ b/hw/ip/mbx/dv/env/seq_lib/mbx_tl_reg_seq.sv @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 diff --git a/hw/ip/mbx/dv/env/seq_lib/mbx_vseq_list.sv b/hw/ip/mbx/dv/env/seq_lib/mbx_vseq_list.sv index 3efb73fdddf61..594ac63e41d09 100644 --- a/hw/ip/mbx/dv/env/seq_lib/mbx_vseq_list.sv +++ b/hw/ip/mbx/dv/env/seq_lib/mbx_vseq_list.sv @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 diff --git a/hw/ip/mbx/dv/mbx_sim.core b/hw/ip/mbx/dv/mbx_sim.core index 05b8d7535addb..7a6db0723c85f 100644 --- a/hw/ip/mbx/dv/mbx_sim.core +++ b/hw/ip/mbx/dv/mbx_sim.core @@ -1,5 +1,5 @@ CAPI=2: -# Copyright lowRISC contributors. +# Copyright lowRISC contributors (OpenTitan project). # Licensed under the Apache License, Version 2.0, see LICENSE for details. # SPDX-License-Identifier: Apache-2.0 name: "lowrisc:dv:mbx_sim:0.1" diff --git a/hw/ip/mbx/dv/mbx_sim_cfg.hjson b/hw/ip/mbx/dv/mbx_sim_cfg.hjson index 4ff984b46a8e9..803039c078fc2 100644 --- a/hw/ip/mbx/dv/mbx_sim_cfg.hjson +++ b/hw/ip/mbx/dv/mbx_sim_cfg.hjson @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 { diff --git a/hw/ip/mbx/dv/sva/mbx_bind.sv b/hw/ip/mbx/dv/sva/mbx_bind.sv index 3a0ed9c2cce98..36cfdcdf0dd60 100644 --- a/hw/ip/mbx/dv/sva/mbx_bind.sv +++ b/hw/ip/mbx/dv/sva/mbx_bind.sv @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 diff --git a/hw/ip/mbx/dv/sva/mbx_sva.core b/hw/ip/mbx/dv/sva/mbx_sva.core index de86e7ce250c3..aab799b77d541 100644 --- a/hw/ip/mbx/dv/sva/mbx_sva.core +++ b/hw/ip/mbx/dv/sva/mbx_sva.core @@ -1,5 +1,5 @@ CAPI=2: -# Copyright lowRISC contributors. +# Copyright lowRISC contributors (OpenTitan project). # Licensed under the Apache License, Version 2.0, see LICENSE for details. # SPDX-License-Identifier: Apache-2.0 name: "lowrisc:dv:mbx_sva:0.1" diff --git a/hw/ip/mbx/dv/tb.sv b/hw/ip/mbx/dv/tb.sv index 4ca890df3bfdd..1b82cda51c387 100644 --- a/hw/ip/mbx/dv/tb.sv +++ b/hw/ip/mbx/dv/tb.sv @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 diff --git a/hw/ip/mbx/dv/tests/mbx_base_test.sv b/hw/ip/mbx/dv/tests/mbx_base_test.sv index a5bcdff4197c8..08de1b16e48f7 100644 --- a/hw/ip/mbx/dv/tests/mbx_base_test.sv +++ b/hw/ip/mbx/dv/tests/mbx_base_test.sv @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 diff --git a/hw/ip/mbx/dv/tests/mbx_test.core b/hw/ip/mbx/dv/tests/mbx_test.core index e2400a6ad0719..d0f625e6f5385 100644 --- a/hw/ip/mbx/dv/tests/mbx_test.core +++ b/hw/ip/mbx/dv/tests/mbx_test.core @@ -1,5 +1,5 @@ CAPI=2: -# Copyright lowRISC contributors. +# Copyright lowRISC contributors (OpenTitan project). # Licensed under the Apache License, Version 2.0, see LICENSE for details. # SPDX-License-Identifier: Apache-2.0 name: "lowrisc:dv:mbx_test:0.1" diff --git a/hw/ip/mbx/dv/tests/mbx_test_pkg.sv b/hw/ip/mbx/dv/tests/mbx_test_pkg.sv index 0b5279a39d188..1c18848f3b221 100644 --- a/hw/ip/mbx/dv/tests/mbx_test_pkg.sv +++ b/hw/ip/mbx/dv/tests/mbx_test_pkg.sv @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 diff --git a/hw/ip/mbx/lint/mbx.vlt b/hw/ip/mbx/lint/mbx.vlt index b619d88d5012b..137d9512c2b70 100644 --- a/hw/ip/mbx/lint/mbx.vlt +++ b/hw/ip/mbx/lint/mbx.vlt @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 // diff --git a/hw/ip/mbx/lint/mbx.waiver b/hw/ip/mbx/lint/mbx.waiver index 3a20320111e42..fe94f4a9fa725 100644 --- a/hw/ip/mbx/lint/mbx.waiver +++ b/hw/ip/mbx/lint/mbx.waiver @@ -1,4 +1,4 @@ -# Copyright lowRISC contributors. +# Copyright lowRISC contributors (OpenTitan project). # Licensed under the Apache License, Version 2.0, see LICENSE for details. # SPDX-License-Identifier: Apache-2.0 # diff --git a/hw/ip/mbx/mbx.core b/hw/ip/mbx/mbx.core index 0eea0defa5da4..fa24ff79d1627 100644 --- a/hw/ip/mbx/mbx.core +++ b/hw/ip/mbx/mbx.core @@ -1,5 +1,5 @@ CAPI=2: -# Copyright lowRISC contributors. +# Copyright lowRISC contributors (OpenTitan project). # Licensed under the Apache License, Version 2.0, see LICENSE for details. # SPDX-License-Identifier: Apache-2.0 name: "lowrisc:ip:mbx:0.1" diff --git a/hw/ip/mbx/rtl/mbx.sv b/hw/ip/mbx/rtl/mbx.sv index 947896de2d7b9..9cb4dd46aa677 100644 --- a/hw/ip/mbx/rtl/mbx.sv +++ b/hw/ip/mbx/rtl/mbx.sv @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 diff --git a/hw/ip/mbx/rtl/mbx_fsm.sv b/hw/ip/mbx/rtl/mbx_fsm.sv index 2d79e2ea0ada5..242cbd18719bf 100644 --- a/hw/ip/mbx/rtl/mbx_fsm.sv +++ b/hw/ip/mbx/rtl/mbx_fsm.sv @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 diff --git a/hw/ip/mbx/rtl/mbx_hostif.sv b/hw/ip/mbx/rtl/mbx_hostif.sv index f351e937ccd72..c1df8e8f9c9ac 100644 --- a/hw/ip/mbx/rtl/mbx_hostif.sv +++ b/hw/ip/mbx/rtl/mbx_hostif.sv @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 diff --git a/hw/ip/mbx/rtl/mbx_imbx.sv b/hw/ip/mbx/rtl/mbx_imbx.sv index 7eaca88f8b94c..8c7027f0245ed 100644 --- a/hw/ip/mbx/rtl/mbx_imbx.sv +++ b/hw/ip/mbx/rtl/mbx_imbx.sv @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 diff --git a/hw/ip/mbx/rtl/mbx_ombx.sv b/hw/ip/mbx/rtl/mbx_ombx.sv index ae8988da8c167..1436f73fd03c9 100644 --- a/hw/ip/mbx/rtl/mbx_ombx.sv +++ b/hw/ip/mbx/rtl/mbx_ombx.sv @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 diff --git a/hw/ip/mbx/rtl/mbx_sramrwarb.sv b/hw/ip/mbx/rtl/mbx_sramrwarb.sv index b3466f93e9341..2844c4ec0aacc 100644 --- a/hw/ip/mbx/rtl/mbx_sramrwarb.sv +++ b/hw/ip/mbx/rtl/mbx_sramrwarb.sv @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 diff --git a/hw/ip/mbx/rtl/mbx_sysif.sv b/hw/ip/mbx/rtl/mbx_sysif.sv index 19351fdb3703d..1360d16c396f7 100644 --- a/hw/ip/mbx/rtl/mbx_sysif.sv +++ b/hw/ip/mbx/rtl/mbx_sysif.sv @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 From e0294522c65893d267a13015915ec5f6bc013a05 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Thu, 29 Aug 2024 16:19:57 +0200 Subject: [PATCH 88/88] [hw,mbx] Update bazel rules for generating C/Rust headers Signed-off-by: Robert Schilling --- hw/ip/mbx/data/BUILD | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/hw/ip/mbx/data/BUILD b/hw/ip/mbx/data/BUILD index 718fbf89ed168..d252a50b4bc27 100644 --- a/hw/ip/mbx/data/BUILD +++ b/hw/ip/mbx/data/BUILD @@ -4,10 +4,21 @@ package(default_visibility = ["//visibility:public"]) -load("//rules:autogen.bzl", "autogen_hjson_header") +load( + "//rules:autogen.bzl", + "autogen_hjson_c_header", + "autogen_hjson_rust_header", +) + +autogen_hjson_c_header( + name = "mbx_c_regs", + srcs = [ + "mbx.hjson", + ], +) -autogen_hjson_header( - name = "mbx_regs", +autogen_hjson_rust_header( + name = "mbx_rust_regs", srcs = [ "mbx.hjson", ],